GCC(1)
๐ GCC(1) ๐
Hiii bestie, this is the manual for the GNU project's C and C++ compiler, gcc, and I am so ready to walk you through it ๐โจ
๐ NAME ๐
gcc is the GNU project C and C++ compiler ๐ It's giving compiler queen energy, no cap.
๐ SYNOPSIS ๐
Here's the quick-glance way to 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...
Okay so this is just the highlights reel ๐๏ธ The rest of the options are down below ๐ And g++ takes mostly the same options as gcc, so you're basically good to go ๐ซถ
๐ธ DESCRIPTION ๐ธ
When you invoke GCC, it normally does preprocessing, compilation, assembly and linking. The "overall options" let you stop this whole process at an intermediate stage. For example, -c says don't run the linker, so the output is the object files the assembler spits out ๐ฆ
Other options get passed along to one or more stages. Some of them control the preprocessor, some control the compiler itself, and yet others control the assembler and linker. Most of those last ones aren't documented here, because honestly you rarely need them ๐
Most of the command-line options you can use with GCC are meant for C programs. When an option is only useful with another language (usually C++), the explanation says so explicitly. If the description doesn't mention a source language, you can use that option with all supported languages โจ
The usual way to run GCC is to run the executable called gcc, or machine-gcc when you're cross-compiling, or machine-gcc-version if you want one specific version of GCC. When you compile C++ programs, you should invoke GCC as g++ instead ๐
The gcc program takes options and file names as operands. Lots of options have multi-letter names, so multiple single-letter options can't be grouped together. -dv is very different from -d -v, so don't try to be clever ๐
You can mix options and other arguments. For the most part, the order doesn't matter. Order does matter when you use several options of the same kind. For example, if you specify -L more than once, the directories get searched in the order you specified them. Also, the placement of the -l option is significant ๐
Lots of options have long names that start with -f or with -W---for, like -fmove-loop-invariants or -Wformat and so on ๐ง Most of these come in both positive and negative forms, and the negative form of -ffoo is -fno-foo. This manual only documents one of the two forms, whichever one isn't the default โญ
Some options take one or more arguments, usually separated from the option name by either a space or the equals sign (=). Unless it's documented otherwise, an argument can be either numeric or a string. Numeric arguments should typically be small unsigned decimal or hexadecimal integers, and hexadecimal arguments must begin with the 0x prefix ๐ข
Arguments to options that set a size threshold of some sort can be arbitrarily large decimal or hexadecimal integers, followed by a byte size suffix for a multiple of bytes. So you've got kB and KiB for kilobyte and kibibyte, MB and MiB for megabyte and mebibyte, GB and GiB for gigabyte and gigibyte, and so on ๐ Those arguments get called byte-size in the rest of the text. For the full listing and explanation of the binary and decimal byte size prefixes, check the NIST, IEC, and other relevant national and international standards ๐
โจ OPTIONS โจ
๐ Option Summary
Here's the lowdown on all the options, grouped by type. The explanations live in the following sections ๐
๐ท Overall Options
-c -S -E -o file -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-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 -fms-extensions -fnew-inheriting-ctors
-fnew-ttp-matching -fno-nonansi-builtins -fnothrow-opt
-fno-operator-names -fno-optional-diags -fpermissive
-fno-pretty-templates -frepo -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 -Wabi=n -Wabi-tag -Wconversion-null
-Wctor-dtor-privacy -Wdelete-non-virtual-dtor -Wdeprecated-copy
-Wdeprecated-copy-dtor -Wliteral-suffix -Wmultiple-inheritance
-Wno-init-list-lifetime -Wnamespaces -Wnarrowing -Wpessimizing-move
-Wredundant-move -Wnoexcept -Wnoexcept-type -Wclass-memaccess
-Wnon-virtual-dtor -Wreorder -Wregister -Weffc++
-Wstrict-null-sentinel -Wtemplates -Wno-non-template-friend
-Wold-style-cast -Woverloaded-virtual -Wno-pmf-conversions
-Wno-class-conversion -Wno-terminate -Wsign-promo
-Wvirtual-inheritance
๐ฆ 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-protocol -Wselector -Wstrict-selector-match
-Wundeclared-selector
๐ฉท Diagnostic Message Formatting Options
-fmessage-length=n -fdiagnostics-show-location=[once|every-line]
-fdiagnostics-color=[auto|never|always]
-fdiagnostics-format=[text|json] -fno-diagnostics-show-option
-fno-diagnostics-show-caret -fno-diagnostics-show-labels
-fno-diagnostics-show-line-numbers
-fdiagnostics-minimum-margin-width=width
-fdiagnostics-parseable-fixits -fdiagnostics-generate-patch
-fdiagnostics-show-template-tree -fno-elide-type -fno-show-column
โจ Warning Options โจ
okay bestie, the warning options are a WHOLE buffet ๐ gcc gets super chatty with these, so here's the full menu, no cap ๐ซถ
-fsyntax-only -fmax-errors=n -Wpedantic -pedantic-errors -w
-Wextra -Wall -Waddress -Waddress-of-packed-member
-Waggregate-return -Waligned-new -Walloc-zero
-Walloc-size-larger-than=byte-size -Walloca
-Walloca-larger-than=byte-size -Wno-aggressive-loop-optimizations
-Warray-bounds -Warray-bounds=n -Wno-attributes
-Wattribute-alias=n -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 -Wcast-align
-Wcast-align=strict -Wcast-function-type -Wcast-qual
-Wchar-subscripts -Wcatch-value -Wcatch-value=n -Wclobbered
-Wcomment -Wconditionally-supported -Wconversion
-Wcoverage-mismatch -Wno-cpp -Wdangling-else -Wdate-time
-Wdelete-incomplete -Wno-attribute-warning -Wno-deprecated
-Wno-deprecated-declarations -Wno-designated-init
-Wdisabled-optimization -Wno-discarded-qualifiers
-Wno-discarded-array-qualifiers -Wno-div-by-zero -Wdouble-promotion
-Wduplicated-branches -Wduplicated-cond -Wempty-body
-Wenum-compare -Wno-endif-labels -Wexpansion-to-defined -Werror
-Werror=* -Wextra-semi -Wfatal-errors -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 -Wjump-misses-init -Whsa -Wif-not-aligned
-Wignored-qualifiers -Wignored-attributes
-Wincompatible-pointer-types -Wimplicit -Wimplicit-fallthrough
-Wimplicit-fallthrough=n -Wimplicit-function-declaration
-Wimplicit-int -Winit-self -Winline -Wno-int-conversion
-Wint-in-bool-context -Wno-int-to-pointer-cast
-Winvalid-memory-model -Wno-invalid-offsetof -Winvalid-pch
-Wlarger-than=byte-size -Wlogical-op -Wlogical-not-parentheses
-Wlong-long -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 -Wmissing-profile -Wno-multichar
-Wmultistatement-macros -Wnonnull -Wnonnull-compare
-Wnormalized=[none|id|nfc|nfkc] -Wnull-dereference -Wodr
-Wno-overflow -Wopenmp-simd -Woverride-init-side-effects
-Woverlength-strings -Wpacked -Wpacked-bitfield-compat
-Wpacked-not-aligned -Wpadded -Wparentheses
-Wno-pedantic-ms-format -Wplacement-new -Wplacement-new=n
-Wpointer-arith -Wpointer-compare -Wno-pointer-to-int-cast
-Wno-pragmas -Wno-prio-ctor-dtor -Wredundant-decls -Wrestrict
-Wno-return-local-addr -Wreturn-type -Wsequence-point -Wshadow
-Wno-shadow-ivar -Wshadow=global, -Wshadow=local,
-Wshadow=compatible-local -Wshift-overflow -Wshift-overflow=n
-Wshift-count-negative -Wshift-count-overflow
-Wshift-negative-value -Wsign-compare -Wsign-conversion
-Wfloat-conversion -Wno-scalar-storage-order -Wsizeof-pointer-div
-Wsizeof-pointer-memaccess -Wsizeof-array-argument
-Wstack-protector -Wstack-usage=byte-size -Wstrict-aliasing
-Wstrict-aliasing=n -Wstrict-overflow -Wstrict-overflow=n
-Wstringop-overflow=n -Wstringop-truncation -Wsubobject-linkage
-Wsuggest-attribute=[pure|const|noreturn|format|malloc]
-Wsuggest-final-types -Wsuggest-final-methods -Wsuggest-override
-Wswitch -Wswitch-bool -Wswitch-default -Wswitch-enum
-Wswitch-unreachable -Wsync-nand -Wsystem-headers
-Wtautological-compare -Wtrampolines -Wtrigraphs -Wtype-limits
-Wundef -Wuninitialized -Wunknown-pragmas
-Wunsuffixed-float-constants -Wunused -Wunused-function
-Wunused-label -Wunused-local-typedefs -Wunused-macros
-Wunused-parameter -Wno-unused-result -Wunused-value
-Wunused-variable -Wunused-const-variable -Wunused-const-variable=n
-Wunused-but-set-parameter -Wunused-but-set-variable -Wuseless-cast
-Wvariadic-macros -Wvector-operation-performance -Wvla
-Wvla-larger-than=byte-size -Wvolatile-register-var -Wwrite-strings
-Wzero-as-null-pointer-constant
โจ C and Objective-C-only Warning Options โจ
these ones are C and Objective-C only, so if you're not in those lanes, they're not your vibe ๐ง
-Wbad-function-cast -Wmissing-declarations -Wmissing-parameter-type
-Wmissing-prototypes -Wnested-externs -Wold-style-declaration
-Wold-style-definition -Wstrict-prototypes -Wtraditional
-Wtraditional-conversion -Wdeclaration-after-statement
-Wpointer-sign
โจ Debugging Options โจ
ok debugging time ๐ฆ this is the lineup for when you wanna peek under the hood ๐
-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 -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]
-feliminate-unused-debug-symbols -femit-class-debug-always
-fno-merge-debug-strings -fno-dwarf2-cfi-asm -fvar-tracking
-fvar-tracking-assignments
โจ Optimization Options โจ
and the optimization options ๐ฅ this list is so long it's giving marathon ๐ญ here's everything, no skipping:
-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]]]] -fassociative-math -fauto-profile
-fauto-profile[=path] -fauto-inc-dec -fbranch-probabilities
-fbranch-target-load-optimize -fbranch-target-load-optimize2
-fbtr-bb-exclusive -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 -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-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-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 -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 --param name=value -O
-O0 -O1 -O2 -O3 -Os -Ofast -Og
๐ธ Program Instrumentation Options ๐ธ
okay bestie, this is the instrumentation drip ๐ these are the flags that poke at your program from the inside, and they are a lot ๐ญ
-p-pg-fprofile-arcs--coverage-ftest-coverage-fprofile-abs-path-fprofile-dir=path-fprofile-generate-fprofile-generate=path-fprofile-update=method-fprofile-filter-files=regex-fprofile-exclude-files=regex-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 ๐ง
the preprocessor squad is serving main character energy ๐ get ready for a lot of little flags
-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-fmacro-prefix-map=old=new-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-no-integrated-cpp-P-pthread-remap-traditional-traditional-cpp-trigraphs-Umacro-undef-Wp,option-Xpreprocessor option
๐ฆ Assembler Options ๐ฆ
only two of these, but they're iconic ๐ซถ
-Wa,option-Xassembler option
๐ Linker Options ๐
the linking crew ๐ this is where all your pieces get tied 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 the compiler goes looking for stuff ๐บ๏ธ it's giving scavenger hunt
-Bprefix-Idir-I--idirafter dir-imacros file-imultilib dir-iplugindir=dir-iprefix file-iquote dir-isysroot dir-isystem dir-iwithprefix dir-iwithprefixbefore dir-Ldir-no-canonical-prefixes--no-sysroot-suffix-nostdinc-nostdinc++--sysroot=dir
๐ Code Generation Options ๐
this is where the code gets its whole glow-up โจ
-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-fno-common-fno-ident-fpcc-struct-return-fpic-fPIC-fpie-fPIE-fno-plt-fno-jump-tables-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 ๐งช
the developer zone ๐ฅ bestie if you're poking around under the hood, this is your playground
-dletters-dumpspecs-dumpmachine-dumpversion-dumpfullversion-fchecking-fchecking=n-fdbg-cnt-list-fdbg-cnt=counter-value-list-fdisable-ipa-pass_name-fdisable-rtl-pass_name-fdisable-rtl-pass-name=range-list-fdisable-tree-pass_name-fdisable-tree-pass-name=range-list-fdump-debug-fdump-earlydebug-fdump-noaddr-fdump-unnumbered-fdump-unnumbered-links-fdump-final-insns[=file]-fdump-ipa-all-fdump-ipa-cgraph-fdump-ipa-inline-fdump-lang-all-fdump-lang-switch-fdump-lang-switch-options-fdump-lang-switch-options=filename-fdump-passes-fdump-rtl-pass-fdump-rtl-pass=filename-fdump-statistics-fdump-tree-all-fdump-tree-switch-fdump-tree-switch-options-fdump-tree-switch-options=filename-fcompare-debug[=opts]-fcompare-debug-second-fenable-kind-pass-fenable-kind-pass=range-list-fira-verbose=n-flto-report-flto-report-wpa-fmem-report-wpa-fmem-report-fpre-ipa-mem-report-fpost-ipa-mem-report-fopt-info-fopt-info-options[=file]-fprofile-report-frandom-seed=string-fsched-verbose=n-fsel-sched-verbose-fsel-sched-dump-cfg-fsel-sched-pipelining-verbose-fstats-fstack-usage-ftime-report-ftime-report-details-fvar-tracking-assignments-toggle-gtoggle-print-file-name=library-print-libgcc-file-name-print-multi-directory-print-multi-lib-print-multi-os-directory-print-prog-name=program-print-search-dirs-Q-print-sysroot-print-sysroot-headers-suffix-save-temps-save-temps=cwd-save-temps=obj-time[=file]
๐ Machine-Dependent Options ๐
last but not least, the target-specific flags ๐ every chip gets its own little lineup, so let's go through them one by one ๐
๐ 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]|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 ๐
-mhalf-reg-file-mprefer-short-insn-regs-mbranch-cost=num-mcmove-mnops=num-msoft-cmpsf-msplit-lohi-mpost-inc-mpost-modify-mstack-offset=num-mround-nearest-mlong-calls-mshort-calls-msmall16-mfp-mode=mode-mvect-double-max-vect-align=num-msplit-vecmove-early-m1reg-reg
๐ AMD GCN Options ๐
-march=gpu-mtune=gpu-mstack-size=bytes
๐ฆ ARC Options ๐ฆ
-mbarrel-shifter-mjli-always-mcpu=cpu-mA6-mARC600-mA7-mARC700-mdpfp-mdpfp-compact-mdpfp-fast-mno-dpfp-lrsr-mea-mno-mpy-mmul32x16-mmul64-matomic-mnorm-mspfp-mspfp-compact-mspfp-fast-msimd-msoft-float-mswap-mcrc-mdsp-packa-mdvbf-mlock-mmac-d16-mmac-24-mrtsc-mswape-mtelephony-mxy-misize-mannotate-align-marclinux-marclinux_prof-mlong-calls-mmedium-calls-msdata-mirq-ctrl-saved-mrgf-banked-regs-mlpc-width=width-G num-mvolatile-cache-mtp-regno=regno-malign-call-mauto-modify-reg-mbbit-peephole-mno-brcc-mcase-vector-pcrel-mcompact-casesi-mno-cond-exec-mearly-cbranchsi-mexpand-adddi-mindexed-loads-mlra-mlra-priority-none-mlra-priority-compactmlra-priority-noncompact-mmillicode-mmixed-code-mq-class-mRcq-mRcw-msize-level=level-mtune=cpu-mmultcost=num-mcode-density-frame-munalign-prob-threshold=probability-mmpy-option=multo-mdiv-rem-mcode-density-mll64-mfpu=fpu-mrf16-mbranch-index
๐ ๏ธ ARM Options ๐ ๏ธ
-mapcs-frame-mno-apcs-frame-mabi=name-mapcs-stack-check-mno-apcs-stack-check-mapcs-reentrant-mno-apcs-reentrant-mgeneral-regs-only-msched-prolog-mno-sched-prolog-mlittle-endian-mbig-endian-mbe8-mbe32-mfloat-abi=name-mfp16-format=name-mthumb-interwork-mno-thumb-interwork-mcpu=name-march=name-mfpu=name-mtune=name-mprint-tune-info-mstructure-size-boundary=n-mabort-on-noreturn-mlong-calls-mno-long-calls-msingle-pic-base-mno-single-pic-base-mpic-register=reg-mnop-fun-dllimport-mpoke-function-name-mthumb-marm-mflip-thumb-mtpcs-frame-mtpcs-leaf-frame-mcaller-super-interworking-mcallee-super-interworking-mtp=name-mtls-dialect=dialect-mword-relocations-mfix-cortex-m3-ldrd-munaligned-access-mneon-for-64bits-mslow-flash-data-masm-syntax-unified-mrestrict-it-mverbose-cost-dump-mpure-code-mcmse
โก AVR Options โก
-mmcu=mcu-mabsdata-maccumulate-args-mbranch-cost=cost-mcall-prologues-mgas-isr-prologues-mint8-mn_flash=size-mno-interrupts-mmain-is-OS_task-mrelax-mrmw-mstrict-X-mtiny-stack-mfract-convert-truncate-mshort-calls-nodevicelib-nodevicespecs-Waddr-space-convert-Wmisspelled-isr
๐ซง Blackfin Options ๐ซง
-mcpu=cpu[-sirevision]-msim-momit-leaf-frame-pointer-mno-omit-leaf-frame-pointer-mspecld-anomaly-mno-specld-anomaly-mcsync-anomaly-mno-csync-anomaly-mlow-64k-mno-low64k-mstack-check-l1-mid-shared-library-mno-id-shared-library-mshared-library-id=n-mleaf-id-shared-library-mno-leaf-id-shared-library-msep-data-mno-sep-data-mlong-calls-mno-long-calls-mfast-fp-minline-plt-mmulticore-mcorea-mcoreb-msdram-micplb
๐ฎ C6X Options ๐ฎ
-mbig-endian-mlittle-endian-march=cpu-msim-msdata=sdata-type
๐ฟ CRIS Options ๐ฟ
-mcpu=cpu-march=cpu-mtune=cpu-mmax-stack-frame=n-melinux-stacksize=n-metrax4-metrax100-mpdebug-mcc-init-mno-side-effects-mstack-align-mdata-align-mconst-align-m32-bit-m16-bit-m8-bit-mno-prologue-epilogue-mno-gotplt-melf-maout-melinux-mlinux-sim-sim2-mmul-bug-workaround-mno-mul-bug-workaround
๐น๏ธ CR16 Options ๐น๏ธ
-mmac-mcr16cplus-mcr16c-msim-mint32-mbit-ops-mdata-model=model
๐ฟ C-SKY Options ๐ฟ
-march=arch-mcpu=cpu-mbig-endian-EB-mlittle-endian-EL-mhard-float-msoft-float-mfpu=fpu-mdouble-float-mfdivdu-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
The original page just lists these flags without explaining them, so I'm sharing the full lineup exactly as written. I haven't made up any behaviour ๐ซถ
๐ Darwin Options ๐
Okay bestie, the Darwin squad is HUGE ๐ Here's every single one:
-all_load-allowable_client-arch-arch_errors_fatal-arch_only-bind_at_load-bundle-bundle_loader-client_name-compatibility_version-current_version-dead_strip-dependency-file-dylib_file-dylinker_install_name-dynamic-dynamiclib-exported_symbols_list-filelist-flat_namespace-force_cpusubtype_ALL-force_flat_namespace-headerpad_max_install_names-iframework-image_base-init-install_name-keep_private_externs-multi_module-multiply_defined-multiply_defined_unused-noall_load-no_dead_strip_inits_and_terms-nofixprebinding-nomultidefs-noprebind-noseglinkedit-pagezero_size-prebind-prebind_all_twolevel_modules-private_bundle-read_only_relocs-sectalign-sectobjectsymbols-whyload-seg1addr-sectcreate-sectobjectsymbols-sectorder-segaddr-segs_read_only_addr-segs_read_write_addr-seg_addr_table-seg_addr_table_filename-seglinkedit-segprot-segs_read_only_addr-segs_read_write_addr-single_module-static-sub_library-sub_umbrella-twolevel_namespace-umbrella-undefined-unexported_symbols_list-weak_reference_mismatches-whatsloaded-F-gused-gfull-mmacosx-version-min=version-mkernel-mone-byte-bool
๐ธ DEC Alpha Options ๐ธ
Next up, the Alpha crew ๐ Look at this lineup:
-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
๐ฆ FR30 Options ๐ฆ
Short and sweet ๐
-msmall-model-mno-lsim
๐ง FT32 Options ๐ง
Six of these, bestie โจ
-msim-mlra-mnodiv-mft32b-mcompress-mnopm
๐ FRV Options ๐
The FRV list is literally massive ๐ญ Here's every single one:
-mgpr-32-mgpr-64-mfpr-32-mfpr-64-mhard-float-msoft-float-malloc-cc-mfixed-cc-mdword-mno-dword-mdouble-mno-double-mmedia-mno-media-mmuladd-mno-muladd-mfdpic-minline-plt-mgprel-ro-multilib-library-pic-mlinked-fp-mlong-calls-malign-labels-mlibrary-pic-macc-4-macc-8-mpack-mno-pack-mno-eflags-mcond-move-mno-cond-move-moptimize-membar-mno-optimize-membar-mscc-mno-scc-mcond-exec-mno-cond-exec-mvliw-branch-mno-vliw-branch-mmulti-cond-exec-mno-multi-cond-exec-mnested-cond-exec-mno-nested-cond-exec-mtomcat-stats-mTLS-mtls-mcpu=cpu
๐ค GNU/Linux Options ๐ค
Penguin energy ๐ง
-mglibc-muclibc-mmusl-mbionic-mandroid-tno-android-cc-tno-android-ld
๐ H8/300 Options ๐
Eight little guys ๐
-mrelax-mh-ms-mn-mexr-mno-exr-mint32-malign-300
๐ HPPA Options ๐
The HPPA list is a whole journey, bestie ๐
-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 ๐
Okay this one is ENORMOUS, but we're still going ๐
-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 ๐ท
Five options, all vibes ๐ท
-mbarrel-shift-enabled-mdivide-enabled-mmultiply-enabled-msign-extend-enabled-muser-enabled
๐ฅ M32R/D Options ๐ฅ
This one's got a lot going on ๐ฅ
-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 ๐ฆ
Three little picks ๐ฆ
-mcpu=cpu-msim-memregs=number
๐ M680x0 Options ๐
The M680x0 list is iconic, and it's long ๐ Let's go:
-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 ๐งธ
Big list, bestie, but every one is a gem ๐งธ
-mhardlit-mno-hardlit-mdiv-mno-div-mrelax-immediates-mno-relax-immediates-mwide-bitfields-mno-wide-bitfields-m4byte-functions-mno-4byte-functions-mcallgraph-data-mno-callgraph-data-mslow-bytes-mno-slow-bytes-mno-lsim-mlittle-endian-mbig-endian-m210-m340-mstack-increment
๐ MeP Options ๐
The MeP crew is giving main character energy ๐
-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 ๐ชจ
Rock solid lineup ๐ชจ
-msoft-float-mhard-float-msmall-divides-mcpu=cpu-mmemcpy-mxl-soft-mul-mxl-soft-div-mxl-barrel-shift-mxl-pattern-compare-mxl-stack-check-mxl-gp-opt-mno-clearbss-mxl-multiply-high-mxl-float-convert-mxl-float-sqrt-mbig-endian-mlittle-endian-mxl-reorder-mxl-mode-app-model-mpic-data-is-text-relative
๐ MIPS Options ๐
MIPS is the biggest boss of them all ๐ Buckle up, bestie ๐
-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 ๐งฉ
Sixteen pieces to this puzzle ๐งฉ
-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 ๐
Little wind chime energy ๐
-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 ๐
Four to keep you company ๐
-meb-mel-mmul.x-mno-crt0
โก MSP430 Options โก
Zappy list, bestie โก
-msim-masm-hex-mmcu=-mcpu=-mlarge-msmall-mrelax-mwarn-mcu-mcode-region=-mdata-region=-msilicon-errata=-msilicon-errata-warn=-mhwmult=-minrt
๐ฆ NDS32 Options ๐ฆ
Prehistoric-sized list, no cap ๐ฆ
-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 ๐ค
This one's long and I'm obsessed with it ๐ค
-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 ๐
Four little options, very green ๐
-m32-m64-mmainkernel-moptimize
๐ ๏ธ OpenRISC Options ๐ ๏ธ
Tool-kit vibes ๐ ๏ธ
-mboard=name-mnewlib-mhard-mul-mhard-div-msoft-mul-msoft-div-mcmov-mror-msext-msfimm-mshftimm
๐น๏ธ PDP-11 Options ๐น๏ธ
Retro era, serving classic energy ๐น๏ธ
-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 ๐
Tiny but mighty ๐
-mae=ae_type-mvliw-lookahead=N-msymbol-as-address-mno-inefficient-warnings
๐ PowerPC Options ๐
And finally, the PowerPC one ๐ It's a cross-reference, not a list, so here's where to look:
See RS/6000 and PowerPC Options.
๐ธ RISC-V Options ๐ธ
okay bestie, the RISC-V squad is up first ๐ here are all the flags:
-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-mstrict-align-mno-strict-align-mcmodel=medlow-mcmodel=medany-mexplicit-relocs-mno-explicit-relocs-mrelax-mno-relax-mriscv-attribute-mmo-riscv-attribute
๐ฆ RL78 Options ๐ฆ
next up, the RL78 crew, lowkey a smaller group but still iconic โจ
-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 biggest list on the whole page and it is absolutely unhinged, no cap ๐ it's giving a lot of flags, so get comfy ๐ซถ
-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-mmfpgpr-mno-mfpgpr-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-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
๐ RX Options ๐
the RX group, short and sweet ๐
-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 ๐ง
now the S/390 and zSeries era, lowkey a whole mood ๐ฎ
-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-mfused-madd-mno-fused-madd-mwarn-framesize-mwarn-dynamicstack-mstack-size-mstack-guard-mhotpatch=halfwords,halfwords
๐ Score Options ๐
the Score bunch, small but mighty โญ
-meb-mel-mnhwloop-muls-mmac-mscore5-mscore5u-mscore7-mscore7d
๐ SH Options ๐
the SH list is so long it needs its own snack break ๐
-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 โ๏ธ
the Solaris 2 flags, quick and clean โจ
-mclear-hwcap-mno-clear-hwcap-mimpure-text-mno-impure-text-pthreads
๐ซง SPARC Options ๐ซง
SPARC is up next and it's giving very structured energy ๐
-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
๐ฎ SPU Options ๐ฎ
the SPU options, very gamer-coded, I'm obsessed ๐ฅ
-mwarn-reloc-merror-reloc-msafe-dma-munsafe-dma-mbranch-hints-msmall-mem-mlarge-mem-mstdmain-mfixed-range=register-range-mea32-mea64-maddress-space-conversion-mno-address-space-conversion-mcache-size=cache-size-matomic-updates-mno-atomic-updates
๐ System V Options ๐
the System V crew, very old-school but still slay ๐
-Qy-Qn-YP,paths-Ym,dir
๐ช TILE-Gx Options ๐ช
-mcpu=CPU-m32-m64-mbig-endian-mlittle-endian-mcmodel=code-model
๐ท TILEPro Options ๐ท
-mcpu=cpu-m32
๐ฆ V850 Options ๐ฆ
the V850 options are a whole lineup, no cap ๐ซถ
-mlong-calls-mno-long-calls-mep-mno-ep-mprolog-function-mno-prolog-function-mspace-mtda=n-msda=n-mzda=n-mapp-regs-mno-app-regs-mdisable-callt-mno-disable-callt-mv850e2v3-mv850e2-mv850e1-mv850es-mv850e-mv850-mv850e3v5-mloop-mrelax-mlong-jumps-msoft-float-mhard-float-mgcc-abi-mrh850-abi-mbig-switch
๐ VAX Options ๐
-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 ๐
the x86 list is absolutely massive, bestie, this is the final boss of flags ๐๐ฅ take a breath and let's go
-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-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-mvpclmulqdq-mavx512bitalg-mmovdiri-mmovdir64b-mavx512vpopcntdq-mavx5124fmaps-mavx512vnni-mavx5124vnniw-mprfchw-mrdpid-mrdseed-msgx-mcldemote-mms-bitfields-mno-align-stringops-minline-all-stringops-minline-stringops-dynamically-mstringop-strategy=alg-mmemcpy-strategy=strategy-mmemset-strategy=strategy-mpush-args-maccumulate-outgoing-args-m128bit-long-double-m96bit-long-double-mlong-double-64-mlong-double-80-mlong-double-128-mregparm=num-msseregparm-mveclibabi=type-mvect8-ret-in-mem-mpc32-mpc64-mpc80-mstackrealign-momit-leaf-frame-pointer-mno-red-zone-mno-tls-direct-seg-refs-mcmodel=code-model-mabi=name-maddress-mode=mode-m32-m64-mx32-m16-miamcu-mlarge-data-threshold=num-msse2avx-mfentry-mrecord-mcount-mnop-mcount-m8bit-idiv-minstrument-return=type-mfentry-name=name-mfentry-section=name-mavx256-split-unaligned-load-mavx256-split-unaligned-store-malign-data=type-mstack-protector-guard=guard-mstack-protector-guard-reg=reg-mstack-protector-guard-offset=offset-mstack-protector-guard-symbol=symbol-mgeneral-regs-only-mcall-ms2sysv-xlogues-mindirect-branch=choice-mfunction-return=choice-mindirect-branch-register
๐ช x86 Windows Options ๐ช
okay the Windows-specific x86 flags, bestie, you've made it ๐ฅน
-mconsole-mcygwin-mno-cygwin-mdll-mnop-fun-dllimport-mthread-municode-mwin32-mwindows-fno-set-stack-executable
๐ผ Xstormy16 Options ๐ผ
-msim
๐บ Xtensa Options ๐บ
the Xtensa lineup to close things out ๐
-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
๐ zSeries Options ๐
- zSeries Options see S/390 and zSeries Options. literally just go check that section ๐
๐ง Options Controlling the Kind of Output ๐ง
okay so this bit is about the stages of compilation, and it's actually lowkey important ๐ซถ there are up to four stages, and they always happen in this order: preprocessing, compilation proper, assembly, and linking.
GCC can preprocess and compile several files into several assembler input files, or squish them all into one assembler input file. Then each assembler input file makes an object file, and linking combines all the object files (the ones freshly compiled plus any you passed in as input) into one executable file โจ
For any given input file, the file name suffix decides what kind of compilation happens. the way that it works is so simple, iykyk ๐
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, bestie: you must link with the libobjc library to make an Objective-C program work. Don't skip this or it won't slay ๐
file.miโ Objective-C source code that should not be preprocessed.file.mm,file.Mโ Objective-C++ source code ๐ You have to link with thelibobjclibrary or your Objective-C++ program won't work ๐ And.Mhas to be a literal capital M, not lowercase.file.miiโ Objective-C++ source code that should not be preprocessed ๐ฆfile.hโ A C, C++, Objective-C, or Objective-C++ header that gets turned into a precompiled header (that's the default โจ), or a C or C++ header that gets turned into an Ada spec through 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 ๐ฅ In.cxx, the last two letters have to be literally lowercasex, and.Chas to be 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 (yes, it's back again, no notes ๐)file.hh,file.H,file.hp,file.hxx,file.hpp,file.HPP,file.h++,file.tccโ C++ headers that get turned into a precompiled header or an Ada spec ๐งfile.f,file.for,file.ftnโ Fixed form Fortran source 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, using 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, using the traditional preprocessor ๐ธfile.goโ Go source code ๐นfile.brigโ BRIG files, which are the binary representation of HSAIL ๐คfile.dโ D source code ๐file.diโ D interface file ๐ซถfile.ddโ D documentation code, aka Ddoc ๐file.adsโ An Ada source file that holds a library unit declaration (a declaration of a package, subprogram, or generic, or a generic instantiation), or a library unit renaming declaration (a package, generic, or subprogram renaming declaration). These are also called specs ๐file.adbโ An Ada source file with a library unit body (a subprogram or package body). These are also called bodies ๐ฆfile.sโ Assembler code ๐งfile.S,file.sxโ Assembler code that must be preprocessed ๐otherโ An object file that gets fed straight into linking. Any file name with no recognized suffix gets treated this way ๐ซ
You can specify the input language yourself with the -x option ๐
-x languageโ Tell the compiler the language for the input files that come after it, instead of letting it guess from the file name suffix. This applies to every following input file until the next-xoption shows up. The possible values forlanguageare:
c c-header cpp-output
c++ c++-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 the files after it get handled by their file name suffixes, just like they would if-xhad never been used at all ๐งน
If you only want some stages of compilation, use -x (or filename suffixes) to tell gcc where to start, and one of the options -c, -S, or -E to say where it should stop ๐ฏ > Heads up: some combinations, like -x cpp-output -E, instruct gcc to do absolutely nothing at all ๐
-cโ Compile or assemble the source files, but don't link ๐ The linking stage just doesn't happen. The final output is an object file for each source file.
By default, the object file name for a source file is made by swapping the suffix .c, .i, .s, etc. for .o.
Unrecognized input files that don't need compiling or assembling get ignored.
-Sโ Stop after the actual compilation stage and skip assembling โจ The output is an assembler code file for each non-assembler input file you give it.
By default, the assembler file name for a source file is made by swapping the suffix .c, .i, etc. for .s.
Input files that don't need compiling get ignored.
-Eโ Stop after preprocessing and don't run the compiler proper ๐ธ The output is preprocessed source code, which gets sent to the standard output.
Input files that don't need preprocessing get ignored.
-o fileโ Put the output in a file calledfile๐ฆ This works for whatever you're making, whether it's an executable, an object file, an assembler file, or preprocessed C code.
If you don't use -o, the defaults are: an executable goes in a.out, the object file for source.suffix goes in source.o, its assembler file goes in source.s, a precompiled header file goes in source.suffix.gch, and all the preprocessed C source goes to standard output.
-vโ Print the commands executed for each stage of compilation to standard error output ๐ต๏ธ It also prints the version number of the compiler driver program, the preprocessor, and the compiler proper.-###โ Like-v, except the commands don't actually run ๐ Arguments get quoted 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 a description of the command-line options gcc understands, straight to standard output ๐ If-vis also specified,--helpgets passed along to the various processes gcc invokes, so they can show you the command-line options they accept. If-Wextrawas specified (before the--helpoption), then command-line options with no documentation attached get displayed too ๐--target-helpโ Prints a description of the target-specific command-line options for each tool, to standard output ๐ฏ For some targets, extra target-specific info might get printed too.--help={class|[^]qualifier}[,...]โ Prints a description of the command-line options the compiler understands that fit into all the classes and qualifiers you specify, to standard output ๐ฐ These are the supported classes:optimizersโ Shows all the optimization options the compiler supports โกwarningsโ Shows all the options that control the warning messages the compiler produces โ ๏ธtargetโ Shows the target-specific options. Unlike--target-help, the target-specific options of the linker and assembler are not shown, because those tools don't support the extended--help=syntax yet ๐paramsโ Shows the values the--paramoption recognizes ๐งพlanguageโ Shows the options supported forlanguage, wherelanguageis the name of one of the languages this version of GCC supports ๐ฃ๏ธcommonโ Shows the options common to all languages ๐
These are the supported qualifiers:
undocumentedโ Shows only the options that are undocumented ๐joinedโ Shows options that take an argument appearing after an equal sign in the same continuous piece of text, like:--help=target๐separateโ Shows options that take an argument appearing as a separate word right after the original option, like:-o output-fileโ๏ธ
So if you want every undocumented target-specific switch the compiler supports, use:
--help=target,undocumented
You can flip a qualifier by putting a ^ in front of it. So if you want 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= should not consist solely of inverted qualifiers ๐ซ
You can combine several classes, but that usually narrows the output down so much there's nothing left to show ๐ญ One case where it does work is when one of the classes is target. For example, to display all the target-specific optimization options, use:
--help=target,optimizers
The --help= option can be repeated on the command line. Each use displays its requested class of options, skipping anything already shown ๐ If --help is also specified anywhere on the command line, it takes precedence over any --help= option ๐
If the -Q option 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 is sensitive to the effects of earlier command-line options, so you can find out which optimizations are enabled at -O2 by using:
-Q -O2 --help=optimizers
Or, if you want to figure out which binary optimizations are enabled by -O3, 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โ Displays the version number and copyrights of the GCC you invoked ๐โจ-pass-exit-codes: okay so normallygccexits with the code of1if any phase of the compiler returns a non-success return code ๐ญ. But if you add-pass-exit-codes, it instead returns the numerically highest error from any phase that reported an error ๐ . The C, C++, and Fortran front ends return4if they hit an internal compiler error ๐.-pipe: uses pipes instead of temporary files to pass stuff between the stages of compilation ๐ฆ. Ngl this one can be sketchy on some systems where the assembler can't read from a pipe, but the GNU assembler has no trouble ๐ซถ.-specs=file: processes file after the compiler reads in the standard specs file, so it can override the defaults thegccdriver uses when deciding which switches to pass tocc1,cc1plus,as,ld, etc. โจ You can give more than one-specs=fileon the command line, and they get processed in order, from left to right ๐.-wrapper: invokes all subcommands under a wrapper program ๐. The wrapper's name and its parameters go in as a comma separated list.
gcc -c t.c -wrapper gdb,--args
This invokes all subprograms of gcc under gdb --args, so the invocation of cc1 is gdb --args cc1 .... ๐ง
-ffile-prefix-map=old=new: when compiling files that live in directory old, any references to them in the result of the compilation get recorded as if the files lived in directory new instead ๐. Specifying this is the same as specifying all the individual-f*-prefix-mapoptions, and it can be used to make reproducible builds that are location independent ๐ซง. See also-fmacro-prefix-mapand-fdebug-prefix-map.-fplugin=name.so: loads the plugin code in name.so, a shared object that the compiler dlopen's ๐. The base name of the shared object file is used to identify the plugin for argument parsing (see-fplugin-arg-name-key=valuebelow). Each plugin should define the callback functions specified in the Plugins API.-fplugin-arg-name-key=value: defines an argument called key with a value of value for the plugin called name ๐งฉ.-fdump-ada-spec[-slim]: for C and C++ source and include files, generates the matching Ada specs ๐.-fada-spec-parent=unit: used together with-fdump-ada-spec[-slim]above, this generates Ada specs as child units of the parent unit ๐.-fdump-go-spec=file: for input files in any language, generates matching Go declarations in file ๐น. You get Go "const", "type", "var", and "func" declarations, which can be a useful way to start writing a Go interface to code written in some other language โจ.@file: reads command-line options from file ๐. The options it reads get inserted in place of the original@fileoption. If file doesn't exist or can't be read, then the option is treated literally and not removed ๐.
Options in file are separated by whitespace. A whitespace character can be included in an option by surrounding the entire option in either single or double quotes. Any character (including a backslash) can be included by prefixing the character you want to include with a backslash. The file may itself contain additional @file options, and any such options get processed recursively ๐.
๐ Compiling C++ Programs ๐
C++ source files conventionally use one of the suffixes .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx ๐ธ. C++ header files often use .hh, .hpp, .H, or (for shared template code) .tcc, and preprocessed C++ files use the suffix .ii ๐ฆ. GCC recognizes files with these names and compiles them as C++ programs, even if you call the compiler the same way you would for C programs (usually with the name gcc) ๐
.
However, using gcc doesn't add the C++ library ๐ค. That's where g++ comes in. It's a program that calls GCC and automatically specifies linking against the C++ library ๐. It treats .c, .h and .i files as C++ source files instead of C source files, unless -x is used. This program is also useful when precompiling a C header file with a .h extension for use in C++ compilations ๐ซถ. On many systems, g++ is also installed with the name c++.
When you compile C++ programs, you can specify many of the same command-line options you use for programs in any language ๐. You can also use command-line options meaningful for C and related languages, or options that are meaningful only for C++ programs โจ.
๐ธ Options Controlling C Dialect ๐ธ
The following options control the dialect of C (or languages derived from C, such as C++, Objective-C and Objective-C++) that the compiler accepts ๐ :
-ansi: in C mode, this is the same as-std=c90. In C++ mode, it's the same as-std=c++98๐ง.
This turns off certain features of GCC that aren't compatible with ISO C90 (when compiling C code), or with standard C++ (when compiling C++ code). That includes the asm and typeof keywords, and predefined macros such as unix and vax that identify the type of system you're on ๐. It also enables the undesirable and rarely used ISO trigraph feature ๐. For the C compiler, it disables recognition of C++ style // comments as well as the inline keyword ๐ฅ.
The alternate keywords __asm__, __extension__, __inline__ and __typeof__ keep working despite -ansi. You wouldn't want to use them in an ISO C program, of course, but they're useful in header files that might get included in compilations done with -ansi ๐ง . Alternate predefined macros such as __unix__ and __vax__ are also available, with or without -ansi ๐.
The -ansi option doesn't cause non-ISO programs to be rejected gratuitously. For that, -Wpedantic is required in addition to -ansi ๐.
The macro __STRICT_ANSI__ is predefined when the -ansi option is used ๐ฏ. Some header files may notice this macro and refrain from declaring certain functions or defining certain macros that the ISO standard doesn't call for. This avoids interfering with any programs that might use those names for other things ๐ซง.
Functions that are normally built in but don't have semantics defined by ISO C (such as alloca and ffs) are not built-in functions when -ansi is used ๐ซ.
-std=: determines the language standard ๐. This option is currently only supported when compiling C or C++.
The compiler can accept several base standards, such as c90 or c++98, and GNU dialects of those standards, such as gnu90 or gnu++98 ๐ญ. When a base standard is specified, the compiler accepts all programs following that standard, plus those using GNU extensions that don't contradict it. For example, -std=c90 turns off certain features of GCC that are incompatible with ISO C90, such as the asm and typeof keywords. It doesn't turn off other GNU extensions that have no meaning in ISO C90, such as omitting the middle term of a ?: expression ๐ฅฐ.
On the other hand, when a GNU dialect of a standard is specified, all features supported by the compiler are enabled, even when those features change the meaning of the base standard. As a result, some strict-conforming programs may be rejected ๐ฌ. The particular standard is used by -Wpedantic to identify which features are GNU extensions, given that version of the standard. For example, -std=gnu90 -Wpedantic warns about C++ style // comments, while -std=gnu99 -Wpedantic does not ๐ฅ.
A value for this option must be provided. The possible values are:
c90,c89,iso9899:1990: supports all ISO C90 programs (certain GNU extensions that conflict with ISO C90 are disabled). Same as-ansifor C code ๐.iso9899:199409: ISO C90 as modified 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). This standard is the same as C11 except for corrections of defects (all of which are also applied with-std=c11) and a new value of__STDC_VERSION__, so it's supported to the same extent as C11 โ .c2x: the next version of the ISO C standard, still under development. Support for this version is experimental and incomplete ๐งช.gnu90,gnu89: GNU dialect of ISO C90 (including some C99 features) ๐.gnu99,gnu9x: GNU dialect of ISO C99. The namegnu9xis deprecated ๐ฆ.gnu11,gnu1x: GNU dialect of ISO C11. The namegnu1xis deprecated ๐.gnu17,gnu18: GNU dialect of ISO C17. This is the default for C code ๐๐.gnu2x: the next version of the ISO C standard, still under development, plus GNU extensions. Support for this version is experimental and incomplete ๐งชโจ.c++98,c++03: the 1998 ISO C++ standard plus the 2003 technical corrigendum and some additional defect reports. Same as-ansifor C++ code ๐.gnu++98,gnu++03: GNU dialect of-std=c++98๐ซถ.c++11,c++0x: the 2011 ISO C++ standard plus amendments. The namec++0xis deprecated ๐ธ.gnu++11,gnu++0x: GNU dialect of-std=c++11. The namegnu++0xis deprecated ๐ .c++14,c++1y: the 2014 ISO C++ standard plus amendments. The namec++1yis deprecated ๐ฆ.gnu++14,gnu++1y: GNU dialect of-std=c++14. This is the default for C++ code. 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๐ The namegnu++1zis deprecated ๐c++2a: the next revision of the ISO C++ standard, tentatively planned for 2020 ๐ฎ Support is highly experimental and will almost certainly change in incompatible ways in future releases ๐gnu++2a: the GNU dialect of-std=c++2aโจ It's just as highly experimental, and it will almost certainly change in incompatible ways in future releases ๐ญ-fgnu89-inline: okay so this tells GCC to use the traditional GNU semantics forinlinefunctions when you're in C99 mode ๐ฆ It's roughly the same as slapping thegnu_inlinefunction attribute on every inline function, lowkey iconic ๐-fno-gnu89-inline: the opposite energy ๐ It tells GCC to use the C99 semantics forinlinewhen you're in C99 orgnu99mode, which is the default behaviour. This option is not supported in-std=c90or-std=gnu90mode ๐ You can check which semantics are active with the preprocessor macros__GNUC_GNU_INLINE__and__GNUC_STDC_INLINE__๐-fpermitted-flt-eval-methods=style: this one is a lot ๐ค ISO/IEC TS 18661-3 adds brand new permissible values forFLT_EVAL_METHOD, saying that operations and constants with a semantic type that's an interchange or extended format should be evaluated to that type's precision and range ๐ These new values are a superset of what C99/C11 allows, and C99/C11 doesn't specify what any other positive values mean, so C11 code might not have been written expecting them ๐-fpermitted-flt-eval-methodsdecides whether the compiler allows only the values from C99/C11, or the extended set from ISO/IEC TS 18661-3 ๐ฏstyleis eitherc11orts-18661-3, as appropriate- In a standards-compliant mode (
-std=c11or similar), the default is-fpermitted-flt-eval-methods=c11๐ - In a GNU dialect (
-std=gnu11or similar), the default is-fpermitted-flt-eval-methods=ts-18661-3โจ
-aux-info filename: this dumps prototyped declarations for all functions declared and/or defined in a translation unit, including the ones in header files, into the given filename ๐ It's silently ignored in any language other than C ๐คซ- Besides the declarations, the file uses comments to show:
- the origin of each declaration (source file and line)
- whether the declaration was implicit, prototyped or unprototyped, shown by
I,N(new) orO(old) in the first character after the line number and the colon - whether it came from a declaration or a definition, shown by
CorFrespectively in the character after that
- For function definitions, a K&R-style list of arguments followed by their declarations also shows up inside comments, right after the declaration ๐งถ
- Besides the declarations, the file uses comments to show:
-fallow-parameterless-variadic-functions: accepts variadic functions without any named parameters ๐ธ You can define one, but it's not super useful since you can't read the arguments ๐ This is only supported for C, because C++ already allows this construct ๐-fno-asm: stopsasm,inlineandtypeoffrom being keywords, so your code can use those words as identifiers ๐ง You can use__asm__,__inline__and__typeof__instead โจ-ansiimplies-fno-asm.- In C++, this only affects
typeof, sinceasmandinlineare standard keywords. You may want to use-fno-gnu-keywordsinstead, which has the same effect ๐ - In C99 mode (
-std=c99or-std=gnu99), it only affectsasmandtypeof, sinceinlineis a standard keyword in ISO C99 ๐ฆ
- In C++, this only affects
-fno-builtin,-fno-builtin-function: don't recognise the built-in functions that don't begin with the__builtin_prefix ๐ซ- GCC normally generates special code to handle certain built-in functions more efficiently. For instance, calls to
allocamay become single instructions that adjust the stack directly, and calls tomemcpymay become inline copy loops ๐งโ๐ง The result is often both smaller and faster ๐๏ธ - But since the function calls no longer appear as calls, you can't set a breakpoint on them, and you can't change what the functions do by linking with a different library ๐ฉ
- When a function is recognised as built-in, GCC may also use info about it to warn about problems with calls to it, or to generate more efficient code, even if the result still contains calls to that function ๐ For example, warnings are given with
-Wformatfor bad calls toprintfwhenprintfis built in andstrlenis known not to modify global memory ๐ฃ - With
-fno-builtin-function, only that one built-in function is disabled. function must not begin with__builtin_. If you name a function that isn't built-in in this version of GCC, the option is ignored ๐คท - There's no corresponding
-fbuiltin-functionoption. If you want to enable built-in functions selectively when using-fno-builtinor-ffreestanding, you can define macros such as:
- GCC normally generates special code to handle certain built-in functions more efficiently. For instance, calls to
#define abs(n) __builtin_abs ((n))
#define strcpy(d, s) __builtin_strcpy ((d), (s))
-fgimple: enables parsing of function definitions marked with__GIMPLE๐งช It's an experimental feature that allows unit testing of 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, andmainhas a return type ofint. Think nearly 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 be 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 specify it, the compiler generates accelerated code according to the OpenACC Application Programming Interface v2.0 (https://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 ๐geomis a triple of:-separated sizes, in the ordergang,workerandvector. 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 specify it, the compiler generates parallel code according to the OpenMP Application Program Interface v4.5 (https://www.openmp.org) ๐ This option implies-pthread, so it's only supported on targets that support-pthread.-fopenmpalso implies-fopenmp-simd.-fopenmp-simd: enables handling of OpenMP's SIMD directives with#pragma ompin C/C++ and!$ompin Fortran ๐ Other OpenMP directives are ignored ๐-fgnu-tm: when you specify this, the compiler generates code for the Linux variant of Intel's current Transactional Memory ABI specification document (Revision 1.1, May 6 2009) ๐ง It's an experimental feature whose interface may change in future GCC versions as the official specification changes โ ๏ธ Please note that not all architectures are supported for this feature ๐- For more information on GCC's support for transactional memory,
- > Heads up, bestie: 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 ๐
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, permits passing pointers to structures with anonymous fields to functions that expect pointers to elements of the type of the field, and permits referring to anonymous fields declared using a typedef ๐ช This is only supported for C, not C++ ๐-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๐ Each kind of machine has a default for whatcharshould be. It's either likeunsigned charby default or likesigned charby default ๐คท- Ideally, a portable program should always use
signed charorunsigned charwhen it depends on the signedness of an object. But many programs were written to use plaincharand expect it to be signed, or expect it to be unsigned, depending on the machines they were written for ๐ฅฒ This option, and its inverse, lets you make such a program work with the opposite default ๐ - The type
charis always a distinct type from each ofsigned charorunsigned char, even though its behaviour is always just like one of those two ๐งฉ
- Ideally, a portable program should always use
-fsigned-char: lets the typecharbe signed, likesigned char๐ This is equivalent to-fno-unsigned-char, which is the negative form of-funsigned-char. Likewise,-fno-signed-charis equivalent to-funsigned-charโจ
-fsigned-bitfields, -funsigned-bitfields, -fno-signed-bitfields, -fno-unsigned-bitfields** โ okay so these decide whether a <pink>bit-field</pink> is signed or unsigned, but only when the declaration doesn't already say signedorunsigned๐
By default it's **signed**, and honestly that's the consistent choice, because basic types likeint` are signed too ๐
-fsso-struct=endiannessโ this sets the default scalar storage order for structs and unions to whatever endianness you pick โจ Your options arebig-endian,little-endian, ornative(the native endianness of your target, which is the default) ๐ Heads up, this one isn't supported for C++ ๐
โ ๏ธ Bestie, be careful with -fsso-struct! If the endianness you pick isn't your target's native one, GCC generates code that is not binary compatible with code built without the flag ๐ญ
โจ Options Controlling C++ Dialect โจ
This section is all about the command-line options that only matter for C++ programs ๐ Good news though, you can use most GNU compiler options no matter what language your program is written in ๐ฆ For example, you could compile a file called firstClass.C like this:
g++ -g -fstrict-enums -O -c firstClass.C
In that example, only -fstrict-enums is meant just for C++ programs. The other options work with any language GCC supports ๐ซถ
Some options that are mainly for C programs, like -std, are also relevant to C++ programs ๐
Here's the list of options that are only for compiling C++ programs ๐
-fabi-version=nโ picks version n of the C++ ABI ๐ฅ The default is version0.- Version 0 is the one that matches the C++ ABI spec the most closely, so the ABI you get from version 0 will keep changing across G++ versions as ABI bugs get squashed ๐
- Version 1 first showed up in G++ 3.2 โจ
- Version 2 first showed up in G++ 3.4 and was the default all the way through G++ 4.9 ๐
- Version 3 fixes a mistake in mangling a constant address used as a template argument ๐
- Version 4 first showed up in G++ 4.5 and adds a standard mangling for vector types ๐ฆ
- Version 5 first showed up in G++ 4.6 and corrects the mangling of attribute const/volatile on function pointer types,
decltypeof a plain decl, and using a function parameter in the declaration of another parameter ๐ธ - Version 6 first showed up in G++ 4.7 and corrects the promotion behavior of C++11 scoped enums, plus the mangling of template argument packs, const/static_cast, prefix
++and--, and a class scope function used as a template argument ๐ - Version 7 first showed up in G++ 4.8 and treats
nullptr_tas a builtin type, and it also corrects the mangling of lambdas in default argument scope ๐ง - Version 8 first showed up in G++ 4.9 and corrects the substitution behavior of function types with function-cv-qualifiers โญ
- Version 9 first showed up in G++ 5.2 and corrects the alignment of
"nullptr_t"๐ - Version 10 first showed up in G++ 6.1 and adds mangling for attributes that affect type identity, like ia32 calling convention attributes (e.g. stdcall) ๐
- Version 11 first showed up in G++ 7 and corrects the mangling of
sizeof...expressions and operator names. For multiple entities with the same name within a function that are declared in different scopes, the mangling now changes starting with the twelfth occurrence. It also implies-fnew-inheriting-ctors๐ - Version 12 first showed up in G++ 8 and corrects the calling conventions for empty classes on the
x86_64target and for classes with only deleted copy/move constructors. It accidentally changes the calling convention for classes with a deleted copy constructor and a trivial move constructor ๐ญ - Version 13 first showed up in G++ 8.2 and fixes that accidental change from version 12 ๐ซถ
- See also
-Wabi. ๐
-fabi-compat-version=nโ okay this one is a whole vibe ๐ธ On targets that support strong aliases, G++ dodges mangling changes by making an alias with the correct mangled name whenever it defines a symbol with an incorrect one. This switch picks which ABI version that alias uses ๐ฆ
With -fabi-version=0 (the default), this defaults to 11 (GCC 7 compatibility). If you explicitly pick a different ABI version, it defaults to 0. If you want compatibility with GCC versions 3.2 through 4.9, use -fabi-compat-version=2 ๐
If you don't give this option but do give -Wabi=n, that version gets used for the compatibility aliases. If you give this option along with -Wabi (no version number), the version from this option is used for the warning โจ
-fno-access-controlโ turns off all access checking ๐ It's mainly useful for working around bugs in the access control code, so it's not really a everyday flex ๐-faligned-newโ enables support for C++17newof types that need more alignment thanvoid* ::operator new(std::size_t)gives you ๐ You can use a number like-faligned-new=32to say how much alignment (in bytes) that function provides, but honestly few people 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โ this turns on support forchar8_t, as adopted for C++2a ๐ง It adds a brand-newchar8_tfundamental type, changes the types of UTF-8 string and character literals, adds new signatures for user-defined literals, updates the standard library, and adds the new"__cpp_char8_t"and"__cpp_lib_char8_t"feature test macros โจ
With this on, functions can be overloaded for ordinary strings and UTF-8 strings, like this:
int f(const char *); // #1
int f(const char8_t *); // #2
int v1 = f("text"); // Calls #1
int v2 = f(u8"text"); // Calls #2
It also introduces new signatures for user-defined literals:
int operator""_udl1(char8_t);
int v3 = u8'x'_udl1;
int operator""_udl2(const char8_t*, std::size_t);
int v4 = u8"text"_udl2;
template<typename T, T...> int operator""_udl3();
int v5 = u8"text"_udl3;
โ ๏ธ Heads up, bestie: changing the types of UTF-8 string and character literals breaks compatibility with ISO C++11 and later standards ๐ญ For example, this code is fine under ISO C++11, but it's ill-formed once -fchar8_t is on:
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โ this makes GCC check that the pointer returned byoperator newis non-null before it touches the allocated storage ๐ซถ Usually you don't need it, because the C++ standard saysoperator newonly returns 0 if it's declaredthrow(), and in that case the compiler always checks the return value even without this option ๐ In every other case, whenoperator newhas a non-empty exception specification, running out of memory gets signalled by throwingstd::bad_alloc. See also new (nothrow). ๐-fconceptsโ enables support for the C++ Extensions for Concepts Technical Specification, ISO 19217 (2015), so you can write code like this ๐ฆ
template <class T> concept bool Addable = requires (T t) { t + t; };
template <Addable T> T add (T a, T b) { return a + b; }
-fconstexpr-depth=nโ sets the maximum nested evaluation depth for C++11constexprfunctions to n ๐ธ You need a limit so endless recursion can be caught during constant expression evaluation. The minimum the standard specifies is512โจ-fconstexpr-loop-limit=nโ sets the maximum number of iterations for a loop in C++14constexprfunctions to n ๐ฅ The limit is there to catch infinite loops during constant expression evaluation. The default is262144(1<<18) ๐-fconstexpr-ops-limit=nโ sets the maximum number of operations allowed during a singleconstexprevaluation ๐ง Even if a single loop's iterations are capped by the option above, you can still run into trouble. If you have several nested loops that each have lots of iterations (but are still under that limit), or if too many expressions need evaluating in a loop body or even outside a loop, theconstexprevaluation might take way too long ๐ญ The default is33554432(1<<25) ๐-fdeduce-init-listโ enables deducing a template type parameter asstd::initializer_listfrom a brace-enclosed initializer list ๐ Check out this example:
template <class T> auto forward(T t) -> decltype (realfn (t))
{
return realfn (t);
}
void f()
{
forward({1,2}); // call forward<std::initializer_list<int>>
}
This deduction was an extension someone floated during the C++11 standard drafting, but it never made it into the final standard, so it's disabled by default ๐ This option is deprecated and may be removed in a future version of G++ ๐
-fno-elide-constructorsโ the C++ standard lets an implementation skip creating a temporary that's only used to initialize another object of the same type ๐ This option turns that optimization off and forces G++ to call the copy constructor in all cases โจ It also makes G++ call trivial member functions that would otherwise be expanded inline ๐
In C++17 the compiler is required to omit these temporaries, but this option still affects trivial member functions ๐ซถ
-fno-enforce-eh-specsโ okay bestie, this one's a bit spicy ๐ถ๏ธ It tells the compiler to skip generating the run-time checks for exception specifications. It goes against the C++ standard, but it can shrink code size in production builds, kinda like definingNDEBUGโจ Also, this does NOT give your code permission to throw exceptions that break those specs. The compiler still optimizes based on the specs, so an unexpected throw leads to undefined behavior at run time ๐-fextern-tls-init,-fno-extern-tls-initโ so C++11 and OpenMP letthread_localandthreadprivatevariables do dynamic (runtime) initialization ๐งต To make that work, every use of one of these variables goes through a wrapper function that handles the setup. If the variable is used and defined in the same translation unit, the compiler can optimize that overhead away. But if the use is in a different translation unit, the overhead sticks around even when the variable doesn't actually need dynamic init ๐ค If you're sure no use in a non-defining TU needs to trigger dynamic initialization (maybe it's statically initialized, or the defining TU runs a use before any other TU does), you can skip the overhead with-fno-extern-tls-init๐ซถ
On targets that support symbol aliases, the default is -fextern-tls-init. On targets that do not support symbol aliases, the default is -fno-extern-tls-init.
-fno-gnu-keywordsโ this tells GCC to stop treatingtypeofas a keyword, so you can use it as a normal identifier ๐ If you still want the keyword version, use__typeof__instead. This is automatically on for the strict ISO C++ dialects:-ansi,-std=c++98,-std=c++11, etc.-fno-implicit-templatesโ never emit code for non-inline templates that get instantiated implicitly (aka just by using them) ๐ฆ Only explicit instantiations get code. If you go this route, you need to structure your code so every explicit instantiation you need is there, or you'll get undefined symbols at link time ๐-fno-implicit-inline-templatesโ same vibe, but for inline templates. No code gets emitted for their implicit instantiations either ๐ธ By default, inlines are handled differently so that compiles with and without optimization need the same set of explicit instantiations, which is a whole mood honestly โจ-fno-implement-inlinesโ to save space, this skips emitting out-of-line copies of inline functions controlled by#pragma implementation๐ Heads up: if those functions don't get inlined everywhere they're called, you'll get linker errors ๐ญ-fms-extensionsโ disables-Wpedanticwarnings about stuff used in MFC, like implicitintand getting a pointer to a member function via non-standard syntax ๐-fnew-inheriting-ctorsโ turns on the P0136 adjustment to C++11 constructor inheritance semantics ๐ง It's technically part of C++17, but it's also considered a Defect Report against C++11 and C++14. This flag is enabled by default unless-fabi-version=10or lower is specified.-fnew-ttp-matchingโ enables the P0522 resolution to Core issue 150, which is about template template parameters and default arguments ๐ It lets a template with default template arguments be used as an argument for a template template parameter that has fewer template parameters. This flag is enabled by default for-std=c++17.-fno-nonansi-builtinsโ disables built-in declarations for functions that aren't required by ANSI/ISO C ๐ That includesffs,alloca,_exit,index,bzero,conjf, and a bunch of other related functions.-fnothrow-optโ treats athrow()exception specification as if it were anoexceptspecification, which can reduce or wipe out the text size overhead compared to a function with no exception spec โญ If the function has local variables with non-trivial destructors, the exception spec can actually make the function smaller, because the EH cleanups for those variables can get optimized away. The catch (literally ๐): an exception thrown out of a function with this kind of spec leads to a call toterminateinstead ofunexpected.-fno-operator-namesโ stops treating the operator name keywordsand,bitand,bitor,compl,not,orandxoras synonyms for keywords ๐-fno-optional-diagsโ disables diagnostics that the standard says a compiler doesn't have to issue ๐ซ Right now, the only one G++ issues in that category is the one for a name that has multiple meanings within a class.-fpermissiveโ downgrades some diagnostics about nonconformant code from errors to warnings ๐ฅ So with-fpermissive, some nonconforming code is allowed to compile. Use it wisely, bestie.-fno-pretty-templatesโ when an error mentions a specialization of a function template, GCC normally prints the template signature followed by the template arguments and any typedefs or typenames in the signature. For example, you'd getvoid f(T) [with T = int]instead ofvoid f(int), so it's super clear which template is involved ๐ When an error mentions a specialization of a class template, GCC leaves out any template arguments that match the template's default arguments. If either of those behaviors makes errors harder to read instead of easier, you can use-fno-pretty-templatesto turn them off ๐-frepoโ enables automatic template instantiation at link time ๐ฆ This option also implies-fno-implicit-templates.-fno-rttiโ disables generating run-time type information for every class with virtual functions. That info is used by the C++ run-time type identification features (dynamic_castandtypeid) ๐ง If you don't use those features, you can save some space with this flag. Note that exception handling uses the same info, but G++ only generates it as needed. Thedynamic_castoperator still works for casts that don't need RTTI, i.e. casts tovoid *or to unambiguous base classes โจ
Mixing code compiled with-frttiand code compiled with-fno-rttimay not work. For example, programs may fail to link if a class compiled with-fno-rttiis used as a base for a class compiled with-frtti. ๐ฌ
-fsized-deallocationโ enables the built-in global declarations introduced in C++14 ๐ท
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
This is super useful for user-defined replacement deallocation functions that, for example, use the object's size to make deallocation faster ๐๏ธ It's enabled by default under -std=c++14 and above. The flag -Wsized-deallocation warns about places that might want to add a definition.
-fstrict-enumsโ lets the compiler optimize based on the assumption that a value of an enumerated type can only be one of the enumeration's values (per the C++ standard, basically a value that fits in the minimum number of bits needed to represent all the enumerators) ๐ฏ This assumption may not hold if the program casts an arbitrary integer to the enumerated type, so be careful with that ๐-fstrong-eval-orderโ evaluates member access, array subscripting, and shift expressions left-to-right, and assignment right-to-left, as adopted for C++17 ๐ It's enabled by default with-std=c++17.-fstrong-eval-order=someonly enables the ordering for member access and shift expressions, and it's the default without-std=c++17.-ftemplate-backtrace-limit=nโ sets the maximum number of template instantiation notes shown for a single warning or error ton๐ The default is10.-ftemplate-depth=nโ sets the maximum instantiation depth for template classes ton๐ A limit is needed to catch endless recursion during template class instantiation. ANSI/ISO C++ conforming programs must not rely on a maximum depth greater than17(which changed to1024in C++11). The default value is900, because the compiler can run out of stack space before hitting1024in some situations ๐ฅฒ-fno-threadsafe-staticsโ stops emitting the extra code that uses the routines from the C++ ABI for thread-safe initialization of local statics ๐งต You can use this to shave a bit off code size in code that doesn't need to be thread-safe.-fuse-cxa-atexitโ registers destructors for objects with static storage duration using the__cxa_atexitfunction instead ofatexit๐ฆข This is required for fully standards-compliant handling of static destructors, but it only works if your C library supports__cxa_atexit.-fno-use-cxa-get-exception-ptrโ don't use the__cxa_get_exception_ptrruntime routine ๐ซ This makesstd::uncaught_exceptionincorrect, but it's necessary if that runtime routine isn't available.-fvisibility-inlines-hiddenโ this switch tells GCC that you won't try to compare pointers to inline functions or methods when the two functions' addresses are taken in different shared objects ๐
The effect is that GCC may, effectively, mark inline methods with __attribute__ ((visibility ("hidden"))), so they don't show up in the export table of a DSO and don't need a PLT indirection when used inside that DSO ๐ Turning this on can have a dramatic effect on load and link times for a DSO, because it massively shrinks the dynamic export table when the library uses lots of templates ๐
The behavior isn't quite the same as marking methods hidden directly, because it doesn't affect static variables local to the function, and it doesn't make the compiler deduce that the function is defined in only one shared object.
You can explicitly give a method a visibility to cancel out the switch for that method. For example, if you do want to compare pointers to a particular inline method, you might mark it with 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โ okay bestie, this one is a whole vibe ๐ฆ It tries to use visibility settings to make GCC's C++ linkage model act like Microsoft Visual Studio's. โจ
Here's what it changes in GCC's linkage model ๐:
- It sets the default visibility to "hidden", same as
-fvisibility=hidden. - Types (but not their members) are not hidden by default.
- The One Definition Rule (ODR) is relaxed for types without explicit visibility specifications that are defined in more than one shared object. Those declarations are allowed if they'd be allowed without this option.
In new code, the move is to use -fvisibility=hidden and export only the classes you actually want visible externally ๐
Unfortunately, code might rely on the Visual Studio behavior, maybe even by accident ๐
Some of the fallout: static data members of the same type, with the same name, defined in different shared objects are different, so changing one won't change the other ๐ญ Also, pointers to function members defined in different shared objects may not compare equal. With this flag on, defining types with the same name differently is an ODR violation ๐
-fno-weakโ don't use weak symbol support, even if the linker provides it. By default, G++ uses weak symbols when they're available, but this option is strictly for testing ๐งช End users shouldn't touch it, since it gives inferior code and has no benefits. It might get removed in a future release of G++ ๐ฅ-nostdinc++โ skips the C++-specific standard directories when hunting for header files, but still searches the other standard directories ๐ (This is the option used when building the C++ library.)
Now for the extra goodies ๐ These optimization, warning, and code generation options only mean something for C++ programs:
-Wabi(C, Objective-C, C++ and Objective-C++ only) โ warns when G++ generates code that's probably not compatible with the vendor-neutral C++ ABI ๐ G++ now updates the ABI with every major release by default, so-Wabinormally only warns about an ABI issue that got a check added later in a release series, after the initial release was out. It'll warn about way more stuff if you pick an older ABI version with-fabi-version=n.
You can also give -Wabi an explicit version number to warn about compatibility with a specific -fabi-version level, like -Wabi=2 to warn about changes relative to -fabi-version=2.
If you pass an explicit version number and don't specify -fabi-compat-version, the version number from this option gets used for compatibility aliases. If you don't pass a version number here but do specify -fabi-compat-version, that version number gets used for ABI warnings instead.
Real talk: an effort was made to warn about all these cases, but there are probably some incompatible cases that slip through anyway. There can also be false alarms where the warning fires even though the generated code is actually compatible โจ
If you care about G++ output not being binary compatible with code from other compilers, you should rewrite your code to dodge these warnings ๐ซถ
Known incompatibilities in -fabi-version=2 (which was the default from GCC 3.4 to 4.9) include:
- A template with a non-type template parameter of reference type was mangled incorrectly:
extern int N;
template <int &> struct S {};
void n (S<N>) {2}
This 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 overloading functions that take vectors of different sizes ๐ค
The mangling was changed in -fabi-version=4.
__attribute ((const))andnoreturnwere mangled as type qualifiers, anddecltypeof a plain declaration got folded away ๐
These mangling issues were fixed in -fabi-version=5.
- Scoped enumerators passed as arguments to a variadic function get promoted like unscoped enumerators, which makes
va_argcomplain. On most targets this doesn't actually change the parameter passing ABI, since there's no way to pass an argument smaller thanint.
The ABI also changed the mangling of template argument packs, const_cast, static_cast, prefix increment/decrement, and a class scope function used as a template argument.
These issues were corrected in -fabi-version=6.
- Lambdas in default argument scope were mangled incorrectly, and the ABI changed the mangling of
nullptr_t.
These issues were corrected in -fabi-version=7.
- When mangling a function type with function-cv-qualifiers, the un-qualified function type was incorrectly treated as a substitution candidate.
This was fixed in -fabi-version=8, the default for GCC 5.1.
decltype(nullptr)incorrectly had an alignment of 1, which led to unaligned accesses. This didn't affect the ABI of a function with anullptr_tparameter though, 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.
It also warns 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. For example:
union U {
long double ld;
int i;
};
union U is always passed in memory.
-Wabi-tag(C++ and Objective-C++ only) โ warns when a type with an ABI tag gets used in a context that doesn't have that ABI tag ๐ท๏ธ See C++ Attributes for more info about ABI tags.-Wctor-dtor-privacy(C++ and Objective-C++ only) โ warns when a class seems unusable because all of its constructors or destructors are private, and it has no friends or public static member functions ๐ It also warns if there are no non-private methods and there's at least one private member function that isn't a constructor or destructor.-Wdelete-non-virtual-dtor(C++ and Objective-C++ only) โ warns whendeleteis used to destroy an instance of a class that has virtual functions and a non-virtual destructor ๐ Deleting a derived class through a base class pointer is unsafe if the base class doesn't have a virtual destructor. This warning is enabled by-Wall.-Wdeprecated-copy(C++ and Objective-C++ only) โ warns that the implicit declaration of a copy constructor or copy assignment operator is deprecated 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 operations if the class has a user-provided destructor.-Wno-init-list-lifetime(C++ and Objective-C++ only) โ stops warnings about uses ofstd::initializer_listthat are likely to end up with dangling pointers ๐ซ The underlying array for aninitializer_listis handled like a normal C++ temporary object, so it's super easy to accidentally keep a pointer to the array after its lifetime has ended. For example:- If a function returns a temporary
initializer_list, or a localinitializer_listvariable, the array's lifetime ends at the end of the return statement, so the returned value has a dangling pointer. - If a new-expression creates an
initializer_list, the array only lives until the end of the enclosing full-expression, so theinitializer_liston the heap has a dangling pointer. - When an
initializer_listvariable is assigned from a brace-enclosed initializer list, the temporary array made for the right side of the assignment only lives until the end of the full-expression. So by the next statement, theinitializer_listvariable has a dangling pointer.
- 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
- When a list constructor stores the
beginpointer from theinitializer_listargument, it 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.
-Wliteral-suffix(C++ and Objective-C++ only) โ warns when a string or character literal is followed by a ud-suffix that doesn't begin with an underscore ๐ง As a conforming extension, GCC treats these suffixes as separate preprocessing tokens so that 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 warns when a user-defined literal operator is declared with a literal suffix identifier that doesn't begin with an underscore. Literal suffix identifiers without a leading underscore are reserved for future standardization ๐
This warning is enabled by default.
-Wlto-type-mismatchโ during link-time optimization, warns about type mismatches in global declarations from different compilation units ๐ฅ It requires-fltoto be enabled. Enabled by default.-Wno-narrowing(C++ and Objective-C++ only) โ okay so for C++11 and later, GCC flags narrowing conversions by default because the standard requires it ๐๐ . A narrowing conversion from a constant is an error, and one from a non-constant is a warning.-Wno-narrowingshuts that whole diagnostic up ๐คซ. It doesn't change what well-formed code means โจ, but narrowing is still ill-formed in SFINAE contexts ๐. With-Wnarrowingin C++98, GCC warns when a narrowing conversion that C++11 prohibits happens inside{ }, like this:
int i = { 2.2 }; // error: narrowing from double to int
This flag is included in -Wall and -Wc++11-compat ๐.
-Wnoexcept(C++ and Objective-C++ only) โ warns when a noexcept-expression evaluates tofalsebecause it calls a function without a non-throwing exception spec (throw()ornoexcept), even though the compiler knows that function never throws ๐ฆ.-Wnoexcept-type(C++ and Objective-C++ only) โ warns if the C++17 feature that makesnoexceptpart of a function type changes the mangled name of a symbol compared to C++14 ๐ธ. It's enabled by-Wabiand-Wc++17-compat. Here's the 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) โ warns when the destination of a raw memory function likememsetormemcpyis an object of class type, and writing into it might bypass a non-trivial or deleted constructor or copy assignment, break const-correctness or encapsulation, or corrupt virtual table pointers ๐ญ. Messing with the raw representation of these objects can break invariants the member functions rely on. This example is undefined behaviour because it modifies a non-trivial class object, so it gets flagged:
std::string str = "abc";
memset (&str, 0, sizeof str);
The safe move is to initialize or clear these objects using the appropriate constructor or assignment operator, if one exists โจ. -Wclass-memaccess is enabled by -Wall. Casting the pointer to the class object to void *, or to a type that can be safely accessed by the raw memory function, quiets the warning ๐ซถ.
-Wnon-virtual-dtor(C++ and Objective-C++ only) โ warns when a class has virtual functions but its own destructor, or the destructor of an accessible polymorphic base class, isn't virtual ๐. Deleting a derived instance through a pointer to the base or class is possible but unsafe in that case. This warning is turned 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 ๐ง. Usingregisteras a storage class specifier was deprecated in C++11 and removed in C++17. It's enabled by default with-std=c++17.-Wreorder(C++ and Objective-C++ only) โ warns when the order of member initializers in your code doesn't match the order they actually have to run in ๐ฅ. Here's the sneaky one:
struct A {
int i;
int j;
A(): j (0), i (1) { }
};
The compiler quietly rearranges the initializers for i and j to match the declaration order of the members, and it warns you about it ๐. This warning is enabled by -Wall.
-Wno-pessimizing-move(C++ and Objective-C++ only) โ this one warns when a call tostd::movestops copy elision from happening ๐. The classic 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 that isn't a function parameter and has the same type as the return type. Look at this:
struct T {
...
};
T fn()
{
T t;
...
return std::move (t);
}
In this example, the std::move call prevents copy elision ๐
. This warning is enabled by -Wall.
-Wno-redundant-move(C++ and Objective-C++ only) โ warns about redundant calls tostd::move, meaning a move would have happened even without thestd::movecall ๐ฆ. This happens because the compiler is forced to treat the object as an rvalue in certain situations, 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 ๐. G++ implements Core Issue 1579, so there's another example:
struct T { // convertible to U
...
};
struct U {
...
};
U fn()
{
T t;
...
return std::move (t);
}
Copy elision isn't applicable in this one because the type of the returned expression and the function's return type differ, but G++ still treats the return value as if it were an rvalue ๐. This warning is enabled by -Wextra.
-fext-numeric-literals(C++ and Objective-C++ only) โ accepts imaginary, fixed-point, or machine-defined literal number suffixes as GNU extensions โจ. When this option is turned off, those suffixes get treated as C++11 user-defined literal numeric suffixes. 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, ...) ๐ฉท.
The following -W... options are not affected by -Wall ๐ซ. Bestie, these need to be turned on by hand ๐ซถ.
-Weffc++(C++ and Objective-C++ only) โ 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 to warn about a missing virtual destructor in accessible non-polymorphic base classes as well. Heads up though: the standard library headers don't obey all of these guidelines, so if the warnings get noisy, use grep -v to filter them out ๐.
-Wstrict-null-sentinel(C++ and Objective-C++ only) โ warns about using an uncastedNULLas a sentinel ๐. When you're compiling only with GCC, this is a valid sentinel, sinceNULLis defined as__null. It's a null pointer constant rather than a null pointer, but it's guaranteed to be the same size as a pointer. Still, this usage isn't portable across different compilers ๐ฌ.-Wno-non-template-friend(C++ and Objective-C++ only) โ disables warnings when non-template friend functions are declared inside a template ๐ธ. In very old GCC versions that predate the ISO standard, declarations likefriend int foo(int), where the friend's name is an unqualified-id, could be read as a particular specialization of a template function. This 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 shows up in a C++ program ๐ โโ๏ธ. The new-style casts (dynamic_cast,static_cast,reinterpret_cast, andconst_cast) are less vulnerable to unintended effects and 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 gets hidden in B, so code like this fails to compile:
B* b;
b->f();
-Wno-pmf-conversions(C++ and Objective-C++ only) โ disables the diagnostic for converting a bound pointer to a member function into a plain pointer ๐ฆ.-Wsign-promo(C++ and Objective-C++ only) โ warns when overload resolution picks a promotion from an unsigned or enumerated type to a signed type, instead of a conversion to an unsigned type of the same size ๐. Older versions of G++ tried to preserve unsignedness, but the standard mandates the current behaviour, so this is the new normal ๐.-Wtemplates(C++ and Objective-C++ only) โ warns when a primary template declaration is encountered ๐ง. Some coding rules disallow templates, and this flag can help enforce that rule. The warning is inactive inside a system header file like the STL, so you can still use the STL ๐. You're also still allowed to instantiate or specialize templates.-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 is inactive inside system headers like the STL, and you're still allowed to define classes that indirectly use multiple inheritance โจ.-Wvirtual-inheritanceโ warns when a class is defined with a virtual direct base class ๐ . Some coding rules disallow multiple inheritance, and this can help enforce that rule. The warning is inactive inside a system header file like the STL, so the STL is still fair game ๐. You can also define classes that indirectly use virtual inheritance.
Okay bestie, this one's a warning flag ๐จ - -Wnamespaces lets you know whenever a namespace definition gets opened. Some coding rules straight up ban namespaces, so this is how you enforce that rule ๐
It stays quiet inside system header files like the STL, so you can still use the STL ๐ซถ Using directives and qualified names are still allowed too, just saying ๐โโ๏ธ
-Wno-terminate(C++ and Objective-C++ only) โ turns off the warning for a throw-expression that's going to immediately result in a call to "terminate" ๐-Wno-class-conversion(C++ and Objective-C++ only) โ turns off the warning for when a conversion function converts an object to the same type, to a base class of that type, or to void. Those conversion functions will never be called ๐
โจ Options Controlling Objective-C and Objective-C++ Dialects โจ
(NOTE: this manual doesn't teach you the Objective-C and Objective-C++ languages themselves, so don't come here expecting a language tutorial ๐๐
This section covers the command-line options that only matter for Objective-C and Objective-C++ programs ๐ You can still use most of the language-independent GNU compiler options too. For example, you might compile a file some_class.m like this:
gcc -g -fgnu-runtime -O -c some_class.m
In that example, -fgnu-runtime is an option meant only for Objective-C and Objective-C++ programs. You can use the other options with any language GCC supports ๐ง
Note that since Objective-C is an extension of the C language, Objective-C compilations can also use options specific to the C front-end (e.g., -Wtraditional). Similarly, Objective-C++ compilations 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โ picks the class that gets instantiated for each literal string written with the syntax"@".."". The default class name is"NXConstantString"if the GNU runtime is being used, and"NSConstantString"if the NeXT runtime is being used (see below). If-fconstant-cfstringsis also there, it overrides-fconstant-string-classand makes"@"..""literals get laid out as constant CoreFoundation strings โจ-fgnu-runtimeโ generates object code compatible with the standard GNU Objective-C runtime. This is the default for most types of systems ๐ธ-fnext-runtimeโ generates output compatible with the NeXT runtime. This is the default for NeXT-based systems, including Darwin and Mac OS X. The macro"__NEXT_RUNTIME__"is predefined if (and only if) this option is used ๐-fno-nil-receiversโ assumes that every Objective-C message dispatch ("[receiver message:arg]") in this translation unit makes sure the receiver is not"nil". That lets more efficient entry points in the runtime get used ๐ฆ This option is only available 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, and here's the breakdown ๐งพ- Version 0 is the traditional (32-bit) ABI, with no support for properties or other Objective-C 2.0 additions
- Version 1 is the traditional (32-bit) ABI, with 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, 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 of 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 invoke all of those methods across an object's inheritance hierarchy ๐ง The runtime calls - (id) .cxx_construct right after a new object instance is allocated, and it calls - (void) .cxx_destruct right before it deallocates an object instance.
โ ๏ธ Heads up: as of this writing, only the NeXT runtime on Mac OS X 10.4 and later has support for invoking the- (id) .cxx_constructand- (void) .cxx_destructmethods. Everyone else is out of luck for now ๐ญ
-fobjc-direct-dispatchโ allows fast jumps to the message dispatcher. On Darwin this is accomplished via the comm page โก-fobjc-exceptionsโ turns on syntactic support for structured exception handling in Objective-C, kinda like what C++ offers ๐ This option is required 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 a different garbage collection implementation that doesn't need any special compiler flags ๐๏ธ-fobjc-nilcheckโ for the NeXT runtime with version 2 of the ABI, checks for a nil receiver 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 for nil this way, no matter what this flag is set to. Right now this flag does nothing when the GNU runtime, or an older version of the NeXT runtime ABI, is used ๐ซ-fobjc-std=objc1โ conforms to the language syntax of Objective-C 1.0, the one recognized by GCC 4.0. This only affects the Objective-C additions to the C/C++ language, and 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 doesn't recognize gets rejected. It's super useful if you need to make sure your Objective-C code still compiles with older versions of GCC ๐ฐ๏ธ-freplace-objc-classesโ emits a special marker that tellsld(1)not to statically link the resulting object file, and letsdyld(1)load it in at run time instead. This is used with the Fix-and-Continue debugging mode, where the object file might get recompiled and dynamically reloaded during program execution, without restarting the program itself. Right now, Fix-and-Continue is only available with the NeXT runtime on Mac OS X 10.3 and later ๐ฅ-fzero-linkโ when compiling for the NeXT runtime, 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 boosts run-time performance ๐๏ธ Specifying-fzero-linkstops that and keeps the calls toobjc_getClass("..."). It's handy in Zero-Link debugging mode, since it lets you modify individual class implementations while the program is running. The GNU runtime currently 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 from within 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. Specifying-fno-local-ivarsturns this behavior off and avoids those variable shadowing issues ๐-fivar-visibility=[public|protected|private|package]โ sets the default instance variable visibility to the option you pick, so that instance variables declared outside the scope of any access modifier directive default to that visibility ๐-gen-declsโ dumps the interface declarations for all classes seen in the source file into a file namedsourcename.decl๐-Wassign-intercept(Objective-C and Objective-C++ only) โ warns whenever an Objective-C assignment is being intercepted by the garbage collector ๐จ-Wno-protocol(Objective-C and Objective-C++ only) โ if a class is declared to implement a protocol, a warning gets issued for every method in the protocol that the class doesn't implement. By default, you get a warning for every method not explicitly implemented in the class, even if the implementation is inherited from the superclass. If you use-Wno-protocol, inherited methods count as implemented, so there's no warning for them ๐-Wselector(Objective-C and Objective-C++ only) โ warns if multiple methods of different types for the same selector are found during compilation. This check runs on the list of methods in the final stage of compilation. There's also a check for each selector that shows up in a"@selector(...)"expression, if a corresponding method for that selector was found during compilation. Since these checks only scan the method table at the very end, these warnings won't be produced if the final stage of compilation isn't reached, like when an error gets found during compilation or when-fsyntax-onlyis being used ๐-Wstrict-selector-match(Objective-C and Objective-C++ only) โ warns if multiple methods with differing argument and/or return types are found for a given selector when you try to send a message with that selector to a receiver of type"id"or"Class". When this flag is off (which is the default), the compiler skips these warnings if the differences are confined to types that share the same size and alignment ๐-Wundeclared-selector(Objective-C and Objective-C++ only) โ okay bestie, this one is a selector cop ๐ฎโโ๏ธ๐ It warns you if a@selector(...)expression points at a selector that hasn't been declared yet. A selector counts as undeclared if no method with that name was declared before the@selector(...)expression, whether that's explicitly in an@interfaceor@protocoldeclaration, or implicitly in an@implementationsection. This option checks the second it spots a@selector(...), whereas-Wselectorwaits until the final stage of compilation. It also enforces the coding style rule that methods and selectors must be declared before they get used. Main character energy ๐-print-objc-runtime-infoโ generates a C header describing the largest structure that gets passed by value, if there is one ๐งโจ
โจ Options to Control Diagnostic Messages Formatting โจ
Okay so, traditionally, diagnostic messages were formatted without caring about the output device's aspect (e.g. its width, ...) ๐ But you can use these options to control the formatting algorithm, like how many characters go on each line and how often source location info gets reported. Lowkey a game changer ๐ฆ Just note that some language front ends may not honor these options.
-fmessage-length=nโ tries to format error messages so they fit on lines of aboutncharacters ๐ Ifnis zero, no line-wrapping 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#errorand#warningpre-processor directives, and the deprecated function/type/variable attribute. It does not however affect thepragma GCC warningandpragma GCC errorpragmas.
-fdiagnostics-show-location=onceโ only meaningful in line-wrapping mode ๐ธ It tells the diagnostic reporter to emit source location info once. So if a message is too long and has to be wrapped, the location won't get slapped on as a prefix again and again on every continuation line. This is the default behavior, and honestly iconic.-fdiagnostics-show-location=every-lineโ also only meaningful in line-wrapping mode ๐ This one emits the same source location (as a prefix) for every physical line that comes out of breaking up a message that's too long to fit on one line.-fdiagnostics-color[=WHEN],-fno-diagnostics-colorโ uses color in diagnostics ๐WHENcan benever,always, orauto. The default depends on how the compiler was configured. It can be any of thoseWHENoptions, or alsoneverif theGCC_COLORSenvironment variable isn't present in the environment, andautootherwise.automeans color only shows up when standard error is a terminal. The forms-fdiagnostics-colorand-fno-diagnostics-colorare aliases for-fdiagnostics-color=alwaysand-fdiagnostics-color=never, respectively.
The colors are controlled by the GCC_COLORS environment variable ๐จ Its value is a colon-separated list of capabilities and Select Graphic Rendition (SGR) substrings. SGR commands get interpreted by the terminal or terminal emulator, so check the section in your text terminal's docs for permitted values and what they mean as character attributes. These substring values are integers in decimal form and can be concatenated with semicolons. The common ones are: 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: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 disables colors ๐
โโ๏ธ These are the supported capabilities:
error=โ SGR substring forerror:markers.warning=โ SGR substring forwarning:markers.note=โ SGR substring fornote:markers.range1=โ SGR substring for the first additional range.range2=โ SGR substring for the second additional range.locus=โ SGR substring for location info, likefile:lineorfile:line:columnetc.quote=โ SGR substring for info printed within quotes.fixit-insert=โ SGR substring for fix-it hints suggesting text to be inserted or replaced.fixit-delete=โ SGR substring for fix-it hints suggesting text to be deleted.diff-filename=โ SGR substring for filename headers within generated patches.diff-hunk=โ SGR substring for the starts of hunks within generated patches.diff-delete=โ SGR substring for deleted lines within generated patches.diff-insert=โ SGR substring for inserted lines within generated patches.type-diff=โ SGR substring for highlighting mismatching types within template arguments in the C++ frontend.
-fno-diagnostics-show-optionโ by default, every diagnostic includes text pointing at the command-line option that directly controls it (if the diagnostic machinery knows about one) ๐ Add-fno-diagnostics-show-optionand that text gets suppressed.-fno-diagnostics-show-caretโ by default, each diagnostic shows the original source line plus a caret^pointing at the column ๐ฏ This option hides all of that. If-fmessage-length=nis given, the source line gets truncated toncharacters. When the output goes to the terminal, the width is capped at the value of theCOLUMNSenvironment variable or, if that's not set, the terminal width.-fno-diagnostics-show-labelsโ when printing source code (via-fdiagnostics-show-caret), diagnostics can label ranges of source code with useful info, like the types of expressions ๐ท๏ธ Something like this:
printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~
| |
char * long int
This option suppresses those labels, so the vertical bars and the "char *" and "long int" text in the example above disappear ๐ซถ
-fno-diagnostics-show-line-numbersโ by default, when printing source code (via-fdiagnostics-show-caret), a left margin with line numbers gets printed ๐ข This option kills that left margin.-fdiagnostics-minimum-margin-width=widthโ controls the minimum width of the left margin printed by-fdiagnostics-show-line-numbers. It defaults to6.-fdiagnostics-parseable-fixitsโ emits fix-it hints in a machine-parseable format, perfect for IDEs to read ๐ค For each fix-it, a line gets printed after the relevant diagnostic, starting with the stringfix-it:. For example:
fix-it:"test.c":{45:3-45:21}:"gtk_widget_show_all"
The location is a half-open range, counted in bytes, starting at byte 1 for the initial column. In the example above, bytes 3 through 20 of line 45 of "test.c" get replaced with the given string:
00000000011111111112222222222
12345678901234567890123456789
gtk_widget_showall (dlg);
^^^^^^^^^^^^^^^^^^
gtk_widget_show_all
The filename and replacement string escape backslash as "\\", tab as "\t", newline as "\n", double quotes as "\"", and non-printable characters as octal (e.g. vertical tab as "\013") ๐งฉ An empty replacement string means the given range gets removed. An empty range (e.g. "45:3-45:3") means the string gets inserted at the given position.
-fdiagnostics-generate-patchโ prints fix-it hints to stderr in unified diff format, after any diagnostics are printed ๐ For example:
--- test.c
+++ test.c
@ -42,5 +42,5 @
void show_cb(GtkDialog *dlg)
{
- gtk_widget_showall(dlg);
+ gtk_widget_show_all(dlg);
}
The diff may or may not be colorized, following the same rules as for diagnostics (see -fdiagnostics-color).
-fdiagnostics-show-template-treeโ in the C++ frontend, when printing diagnostics about mismatching template types, you'd normally see something like this ๐ตโ๐ซ
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
This flag turns on a tree-like structure showing the common and differing parts of the types, like:
map<
[...],
vector<
[double != float]>>
The parts that differ get 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 short โ๏ธ For example:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
Specifying -fno-elide-type suppresses that behavior. This flag also affects the output of the -fdiagnostics-show-template-tree flag.
-fno-show-columnโ does not print column numbers in diagnostics ๐ โโ๏ธ This might be necessary if diagnostics are being scanned by a program that doesn't understand column numbers, such as dejagnu.-fdiagnostics-format=FORMATโ selects a different format for printing diagnostics ๐FORMATistextorjson. The default istext.
okay bestie, the json format is one big top-level JSON array ๐ง, and every item inside it is a JSON object describing one diagnostic ๐. GCC prints it all on a single unformatted line ๐ซถ, so the examples below are prettied up so your eyes can actually read them โจ
Diagnostics can have little child diagnostics too ๐ธ For example, this error and note:
misleading-indentation.c:15:3: warning: this 'if' clause does not
guard... [-Wmisleading-indentation]
15 | if (flag)
| ^~
misleading-indentation.c:17:5: note: ...this statement, but the latter
is misleadingly indented as if it were guarded by the 'if'
17 | y = 2;
| ^
might be printed in JSON form (after formatting) like this:
[
{
"kind": "warning",
"locations": [
{
"caret": {
"column": 3,
"file": "misleading-indentation.c",
"line": 15
},
"finish": {
"column": 4,
"file": "misleading-indentation.c",
"line": 15
}
}
],
"message": "this \u2018if\u2019 clause does not guard...",
"option": "-Wmisleading-indentation",
"children": [
{
"kind": "note",
"locations": [
{
"caret": {
"column": 5,
"file": "misleading-indentation.c",
"line": 17
}
}
],
"message": "...this statement, but the latter is ..."
}
]
},
...
]
where the "note" is a child of the "warning" ๐
A diagnostic has a "kind" ๐ If it's "warning", then there's an "option" key that tells you which command-line option is controlling that warning ๐ฅ
A diagnostic can have zero or more locations ๐ Each location has up to three positions: a "caret" position and optional "start" and "finish" positions. A location can also have an optional "label" string ๐ฆ For example, this error:
bad-binary-ops.c:64:23: error: invalid operands to binary + (have 'S' {aka
'struct s'} and 'T' {aka 'struct t'})
64 | return callee_4a () + callee_4b ();
| ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
| | |
| | T {aka struct t}
| S {aka struct s}
has three locations ๐ Its primary location is at the + token at column 23. It also has two secondary locations, describing the left and right-hand sides of the expression, and those have labels. It might be printed in JSON form as:
{
"children": [],
"kind": "error",
"locations": [
{
"caret": {
"column": 23, "file": "bad-binary-ops.c", "line": 64
}
},
{
"caret": {
"column": 10, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 21, "file": "bad-binary-ops.c", "line": 64
},
"label": "S {aka struct s}"
},
{
"caret": {
"column": 25, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 36, "file": "bad-binary-ops.c", "line": 64
},
"label": "T {aka struct t}"
}
],
"message": "invalid operands to binary + ..."
}
If a diagnostic has fix-it hints, it gets a "fixits" array ๐ That array is made of half-open intervals, kinda like what you get from -fdiagnostics-parseable-fixits. For example, this diagnostic with a replacement fix-it hint:
demo.c:8:15: error: 'struct s' has no member named 'colour'; did you
mean 'color'?
8 | return ptr->colour;
| ^~~~~~
| color
might be printed in JSON form as:
{
"children": [],
"fixits": [
{
"next": {
"column": 21,
"file": "demo.c",
"line": 8
},
"start": {
"column": 15,
"file": "demo.c",
"line": 8
},
"string": "color"
}
],
"kind": "error",
"locations": [
{
"caret": {
"column": 15,
"file": "demo.c",
"line": 8
},
"finish": {
"column": 20,
"file": "demo.c",
"line": 8
}
}
],
"message": "\u2018struct s\u2019 has no member named ..."
}
where the fix-it hint suggests replacing the text from "start" up to but not including "next" with the value of "string". Deletions are written with an empty value for "string", and insertions are written by having "start" equal "next" ๐
โจ Options to Request or Suppress Warnings โจ
Warnings are diagnostic messages ๐ They flag constructions that aren't inherently erroneous, but that are risky or might mean there was an error somewhere ๐
The following language-independent options don't turn on any specific warnings. Instead, they control the kinds of diagnostics GCC produces ๐
-fsyntax-onlyโ Checks your code for syntax errors and then stops right there, no extra stuff ๐-fmax-errors=nโ Caps the number of error messages atn, and when that limit is hit GCC bails out instead of trying to keep going ๐ Ifnis0(the default), there's no limit on how many error messages get printed. If-Wfatal-errorsis also specified, then-Wfatal-errorstakes precedence over this option ๐-wโ Inhibits all warning messages ๐คซ-Werrorโ Turns all warnings into errors ๐ญ-Werror=โ Turns one specific warning into an error. You append the warning's specifier, so for example-Werror=switchturns the warnings controlled by-Wswitchinto errors ๐ฅ This one also has a negative form that undoes-Werrorfor specific warnings. For example,-Wno-error=switchmakes-Wswitchwarnings not be errors, even when-Werroris in effect ๐ โโ๏ธ
The warning message for each controllable warning includes the option that controls it ๐ฆ You can then use that option with -Werror= and -Wno-error=, as described above. (Printing of the option in the warning message can be turned off with the -fno-diagnostics-show-option flag ๐)
Note that specifying -Werror=foo automatically implies -Wfoo. However, -Wno-error=foo does not imply anything ๐ง
-Wfatal-errorsโ Makes the compiler abort compilation on the first error it runs into, instead of trying to keep going and printing more error messages ๐
You can request lots of specific warnings with options that begin with -W. For example, -Wimplicit requests warnings on implicit declarations ๐ Each of these specific warning options also has a negative form beginning with -Wno- that turns the warnings off. For example, -Wno-implicit. This manual only lists one of the two forms, whichever one isn't the default ๐ For more language-specific options, also check out C++ Dialect Options and Objective-C and Objective-C++ Dialect Options ๐ธ
Some options, such as -Wall and -Wextra, turn on other options, like -Wunused, and those might turn on even more, like -Wunused-value โจ The combined effect of positive and negative forms is that more specific options win over less specific ones, no matter where they sit on the command-line ๐ฆ For options of the same specificity, the last one takes effect. Options enabled or disabled via pragmas act as if they appeared at the end of the command-line ๐ฅ
When you request an unrecognized warning option (e.g., -Wunknown-warning), GCC emits a diagnostic saying the option isn't recognized ๐ The -Wno- form is a little different though: no diagnostic is produced for -Wno-unknown-warning unless other diagnostics are being produced anyway ๐ซถ 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 won't 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 also 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 ๐
Okay so, bestie, -Wpedantic is about to get real ๐
Valid ISO C and ISO C++ programs should compile fine with or without this option ๐ซถ. A rare few do need -ansi or a -std option naming the exact ISO C version they want. Without this option, certain GNU extensions and traditional C and C++ features still work โจ. With this option, they get rejected ๐ซ.
-Wpedantic won't warn about the alternate keywords whose names begin and end with __ ๐. Pedantic warnings are also turned off in the expression that follows __extension__. Real talk though: only system header files should use these escape routes, so application programs should avoid them ๐
โโ๏ธ.
Some users try to use -Wpedantic to check programs for strict ISO C conformance ๐ง, and then they find it doesn't quite do what they want. It finds some non-ISO practices, but not all. It only catches the ones where ISO C requires a diagnostic, plus a few others that got diagnostics added later ๐.
A feature that reports any failure to conform to ISO C would be useful sometimes, but it would take a ton of extra work and would be totally different from -Wpedantic ๐ญ. We don't have plans to support that in the near future, sorry bestie.
When the standard picked with -std is a GNU extended dialect of C, like gnu90 or gnu99, there's a matching base standard. That's the version of ISO C the GNU dialect is built on ๐. -Wpedantic warnings show up wherever that base standard requires them. (It wouldn't make sense to warn only about features outside the chosen GNU dialect, because by definition the GNU dialects include every feature the compiler supports with that option, so there'd be nothing to warn about ๐คทโโ๏ธ.)
-pedantic-errorsโ Okay, this one is the strict version ๐ค. It gives an error whenever the base standard (see-Wpedantic) requires a diagnostic. That includes some cases with undefined behavior at compile-time, and some other cases that don't stop compilation of programs that are valid according to the standard. It is not the same as-Werror=pedantic, because there are errors this option turns on that the latter doesn't, and vice versa ๐ฅ.-Wallโ This turns on all the warnings about constructions that some users consider questionable, and that are easy to avoid (or to modify so the warning goes away), even when macros are involved ๐. It also turns on some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.
-Wall turns on these bad boys: -Waddress -Warray-bounds=1 (only with -O2) -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 -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 -Wreorder -Wrestrict -Wreturn-type -Wsequence-point -Wsign-compare (only in C++) -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 -Wvolatile-register-var
Note that some warning flags are not implied by -Wall ๐. Some of them warn about constructions that users generally don't consider questionable, but that you might occasionally want to check for. Others warn about constructions that are necessary or hard to avoid in some cases, with no simple way to change the code to suppress the warning. Some of them are enabled by -Wextra, but many of them must be enabled individually.
-Wextraโ This turns on some extra warning flags that-Walldoesn't ๐ธ. (This option used to be called-W. The older name is still supported, but the newer name is more descriptive ๐.)
-Wextra turns on these: -Wclobbered -Wcast-function-type -Wdeprecated-copy (C++ only) -Wempty-body -Wignored-qualifiers -Wimplicit-fallthrough=3 -Wmissing-field-initializers -Wmissing-parameter-type (C only) -Wold-style-declaration (C only) -Woverride-init -Wsign-compare (C only) -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)
The option -Wextra also prints warning messages for these cases:
- A pointer is compared against integer zero with
<,<=,>, or>=. - (C++ only) An enumerator and a non-enumerator both appear in a conditional expression.
- (C++ only) Ambiguous virtual bases.
- (C++ only) Subscripting an array that has been declared
register. - (C++ only) Taking the address of a variable that has been declared
register. - (C++ only) A base class is not initialized in the copy constructor of a derived class.
-Wchar-subscriptsโ Warns if an array subscript has typechar๐. This is a super common mistake, because programmers often forget this type is signed on some machines. This warning is enabled by-Wall.-Wno-coverage-mismatchโ Warns if feedback profiles don't match when you use-fprofile-use๐. If a source file changes between compiling with-fprofile-generateand 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 treated as an error.-Wno-coverage-mismatchcan disable the warning, and-Wno-error=coverage-mismatchcan disable the error. Disabling the error for this warning can result in poorly optimized code, so it's only useful for very minor changes like bug fixes to an existing code-base. Completely disabling the warning is not recommended ๐ซ.-Wno-cppโ (C, Objective-C, C++, Objective-C++ and Fortran only) Suppresses warning messages emitted by#warningdirectives ๐คซ.-Wdouble-promotionโ (C, C++, Objective-C and Objective-C++ only) Gives a warning when a value of typefloatis implicitly promoted todouble๐ข. CPUs with a 32-bit single-precision floating-point unit implementfloatin hardware, but they emulatedoublein software. On a machine like that, doing computations withdoublevalues is way more expensive because of the overhead of 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;
}
Yep, the compiler does the entire computation with double, because the floating-point literal is a double ๐.
-Wduplicate-decl-specifierโ (C and Objective-C only) Warns if a declaration has a duplicateconst,volatile,restrictor_Atomicspecifier โจ. This warning is enabled by-Wall.-Wformat,-Wformat=nโ Checks calls toprintfandscanf, etc., to make sure the arguments supplied have types that match the format string, and that the conversions in the format string actually make sense ๐. This covers standard functions and others specified by format attributes, in theprintf,scanf,strftimeandstrfmon(an X/Open extension, not in the C standard) families (or other target-specific families). Which functions get checked without format attributes depends on the standard version selected, and those checks are disabled by-ffreestandingor-fno-builtin.
The formats are checked against the format features supported by GNU libc version 2.2 ๐ง. That includes all ISO C90 and C99 features, plus features from the Single Unix Specification and some BSD and GNU extensions. Other library implementations might not support all of these, and GCC doesn't warn about features that go beyond a particular library's limitations ๐คท. However, if you use -Wpedantic with -Wformat, you get warnings about format features that aren't in the selected standard version (but not for strfmon formats, since those aren't in any version of the C standard).
-Wformat=1,-Wformatโ-Wformatis equivalent to-Wformat=1, and-Wno-formatis equivalent to-Wformat=0๐. Since-Wformatalso checks for null format arguments for several functions, it also implies-Wnonnull. Some aspects of this level of format checking can be disabled with-Wno-format-contains-nul,-Wno-format-extra-args, and-Wno-format-zero-length.-Wformatis enabled by-Wall.-Wno-format-contains-nulโ If-Wformatis specified, don't warn about format strings that contain NUL bytes ๐.-Wno-format-extra-argsโ If-Wformatis specified, don't warn about excess arguments to aprintforscanfformat function. The C standard says those 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 tova_argto skip the unused arguments. However, forscanfformats, 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โ okay bestie, this one is a whole vibe ๐ It warns about calls to formatted input/output functions likesprintfandvsprintfthat might overflow the destination buffer ๐ญ When GCC can't figure out exactly how many bytes a format directive will write at compile time, it makes a guess using heuristics that depend on the level argument and on optimization. Turning optimization on usually makes the warning more accurate, but it can also give you false positives ๐-Wformat-overflow,-Wformat-overflow=1โ Level 1 gets switched on by-Wformatand it's the chill, conservative option โจ It only warns about calls that most likely overflow the buffer. Numeric arguments with unknown values get treated as one, 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 their directive's precision or by a finite set of string literals, get assumed to take on the value within that range that produces the most bytes on output. For example, thesprintfcall below gets diagnosed because even with bothaandbequal to zero, the terminating NUL character ('\0') that the function appends to the destination buffer still gets written past its end ๐ Making the buffer one byte bigger is enough to dodge the warning, though it might not be enough to actually avoid the overflow ๐ซถ
void f (int a, int b)
{
char buf [13];
sprintf (buf, "a = %i, b = %i\n", a, b);
}
-Wformat-overflow=2โ Level 2 goes a step further and also warns about calls that might overflow the destination buffer given an argument of sufficient length or magnitude ๐ฅ At this level, 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 to be 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, get assumed to be 1 character long. At level 2, the call in the example above gets diagnosed again, but this time it's because withaequal to a 32-bitINT_MIN, the first%idirective 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 that minimum buffer size in an informational note right after the warning ๐
Instead of making the buffer bigger, you can also constrain the range of the formatted values โจ The maximum length of string arguments can be bounded by specifying the 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 this one is just being extra ๐ธ-Wformat=2โ enables-Wformatplus some additional format checks ๐ Right now it's equivalent to-Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k.-Wformat-nonliteralโ if-Wformatis specified, also warn if the format string isn't a string literal, since that means it 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 uses of format functions that could be a security problem ๐จ Right now this warns about calls toprintfandscanffunctions where 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โ warns about calls to formatted input/output functions likesnprintfandvsnprintfthat might result in output truncation โ๏ธ Just like the overflow one, when the exact number of bytes a format directive writes can't be determined at compile time, it's estimated using heuristics that depend on the level argument and on optimization. Optimization usually makes it 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 gets enabled by-Wformatand is the conservative one ๐ซถ 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 only yield a two-digit year. Y2K is not the vibe ๐
-Wnonnullโ warns about passing a null pointer for arguments marked as requiring a non-null value by thenonnullfunction attribute ๐ โโ๏ธ-Wnonnullis included in-Walland-Wformat. It can be disabled with the-Wno-nonnulloption.-Wnonnull-compareโ warns when comparing an argument marked with thenonnullfunction attribute against null inside the function ๐-Wnonnull-compareis included in-Wall. It can be disabled with the-Wno-nonnull-compareoption.-Wnull-dereferenceโ warns if the compiler detects paths that trigger erroneous or undefined behavior because of dereferencing a null pointer ๐ญ This option is only active when-fdelete-null-pointer-checksis active, which is enabled by optimizations on most targets. The precision of the warnings depends on the optimization options you use.-Winit-self(C, C++, Objective-C and Objective-C++ only) โ warns about uninitialized variables that get initialized with themselves ๐ Note that this option can only be used together with-Wuninitialized. GCC warns aboutibeing uninitialized in the snippet below only when-Winit-selfhas been specified:
int f()
{
int i = i;
return i;
}
This warning is enabled by -Wall in C++ โจ
-Wimplicit-int(C and Objective-C only) โ warns when a declaration doesn't specify a type. This warning is enabled by-Wall๐ธ-Wimplicit-function-declaration(C and Objective-C only) โ gives a warning whenever a function is used before it's declared ๐ In C99 mode (-std=c99or-std=gnu99), this warning is enabled by default, and it gets turned into an error by-pedantic-errors. This warning is also enabled by-Wall.-Wimplicit(C and Objective-C only) โ same as-Wimplicit-intand-Wimplicit-function-declaration๐ This warning is enabled by-Wall.-Wimplicit-fallthroughโ is the same as-Wimplicit-fallthrough=3, and-Wno-implicit-fallthroughis the same as-Wimplicit-fallthrough=0๐ฆ-Wimplicit-fallthrough=nโ warns when a switch case falls through to the next one ๐ Here's the tea:
switch (cond)
{
case 1:
a = 1;
break;
case 2:
a = 2;
case 3:
a = 3;
break;
}
This warning doesn't fire when the last statement of a case can't fall through, like when there's a return statement or a call to a function declared with the noreturn attribute. -Wimplicit-fallthrough= also takes control flow statements, like ifs, into account, so it only warns when it's actually appropriate. For example:
switch (cond)
{
case 1:
if (i > 3) {
bar (5);
break;
} else if (i < 1) {
bar (0);
} else
return;
default:
...
}
Sometimes a switch case falling through is exactly what you want ๐ซถ For those times, GCC provides an attribute, __attribute__ ((fallthrough)), that goes 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 us a standard way to shush -Wimplicit-fallthrough: [[fallthrough]]; ๐
No GNU-only attribute needed! If you're stuck on C++11 or C++14, you can use [[gnu::fallthrough]]; instead, which is a GNU extension ๐. Bestie, you can also skip attributes entirely and drop a fallthrough comment ๐ซถ. The whole body of the C or C++ style comment has to match one of the regular expressions below, and the option argument n decides which kinds of comments count:
-Wimplicit-fallthrough=0turns the warning off completely ๐.-Wimplicit-fallthrough=1uses the".*"regular expression, so literally any comment counts as a fallthrough comment โจ.-Wimplicit-fallthrough=2matches the".*falls?[ \t-]*thr(ough|u).*"regular expression, and it doesn't care about capital letters ๐ฆ.-Wimplicit-fallthrough=3is case sensitive and needs to match one of these regular expressions:"-fallthrough""@fallthrough@""lint -fallthrough[ \t]*""[ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?FALL(S | |-)?THR(OUGH|U)[ \t.!]*(-[^\n\r]*)?""[ \t.!]*(Else,? |Intentional(ly)? )?Fall((s | |-)[Tt]|t)hr(ough|u)[ \t.!]*(-[^\n\r]*)?""[ \t.!]*([Ee]lse,? |[Ii]ntentional(ly)? )?fall(s | |-)?thr(ough|u)[ \t.!]*(-[^\n\r]*)?"
-Wimplicit-fallthrough=4is also case sensitive and needs to match one of these:"-fallthrough""@fallthrough@""lint -fallthrough[ \t]*""[ \t]*FALLTHR(OUGH|U)[ \t]*"
-Wimplicit-fallthrough=5doesn't recognize any comments as fallthrough comments, so only attributes will shut the warning up ๐.
The comment has to come right before a case or default keyword (optional whitespace and other comments are fine in between), or before a user label that sits in front of a case or default label ๐.
switch (cond)
{
case 1:
bar (0);
/* FALLTHRU */
default:
...
}
๐ฅ -Wimplicit-fallthrough=3 is turned on by -Wextra, so you get it for free there.
๐ธ -Wif-not-aligned (C, C++, Objective-C and Objective-C++ only)
This controls whether the warning triggered by the warn_if_not_aligned attribute gets issued. It's on by default, but if it's annoying you, -Wno-if-not-aligned turns it off ๐
โโ๏ธ.
๐ง -Wignored-qualifiers (C and C++ only)
Warns if a function's return type has a type qualifier like "const". In ISO C that qualifier does nothing, because a function's return value isn't an lvalue ๐คทโโ๏ธ. In C++, the warning only shows up for scalar types or "void". ISO C doesn't allow qualified "void" return types on function definitions, so those always get a warning, even without this option.
This warning is also turned on by -Wextra.
๐ฆ -Wignored-attributes (C and C++ only)
Warns when an attribute gets ignored. This is different from -Wattributes, which is about attributes being unknown or used in the wrong place. This one fires whenever the compiler decides to drop an attribute ๐. It's enabled by default.
๐ -Wmain
Warns if the type of main looks sus ๐ง. main should be a function with external linkage that returns int, and it should take either zero arguments, or two or three arguments of the right types. This warning is enabled by default in C++, and it's turned on by either -Wall or -Wpedantic.
๐ -Wmisleading-indentation (C and C++ only)
Warns when the indentation doesn't match the actual block structure โ ๏ธ. Specifically, it fires for if, else, while, and for clauses that have a guarded statement without braces, followed by an unguarded statement with the same indentation.
In this example, the call to bar looks like it's guarded by the if, but it isn't:
if (some_condition ())
foo ();
bar (); /* Gotcha: this is not guarded by the "if". */
If you mix tabs and spaces, the warning uses -ftabstop= to figure out whether the statements actually line up, and it defaults to 8 ๐.
It won't warn about code with multiline preprocessor logic, like this:
if (flagA)
foo (0);
#if SOME_CONDITION_THAT_DOES_NOT_HOLD
if (flagB)
#endif
foo (1);
It also won't warn after a #line directive. That usually means the code was autogenerated, and nobody can make assumptions about the layout of the file that the directive points to ๐ค.
This warning is enabled by -Wall in C and C++.
๐ -Wmissing-attributes
This one warns when a function declaration is missing one or more attributes that a related function is declared with, and where that missing attribute could hurt the correctness or efficiency of the generated code ๐ง . For example, it fires for alias declarations that use attributes to set less restrictive requirements than their targets. That usually means there's a potential optimization opportunity. The opposite case is handled by -Wattribute-alias=2, which warns when the alias is more restrictive than the target, and that could lead to incorrect code generation ๐จ.
The attributes it considers are alloc_align, alloc_size, cold, const, hot, leaf, malloc, nonnull, noreturn, nothrow, pure, returns_nonnull, and returns_twice.
In C++, it warns when an explicit specialization of a primary template is declared without an attribute that the primary template was declared with. The attributes it checks are alloc_align, alloc_size, assume_aligned, format, format_arg, malloc, and nonnull. The attributes deprecated, error, and warning suppress the warning..
You can use the copy attribute to apply the same set of attributes from one declaration to another, without having to list them all out ๐ซถ. It works on declarations of functions, variables, or types.
-Wmissing-attributes is enabled by -Wall.
Here's an example. The primary function template below uses both malloc and alloc_size, so the explicit specialization gets flagged for missing one of them ๐:
template <class T>
T* __attribute__ ((malloc, alloc_size (1)))
allocate (size_t);
template <>
void* __attribute__ ((malloc)) // missing alloc_size
allocate<void> (size_t);
๐ -Wmissing-braces
Warns if an aggregate or union initializer isn't fully bracketed ๐งบ. In the example below, the initializer for a isn't fully bracketed, but the one for b is.
int a[2][2] = { 0, 1, 2, 3 };
int b[2][2] = { { 0, 1 }, { 2, 3 } };
This warning is enabled by -Wall in C.
๐ -Wmissing-include-dirs (C, C++, Objective-C and Objective-C++ only)
Warns if a user-supplied include directory doesn't exist ๐.
๐ท -Wmissing-profile
Warns if feedback profiles are missing when you use -fprofile-use ๐. It catches the cases where a new function or a new file got added between compiling with -fprofile-generate and compiling with -fprofile-use, and you didn't regenerate the profiles. In those cases, the profile feedback data files don't have any feedback 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 a warning letting you know a profile generation step is due ๐.
-Wno-missing-profile can be used to disable the warning. Ignoring the warning can result in poorly optimized code.
โ ๏ธ Completely disabling this warning isn't recommended. Only do it when having no profile data at all is actually justified.
๐
-Wmultistatement-macros
Warns about unsafe multiple-statement macros that look like they're guarded by an if, else, for, switch, or while clause, when only the first statement is actually guarded once the macro expands ๐ญ.
For example:
#define DOIT x++; y++
if (c)
DOIT;
Here y gets incremented unconditionally, not only when c holds. You can usually fix this 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 when parentheses are left out in certain spots, like an assignment where a truth value is expected, or nested operators whose precedence people often mix up ๐คฏ.
It also warns about a comparison like x<=y<=z. That's equivalent to (x<=y ? 1 : 0) <= z, which is a different meaning from regular math notation, so bestie, watch out ๐.
It also warns about dangerous uses of the GNU extension to ?: with an omitted middle operand. When the condition in the ?: operator is a boolean expression, the omitted value is always 1. Programmers often expect it to be a value computed inside the conditional expression instead ๐.
For C++, it also warns about some cases of unnecessary parentheses in declarations. Those can mean you were trying 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 ๐ซ.
Okay so sequence points are basically how the C and C++ standards say "this part finishes before that part starts" โจ. They're only a partial ordering, so they lock in some of the order and leave the rest open ๐. They show up after a full expression (one that isn't stuck inside a bigger expression) ๐, after the first operand of a &&, ||, ? : or , (comma) operator ๐ฆ, and right before a function gets called, but only after its arguments and the expression naming the function are done. There are a few other spots too. Everywhere else, the order that subexpressions get evaluated in is not specified. Like, if two functions get called in one expression with no sequence point between them, the order they run in is up for grabs ๐
. The standards committee did rule that function calls don't overlap, though, so at least that's locked in ๐.
It's also not specified when, between sequence points, changes to object values actually take effect ๐ญ. Programs that depend on that have undefined behavior. The standards say that "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.". If a program breaks those rules, the results on any given implementation are entirely unpredictable ๐.
Examples of 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 throw a false positive ๐. But overall it's been found to be pretty effective at catching this kind of problem in programs ๐.
The C++17 standard is going to define the order of evaluation for operands in more cases ๐. Specifically, 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 warning will still yell about them though, so people can avoid writing code that's undefined in C and earlier revisions of C++ ๐ซถ.
The standard is worded kinda confusingly, so there's some debate about what the sequence point rules mean in subtle cases ๐ค. If you want to dig into the discussions, including proposed formal definitions, check 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โ Chill, don't warn about returning a pointer (or a reference in C++) to a variable that goes out of scope once the function returns ๐ธ.-Wreturn-typeโ Warns whenever a function is defined with a return type that defaults toint๐. It also warns about anyreturnstatement with no return value in a function whose return type isn'tvoid. Falling off the end of the function body counts as returning without a value, so yeah, that gets flagged too ๐.
For C only, it warns about a return statement with an expression in a function whose return type is void, unless the expression's type is also void. As a GNU extension, that last case is accepted without a warning unless -Wpedantic is used ๐ง. Using the return value of a non-void function (other than main) that flows off the end by hitting the closing curly brace is undefined ๐.
Unlike C, in C++, flowing off the end of a non-void function (other than main) results in undefined behavior even when the function's value isn't used ๐ญ. This warning is enabled by default in C++ and by -Wall otherwise ๐.
-Wshift-count-negativeโ Warns if the shift count is negative. This warning is enabled by default ๐ .-Wshift-count-overflowโ Warns if the shift count is>=the width of the type. This warning is enabled by default โจ.-Wshift-negative-valueโ Warns if you're left shifting a negative value ๐ฆ. This warning is enabled by-Wextrain C99 (and newer) and C++11 to C++17 modes.-Wshift-overflow,-Wshift-overflow=nโ Warns about left shift overflows ๐ฅ. This warning is enabled by default in C99 and C++11 modes (and newer).-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-shifting1into 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++2A mode (and newer), since signed left shifts always wrap ๐ซถ.-Wshift-overflow=2โ This level also warns about left-shifting1into the sign bit, unless C++14 mode (or newer) is active ๐.
-Wswitchโ Warns whenever aswitchstatement has an index of enumerated type and is missing acasefor one or more of the named codes in that enumeration ๐. (Adefaultlabel stops this warning.)caselabels outside the enumeration range also get warnings with this option, even if there's adefaultlabel. This warning is enabled by-Wall๐.-Wswitch-defaultโ Warns whenever aswitchstatement doesn't have adefaultcase ๐ธ.-Wswitch-enumโ Same vibe as-Wswitch: warns when aswitchon an enumerated type is missing acasefor one or more of the named codes, and whencaselabels fall outside the enumeration range ๐ฆ. The only difference is that this option warns about an omitted enumeration code even if there's adefaultlabel ๐.-Wswitch-boolโ Warns whenever aswitchstatement has an index of boolean type and the case values are outside the range of a boolean type ๐. You can suppress this 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 โจ.
-Wswitch-unreachableโ Warns whenever aswitchstatement has statements between the controlling expression and the firstcaselabel, since those will never be executed ๐. For example:
switch (cond)
{
i = 15;
...
case 5:
...
}
-Wswitch-unreachable won't warn if the statement between the controlling expression and the first case label is just a declaration:
switch (cond)
{
int i;
...
case 5:
i = 5;
...
}
This warning is enabled by default for C and C++ programs ๐ซถ.
-Wsync-nand(C and C++ only) โ Warns when the__sync_fetch_and_nandand__sync_nand_and_fetchbuilt-in functions are used ๐ฅ. These functions changed semantics in GCC 4.4 ๐ญ.-Wunused-but-set-parameterโ Warns whenever a function parameter gets assigned to but otherwise goes unused (aside from its declaration) ๐.
To suppress this warning, use the unused attribute ๐ง.
This warning is also enabled by -Wunused together with -Wextra โจ.
-Wunused-but-set-variableโ Warns whenever a local variable gets assigned to but otherwise goes unused (aside from its declaration) ๐ . This warning is enabled by-Wall.
To suppress this warning, use the unused attribute ๐.
This warning is also enabled by -Wunused, which is enabled by -Wall ๐.
-Wunused-functionโ Warns whenever astaticfunction is declared but not defined, or a non-inlinestaticfunction is unused ๐ฆ. This warning is enabled by-Wall.-Wunused-labelโ Warns whenever a label is declared but never used ๐ท๏ธ. This warning is enabled by-Wall.
To suppress this warning, use the unused attribute ๐ธ.
-Wunused-local-typedefs(C, Objective-C, C++ and Objective-C++ only) โ Warns when a typedef defined locally inside a function isn't used ๐. This warning is enabled by-Wallโจ.-Wunused-parameterโ Warns whenever a function parameter goes unused aside from its declaration ๐ง.
To suppress this warning, use the unused attribute ๐.
-Wno-unused-resultโ Don't warn if a caller of a function marked with the attributewarn_unused_resultdoesn't use its return value ๐. The default is-Wunused-result๐.-Wunused-variableโ Warns whenever a local orstaticvariable is unused aside from its declaration ๐ซถ. This option implies-Wunused-const-variable=1for C, but not for C++ ๐ค. This warning is enabled by-Wall๐.
To suppress this warning, use the unused attribute ๐.
-Wunused-const-variable,-Wunused-const-variable=nโ Warns whenever a constantstaticvariable is unused aside from its declaration ๐.-Wunused-const-variable=1is enabled by-Wunused-variablefor C, but not for C++. In C this declares variable storage, but in C++ it isn't an error, sinceconstvariables take the place of#defines ๐ง.
To suppress this warning, use the unused attribute โจ.
-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 header that gets included ๐ฆ.-Wunused-const-variable=2โ This level also warns about unused constantstaticvariables in headers (excluding system headers) ๐. It's the level of-Wunused-const-variableand has to be explicitly requested, since in C++ it isn't an error and in C it might be harder to clean up every header that's included ๐.
-Wunused-valueโ Warns whenever a statement computes a result that's explicitly not used ๐ฅ. To suppress it, cast the unused expression tovoid๐ซถ. This includes an expression statement, or the left-hand side of a comma expression, that contains no side effects. For example,x[i,j]causes a warning, whilex[(void)i,j]does not ๐ .
This warning is enabled by -Wall โจ.
-Wunusedโ All the above-Wunusedoptions combined ๐.
So, to get a warning about an unused function parameter, bestie, you gotta either specify -Wextra -Wunused (ngl -Wall already implies -Wunused ๐ซถ), or separately specify -Wunused-parameter ๐.
-Wuninitializedโ ๐ฅบ Warns if an automatic variable gets used before it's ever initialized, or if a variable might get clobbered by asetjmpcall. In C++, it also warns if a non-static reference or a non-staticconstmember shows up in a class with no constructors.
If you want to catch code that uses a variable's uninitialized value inside its own initializer, that's what -Winit-self is for ๐
.
These warnings show up for individual uninitialized or clobbered elements of structs, unions, or arrays, and also for variables that are uninitialized or clobbered as a whole. They do not show up for variables or elements declared volatile ๐. Since these depend on optimization, the exact variables or elements that get flagged depend on the precise optimization options and the GCC version you're using, so it's a whole vibe ๐.
Heads up: there may be no warning about a variable that's only used to compute a value that's never used, because data flow analysis can delete those computations before the warnings are printed ๐.
-Winvalid-memory-modelโ ๐ฅ Warns for invocations of__atomicbuiltins,__syncbuiltins, and the C11 atomic generic functions when the memory consistency argument is either invalid for the operation or outside the range of values in thememory_orderenumeration. For example,__atomic_storeand__atomic_store_nare only defined for the relaxed, release, and sequentially consistent memory orders, so the code below 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 automatic (aka local) variable, if there's a path from the function entry to a use of the variable that is initialized, but other paths exist where it isn't, the compiler emits a warning if it can't prove those uninitialized paths never run at runtime.
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 way that can happen:
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
foo (x);
}
If y is always 1, 2, or 3, then x is always initialized, but GCC doesn't know that ๐ฅน. To suppress the warning, 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. So you may get a warning even when there's actually no problem, because longjmp can't really 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 get issued even 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โ ๐ธ Turns off warnings about pragma misuses, like incorrect parameters, invalid syntax, or conflicts between pragmas. See also-Wunknown-pragmas.-Wno-prio-ctor-dtorโ ๐ Stops warnings 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 between 0--100 for 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 the strict aliasing rules. Higher levels mean higher accuracy (fewer false positives), but also more effort, kinda like how-Oworks.-Wstrict-aliasingis equivalent to-Wstrict-aliasing=3.- Level 1 โ Most aggressive, quick, and least accurate ๐ค. It's possibly useful when 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, quick, and not too precise ๐ซ . It may still have many false positives (not as many as level 1 though), and few false negatives (but possibly more than level 1). Unlike level 1, it only warns when an address is taken. It warns about incomplete types. It runs in the front end only.
- Level 3 (default for
-Wstrict-aliasing) โ The main character ๐. It should have very few false positives and few false negatives. It's slightly slower than levels 1 or 2 when optimization is enabled. It handles the common pun+dereference pattern in the front end, like*(int*)&some_float. If optimization is enabled, it also runs in the back end, where it deals with multiple statement cases using flow-sensitive points-to information. It only warns when the converted pointer is dereferenced. It does not warn about incomplete types.
- Level 1 โ Most aggressive, quick, and least accurate ๐ค. It's possibly useful when higher levels don't warn but
-Wstrict-overflow,-Wstrict-overflow=nโ ๐ This option is only active when signed overflow is undefined. It warns about cases where the compiler optimizes based on the assumption that signed overflow doesn't happen. It doesn't warn about every place the code might overflow, only where the compiler actually implements some optimization, so this warning depends on the optimization level ๐ง.
An optimization that assumes signed overflow never happens is perfectly safe if the values involved are such that overflow never does happen. So this warning can easily give a false positive: 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 the use of undefined signed overflow when estimating how many iterations a loop requires, especially when figuring out whether a loop will run at all ๐ฅ.
-Wstrict-overflow=1โ Warns about cases that are both questionable and easy to avoid. For example, the compiler simplifiesx + 1 > xto1. This level is enabled by-Wall; 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 cases above. For example:(x * 10) / 5is simplified tox * 2.-Wstrict-overflow=5โ Also warns about cases where the compiler reduces the magnitude of a constant involved in a comparison. For example:x + 2 > yis simplified tox + 1 >= y. This is only reported at the highest warning level, because this simplification applies to many comparisons, so this level gives a very large number of false positives ๐ตโ๐ซ.
-Wstringop-overflow,-Wstringop-overflow=typeโ ๐ง Warns for calls to string manipulation functions likememcpyandstrcpythat are determined to overflow the destination buffer. The optional type argument is one greater than the type of Object Size Checking to perform to determine the size of the destination ๐ง .
That argument only matters for functions that operate on character arrays, not raw memory functions like memcpy, which always make use of Object Size type-0. This option also warns for calls that specify a size bigger than the largest possible object, or at most SIZE_MAX / 2 bytes ๐ซถ.
It gives the best results with optimization enabled, but it can detect a small subset of simple buffer overflows even without optimization, in calls to GCC built-in functions like __builtin_memcpy that correspond to the standard functions. Either way, the option only warns about a subset of the buffer overflows that the corresponding overflow checking built-ins detect ๐ฆ.
For example, this option will issue a warning for a strcpy call that copies at least 5 characters (the string "blue" including the terminating NUL) into a buffer of size 4 ๐โจ.
Check out the // warning here line, bestie, because that's where GCC is gonna scream ๐ฃ๐ซถ
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
}
Quick tea โ: the manual says -Wstringop-overflow=2 is enabled by default, and then the =1 entry below says =1 is the default setting. The page is having a whole identity crisis ๐ so I'm just reporting both, no cap.
๐ -Wstringop-overflow
-Wstringop-overflow,-Wstringop-overflow=1โ The main character of the family ๐. It uses type-zero Object Size Checking to figure out how big destination objects are, and this is the default setting. At this level it won't yell about writes past the end of subobjects inside bigger objects reached 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 largest one. On Linux systems, with optimization turned on at this level, it warns for the same code you'd get when the_FORTIFY_SOURCEmacro is defined to a non-zero value ๐ก๏ธ.-Wstringop-overflow=2โ 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 referenced by pointers, since those might point at arrays with an unknown number of elements ๐คทโโ๏ธ.-Wstringop-overflow=3โ Uses type-two Object Size Checking. It warns about overflowing the smallest object or data member. This is the strictest setting that can still flag safe code, so be ready for a few false alarms ๐ฅฒ.-Wstringop-overflow=4โ Uses type-three Object Size Checking ๐. It warns about overflowing any data members. When the destination is one of several objects, it uses the size of the largest one to decide whether to warn. Just like=3, this setting may flag totally benign code.
๐ -Wstringop-truncation
-Wstringop-truncationโ Warns for calls to bounded string functions likestrncat,strncpy, andstpncpythat might either truncate the copied string or leave the destination unchanged โ๏ธ.
Look at this strncat call. The bound is smaller than the length of the source string, so the copy gets chopped and the call gets diagnosed. To avoid the warning, use bufsize - strlen (buf) - 1) as the bound.
void append (char *buf, size_t bufsize)
{
strncat (buf, ".txt", 3);
}
Next up, strncpy. This call copies only the characters before the terminating NUL, and it doesn't add the NUL to the end. Assuming the result is always NUL-terminated is a super common mistake, so this one gets flagged too ๐. If the result isn't expected to be NUL-terminated, call memcpy instead.
void copy (char *d, const char *s)
{
strncpy (d, s, strlen (s));
}
Last one! Here the bound is the size of the destination buffer. If the source length is equal to or greater than that size, the result won't be NUL-terminated, so it gets diagnosed. To avoid the warning, specify sizeof buf - 1 as the bound and set the last element of the buffer to NUL.
void copy (const char *s)
{
char buf[80];
strncpy (buf, s, sizeof buf);
...
}
If a character array is meant to store a sequence of bytes with no terminating NUL, you can annotate it with the attribute nonstring to avoid this warning ๐งต. Just know that those arrays aren't suitable for functions that expect NUL-terminated strings. To help catch accidental misuse, GCC still issues warnings unless it can prove the use is safe ๐ง.
๐ -Wsuggest-attribute
-Wsuggest-attribute=[pure|const|noreturn|format|cold|malloc]โ Warns for cases where adding an attribute might be beneficial โจ. The supported attributes are listed below.-Wsuggest-attribute=pure,-Wsuggest-attribute=const,-Wsuggest-attribute=noreturn,-Wmissing-noreturn,-Wsuggest-attribute=mallocโ Flags functions that might be candidates for thepure,const,noreturn, ormallocattributes ๐ธ. 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 and doesn't return abnormally by throwing, callingabort, or trapping. This analysis requires option-fipa-pure-const, which is enabled by default at-Oand higher. Higher optimization levels improve the accuracy of the analysis.-Wsuggest-attribute=format,-Wmissing-format-attributeโ Flags function pointers that might be candidates forformatattributes ๐จ๏ธ. These are only possible candidates, not absolute ones. GCC guesses that function pointers withformatattributes used in assignment, initialization, parameter passing, or return statements should have a matchingformatattribute in the resulting type. So the left-hand side of the assignment or initialization, the type of the parameter variable, or the return type of the containing function should also have aformatattribute to avoid the warning. GCC also warns about function definitions that might be candidates forformatattributes, again only as possible candidates. It guessesformatattributes might be appropriate for any function that calls a function likevprintforvscanf, but that's not always the case, and some functions whereformatattributes are appropriate might not get detected.-Wsuggest-attribute=coldโ Flags functions that might be candidates for thecoldattribute ๐ง. This is based on static detection, so it generally only warns about functions that always lead to a call to anothercoldfunction, like wrappers of C++throwor fatal error reporting functions that lead toabort.
๐ -Wsuggest-final-types
-Wsuggest-final-typesโ Warns about types with virtual methods where code quality would improve if the type were declared with the C++11finalspecifier or, if possible, declared in an anonymous namespace ๐น. This lets GCC devirtualize the polymorphic calls more aggressively. It's more effective with link time optimization, where the information about the class hierarchy graph is more complete.
๐ -Wsuggest-final-methods
-Wsuggest-final-methodsโ Warns about virtual methods where code quality would improve if the method were declared with the C++11finalspecifier, or, if possible, if its type were declared in an anonymous namespace or with thefinalspecifier ๐. It's more effective with link-time optimization, where the class hierarchy graph is more complete. It's recommended to first consider the suggestions from-Wsuggest-final-typesand then rebuild with new annotations.
๐ -Wsuggest-override
-Wsuggest-overrideโ Warns about overriding virtual functions that aren't marked with theoverridekeyword ๐.
๐ -Walloc-zero
-Walloc-zeroโ Warns about calls to allocation functions decorated with thealloc_sizeattribute that specify zero bytes ๐ โโ๏ธ. This includes the built-in forms ofaligned_alloc,alloca,calloc,malloc, andrealloc. The behavior of these functions with a zero size differs among implementations (and forrealloc, that behavior has been deprecated), so relying on it can cause subtle portability bugs. Avoid it!
๐ -Walloc-size-larger-than
-Walloc-size-larger-than=byte-sizeโ Warns about calls to functions decorated with thealloc_sizeattribute that try to allocate objects larger than the specified number of bytes ๐. It also warns when the result of the size computation, done in an integer type with infinite precision, would exceed the value ofPTRDIFF_MAXon the target.-Walloc-size-larger-than=PTRDIFF_MAXis enabled by default ๐ฅณ. You can disable these warnings by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-alloc-size-larger-than.-Wno-alloc-size-larger-thanโ Disables the-Walloc-size-larger-than=warnings ๐ . It's equivalent to-Walloc-size-larger-than=SIZE_MAXor larger.
๐ -Walloca
-Wallocaโ Warns on all uses ofallocain the source. Every single one ๐.
๐ -Walloca-larger-than
-Walloca-larger-than=byte-sizeโ This one warns on calls toallocawith an integer argument whose value is either zero, or that isn't bounded by a controlling predicate limiting its value to at most byte-size ๐ช. It also warns for calls toallocawhere the bound value is unknown. Arguments of non-integer types count as unbounded, even if they look like they're constrained to the expected range.
For example, a bounded case of alloca could look like this:
void func (size_t n)
{
void *p;
if (n <= 1000)
p = alloca (n);
else
p = malloc (n);
f (p);
}
In the example above, passing -Walloca-larger-than=1000 wouldn't 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 ๐จ.
Okay so the alloca thing gets even spicier, bestie ๐
Unbounded uses are the ones with no controlling predicate keeping the integer argument in check. Like this:
void func ()
{
void *p = alloca (n);
f (p);
}
If you pass -Walloca-larger-than=500, this one trips a warning too, but this time it's because there's zero bounds checking. Not a vibe ๐ญ
Even code that looks totally fine with signed integers can get a warning ๐
void func (signed int n)
{
if (n < 500)
{
p = alloca (n);
f (p);
}
}
Like, n could be negative, and then a way-too-big number gets implicitly cast into the alloca call. Plot twist, iykyk ๐ซ
This option also warns when alloca is used inside a loop ๐
-Walloca-larger-than=PTRDIFF_MAX is on by default, but it's usually only really effective when -ftree-vrp is active, which is the default for -O2 and above โจ
See also -Wvla-larger-than=byte-size ๐ฆ
-Wno-alloca-larger-thanโ the big ol' off switch for-Walloca-larger-than=warnings ๐ โโ๏ธ It's the same as-Walloca-larger-than=SIZE_MAXor larger.-Warray-bounds,-Warray-bounds=nโ this one only does its thing when-ftree-vrpis active (default for-O2and above) ๐ It warns about subscripts to arrays that are always out of bounds, and-Wallturns it on.-Warray-bounds=1โ this is the level-Warray-boundsruns at, and-Wallenables it. Higher levels aren't on with-Wall, so you have to ask for them explicitly ๐โโ๏ธ-Warray-bounds=2โ this level also catches out-of-bounds access for arrays at the end of a struct and arrays accessed through pointers ๐ It can throw a bigger pile of false positives, so it's deactivated by default ๐
-Wattribute-alias=n,-Wno-attribute-aliasโ warns about declarations using thealiasattribute (and similar ones) whose target doesn't match the type of the alias ๐-Wattribute-alias=1โ this is the default level ๐ It flags mismatches between the type of the alias declaration and its target. Those are usually a sign of bugs, bestie.-Wattribute-alias=2โ now it also flags cases where the alias declaration is more restrictive than its target's attributes โ ๏ธ Those mismatches can lead to incorrect code generation! In other cases they're harmless and can be fixed by just adding the missing attribute to the target. For comparison, check out-Wmissing-attributes, which covers the opposite situation, where the alias is less restrictive than the target.
The attributes it considers are "alloc_align", "alloc_size", "cold", "const", "hot", "leaf", "malloc", "nonnull", "noreturn", "nothrow", "pure", "returns_nonnull", and "returns_twice" ๐ง
-Wattribute-alias is the same as -Wattribute-alias=1, and that's the default โจ To turn these warnings off, use either -Wno-attribute-alias or -Wattribute-alias=0 ๐ซถ
-Wbool-compareโ warns about a boolean expression being compared to an integer value that isn'ttrueorfalse๐ง This comparison is always false:
int n = 5;
...
if ((n > 1) == 2) { ... }
It's enabled by -Wall ๐
-Wbool-operationโ flags sus operations on boolean expressions ๐ฉ Like, bitwise negation of a boolean is very likely a bug. For C, this also warns about incrementing or decrementing a boolean, which rarely makes sense. (In C++, decrementing a boolean is always invalid, and incrementing one is invalid in C++17 and deprecated otherwise ๐ ) It's enabled by-Wall๐ธ-Wduplicated-branchesโ warns when anif-elsehas identical branches ๐ฏ Like this one:
if (p != NULL)
return 0;
else
return 0;
It doesn't warn when both branches contain just a null statement ๐ It also warns for conditional operators, like:
int i = x ? *p : *p;
-Wduplicated-condโ warns about duplicated conditions in anif-else-ifchain ๐ For example, it'll warn on this:
if (p->q != NULL) { ... }
else if (p->q != NULL) { ... }
-Wframe-addressโ warns when__builtin_frame_addressor__builtin_return_addressgets called with an argument greater than0๐ฌ Those calls might return indeterminate values or crash the program. It's included in-Wallโจ-Wno-discarded-qualifiers(C and Objective-C only) โ doesn't warn when type qualifiers on pointers get dropped ๐ โโ๏ธ Normally the compiler complains if aconst char *variable gets passed to a function that takes achar *parameter. This option quiets that one ๐คซ-Wno-discarded-array-qualifiers(C and Objective-C only) โ same energy, but for arrays that are pointer targets. Normally it warns if aconst int (*)[]variable gets passed to a function taking anint (*)[]parameter. This option suppresses that warning ๐-Wno-incompatible-pointer-types(C and Objective-C only) โ doesn't warn when there's a conversion between pointers with incompatible types ๐ฆ This one covers cases that-Wno-pointer-signdoesn't. That one handles pointer argument passing or assignment with different signedness.-Wno-int-conversion(C and Objective-C only) โ doesn't warn about incompatible integer-to-pointer and pointer-to-integer conversions ๐ข This is about implicit conversions. For explicit ones, you can use-Wno-int-to-pointer-castand-Wno-pointer-to-int-castinstead ๐ซถ-Wno-div-by-zeroโ doesn't warn about compile-time integer division by zero ๐ Floating-point division by zero isn't warned about either, since it can be a legit way to get infinities and NaNs ๐-Wsystem-headersโ prints warning messages for constructs found in system header files ๐ Warnings from system headers are normally suppressed, on the assumption that they usually aren't real problems and would just make the compiler output harder to read. This option tells GCC to emit those warnings as if they came from user code ๐
Heads up, bestie! Using-Walltogether with this option does not warn about unknown pragmas in system headers. For that, you also need-Wunknown-pragmas๐จ
-Wtautological-compareโ warns if a self-comparison always evaluates to true or false ๐ช This catches mistakes like:
int i = 1;
...
if (i > i) { ... }
It also warns about bitwise comparisons that always evaluate to true or false. For instance, this one is always false:
if ((a & 16) == 10) { ... }
It's enabled by -Wall ๐
-Wtrampolinesโ warns about trampolines generated for pointers to nested functions ๐ข A trampoline is a small piece of data or code created at run time on the stack when the address of a nested function is taken, and it's used to call the nested function indirectly. On some targets it's just data and needs no special treatment. But on most targets it's made of code, which means the stack has to be made executable for the program to work properly ๐ณ-Wfloat-equalโ warns if floating-point values are used in equality comparisons ๐งฎ The idea is that sometimes it's convenient to treat floating-point values as approximations of infinitely precise real numbers. If you're doing that, you need to figure out (by analyzing the code, or some other way) the maximum or likely maximum error the computation introduces, and allow for it when comparing (and when producing output, but that's a different problem ๐). 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 a mistake ๐ธ-Wtraditional(C and Objective-C only) โ warns about certain constructs that behave differently in traditional and ISO C ๐ฐ๏ธ It also warns about ISO C constructs with no traditional C equivalent, and about problematic constructs you should avoid. Here's what it flags:- Macro parameters that appear within 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 these macros in user code might normally lead to spurious warnings, but GCC's integrated preprocessor has enough context to avoid warning in these cases ๐ซง - A function declared external in one block and then used after the end of that block ๐งฉ
- A
switchstatement with an operand of typelong๐
- ๐
โโ๏ธ A non-
staticfunction declaration that shows up after astaticone. Some traditional C compilers absolutely refuse this, so it's giving "nope" ๐ - ๐ข An integer constant whose ISO type has a different width or signedness than its traditional type. Lowkey important: this only fires when the constant's base is ten. I.e., hexadecimal or octal values, which usually represent bit patterns, are not warned about ๐ซถ
- ๐งต GCC clocks it whenever you use ISO string concatenation.
- ๐ฆ Initializing automatic aggregates.
- ๐ท๏ธ An identifier that clashes with a label. Traditional C doesn't have a separate namespace for labels, so this one is a classic gotcha.
- ๐ซง Initializing unions! If the initializer is zero, GCC stays quiet. The thinking is that a zero initializer in user code usually sits behind a condition on e.g.
__STDC__so it doesn't set off missing initializer warnings, and that it relies on default initialization to zero in the traditional C case. - ๐ Conversions by prototypes between fixed/floating-point values and vice versa. Without those prototypes, compiling with traditional C can cause serious problems. This is only a subset of the possible conversion warnings, so for the full set, use
-Wtraditional-conversion. - ๐ ISO C style function definitions! GCC intentionally skips this for prototype declarations and variadic functions, since those ISO C features sneak into your code when you use libiberty's traditional C compatibility macros,
PARAMSandVPARAMS. It also skips nested functions, because those are already a GCC extension and aren't relevant to traditional C compatibility.
-Wtraditional-conversion(C and Objective-C only) โ Heads up if a prototype causes a type conversion that's different from what would happen to the same argument without a prototype. This covers fixed-point to floating-point conversions and vice versa, plus conversions that change the width or signedness of a fixed-point argument, unless it 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 one's borrowed from C++, was introduced with ISO C99, and is allowed by default in GCC. ISO C90 doesn't support it ๐-Wshadowโ Warns whenever a local variable or type declaration shadows another variable, parameter, type, class member (in C++), or instance variable (in Objective-C), or whenever a built-in function gets shadowed. Quick note: in C++, the compiler warns if a local variable shadows an explicit typedef, but not if it shadows a struct/class/enum. This is the 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. Chill ๐งโโ๏ธ-Wshadow=globalโ The default for-Wshadow. Warns for any (global) shadowing.-Wshadow=localโ Warns when a local variable shadows another local variable or parameter. This warning gets turned on by-Wshadow=global.-Wshadow=compatible-localโ Warns when a local variable shadows another local variable or parameter whose type is compatible with the shadowing variable's type. In C++, "compatible" here means the shadowing variable's type can be converted to the shadowed variable's type. This flag exists (alongside-Wshadow=local) because when a local variable shadows one of an incompatible type, it's most likely on purpose and not a bug or typo. Check out this example ๐
for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i)
{
for (int i = 0; i < N; ++i)
{
...
}
...
}
Since the two i variables in that example have incompatible types, turning on only -Wshadow=compatible-local won't emit a warning. And because their types are incompatible, if a programmer accidentally uses one in place of the other, type checking will catch it and emit an error or warning. So skipping the shadowing warning here won't lead to undetected bugs. Using this flag instead of -Wshadow=local can cut down on the number of warnings triggered by intentional shadowing. โจ
This warning gets turned on by -Wshadow=local.
-Wlarger-than=_byte-size_ โ Warns whenever an object is defined whose size exceeds byte-size.-Wlarger-than=PTRDIFF_MAXis on by default. You can switch these warnings off by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-larger-than๐-Wno-larger-thanโ Disables-Wlarger-than=warnings. This is equivalent to-Wlarger-than=SIZE_MAXor larger.-Wframe-larger-than=_byte-size_ โ Warns if the size of a function frame exceeds byte-size. Heads up: the math used to figure out the stack frame size is approximate and not conservative. The real requirements might be somewhat bigger than byte-size even if you don't get a warning. Also, any space allocated viaalloca, variable-length arrays, or related constructs isn't counted by the compiler when it decides whether to warn.-Wframe-larger-than=PTRDIFF_MAXis on by default. You can disable these warnings by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-frame-larger-than๐ช-Wno-frame-larger-thanโ Disables-Wframe-larger-than=warnings. This is equivalent to-Wframe-larger-than=SIZE_MAXor larger.-Wno-free-nonheap-objectโ Don't warn when you try to free an object that wasn't allocated on the heap. ๐๏ธ-Wstack-usage=_byte-size_ โ Warns if the stack usage of a function might exceed byte-size. This one's more careful: the math is conservative, and any space allocated viaalloca, variable-length arrays, or related constructs is included when the compiler decides whether to warn. The message matches the output of-fstack-usage. Here's what you'll see:- If the stack usage is fully static but goes over the specified amount, 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
- If the stack usage is fully static but goes over the specified amount, it's:
-Wstack-usage=PTRDIFF_MAX is on by default. You can switch these warnings off by specifying a byte-size of SIZE_MAX or more, or by using -Wno-stack-usage ๐ฅ
-Wno-stack-usageโ Disables-Wstack-usage=warnings. This is equivalent to-Wstack-usage=SIZE_MAXor larger.-Wunsafe-loop-optimizationsโ Warns if a loop can't be optimized because the compiler can't assume anything about the bounds of the loop indices. With-funsafe-loop-optimizations, it warns if the compiler makes those assumptions instead ๐-Wno-pedantic-ms-format(MinGW targets only) โ When you combine it with-Wformatand-pedantic(without GNU extensions), this turns off the warnings about non-ISOprintf/scanfformat width specifiersI32,I64, andIused on Windows targets. Those depend on the MS runtime, so they're kind of a Windows-only moment ๐ช-Waligned-newโ Warns about a new-expression of a type that needs greater alignment thanalignof(std::max_align_t), but uses an allocation function without an explicit alignment parameter. This option is enabled by-Wall. Normally it only warns about global allocation functions, but-Waligned-new=allalso warns about class member allocation functions. ๐งฑ-Wplacement-new,-Wplacement-new=nโ Warns about placement new expressions with undefined behavior, like constructing an object in a buffer that's smaller than the object's type. For example, the placement new expression below gets flagged, because it tries to construct an array of 64 integers in a buffer that's only 64 bytes large ๐
char buf [64];
new (buf) int[64];
This warning is enabled by default.
-Wplacement-new=1โ This is the default 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 followingnewexpression isn't diagnosed at this level, even though it has undefined behavior according to the C++ standard, because it writes past the end of the one-element array.
struct S { int n, a[1]; };
S *s = (S *)malloc (sizeof *s + 31 * sizeof s->a[0]);
new (s->a)int [32]();
-Wplacement-new=2โ At this level, GCC diagnoses all the same constructs as level 1, plus placement new expressions that construct an object in the last member of a structure, where that member is an array of a single element and the object being constructed is bigger than it. The previous example would get 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]();
-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, for convenience in calculations withvoid *pointers and pointers to functions. In C++, it also warns when an arithmetic operation involvesNULL. This warning is also enabled by-Wpedantic๐งฎ-Wpointer-compareโ Warns if a pointer is compared with a zero character constant. This usually means the pointer was meant to be dereferenced. Like this:
const char *p = foo ();
if (p == '\0')
return 42;
Note that the code above is invalid in C++11. ๐ซ
This warning is enabled by default. ๐
-Wtype-limits๐ โ okay so this one warns when 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 is compared against zero with<or>=. It's also turned on by-Wextra. ๐ง-Wabsolute-value(C and Objective-C only) โ bestie, this one catches you calling a standard absolute-value function when there's a better one for the job ๐ญ. Callingabs(3.14)triggers it, sincefabsis the right call for a double. It also warns when the argument to one of these functions has an unsigned type. You can shut it up with an explicit type cast, and it's enabled by-Wextratoo. ๐-Wcomment,-Wcommentsโ this one is a whole vibe check on comments ๐ซถ. It warns when a/*start sequence shows up inside a/*comment, or when a backslash-newline shows up inside a//comment. It's enabled by-Wall. ๐ธ-Wtrigraphsโ warns if any trigraphs pop up that could change what the program means ๐. Trigraphs inside comments don't get flagged, except the ones that would form escaped newlines. This option is implied by-Wall. If you don't pass-Wall, it's still on unless trigraphs are enabled. Want trigraph conversion without the warnings but still all the other-Wallwarnings? Use-trigraphs -Wall -Wno-trigraphs. The main character move ๐.-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 gets expanded by an#ifdirective. That usage isn't portable, so this one is giving caution ๐. It's also enabled by-Wpedanticand-Wextra.-Wunused-macrosโ warns about macros defined in the main file that never get used ๐งน. A macro counts as used if it's expanded or tested for existence at least once. The preprocessor also warns if the macro hasn't been used by the time it gets redefined or undefined. Built-in macros, macros defined on the command line, and macros defined in include files are not warned about.
Note: If a macro is used, but only inside skipped conditional blocks, the preprocessor still reports it as unused ๐ญ. To dodge the warning in that case, you might improve the scope of the macro's definition, for example by moving it into the first skipped block. Or you could give it a dummy use with something like this:
#if defined the_macro_causing_the_warning
#endif
-Wno-endif-labelsโ this one turns off the warning for when an#elseor an#endifhas text after it ๐. It happens in older programs with code that looks like this:
#if FOO
...
#else FOO
...
#endif FOO
The second and third FOO are supposed to be in comments, so this is an old-school situation. The warning is on by default. ๐
-Wbad-function-cast(C and Objective-C only) โ warns when a function call gets cast to a type it doesn't match. For example, it warns if a call to a function returning an integer type gets cast to a pointer type ๐.-Wc90-c99-compat(C and Objective-C only) โ warns about features that exist in ISO C99 but not in ISO C90 โจ. Think variable length arrays, thelong longtype, thebooltype, compound literals, designated initializers, and so on. This option doesn't care what standards mode you're in. Warnings are disabled in the expression that follows__extension__.-Wc99-c11-compat(C and Objective-C only) โ same energy, but for features in ISO C11 that aren't in ISO C99 ๐. Examples are anonymous structures and unions, the_Atomictype qualifier, the_Thread_localstorage-class specifier, the_Alignasspecifier, theAlignofoperator, the_Generickeyword, and so on. Also independent of the standards mode, and warnings are disabled in the expression that follows__extension__.-Wc11-c2x-compat(C and Objective-C only) โ warns about features in ISO C2X that aren't in ISO C11 ๐ฅ. For instance, it warns about leaving out the string in_Static_assert. 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++ ๐ง. One example is asking for an implicit conversion fromvoid *to a pointer to a non-voidtype.-Wc++11-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning changed between ISO C++ 1998 and ISO C++ 2011 ๐. For example, identifiers that were fine in ISO C++ 1998 but are keywords in ISO C++ 2011. This warning turns on-Wnarrowingand is enabled by-Wall.-Wc++14-compat(C++ and Objective-C++ only) โ same idea, but for changes between ISO C++ 2011 and ISO C++ 2014 ๐. It's enabled by-Wall.-Wc++17-compat(C++ and Objective-C++ only) โ warns about C++ constructs that changed between ISO C++ 2014 and ISO C++ 2017 ๐ฆ. It's enabled by-Wall.-Wcast-qualโ warns whenever a pointer gets cast in a way that drops a type qualifier from the target type ๐ซฃ. For example, it warns if aconst char *gets cast to a plainchar *. It also warns when a cast adds a type qualifier in an unsafe way. Castingchar **toconst char **is unsafe, as you can see here:
/* p is char ** value. */
const char **q = (const char **) p;
/* Assignment of readonly string to const char * is OK. */
*q = "string";
/* Now char** pointer points to read-only memory. */
**p = 'b';
-Wcast-alignโ warns whenever a pointer gets cast so the required alignment of the target goes up ๐. For example, it warns if achar *gets cast to anint *on machines where integers can only be accessed at two- or four-byte boundaries.-Wcast-align=strictโ same warning as above, but stricter ๐ค. It warns whenever a pointer gets cast so the target's required alignment increases, for example achar *cast to anint *, regardless of the target machine.-Wcast-function-typeโ warns when a function pointer gets cast to an incompatible function pointer type ๐งฉ. For casts involving function types with a variable argument list, only the types of the initial arguments that are provided get considered. Any parameter of pointer type matches any other pointer type. Benign differences in integral types get ignored, likeintvs.longon ILP32 targets. Type qualifiers are ignored too. The function typevoid (*) (void)is special and matches everything, so you can use it to suppress this warning. For casts involving pointer to member types, the warning fires whenever the cast changes the pointer to member type. It's enabled by-Wextra. ๐-Wwrite-stringsโ when you're compiling C, string constants get the typeconst char[length]. That way, copying the address of one into a non-constchar *pointer gives you a warning โ ๏ธ. These warnings can catch code that tries to write into a string constant at compile time, but only if you've been super careful withconstin your declarations and prototypes. Otherwise it's just a nuisance, which is 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. ๐-Wcatch-value,-Wcatch-value=n(C++ and Objective-C++ only) โ warns about catch handlers that don't catch via reference ๐. With-Wcatch-value=1(or just-Wcatch-value), it warns about polymorphic class types that get caught by value. With-Wcatch-value=2, it warns about all class types caught by value. With-Wcatch-value=3, it warns about all types that aren't caught by reference.-Wcatch-valueis enabled by-Wall.-Wclobberedโ warns about variables that might get changed bylongjmporvfork๐ต. It's also enabled by-Wextra.-Wconditionally-supported(C++ and Objective-C++ only) โ warns about conditionally-supported constructs, as defined in C++11[intro.defs]โจ.-Wconversionโ warns about implicit conversions that might change a value ๐. That includes conversions between real and integer types, likeabs (x)whenxis adouble. It also covers conversions between signed and unsigned, likeunsigned ui = -1, and conversions to smaller types, likesqrtf (M_PI). It won't warn about explicit casts likeabs ((int) x)orui = (unsigned) -1, or about cases where the conversion doesn't change the value, likeabs (2.0). You can turn off the warnings about signed/unsigned conversions with-Wno-sign-conversion.
For C++, it also warns about confusing overload resolution for user-defined conversions. It warns about conversions that never use a type conversion operator too: conversions to void, to the same type, to a base class, or to a reference to any of those. In C++, warnings about conversions between signed and unsigned integers are disabled by default unless -Wsign-conversion is explicitly enabled. ๐ธ
-Wno-conversion-null(C++ and Objective-C++ only) โ don't warn about conversions betweenNULLand non-pointer types ๐ .-Wconversion-nullis enabled by default.-Wzero-as-null-pointer-constant(C++ and Objective-C++ only) โ warns when a literal0is used as a null pointer constant ๐งผ. This can help when you're converting tonullptrin C++11.-Wsubobject-linkage(C++ and Objective-C++ only) โ warns if a class type has a base or a field whose type uses the anonymous namespace or depends on a type with no linkage ๐ง . If a type A depends on a type B with no linkage or internal linkage, defining it in multiple translation units would be an ODR violation, because the meaning of B is different in each translation unit. If A only shows up in one translation unit, the best way to silence the warning is to give it internal linkage by putting it in an anonymous namespace too. The compiler doesn't give this warning for types defined in the main.Cfile, since those are unlikely to have multiple definitions.-Wsubobject-linkageis enabled by default. ๐-Wdangling-elseโ okay bestie, this one is all about "else" drama ๐ It warns you about code where it's unclear which "if" an "else" branch actually belongs to. Check this out:
{
if (a)
if (b)
foo ();
else
bar ();
}
In C/C++, every "else" belongs to the innermost possible "if", which here is if (b) ๐. That's usually NOT what the programmer meant, even though the indentation says otherwise. When this kind of confusion is possible, GCC warns you as long as this flag is on. To make the warning disappear, add explicit braces around the innermost "if" so the "else" can't possibly belong to the outer one โจ. It looks like this:
{
if (a)
{
if (b)
foo ();
else
bar ();
}
}
This warning gets switched on by -Wparentheses ๐.
-Wdate-timeโ warn me when__TIME__,__DATE__or__TIMESTAMP__show up, because they can stop your builds from being bit-wise-identical and reproducible ๐ฐ๏ธ-Wdelete-incomplete(C++ and Objective-C++ only) โ warns when you delete a pointer to an incomplete type, which can cause undefined behavior at runtime ๐ฌ This one is enabled by default, so you get it for free ๐-Wuseless-cast(C++ and Objective-C++ only) โ warns when you cast an expression to its own type. Literally pointless, no cap ๐-Wempty-bodyโ warns if there's an empty body in an "if", "else" or "do while" statement. This one is also turned on by-Wextra๐งน-Wenum-compareโ warns about comparing values from different enumerated types. In C++, enum mismatches in conditional expressions get flagged too, and the warning is on by default there. In C, it's turned on by-Wall๐-Wextra-semi(C++, Objective-C++ only) โ warns about a redundant semicolon after an in-class function definition. Tiny little extra semicolon, big energy ๐ญ-Wjump-misses-init(C, Objective-C only) โ warns if agotoor aswitchjumps forward across the initialization of a variable, or jumps backward to a label after that variable has already been initialized ๐ฆ It only cares about variables that get initialized when they're declared. This warning is only supported for C and Objective-C. In C++, this kind of branch is an error anyway, so it doesn't matter there ๐ โโ๏ธ
-Wjump-misses-init is included in -Wc++-compat. You can turn it off with the -Wno-jump-misses-init option ๐ธ
-Wsign-compareโ warns when comparing signed and unsigned values could give you a wrong answer, because the signed value gets converted to unsigned. In C++, this is also enabled by-Wall. In C, it's also enabled by-Wextra๐ง-Wsign-conversionโ warns about implicit conversions that might flip the sign of an integer, like assigning a signed integer expression to an unsigned integer variable. An explicit cast quiets the warning ๐คซ In C, this option is also enabled by-Wconversion.-Wfloat-conversionโ warns about implicit conversions that drop the precision of a real value. That includes real-to-integer conversions, and conversions from higher precision real values to lower precision ones ๐ This option is also enabled by-Wconversion.-Wno-scalar-storage-orderโ nah, don't warn me about sketchy constructs involving reverse scalar storage order ๐ โโ๏ธ-Wsized-deallocation(C++ and Objective-C++ only) โ warns about defining an unsized deallocation function like this:
void operator delete (void *) noexcept;
void operator delete[] (void *) noexcept;
โฆwithout also defining the matching sized deallocation function, like this:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
Or the other way around, too ๐ This one gets enabled by -Wextra along with -fsized-deallocation ๐
-Wsizeof-pointer-divโ warns about suspicious divisions of twosizeofexpressions that divide the pointer size by the element size. That's the usual trick for computing an array's size, but it won't work out right with pointers ๐ต For example, it warns aboutsizeof (ptr) / sizeof (ptr[0])whenptris a pointer and not an array. This warning is enabled by-Wall๐-Wsizeof-pointer-memaccessโ warns about sketchy 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 and not an array. It'll even suggest a possible fix. It also triggers on something likememcpy (&foo, ptr, sizeof (&foo));๐ง
It also warns about calls to bounded string copy functions like strncat or strncpy that use a sizeof expression of the source array as their bound. In the example below, the strncat call uses the size of the source string as its bound. That's almost certainly a mistake, so the call gets flagged ๐ฉ
void make_file (const char *name)
{
char path[PATH_MAX];
strncpy (path, name, sizeof path - 1);
strncat (path, ".text", sizeof ".text");
...
}
This warning is enabled by -Wall โจ
-Wsizeof-array-argumentโ warns when thesizeofoperator gets applied to a parameter that's declared as an array in a function definition. This one is enabled by default for C and C++ programs ๐ซถ-Wmemset-elt-sizeโ warns about suspicious calls to thememsetbuilt-in function. It triggers when the first argument references an array, and the third argument is a number equal to the number of elements but not equal to the array's size in memory. That usually means you forgot to multiply by the element size ๐ This warning is enabled by-Wall.-Wmemset-transposed-argsโ warns about suspicious calls tomemsetwhere the second argument is not zero and the third argument is zero. For example,memset (buf, sizeof buf, 0)gets diagnosed, becausememset (buf, 0, sizeof buf)was what you meant ๐ The diagnostic only fires 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 be mixed up by mistake, so no warning is emitted ๐คทโโ๏ธ This warning is enabled by-Wall.-Waddressโ warns about suspicious uses of memory addresses ๐ That includes using a function's address in a conditional expression, likevoid func(void); if (func), and comparing against the memory address of a string literal, likeif (x == "abc"). These typically mean a programmer error. A function's address always evaluates to true, so using it in a conditional usually means you forgot the parentheses in a function call. Comparing against string literals gives unspecified behavior and isn't portable in C, so the programmer probably meant to usestrcmp๐ This warning is enabled by-Wall.-Waddress-of-packed-memberโ warns when you take the address of a packed member of a struct or union, 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 where a bit-wise operator is probably what you wanted ๐ค It also warns when both operands of a logical operator are the same:
extern int a;
if (a < 0 && a < 0) { ... }
-Wlogical-not-parenthesesโ warns about a logical not used on the left-hand side operand of a comparison. It won't warn if the right operand is considered a boolean expression. Its whole purpose is to catch sus code like this:
int a;
...
if (!a > 1) { ... }
You can suppress the warning by wrapping the left-hand side in parentheses:
if ((!a) > 1) { ... }
This warning is enabled by -Wall ๐
-Waggregate-returnโ warns if any functions that return 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 detects undefined behavior in some statement during one or more of the iterations ๐-Wno-attributesโ don't warn if an unexpected__attribute__gets used, like unrecognized attributes, function attributes applied to variables, etc. This does NOT stop errors for incorrect use of supported attributes, so don't get it twisted ๐-Wno-builtin-declaration-mismatchโ warns if a built-in function is declared with an incompatible signature or as a non-function. It also warns when a built-in function declared with a type that doesn't include a prototype gets called with arguments whose promoted types don't match what the function expects ๐งฉ When-Wextrais specified, it also warns when a built-in function that takes arguments is declared without a prototype. The-Wno-builtin-declaration-mismatchwarning is enabled by default. To avoid it, include the appropriate header so the prototypes of built-in functions are in scope ๐ซง
For example, the memset call below gets diagnosed, because the function expects a value of type size_t as its argument but the type of 32 is int. With -Wextra, the declaration of the function is diagnosed too:
extern void* memset ();
void f (void *d)
{
memset (d, '\0', 32);
}
-Wno-builtin-macro-redefinedโ don't warn if certain built-in macros get redefined. This quiets warnings for redefining__TIMESTAMP__,__TIME__,__DATE__,__FILE__, and__BASE_FILE__๐ท-Wstrict-prototypes(C and Objective-C only) โ warns if a function is declared or defined without specifying its argument types ๐ An old-style function definition is allowed without a warning if it's preceded by a declaration that specifies the argument types โจ-Wold-style-declaration(C and Objective-C only) โ okay so this one is the obsolete-syntax police ๐ฎโโ๏ธโจ. It warns about declarations that the C Standard considers outdated, like when storage-class specifiers such asstaticaren't the very first thing in a declaration. It's also turned on by-Wextra๐ธ.-Wold-style-definition(C and Objective-C only) โ warns if you write an old-style function definition ๐. And it still warns even when there's already a previous prototype, so no sneaking past it ๐ .-Wmissing-parameter-type(C and Objective-C only) โ catches a function parameter that's declared with no type in K&R-style functions. Like this:
void foo(bar) { }
It's also enabled by -Wextra ๐.
-Wmissing-prototypes(C and Objective-C only) โ warns if a global function gets defined without a previous prototype declaration ๐ฆ. This happens even if the definition itself has a prototype. Use it to find global functions that don't have a matching prototype in a header file ๐. This one isn't valid for C++ ๐, because every function declaration there already gives a prototype, and a non-matching one just makes an overload instead of clashing with an earlier declaration. For missing declarations in C++, use-Wmissing-declarationsinstead.-Wmissing-declarationsโ warns if a global function gets defined without a previous declaration, even when the definition itself provides a prototype ๐. This is your go-to for spotting global functions that aren't declared in header files. In C, you won't get warnings for functions that have previous non-prototype declarations, so use-Wmissing-prototypesto catch those missing prototypes. In C++, there are no warnings for function templates, inline functions, or functions in anonymous namespaces ๐ง.-Wmissing-field-initializersโ warns if a struct's initializer is missing some fields ๐. In this example,x.his implicitly zero, so you'll get a warning:
struct s { int f, g, h; };
struct s x = { 3, 4 };
Designated initializers are exempt though ๐ซถ, so this one won't trigger a warning:
struct s { int f, g, h; };
struct s x = { .f = 3, .g = 4 };
In C, the universal zero initializer { 0 } is also safe from this warning:
struct s { int f, g, h; };
struct s x = { 0 };
And in C++, the empty { } initializer doesn't get flagged either, for example:
struct s { int f, g, h; };
s x = { };
This warning is included in -Wextra. If you want the other -Wextra warnings without this one, use -Wextra -Wno-missing-field-initializers ๐.
-Wno-multicharโ stops the warning for multicharacter constants like'FOOF'๐ โโ๏ธ. Those usually mean there's a typo in your code, since their values are implementation-defined and they shouldn't show up in portable code.-Wnormalized=[none|id|nfc|nfkc]โ okay this one is a whole vibe ๐ธ. In ISO C and ISO C++, two identifiers are different if their character sequences are different. But when you use characters outside basic ASCII, two different sequences can look exactly the same ๐. The ISO 10646 standard has normalization rules that turn look-alike sequences into the same sequence, and GCC can warn you when your identifiers haven't been normalized. This option controls that warning.
There are four levels of warning. The default is -Wnormalized=nfc, which warns about any identifier that isn't in the ISO 10646 "C" normalized form, NFC. NFC is the recommended form for most uses, and it's equivalent to -Wnormalized โจ.
Unfortunately, some characters that ISO C and ISO C++ allow in identifiers aren't allowed once they're converted to NFC. So there's no way to use those symbols in portable ISO C or C++ and still have every identifier in NFC ๐ญ. -Wnormalized=id suppresses the warning for those characters. The hope is that future versions of the standards fix this, which is why it isn't the default ๐.
You can switch the warning off for every character with -Wnormalized=none or -Wno-normalized. Only do this if you're using some other normalization scheme (like "D"), because otherwise you can easily create bugs that are literally impossible to see ๐.
Some characters in ISO 10646 have distinct meanings but look identical in some fonts or display methods, especially once formatting is applied ๐ซ . For example, "\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 is kind of like warning about every identifier with the letter O, since it might get confused with the digit 0. So it isn't the default, but it can be a handy local coding convention if your programming environment can't be fixed to display these characters distinctly ๐ง .
-Wno-attribute-warningโ don't warn about using functions declared with the "warning" attribute ๐. This warning is enabled by default. You can use-Wno-attribute-warningto turn off the warning, or-Wno-error=attribute-warningto turn off the error when you compile with the-Werrorflag.-Wno-deprecatedโ don't warn about using deprecated features ๐ฐ๏ธ.-Wno-deprecated-declarationsโ don't warn about uses of functions, variables, and types marked as deprecated with the "deprecated" attribute ๐ฅฑ.-Wno-overflowโ don't warn about compile-time overflow in constant expressions ๐ข.-Wno-odrโ this one warns about One Definition Rule violations during link-time optimization ๐ฆ. It requires-flto-odr-type-mergingto be enabled, and it's on by default.-Wopenmp-simdโ warns if the vectorizer cost model overrides the OpenMP simd directive you set ๐๏ธ. If you want to loosen the cost model, you can use-fsimd-cost-model=unlimited.-Woverride-init(C and Objective-C only) โ warns if an initialized field without side effects gets overridden when you use designated initializers ๐. This warning is included in-Wextra. To get the other-Wextrawarnings without this one, use-Wextra -Wno-override-init.-Woverride-init-side-effects(C and Objective-C only) โ same deal, but for an initialized field with side effects that gets overridden by designated initializers ๐ฅ. This warning is enabled by default.-Wpackedโ warns if a structure has the packed attribute but that attribute doesn't change the layout or size of the structure ๐คทโโ๏ธ. Those structures can end up misaligned for very little benefit. In this code, the variablef.xinstruct baris misaligned, even thoughstruct bardoesn't have the packed attribute itself:
struct foo {
int x;
char a, b, c, d;
} __attribute__((packed));
struct bar {
char z;
struct foo f;
};
-Wpacked-bitfield-compatโ the 4.1, 4.2, and 4.3 series of GCC ignore the packed attribute on bit-fields of typechar๐ฌ. That got fixed in GCC 4.4, but the change can lead to differences in structure layout. GCC tells you when the offset of such a field has changed in GCC 4.4. For example, there's no longer a 4-bit padding between fieldsaandbin this structure:
struct foo
{
char a:4;
char b:8;
} __attribute__ ((packed));
This warning is enabled by default. Use -Wno-packed-bitfield-compat to disable it ๐ซ.
-Wpacked-not-aligned(C, C++, Objective-C and Objective-C++ only) โ warns if a structure field with explicitly specified alignment inside a packed struct or union is misaligned ๐. In this code, you'll get a warning onstruct Sthat looks like "warning: alignment 1 of 'struct S' is less than 8":
struct __attribute__ ((aligned (8))) S8 { char a[8]; };
struct __attribute__ ((packed)) S {
struct S8 s8;
};
This warning is enabled by -Wall ๐.
-Wpaddedโ warns if padding gets added to a structure, either to align one of its elements or to align the whole structure ๐งฉ. Sometimes you can rearrange the fields to reduce the padding, which makes the structure smaller.-Wredundant-declsโ warns if anything gets declared more than once in the same scope ๐. This happens even when multiple declarations are valid and don't change anything.-Wno-restrictโ this is aboutrestrict-qualified parameters (or__restrict-qualified ones in C++) ๐ง. It warns when the object a parameter points to is aliased by another argument, or when copies between those objects overlap. In the example below,strcpytries to truncate the string by replacing its first characters with the last four. But because the call writes the terminating NUL intoa[4], the copies overlap, and the call gets flagged:
void foo (void)
{
char a[] = "abcd1234";
strcpy (a, a + 4);
...
}
The -Wrestrict option can catch some simple overlaps even without optimization, but it works best at -O2 and above. It's included in -Wall ๐.
-Wnested-externs(C and Objective-C only) โ warns if anexterndeclaration shows up inside a function ๐ต๏ธโโ๏ธ.-Wno-inherited-variadic-ctorโ silences warnings about using C++11 inheriting constructors when the base class you're inheriting from has a C variadic constructor ๐. The warning is on by default, since the ellipsis doesn't get inherited.-Winlineโ warns if a function declared asinlinecan't actually be inlined ๐ฆข. Even with this option on, the compiler won't warn about failures to inline functions declared in system headers.
okay so the compiler is out here using a whole pile of heuristics to decide whether it's gonna inline a function ๐ง โจ it looks at how big the function being inlined is and how much inlining has already happened in the current function. so yeah, seemingly tiny changes in your source can make the -Winline warnings pop up or vanish ๐ญ not you, the compiler is just being dramatic ๐
-Wno-invalid-offsetof(C++ and Objective-C++ only) โ ๐ this one shuts up warnings for using theoffsetofmacro on a non-POD type. heads up, the 2014 ISO C++ standard says usingoffsetofon a non-standard-layout type is undefined. but in existing C++ implementations,offsetofusually gives meaningful results anyway. this flag is for the users who know they're writing nonportable code and have deliberately chosen to ignore the warning. the restrictions onoffsetofmight get relaxed in a future version of the C++ standard, so keep an eye on that ๐-Wint-in-bool-contextโ โ ๏ธ warns about sus integer values showing up where booleans are expected. for example,?:conditionals using non-boolean integer constants in a boolean context, likeif (a <= b ? 2 : 3). or left shifting signed integers in a boolean context, likefor (a = 0; 1 << a; a++);. same goes for all kinds of multiplications, no matter the data type. this one is enabled by-Wall๐ฅ-Wno-int-to-pointer-castโ ๐ง suppresses warnings about casts to a pointer type from an integer of a different size. in C++, casting to a pointer type of smaller size is an error, not just a warning.Wint-to-pointer-castis enabled by default.-Wno-pointer-to-int-cast(C and Objective-C only) โ ๐ฆ mutes warnings about casts from a pointer to an integer type of a different size.-Winvalid-pchโ ๐ธ warns if a precompiled header is found in the search path but can't actually be used.-Wlong-longโ ๐ warns if thelong longtype is used. this is enabled by either-Wpedanticor-Wtraditionalin ISO C90 and C++98 modes. if you want those warning messages gone, 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. enabled by either-Wpedanticor-Wtraditional. to inhibit the messages, use-Wno-variadic-macros.-Wvarargsโ ๐ warns upon questionable usage of the macros that handle variable arguments, likeva_start. this one is on by default. to silence it, use-Wno-varargs.-Wvector-operation-performanceโ ๐ฅ warns if a vector operation isn't implemented using the SIMD capabilities of the architecture. honestly mostly useful for performance tuning. a vector operation can be implemented in three ways:- "piecewise", which means the scalar operation is performed on every vector element
- "in parallel", which means the vector operation is implemented using scalars of a wider type, which normally is more performance efficient
- "as a single scalar", which means the vector fits into a scalar type
-Wno-virtual-move-assignโ ๐ suppresses warnings about inheriting from a virtual base with a non-trivial C++11 move assignment operator.
โ ๏ธ this one is dangerous, bestie. if the virtual base is reachable along more than one path, it gets moved multiple times, which can mean both objects end up in the moved-from state. if your move assignment operator is written to avoid moving from a moved-from object, then this warning is safe to disable.
-Wvlaโ ๐ warns if a variable-length array is used in the code.-Wno-vlaprevents the-Wpedanticwarning about the variable-length array.-Wvla-larger-than=byte-sizeโ ๐งฎ if you use this, the compiler warns for declarations of variable-length arrays whose size is either unbounded, or bounded by an argument that lets the array size exceedbyte-sizebytes. it's kinda like how-Walloca-larger-than=byte-sizeworks, just for variable-length arrays instead.
โจ note that GCC may optimize small variable-length arrays of a known value into plain arrays, so this warning may not trigger for those.
โจ -Wvla-larger-than=PTRDIFF_MAX is enabled by default, but it's typically only effective when -ftree-vrp is active, which is the default for -O2 and above.
see also -Walloca-larger-than=byte-size.
-Wno-vla-larger-thanโ ๐ disables-Wvla-larger-than=warnings. this is equivalent to-Wvla-larger-than=SIZE_MAXor larger.-Wvolatile-register-varโ ๐ซถ warns if a register variable is declaredvolatile. thevolatilemodifier doesn't stop every optimization that might eliminate reads and/or writes to register variables. enabled by-Wall.-Wdisabled-optimizationโ ๐ข warns if a requested optimization pass is disabled. this doesn't usually mean anything is wrong with your code, it just means GCC's optimizers can't handle the code effectively. often the problem is that your code is too big or too complex, and GCC refuses to optimize programs when the optimization is likely to take inordinate amounts of time.-Wpointer-sign(C and Objective-C only) โ ๐งท warns for pointer argument passing or assignment with different signedness. this is only supported for C and Objective-C. it's implied by-Walland by-Wpedantic, and you can turn it off with-Wno-pointer-sign.-Wstack-protectorโ ๐ก๏ธ only active when-fstack-protectoris active. it warns about functions that are not protected against stack smashing.-Woverlength-stringsโ ๐ warns about string constants that are longer than the "minimum maximum" length specified in the C standard. modern compilers are generally chill with string constants way longer than that minimum, but very portable programs should avoid longer strings.
the limit applies after string constant concatenation, and it doesn't count the trailing NUL. in C90 the limit was 509 characters, and in C99 it got raised to 4095. C++98 doesn't specify a normative minimum maximum, so overlength strings aren't diagnosed in C++. this option is implied by -Wpedantic, and you can disable it with -Wno-overlength-strings.
-Wunsuffixed-float-constants(C and Objective-C only) โ ๐ข issues a warning for 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 can be useful when you're prepping code to use with theFLOAT_CONST_DECIMAL64pragma from the decimal floating-point extension to C99.-Wno-designated-init(C and Objective-C only) โ ๐ suppresses warnings when a positional initializer is used to initialize a structure that has been marked with thedesignated_initattribute.-Whsaโ ๐งต issues a warning when HSAIL can't be emitted for the compiled function or OpenMP construct.
๐ Options for Debugging Your Program ๐
okay this section is giving main character energy ๐ง to tell GCC to emit extra info for a debugger, you pretty much only need to add -g to your other options in almost all cases.
GCC lets you use -g with -O. ngl the shortcuts taken by optimized code can be surprising ๐ญ some variables you declared may not exist at all, flow of control may briefly move somewhere you didn't expect, some statements may not get executed because they compute constant results or their values are already at hand, and some statements may execute in different places because they've been moved out of loops. but it's still possible to debug optimized output! which makes it reasonable to use the optimizer for programs that might have bugs ๐
if you aren't using some other optimization option, consider using -Og with -g. with no -O option at all, some compiler passes that collect information useful for debugging don't run, so -Og may give you a better debugging experience โจ
-gโ ๐ produces debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF). GDB can work with this debugging information.
on most systems that use stabs format, -g turns on extra debugging information that only GDB can use. that makes debugging work better in GDB, but it 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) ๐
-ggdbโ ๐ produces debugging information for use by GDB. this means it uses the most expressive format available (DWARF, stabs, or the native format if neither of those are supported), including GDB extensions if at all possible ๐ฆ-gdwarf,-gdwarf-versionโ ๐ produces debugging information in DWARF format (if that's supported). the value ofversionmay be either 2, 3, 4 or 5, and the default version for most targets is 4. DWARF Version 5 is only experimental, so be careful ๐งช
with DWARF Version 2, some ports require and always use some non-conflicting DWARF 3 extensions in the unwind tables.
Version 4 may require GDB 7.0 and -fvar-tracking-assignments for maximum benefit.
๐ซ GCC no longer supports DWARF Version 1, which is substantially different from Version 2 and later. for historical reasons, some other DWARF-related options such as -fno-dwarf2-cfi-asm) still have a reference to DWARF Version 2 in their names, but they apply to all currently-supported versions of DWARF.
-gstabsโ ๐ produces debugging information in stabs format (if that's supported), without GDB extensions. this is the format DBX uses on most BSD systems. on MIPS, Alpha and System V Release 4 systems, this option produces stabs debugging output that DBX doesn't understand. on System V Release 4 systems this option requires the GNU assembler.-gstabs+โ ๐ง produces debugging information in stabs format (if that's supported), using GNU extensions that only the GNU debugger (GDB) understands. using these extensions is likely to make other debuggers crash or refuse to read the program.-gxcoffโ ๐ฅ๏ธ produces debugging information in XCOFF format (if that's supported). this is the format the DBX debugger uses on IBM RS/6000 systems.-gxcoff+โ okay bestie, this one spits out debug info in XCOFF format (if your setup supports it ๐ ) using GNU extensions that ONLY the GNU debugger (GDB) understands ๐. Heads up though: other debuggers might crash or straight up refuse to read your program ๐, and assemblers that aren't the GNU assembler (GAS) could throw an error at you.-gvmsโ produces debug info in the Alpha/VMS debug format (if it's supported) ๐ฆ. This is the format DEBUG uses on Alpha/VMS systems, so it's very much their thing โจ.-glevel,-ggdblevel,-gstabslevel,-gxcofflevel,-gvmslevelโ requests debug info AND lets you pick how much you want ๐. The default level is2๐.- Level
0gives you zero debug info, so-g0cancels out-g๐ โโ๏ธ. - Level
1is the minimal, lowkey version ๐ธ. It's enough to make backtraces in the parts you're not planning to debug. You get descriptions of functions and external variables plus line number tables, but NO info about local variables. - Level
3goes extra ๐ง, including stuff like all the macro definitions present in the program. Some debuggers can even do macro expansion when you use-g3๐ฅ. - If you stack up multiple
-goptions, with or without level numbers, the LAST one is the one that counts ๐. - > Quick heads up:
-gdwarfwon't accept a concatenated debug level, so nobody gets confused with-gdwarf-level. Instead, add an extra-gleveloption to change the debug level for DWARF ๐ซถ.
- Level
-feliminate-unused-debug-symbolsโ produces debug info in stabs format (if that's supported), but ONLY for symbols that are actually used ๐งน.-femit-class-debug-alwaysโ instead of putting the debug info for a C++ class in just one object file, this emits it in every object file that uses the class ๐ฆ. Only use this with debuggers that can't handle how GCC normally does it ๐. It's a big ask, too: it can make the debug info up to a factor of two bigger ๐ญ.-fno-merge-debug-stringsโ tells the linker NOT to merge together strings in the debug info that are identical across different object files ๐งต. Not every assembler or linker supports merging anyway. Merging shrinks the debug info in your output file, but the tradeoff is slower link time โณ. Merging is on by default, btw ๐ .-fdebug-prefix-map=old=newโ when you compile files living in directoryold, the debug info describes them as if they lived in directorynewinstead ๐บ๏ธ. This is perfect for swapping a build-time path for an install-time path. You can also turn an absolute path into a relative one by using.fornew๐ฟ. It can give you more reproducible builds that don't depend on location ๐, but you might need an extra command to tell GDB where to find the source files ๐. See also-ffile-prefix-map.-fvar-trackingโ runs the variable tracking pass ๐ต๏ธโโ๏ธ. It figures out where variables are stored at each position in the code, so the debug info can be better (if your debug info format supports that). It's turned on by default when you compile with optimization (-Os,-O,-O2, ...), debug info (-g), and a format that supports it ๐ฏ.-fvar-tracking-assignmentsโ annotates assignments to user variables early in compilation, then tries to carry those annotations all the way to the end ๐. The goal is better debug info while optimizing โจ. Using-gdwarf-4alongside it is recommended ๐. It can be enabled even when var-tracking is disabled, in which case the annotations get created and maintained but tossed at the end ๐๏ธ. By default this flag rides along with-fvar-tracking, EXCEPT when selective scheduling is enabled ๐ โโ๏ธ.-gsplit-dwarfโ separates as much DWARF debug info as possible into its own output file with the.dwoextension ๐. This lets your build system skip linking files that have debug info, which is so helpful ๐. To be useful though, you need a debugger that can read.dwofiles ๐ง.-gdescribe-diesโ adds description attributes to some DWARF DIEs that don't have a name attribute ๐ท๏ธ. Examples are artificial variables, external references, and call site parameter DIEs ๐งฉ.-gpubnamesโ generates the DWARF".debug_pubnames"and".debug_pubtypes"sections ๐.-ggnu-pubnamesโ generates".debug_pubnames"and".debug_pubtypes"sections in a format that's ready to be converted into a GDB index ๐๏ธ. This is only useful with a linker that can produce GDB index version 7 ๐ง .-fdebug-types-sectionโ when you're using DWARF Version 4 or higher, type DIEs can get their own".debug_types"section instead of living inside".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_types"sections yet, and on some objects it makes the debug info bigger instead of smaller ๐ฌ.-grecord-gcc-switches,-gno-record-gcc-switchesโ this one tacks the command-line options that might affect code generation onto theDW_AT_producerattribute in the 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 of storing compiler options in the object file ๐ .-gstrict-dwarfโ no cap, this one disallows using extensions from a later DWARF standard version than the one you picked with-gdwarf-version๐ซ. On most targets, using non-conflicting DWARF extensions from later standard versions is allowed anyway ๐.-gno-strict-dwarfโ the opposite energy ๐ฆ: it 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".loc"directives ๐. The compiler can then use them so the assembler generates DWARF2+ line number tables for you ๐. This is usually the move, because assembler-generated line number tables are a LOT more compact than the ones the compiler can make itself ๐ค. This option gets turned on by default if the assembler was found to support those directives at GCC configure time โ๏ธ.-gno-as-loc-supportโ forces GCC to generate DWARF2+ line number tables internally, if they're going to be generated at all ๐ ๏ธ.gas-locview-supportโ tells the compiler the assembler supports"view"assignment and reset assertion checking in".loc"directives ๐. This is enabled by default if the assembler was found to support them at GCC configure time ๐.gno-as-locview-supportโ forces GCC to assign view numbers internally, but only if-gvariable-location-viewshas been explicitly requested ๐ซ .-gcolumn-info,-gno-column-infoโ emits location column information into the DWARF debug info, not just the file and line ๐. It's enabled by default ๐.-gstatement-frontiers,-gno-statement-frontiersโ this makes GCC drop markers into the internal representation at the beginning of statements ๐. It keeps them roughly in place all through compilation, and uses them to guide the output of"is_stmt"markers in the line number table ๐งญ. This is enabled by default when you compile with optimization (-Os,-O,-O2, ...) AND output DWARF 2 debug info at the normal level ๐ฏ.-gvariable-location-views,-gvariable-location-views=incompat5,-gno-variable-location-viewsโ this one augments variable location lists with progressive view numbers, implied from the line number table ๐ข. The payoff is that debug info consumers can inspect state at certain points in the program, even when no instructions linked to those source locations exist there ๐โจ. If the assembler doesn't support view numbers in line number tables, the compiler ends up emitting the line number table itself, which makes them somewhat less compact ๐. The augmented line number tables and location lists are fully backward-compatible, so consumers that don't know about these augmentations can still read them, they just won't get any benefit 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. Without assembler support it may still be enabled, but it forces GCC to output internal line number tables. And if -ginternal-reset-location-views isn't enabled, that will most certainly lead to silently mismatching location views ๐.
Careful with -gvariable-location-views=incompat5! It's a proposed representation for view numbers that is NOT backward compatible with the location list format introduced in DWARF 5 โ ๏ธ. It may be removed in the future and is only provided as a reference implementation of the proposed representation ๐งช. Debug info consumers aren't expected to support this extended format, and they'd be unable to decode location lists that use it ๐ญ.
-ginternal-reset-location-views,-gno-internal-reset-location-viewsโ this attempts to figure out which location views can be left out of location view lists ๐ง. It requires the compiler to have very accurate instruction length estimates, which isn't always the case ๐. When using an assembler that doesn't support location view lists, it may silently generate incorrect 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 are 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]โ okay so this one makes compressed debug sections in DWARF format, if that's supported ๐๏ธ If you don't give atype, the default depends on what your assembler and linker can handle. Thetypecan benone(don't compress debug sections),zlib(zlib compression in ELF gABI format), orzlib-gnu(zlib compression in traditional GNU format). If the linker can't write compressed debug sections, the option gets rejected. Otherwise, if the assembler doesn't support them,-gzis silently ignored when producing object files ๐ซ-femit-struct-debug-baseonlyโ bestie, this one only emits debug info for struct-like types when the base name of the compilation source file matches the base name of the file where the struct is defined ๐ It substantially shrinks the debug info, but there's significant potential loss in type information for the debugger ๐ See-femit-struct-debug-reducedfor a less aggressive option, and-femit-struct-debug-detailedfor more detailed control. This option works only with DWARF debug output.-femit-struct-debug-reducedโ a middle-ground vibe โจ It emits debug info for struct-like types only when the base name of the compilation source file matches the base name of the file where the type is defined, unless the struct is a template or defined in a system header. It significantly shrinks the debug info, with some potential loss in type information to the debugger. See-femit-struct-debug-baseonlyfor a more aggressive option, and-femit-struct-debug-detailedfor more detailed control. This option works only with DWARF debug output.
-femit-struct-debug-detailed[=spec-list]
okay this is the detailed, customizable one ๐ฆ It lets you pick exactly which struct-like types get debug info. The whole point is to cut down on duplicate struct debug info between different object files in the same program ๐
It's a detailed version of -femit-struct-debug-reduced and -femit-struct-debug-baseonly, and it covers most needs.
A specification has the syntax:
[dir:|ind:][ord:|gen:](any|sys|base|none)
The optional first word limits the spec to structs that are used directly (dir:) or used indirectly (ind:). A struct type is used directly when it's the type of a variable or member. Indirect uses come through pointers to structs. In other words, when using an incomplete struct is valid, the use is indirect. For example:
struct one direct;
struct two * indirect;
The optional second word limits the spec to ordinary structs (ord:) or generic structs (gen:). Generic structs are a bit tricky to explain ๐ For C++, these are non-explicit specializations of template classes, or non-template classes within the above. Other programming languages have generics, but -femit-struct-debug-detailed does not yet implement them.
The third word specifies the source files for the structs that should get debug info. The values none and any have their normal meaning. The value base means the base of the name of the file where the type declaration appears must match the base of the name of the main compilation file. In practice, that means when compiling foo.c, debug info is generated for types declared in that file and foo.h, but not other header files ๐ง The value sys means those types satisfying base or declared in system or compiler headers.
You may need to experiment to find the best settings for your app ๐ฅ
The default is -femit-struct-debug-detailed=all. This option works only with DWARF debug output.
-fno-dwarf2-cfi-asmโ emits DWARF unwind info as a compiler-generated.eh_framesection, instead of using GAS.cfi_*directives ๐-fno-eliminate-unused-debug-typesโ normally, when producing DWARF output, GCC skips debug symbol output for types that are nowhere used in the source file being compiled ๐งน Sometimes you actually want debug info for every type declared in a compilation unit, even unused ones. For example, if you want to cast a value to a type in the debugger that's declared but never used in your program. More often though, this just wastes a ton of space ๐
โจ Options That Control Optimization โจ
these options control various sorts of optimizations ๐
Without any optimization option, the compiler's goal is to reduce the cost of compilation and make debugging produce the expected results. Statements are independent: if you stop the program with a breakpoint between statements, you can assign a new value to any variable or change the program counter to any other statement in the function, and get exactly the results you expect from the source code ๐ฏ
Turning on optimization flags makes the compiler attempt to improve performance and/or code size, at the expense of compilation time and possibly your ability to debug the program ๐ซถ
The compiler performs optimization based on what it knows about the program. Compiling multiple files at once to a single output file mode lets the compiler use info gathered from all the files when compiling each of them โจ
Not all optimizations are controlled directly by a flag. Only optimizations that have a flag are listed in this section.
Most optimizations are completely disabled at -O0, or if an -O level isn't set on the command line, even if individual optimization flags are specified ๐
โโ๏ธ Similarly, -Og suppresses many optimization passes.
Depending on the target and how GCC was configured, a slightly different set of optimizations may be enabled at each -O level than the ones listed here. You can invoke GCC with -Q --help=optimizers to find out the exact set enabled at each level ๐
-O, -O1
Optimize ๐ธ Optimizing compilation takes somewhat more time, and a lot more memory for a large function.
With -O, the compiler tries to reduce code size and execution time, without performing any optimizations that take a great deal of compilation time.
-O turns on the following optimization flags:
-fauto-inc-dec -fbranch-count-reg -fcombine-stack-adjustments
-fcompare-elim -fcprop-registers -fdce -fdefer-pop -fdelayed-branch
-fdse -fforward-propagate -fguess-branch-probability -fif-conversion
-fif-conversion2 -finline-functions-called-once -fipa-profile
-fipa-pure-const -fipa-reference -fipa-reference-addressable
-fmerge-constants -fmove-loop-invariants -fomit-frame-pointer
-freorder-blocks -fshrink-wrap -fshrink-wrap-separate
-fsplit-wide-types -fssa-backprop -fssa-phiopt -ftree-bit-ccp
-ftree-ccp -ftree-ch -ftree-coalesce-vars -ftree-copy-prop
-ftree-dce -ftree-dominator-opts -ftree-dse -ftree-forwprop
-ftree-fre -ftree-phiprop -ftree-pta -ftree-scev-cprop -ftree-sink
-ftree-slsr -ftree-sra -ftree-ter -funit-at-a-time
-O2
Optimize even more ๐ฅ GCC performs nearly all supported optimizations that don't involve a space-speed tradeoff. Compared to -O, this option increases both compilation time and the performance of the generated code.
-O2 turns on all optimization flags specified by -O. It also turns on the following optimization flags:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fcaller-saves -fcode-hoisting -fcrossjumping -fcse-follow-jumps
-fcse-skip-blocks -fdelete-null-pointer-checks -fdevirtualize
-fdevirtualize-speculatively -fexpensive-optimizations -fgcse
-fgcse-lm -fhoist-adjacent-loads -finline-small-functions
-findirect-inlining -fipa-bit-cp -fipa-cp -fipa-icf -fipa-ra
-fipa-sra -fipa-vrp -fisolate-erroneous-paths-dereference
-flra-remat -foptimize-sibling-calls -foptimize-strlen
-fpartial-inlining -fpeephole2 -freorder-blocks-algorithm=stc
-freorder-blocks-and-partition -freorder-functions
-frerun-cse-after-loop -fschedule-insns -fschedule-insns2
-fsched-interblock -fsched-spec -fstore-merging -fstrict-aliasing
-fthread-jumps -ftree-builtin-call-dce -ftree-pre
-ftree-switch-conversion -ftree-tail-merge -ftree-vrp
Please note the warning under-fgcseabout invoking-O2on programs that use computed gotos ๐
NOTE: In Ubuntu 8.10 and later versions,-D_FORTIFY_SOURCE=2is set by default, and is activated when-Ois set to 2 or higher. This enables additional compile-time and run-time checks for several libc functions. To disable it, specify either-U_FORTIFY_SOURCEor-D_FORTIFY_SOURCE=0๐ก๏ธ
-O3
Optimize yet more ๐
-O3 turns on all optimizations specified by -O2, and also turns on the following optimization flags:
-fgcse-after-reload -finline-functions -fipa-cp-clone
-floop-interchange -floop-unroll-and-jam -fpeel-loops
-fpredictive-commoning -fsplit-paths -ftree-loop-distribute-patterns
-ftree-loop-distribution -ftree-loop-vectorize -ftree-partial-pre
-ftree-slp-vectorize -funswitch-loops -fvect-cost-model
-fversion-loops-for-strides
-O0
Reduce compilation time and make debugging produce the expected results ๐ This is the default.
-Os
Optimize for size ๐ท -Os enables all -O2 optimizations except the ones that often increase code size:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fprefetch-loop-arrays -freorder-blocks-algorithm=stc
It also enables -finline-functions, causes the compiler to tune for code size rather than execution speed, and performs further optimizations designed to reduce code size ๐งธ
-Ofast
Disregard strict standards compliance ๐ -Ofast enables all -O3 optimizations. It also enables optimizations that are not valid for all standard-compliant programs. It turns on -ffast-math and the Fortran-specific -fstack-arrays, unless -fmax-stack-var-size is specified, and -fno-protect-parens.
Heads up bestie โ ๏ธ -Ofast enables optimizations that are not valid for all standard-compliant programs, so only reach for it when you know your code can handle that ๐ญ
-Og
Optimize debugging experience ๐ฆ -Og should be the optimization level of choice for the standard edit-compile-debug cycle. It offers a reasonable level of optimization while keeping compilation fast and the debugging experience good โจ It's a better choice than -O0 for producing debuggable code, because some compiler passes that collect debug information are disabled at -O0.
Okay so -Og is lowkey the debugging girlie option ๐ฆ Like -O0, it completely turns off a bunch of optimization passes, so the individual options that control those passes do literally nothing ๐ Otherwise -Og switches on every -O1 optimization flag EXCEPT the ones that could interfere with debugging ๐ Those are:
-fbranch-count-reg -fdelayed-branch -fif-conversion
-fif-conversion2 -finline-functions-called-once
-fmove-loop-invariants -fssa-phiopt -ftree-bit-ccp -ftree-pta
-ftree-sra
Bestie, if you stack up multiple -O options, with or without level numbers, only the last one is the one that slays โจ Everything before it gets ignored ๐
Options of the form -fflag are machine-independent flags ๐ Most of them have a positive and a negative form, and the negative form of -ffoo is -fno-foo. In the list below, only one form is shown, the one you'll usually reach for. You can figure out the other one just by removing no- or adding it ๐ซถ
These options control specific optimizations. They're either switched on by -O options or they're related to ones that are ๐ธ Only pull out these "fine-tuning" flags in the rare cases where you actually want to tweak which optimizations get performed ๐
-fno-defer-popโ On machines that have to pop arguments after a function call, this makes the compiler pop them the second each function returns. At-O1and higher,-fdefer-popis already the default, which lets arguments pile up on the stack across several function calls and get popped all at once ๐งน-fforward-propagateโ 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 get performed, and the second one is scheduled after loop unrolling. This option is enabled by default at optimization levels-O,-O2,-O3,-Os.-ffp-contract=styleโ-ffp-contract=offdisables floating-point expression contraction ๐ซ-ffp-contract=fastturns contraction on, like forming fused multiply-add operations if the target natively supports them ๐ฅ-ffp-contract=onturns contraction on only if the language standard allows it. Heads up, this one is currently not implemented and gets treated the same as-ffp-contract=off๐ The default is-ffp-contract=fast.-fomit-frame-pointerโ Omits the frame pointer in functions that don't need one, skipping the instructions that save, set up and restore it โ๏ธ On many targets this also frees up an extra register ๐ On some targets this flag does nothing, because the standard calling sequence always uses a frame pointer, so it can't be omitted. Also,-fno-omit-frame-pointerdoesn't guarantee the frame pointer gets used in all functions, since several targets always omit it in leaf functions. Enabled by default at-Oand higher.-foptimize-sibling-callsโ Optimizes sibling and tail recursive calls ๐ฆ Enabled at levels-O2,-O3,-Os.-foptimize-strlenโ Optimizes various standard C string functions (e.g.strlen,strchrorstrcpy) and their_FORTIFY_SOURCEcounterparts into faster alternatives ๐๏ธ Enabled at levels-O2,-O3.-fno-inlineโ Doesn't expand any functions inline, except the ones marked with thealways_inlineattribute ๐ โโ๏ธ This is the default when you're not optimizing. If you want to exempt a single function from inlining, mark it with thenoinlineattribute.-finline-small-functionsโ Integrates functions into their callers when their body is smaller than the expected function call code, so the overall program size gets smaller ๐ The compiler heuristically decides which functions are simple enough to be worth it. This applies to ALL functions, even ones not declared inline. Enabled at levels-O2,-O3,-Os.-findirect-inliningโ Inlines indirect calls that are discovered to be known at compile time, thanks to previous inlining ๐ง This option only has an effect when inlining itself is turned on by the-finline-functionsor-finline-small-functionsoptions. Enabled at levels-O2,-O3,-Os.-finline-functionsโ Considers all functions for inlining, even if they aren't declared inline ๐ The compiler heuristically decides which ones are worth integrating. If all calls to a given function get integrated and the function is declaredstatic, then it's normally not output as assembler code in its own right. Enabled at levels-O3,-Os. Also enabled by-fprofile-useand-fauto-profile.-finline-functions-called-onceโ Considers allstaticfunctions that get called once for inlining into their caller, even if they aren't markedinline๐ If a call to a given function gets integrated, the function isn't output as assembler code on its own. Enabled at levels-O1,-O2,-O3and-Os, but NOT-Og.-fearly-inliningโ Inlines functions marked byalways_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 on programs with big chains of nested wrapper functions ๐ Enabled by default.-fipa-sraโ Performs interprocedural scalar replacement of aggregates, removes unused parameters, and replaces parameters passed by reference with parameters passed by value ๐งฝ Enabled at levels-O2,-O3and-Os.-finline-limit=nโ By default GCC limits how big a function can be and still get inlined ๐ This flag gives you coarse control over that limit.nis the size of functions that can be inlined, measured in pseudo instructions. Inlining is actually controlled by a bunch of parameters, which you can set one at a time with--param name=value. The-finline-limit=noption sets some of them for you, like so:max-inline-insns-singleis set ton/2.max-inline-insns-autois set ton/2.
Check out the docs for the individual inlining parameters below for their defaults ๐
Note: there may be NO value of -finline-limit that gives you default behavior ๐
Note: a "pseudo instruction" here is just an abstract measurement of a function's size ๐ซ It is in NO way a count of assembly instructions, so what it means could change from one release to another.
-fno-keep-inline-dllexportโ A more fine-grained version of-fkeep-inline-functions, and it only applies to functions declared with thedllexportattribute or declspec ๐ง-fkeep-inline-functionsโ In C, emitsstaticfunctions that are declaredinlineinto the object file, even if they've been inlined into all of their callers ๐ฆ This switch doesn't affect functions using theextern inlineextension in GNU C90. In C++, it emits any and all inline functions into the object file.-fkeep-static-functionsโ Emitsstaticfunctions into the object file, even if they're never used ๐๏ธ-fkeep-static-constsโ Emits variables declaredstatic constwhen optimization isn't turned on, even if they aren't referenced ๐ GCC enables this option by default. If you want the compiler to check whether a variable is referenced no matter what optimization is on, use-fno-keep-static-consts.-fmerge-constantsโ Attempts to merge identical constants (string constants and floating-point constants) across compilation units ๐งฉ This is the default for optimized compilation if the assembler and linker support it. Use-fno-merge-constantsto stop this from happening. Enabled at levels-O,-O2,-O3,-Os.-fmerge-all-constantsโ Attempts to merge identical constants AND identical variables ๐ซฃ This option implies-fmerge-constants. On top of that, it also considers things like constant initialized arrays, or initialized constant variables with integral or floating-point types.
Big warning, bestie โ ๏ธ C and C++ require each variable, including multiple instances of the same variable in recursive calls, to have distinct locations. Using this option results in non-conforming behavior, so it's NOT it for standards-compliant code ๐จ
-fmodulo-schedโ Performs swing modulo scheduling right 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 when-fmodulo-schedis enabled.-fno-branch-count-regโ Disables the optimization pass that hunts for chances to use "decrement and branch" instructions on a count register. The alternative is instruction sequences that decrement a register, compare it against zero, and then branch based on the result ๐ข This option only means something on architectures that support such instructions, which include x86, PowerPC, IA-64 and S/390. Note that-fno-branch-count-regdoesn't remove the decrement and branch instructions introduced by other optimization passes ๐ The default is-fbranch-count-regat-O1and higher, except for-Og.-fno-function-cseโ Doesn't put function addresses in registers. Instead, each instruction that calls a constant function contains the function's address explicitly ๐ This makes the code less efficient, but some strange hacks that alter the assembler output might get confused by the optimizations that happen when this option isn't used ๐งช The default is-ffunction-cse-fno-zero-initialized-in-bssโ When 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 behavior OFF, because some programs explicitly rely on variables going into the data section ๐งธ For example, the executable might want to find the beginning of that section and/or make assumptions based on it. The default is-fzero-initialized-in-bss.-fthread-jumps
Okay so this one is about jump threading, bestie ๐งตโจ. The compiler checks whether a jump lands somewhere that another comparison (one the first comparison already covers) gets tested. If it does, the first branch gets redirected either to the destination of the second branch or to the spot right after it, depending on whether the condition is known to be true or false. Main character optimization energy ๐๐ .
Enabled at levels -O2, -O3, -Os. ๐ธ
-fsplit-wide-types
Bestie, this one is for types that take up multiple registers, like long long on a 32-bit system ๐ซถ. The registers get split apart and allocated independently. This usually gives better code for those types, but it can make debugging more difficult ๐ญ. Lowkey a tradeoff, but the code is usually fire ๐ฅ.
Enabled at levels -O, -O2, -O3, -Os. ๐ฆ
-fcse-follow-jumps
Common subexpression elimination (CSE) is giving detective ๐ต๏ธโโ๏ธ. When it runs into jump instructions, it scans through them as long as the jump's target isn't reached by any other path. Like, when CSE hits an if statement with an else clause, it follows the jump when the condition tested is false. It's giving efficiency, no cap ๐.
Enabled at levels -O2, -O3, -Os. โจ
-fcse-skip-blocks
This is basically the cousin of -fcse-follow-jumps ๐ง, but it targets jumps that conditionally skip over blocks. When CSE sees a simple if statement with no else clause, -fcse-skip-blocks tells it to follow the jump around the body of the if. Iconic behavior ๐
.
Enabled at levels -O2, -O3, -Os. ๐
-frerun-cse-after-loop
Okay, this one just runs common subexpression elimination again once the loop optimizations are done ๐๐. Second glow-up, bestie โจ.
Enabled at levels -O2, -O3, -Os. ๐
-fgcse
This turns on a global common subexpression elimination pass ๐. It also handles global constant and copy propagation, so it's doing a lot of work behind the scenes ๐.
Heads up: if you're compiling a program that uses computed gotos (a GCC extension ๐), you might get better run-time performance by disabling this pass with -fno-gcse on the command line. Just something to keep in mind, fr fr ๐.
Enabled at levels -O2, -O3, -Os. ๐ฆ
-fgcse-lm
When -fgcse-lm is on, global common subexpression elimination tries to move loads that only get killed by stores into themselves ๐งฒ. This lets a loop with a load/store sequence become a load outside the loop and a copy/store inside it. Lowkey genius ๐ซถ.
Enabled by default when -fgcse is enabled. ๐ธ
-fgcse-sm
When -fgcse-sm is enabled, a store motion pass runs after global common subexpression elimination โจ. It tries to move stores out of loops. When it's used together with -fgcse-lm, loops containing a load/store sequence can become a load before the loop and a store after it. Store motion, but make it aesthetic ๐.
Not enabled at any optimization level. ๐ฅ
-fgcse-las
When -fgcse-las is enabled, the global common subexpression elimination pass gets rid of redundant loads that come after stores to the same memory location ๐งน. That covers both partial and full redundancies. Decluttering era ๐ท.
Not enabled at any optimization level. ๐ฅ
-fgcse-after-reload
When -fgcse-after-reload is enabled, a redundant load elimination pass runs after reload ๐. Its whole purpose is to clean up redundant spilling. Spring cleaning but for registers ๐ธ๐งผ.
Enabled by -fprofile-use and -fauto-profile. ๐ฆ
-faggressive-loop-optimizations
This one tells the loop optimizer to use language constraints to figure out bounds for how many times a loop iterates ๐ข. It assumes that loop code does not invoke undefined behavior, like causing signed integer overflows or out-of-bound array accesses ๐ซ. Those bounds then guide loop unrolling, loop peeling, and loop exit test optimizations. This option is enabled by default, so you're already getting the glow-up ๐โจ.
-funconstrained-commons
This tells the compiler that variables declared in common blocks (for example, Fortran) might later get overridden with longer trailing arrays ๐. It stops certain optimizations that depend on knowing the array bounds, so it's a bit of a trade-off ๐.
-fcrossjumping
This performs the cross-jumping transformation ๐งฉ. It unifies equivalent code and saves code size, which is very low-key iconic ๐ . The resulting code may or may not perform better than without cross-jumping, so it's not a guaranteed win ngl ๐คทโโ๏ธ.
Enabled at levels -O2, -O3, -Os. ๐
-fauto-inc-dec
This combines increments or decrements of addresses with memory accesses โ๐ง . The pass is always skipped on architectures that don't have instructions to support it. It's enabled by default at -O and higher on architectures that do support it ๐.
-fdce
This performs dead code elimination (DCE) on RTL ๐๏ธ. It's enabled by default at -O and higher, so it's basically on the reg ๐.
-fdse
This performs dead store elimination (DSE) on RTL ๐งฝ. It's enabled by default at -O and higher. Clean girl energy, fr ๐ซง.
-fif-conversion
This tries to transform conditional jumps into branch-less equivalents ๐. That includes conditional moves, min, max, set flags, abs instructions, and some tricks you can do with standard arithmetic. Whether conditional execution gets used on chips that support it is controlled by -fif-conversion2 ๐.
Enabled at levels -O, -O2, -O3, -Os, but not with -Og. ๐ซ๐ฆ
-fif-conversion2
This uses conditional execution (where the hardware has it) to transform conditional jumps into branch-less equivalents ๐งโโ๏ธ.
Enabled at levels -O, -O2, -O3, -Os, but not with -Og. ๐ซ๐ธ
-fdeclone-ctor-dtor
Okay, C++ ABI moment ๐ค. The ABI requires multiple entry points for constructors and destructors: one for a base subobject, one for a complete object, and one for a virtual destructor that calls operator delete afterwards ๐ฆ. For a hierarchy with virtual bases, the base and complete variants are clones, which means two copies of the same function ๐ฏโโ๏ธ. With this option, those base and complete variants become thunks that call a common implementation, so you're not stuck with duplicate copies. Smaller code, bestie ๐.
Enabled by -Os. ๐ท
-fdelete-null-pointer-checks
This assumes that programs cannot safely dereference null pointers, and that no code or data element lives at address zero ๐ โโ๏ธ. It enables simple constant folding optimizations at all optimization levels. Other GCC passes also use this flag to control global dataflow analyses that eliminate useless null pointer checks ๐งน. These assume that a memory access to address zero always results in a trap, so if a pointer gets checked after it's already been dereferenced, it can't be null ๐คฏ.
Note however that in some environments this assumption is not true. If your program depends on that behavior, use -fno-delete-null-pointer-checks to disable this optimization ๐จ.
This option is enabled by default on most targets. On Nios II ELF, it defaults to off. On AVR, CR16, and MSP430, this option is completely disabled ๐.
Passes that use the dataflow information are enabled independently at different optimization levels ๐ .
-fdevirtualize
This tries to convert calls to virtual functions into direct calls ๐. It does this both within a procedure and interprocedurally, as part of indirect inlining (-findirect-inlining) and interprocedural constant propagation (-fipa-cp) ๐ฎ. Enabled at levels -O2, -O3, -Os. ๐ฆ
-fdevirtualize-speculatively
This tries to convert calls to virtual functions into speculative direct calls ๐ฒ. Based on the analysis of the type inheritance graph, it figures out the set of 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 ๐. The speculative calls enable more optimizations, like inlining ๐. If they seem useless after further optimization, they get converted back to their original form ๐.
-fdevirtualize-at-ltrans
This streams extra information needed for aggressive devirtualization when the link-time optimizer runs in local transformation mode ๐ก. It enables more devirtualization, but it significantly increases the size of the streamed data ๐. Because of that, it's disabled by default ๐ญ.
-fexpensive-optimizations
This performs a bunch of minor optimizations that are relatively expensive โณ. Enabled at levels -O2, -O3, -Os. ๐
-free
This attempts to remove redundant extension instructions โ๏ธ. It's especially helpful for the x86-64 architecture, which implicitly zero-extends 64-bit registers after writing to their lower 32-bit half ๐ง .
Enabled for Alpha, AArch64 and x86 at levels -O2, -O3, -Os. ๐
-fno-lifetime-dse
In C++, an object's value is only affected by changes within its lifetime ๐ญ. When the constructor begins, the object has an indeterminate value, and any changes made during its lifetime are dead once the object is destroyed ๐. Normally dead store elimination takes advantage of this. If your code relies on the value of the object storage sticking around after the object's lifetime ends, you can use this flag to turn the optimization off ๐. To keep stores made before the constructor starts (for example, because your operator new clears the object storage) but still treat the object as dead after the destructor, you can use -flifetime-dse=1 ๐งฉ. The default behavior can be explicitly selected with -flifetime-dse=2 ๐ฏ. -flifetime-dse=0 is equivalent to -fno-lifetime-dse ๐ซถ.
-flive-range-shrinkage
This attempts to decrease register pressure through register live range shrinkage ๐งโโ๏ธ. It's helpful for fast processors with small or moderate-sized register sets ๐๏ธ.
-fira-algorithm=algorithm
This picks the coloring algorithm used by the integrated register allocator ๐จ. The algorithm argument can be priority, which specifies Chow's priority coloring, or CB, which specifies Chaitin-Briggs coloring ๐๏ธ. Chaitin-Briggs coloring isn't implemented for every architecture, but for targets that do support it, it's the default because it generates better code ๐.
-fira-region=region
This picks which regions the integrated register allocator uses ๐บ๏ธ. The region argument should be one of the following:
allโ Uses all loops as register allocation regions. This can give the best results for machines with a small and/or irregular register set ๐งฉ.mixedโ Uses all loops except for loops with small register pressure as the regions. This value usually gives the best results in most cases and for most architectures, and it's enabled by default when compiling with optimization for speed (-O,-O2, ...) ๐.oneโ Uses all functions as a single region. This typically results in the smallest code size, and it's enabled by default for-Osor-O0๐ธ.
-fira-hoist-pressureโ okay so this one tells IRA to check register pressure during the code hoisting pass when it's deciding whether to hoist expressions ๐ง It usually gives you smaller code, but the compiler can slow down because of it ๐ข Enabled at level-Osfor all targets ๐-fira-loop-pressureโ this one has IRA look at register pressure inside loops when it's deciding whether to move loop invariants ๐ It usually gives faster and smaller code on machines with large register files (>= 32 registers), but the compiler can slow down ๐ Enabled at level-O3for some targets ๐ฆ-fno-ira-share-save-slotsโ the bestie-unfriendly option ๐ It turns OFF sharing of stack slots used for saving call-used hard registers that live through a call. Every hard register gets its own stack slot, so function stack frames end up bigger ๐ฆ-fno-ira-share-spill-slotsโ same energy, different slots ๐ This disables sharing of stack slots for pseudo-registers. Every pseudo-register that doesn't get a hard register gets its own stack slot, and yep, the stack frames get bigger too ๐ญ-flra-rematโ this one is giving CFG-sensitive rematerialization inside LRA โจ Instead of loading values of spilled pseudos, LRA tries to rematerialize (recalculate) them if it's profitable. Enabled at levels-O2,-O3,-Os๐ธ-fdelayed-branchโ if the target machine supports it, the compiler will try to reorder instructions so they fill the instruction slots available after delayed branch instructions ๐ง Enabled at levels-O,-O2,-O3,-Os, but not at-Og๐ซ
-fschedule-insnsโ if the target supports it, the compiler reorders instructions to get rid of execution stalls caused by required data not being 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 floating-point result is still cooking ๐ณ Enabled at levels-O2,-O3๐-fschedule-insns2โ basically the sequel to-fschedule-insns๐ It asks for an additional pass of instruction scheduling after register allocation is done. It's especially iconic on machines with a relatively small number of registers where memory load instructions take more than one cycle โญ Enabled at levels-O2,-O3,-Os๐-fno-sched-interblockโ disables instruction scheduling across basic blocks. Normally this is on when scheduling happens before register allocation, which means with-fschedule-insnsor at-O2or higher ๐ โโ๏ธ-fno-sched-specโ disables speculative motion of non-load instructions. Normally this is enabled when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher ๐ซ-fsched-pressureโ enables register pressure sensitive instruction scheduling before register allocation ๐ This only makes sense when scheduling before register allocation is enabled, i.e. with-fschedule-insnsor at-O2or higher. It can improve the generated code and shrink its size by stopping register pressure from going above the number of available hard registers, which would otherwise mean spills during register allocation ๐งโโ๏ธ-fsched-spec-loadโ allows speculative motion of some load instructions ๐ This only makes sense when scheduling before register allocation, i.e. with-fschedule-insnsor at-O2or higher ๐-fsched-spec-load-dangerousโ allows speculative motion of more load instructions ๐ฌ Same deal: it only makes sense when scheduling before register allocation, i.e. with-fschedule-insnsor at-O2or higher ๐-fsched-stalled-insns,-fsched-stalled-insns=nโ this sets how many insns (if any) can get moved early from the queue of stalled insns into the ready list during the second scheduling pass ๐-fno-sched-stalled-insnsmeans no insns get moved early.-fsched-stalled-insns=0means there's no limit on how many queued insns can be moved early.-fsched-stalled-insnswithout a 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 being moved early ๐ It only has an effect during the second scheduling pass, and only if-fsched-stalled-insnsis used.-fno-sched-stalled-insns-depis the same as-fsched-stalled-insns-dep=0.-fsched-stalled-insns-depwithout a value is the same as-fsched-stalled-insns-dep=1๐ฆ-fsched2-use-superblocksโ when scheduling after register allocation, this uses superblock scheduling ๐ง That lets motion happen across basic block boundaries, which can give you faster schedules. โ ๏ธ This option is experimental, because not all machine descriptions used by GCC model the CPU closely enough to avoid unreliable results from the algorithm ๐
โ ๏ธ Heads up bestie: -fsched2-use-superblocks is experimental, and some machine descriptions don't model the CPU closely enough, so the results can be unreliable. Use with caution ๐
This only makes sense when scheduling after register allocation, i.e. with -fschedule-insns2 or at -O2 or higher ๐ซถ
-fsched-group-heuristicโ enables the group heuristic in the scheduler ๐ฏ It favors the instruction that belongs to a schedule group. This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐-fsched-critical-path-heuristicโ enables the critical-path heuristic in the scheduler ๐ฃ๏ธ It favors instructions that sit on the critical path. This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐-fsched-spec-insn-heuristicโ enables the speculative instruction heuristic in the scheduler ๐ฒ It favors speculative instructions with greater dependency weakness. This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐ธ-fsched-rank-heuristicโ enables the rank heuristic in the scheduler ๐ It favors the instruction belonging to a basic block with greater size or frequency. This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐-fsched-last-insn-heuristicโ enables the last-instruction heuristic in the scheduler ๐ฏ It favors the instruction that is less dependent on the last instruction scheduled. This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐ซง-fsched-dep-count-heuristicโ enables the dependent-count heuristic in the scheduler ๐งฎ It favors the instruction that has more instructions depending on it. This is enabled by default when scheduling is enabled, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher ๐
-freschedule-modulo-scheduled-loopsโ modulo scheduling happens before traditional scheduling ๐ If a loop is modulo scheduled, later scheduling passes may change its schedule. Use this option to control that behavior ๐๏ธ-fselective-schedulingโ schedules instructions using the selective scheduling algorithm ๐งฉ Selective scheduling runs instead of the first scheduler pass ๐-fselective-scheduling2โ schedules instructions using the selective scheduling algorithm too ๐ช This time it runs instead of the second scheduler pass ๐ซ-fsel-sched-pipeliningโ enables software pipelining of innermost loops during selective scheduling ๐ฅ This has no effect unless-fselective-schedulingor-fselective-scheduling2is turned on ๐-fsel-sched-pipelining-outer-loopsโ when pipelining loops during selective scheduling, this also pipelines the outer loops too ๐ช It has no effect unless-fsel-sched-pipeliningis turned on ๐ซ-fsemantic-interpositionโ okay, this one is a whole vibe ๐ง Some object formats, like ELF, let the dynamic linker interpose symbols. That means for symbols exported from the DSO, the compiler can't do interprocedural propagation, inlining, and other optimizations, because the function or variable might get swapped out for something else ๐ It's useful, like if you want to rewrite memory allocation functions with a debugging implementation, but it's expensive when it comes to code quality ๐ธ With-fno-semantic-interposition, the compiler assumes that if interposition happens for functions, the overwriting function will have precisely the same semantics (and side effects). Similarly, if interposition happens for variables, the constructor of the variable will be the same ๐ค The flag has no effect for functions explicitly declared inline (where it's never allowed for interposition to change semantics), and it has no effect for symbols explicitly declared weak ๐ท-fshrink-wrapโ emits function prologues only before the parts of the function that actually need them, instead of at the top of the function ๐ This flag is enabled by default at-Oand higher ๐ฅฐ-fshrink-wrap-separateโ shrink-wraps separate parts of the prologue and epilogue separately, so those parts only run when they're needed ๐งผ This option is on by default, but it has no effect unless-fshrink-wrapis also turned on and the target supports this ๐-fcaller-savesโ enables allocation of values to registers that get clobbered by function calls ๐ It does this by emitting extra instructions to save and restore the registers around those 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 with no call-preserved registers to use instead ๐ Enabled at levels-O2,-O3,-Os๐-fcombine-stack-adjustmentsโ tracks stack adjustments (pushes and pops) and stack memory references, then tries to find ways to combine them ๐งบ Enabled by default at-O1and higher ๐-fipa-raโ uses caller save registers for allocation if those registers aren't used by any called function ๐งโ๐คโ๐ง That means they don't need to be saved and restored around calls. This is only possible if the called functions are part of the same compilation unit as the current function and they're compiled before it ๐ Enabled at levels-O2,-O3,-Os, however the option is disabled if the generated code will be instrumented for profiling (-p, or-pg), or if the callee's register usage can't be known exactly (this happens on targets that don't expose prologues and epilogues in RTL) ๐ญโจ
-fconserve-stack Okay so this one is for when you want the compiler to be stingy with stack space ๐ฅบ๐ง It tries to use less stack, even if your program ends up running a little slower. This option also sets 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 Okay bestie, code hoisting is so iconic ๐ It tries to move the evaluation of expressions that run on every path to the function exit as early as possible. It's especially useful as a code size optimization, but it often helps code speed too. Enabled by default at -O2 and higher. ๐ฆ
-ftree-pre Performs partial redundancy elimination (PRE) on trees. Enabled by default at -O2 and -O3. ๐
-ftree-partial-pre Makes partial redundancy elimination (PRE) more aggressive. Enabled by default at -O3. ๐ฅ
-ftree-forwprop Performs forward propagation on trees. Enabled by default at -O and higher. ๐ธ
-ftree-fre Performs full redundancy elimination (FRE) on trees. The difference between FRE and PRE is that FRE only considers expressions that are computed on all paths leading to the redundant computation. FRE is faster than PRE, though it exposes fewer redundancies. Enabled by default at -O and higher. ๐ซถ
-ftree-phiprop Performs hoisting of loads from conditional pointers on trees. This pass is enabled by default at -O and higher. ๐
-fhoist-adjacent-loads Speculatively hoists loads from both branches of an if-then-else if the loads come from adjacent locations in the same structure and the target architecture has a conditional move instruction. Enabled by default at -O2 and higher. ๐
-ftree-copy-prop Performs copy propagation on trees. This pass gets rid of unnecessary copy operations. Enabled by default at -O and higher. ๐ง
-fipa-pure-const Discovers which functions are pure or constant. Enabled by default at -O and higher. ๐
-fipa-reference Discovers which static variables do not escape the compilation unit. Enabled by default at -O and higher. ๐ฆ
-fipa-reference-addressable Discovers read-only, write-only and non-addressable static variables. Enabled by default at -O and higher. โจ
-fipa-stack-alignment Reduces stack alignment on call sites if possible. Enabled by default. ๐
-fipa-pta Performs interprocedural pointer analysis and interprocedural modification and reference analysis. Warning, bestie ๐ This option can cause excessive memory and compile-time usage on large compilation units. It is not enabled by default at any optimization level. ๐ญ
-fipa-profile Performs interprocedural profile propagation. Functions called only from cold functions are marked as cold, and functions executed once (such as "cold", "noreturn", static constructors or destructors) are identified. Cold functions and loop-less parts of functions executed once are then optimized for size. Enabled by default at -O and higher. ๐ธ
-fipa-cp Performs interprocedural constant propagation. This optimization figures out when values passed to functions are constants and then optimizes accordingly. It can substantially increase performance if the application has constants passed to functions. Enabled by default at -O2, -Os and -O3. It is also enabled by -fprofile-use and -fauto-profile. ๐
-fipa-cp-clone Performs function cloning to make interprocedural constant propagation stronger. When enabled, interprocedural constant propagation clones externally visible functions that can be called with constant arguments. Because this can create multiple copies of functions, it may significantly increase code size (see --param ipcp-unit-growth=value). Enabled by default at -O3. It is also enabled by -fprofile-use and -fauto-profile. ๐
-fipa-bit-cp When enabled, performs interprocedural bitwise constant propagation. Enabled by default at -O2 and by -fprofile-use and -fauto-profile. It requires that -fipa-cp is enabled. ๐ง
-fipa-vrp When enabled, performs interprocedural propagation of value ranges. Enabled by default at -O2. It requires that -fipa-cp is enabled. ๐
-fipa-icf Performs Identical Code Folding for functions and read-only variables. The optimization reduces code size and may disturb unwind stacks by replacing a function with an equivalent one that has a different name. It works more effectively with link-time optimization enabled. ๐ซถ
Although the behavior is similar to the Gold Linker's ICF optimization, GCC ICF works on different levels, so the optimizations are not the same. There are equivalences that only GCC finds and equivalences that only Gold finds. ๐
Enabled by default at -O2 and -Os. ๐
-flive-patching=level Controls GCC's optimizations so the output is suitable for live-patching. ๐ฆ
If the compiler's optimization uses a function's body, or information pulled from its body, to optimize or change another function, the latter is called an impacted function of the former. If a function is patched, its impacted functions should be patched too. ๐
The impacted functions are decided by the compiler's interprocedural optimizations. For example, a caller is impacted when a function is inlined into it, when a function is cloned and its caller is changed to call the new clone, or when a function's pureness or constness information is extracted to optimize its direct or indirect callers, and so on. ๐
Usually, the more IPA optimizations are enabled, the larger the number of impacted functions for each function. To control the number of impacted functions and make the list easier to compute, IPA optimizations can be partially enabled at two different levels. ๐ธ
The level argument should be one of the following: โจ
inline-cloneโ Only enables inlining and cloning optimizations, which includes inlining, cloning, interprocedural scalar replacement of aggregates and partial inlining. As a result, when patching a function, all its callers and its clones' callers are impacted, so they need to be patched as well.-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๐inline-only-staticโ Only enables inlining of static functions. As a result, when patching a static function, all its callers are impacted and so they need to be patched as well. In addition to all the flags that-flive-patching=inline-clonedisables,-flive-patching=inline-only-staticdisables the following additional optimization flags:-fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp๐ง
When -flive-patching is specified without any value, the default value is inline-clone. ๐
This flag is disabled by default. ๐
Note, bestie:-flive-patchingis not supported with link-time optimization (-flto). ๐ญ
-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. Enabled by default at -O2 and higher, and it depends on -fdelete-null-pointer-checks also being enabled. ๐ฅบ
-fisolate-erroneous-paths-attribute Detects paths that trigger erroneous or undefined behavior due to a null value being used in a way forbidden by a "returns_nonnull" or "nonnull" attribute. It isolates those paths from the main control flow and turns the statement with erroneous or undefined behavior into a trap. This is not currently enabled, but it may be enabled by -O2 in the future. ๐
-ftree-sink Performs forward store motion on trees. Enabled by default at -O and higher. ๐
-ftree-bit-ccp Performs sparse conditional bit constant propagation on trees and propagates pointer alignment information. This pass only operates on local scalar variables and is enabled by default at -O1 and higher, except for -Og. It requires that -ftree-ccp is enabled. ๐
-ftree-ccp Performs sparse conditional constant propagation (CCP) on trees. This pass only operates on local scalar variables and is enabled by default at -O and higher. โจ
-fssa-backprop Propagates information about uses of a value up the definition chain in order to simplify the definitions. For example, this pass strips sign operations if the sign of a value never matters. Enabled by default at -O and higher. ๐ฆ
-fssa-phiopt Performs pattern matching on SSA PHI nodes to optimize conditional code. This pass is enabled by default at -O1 and higher, except for -Og. ๐
-ftree-switch-conversion Performs conversion of simple initializations in a switch to initializations from a scalar array. Enabled by default at -O2 and higher. ๐
-ftree-tail-merge Looks for identical code sequences. When found, replaces one with a jump to the other. This optimization is known as tail merging or cross jumping. Enabled by default at -O2 and higher. The compilation time in this pass can be limited using the max-tail-merge-comparisons parameter and the max-tail-merge-iterations parameter. ๐ธ
-ftree-dce Performs dead code elimination (DCE) on trees. Enabled by default at -O and higher. ๐ซถ
-ftree-builtin-call-dce Performs conditional dead code elimination (DCE) for calls to built-in functions that may set errno but are otherwise free of side effects. Enabled by default at -O2 and higher if -Os is not also specified. ๐
-ftree-dominator-optsโ okay bestie, this one is a whole vibe ๐ It does a bunch of simple scalar cleanups (constant/copy propagation, redundancy elimination, range propagation and expression simplification) by walking a dominator tree โจ It also does jump threading, which cuts down on jumps that just lead to other jumps ๐ฆ Enabled by default at-Oand higher ๐-ftree-dseโ dead store elimination (DSE) on trees ๐๏ธ A dead store is a store into a memory location that another store overwrites later, with no loads in between. In that case the earlier store can be deleted ๐ Enabled by default at-Oand higher.-ftree-chโ loop header copying on trees ๐ธ It's super beneficial because it makes code motion optimizations way more effective, and it also saves one jump ๐ซถ Enabled by default at-Oand higher. It's not enabled for-Os, since it usually bloats code size ๐ญ-ftree-loop-optimizeโ loop optimizations on trees ๐ Enabled by default at-Oand higher.-ftree-loop-linear,-floop-strip-mine,-floop-blockโ loop nest optimizations, same as-floop-nest-optimize๐งฑ To use this transformation, GCC has to be configured with--with-islso the Graphite loop transformation infrastructure gets switched on โ๏ธ-fgraphite-identityโ the identity transformation for graphite ๐ช For every SCoP, GCC generates the polyhedral representation and then transforms it back to GIMPLE. With this you can check the costs or benefits of the GIMPLE -> GRAPHITE -> GIMPLE round trip ๐ Some minimal optimizations also happen in the isl code generator, like index splitting and dead code elimination in loops ๐งน-floop-nest-optimizeโ 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 ๐ This option is experimental ๐งช-floop-parallelize-allโ uses Graphite data dependence analysis to find loops that can be parallelized ๐งต It parallelizes all the loops that can be analyzed to not contain loop carried dependences, without checking whether parallelizing them is actually profitable ๐ซ-ftree-coalesce-varsโ when transforming the program out of SSA representation, it tries to reduce copying by coalescing versions of different user-defined variables, not just compiler temporaries โจ
Heads up: this may severely limit your ability to debug an optimized program compiled with -fno-var-tracking-assignments ๐ญ
In the negated form, this flag prevents SSA coalescing of user variables. It's enabled by default if optimization is enabled, and it does very little otherwise ๐ค
-ftree-loop-if-convertโ tries to transform conditional jumps in the innermost loops into branch-less equivalents ๐ช The goal is to remove control flow from the innermost loops so the vectorization pass can handle them better ๐ฆ Enabled by default if vectorization is enabled.-ftree-loop-distributionโ performs loop distribution ๐ฐ It can improve cache performance on big loop bodies and lets further loop optimizations, like parallelization or vectorization, take place. For example, this loop:
DO I = 1, N
A(I) = B(I) + C
D(I) = E(I) * F
ENDDO
gets split into this:
DO I = 1, N
A(I) = B(I) + C
ENDDO
DO I = 1, N
D(I) = E(I) * F
ENDDO
This flag is enabled by default at -O3. It's also enabled by -fprofile-use and -fauto-profile ๐
-ftree-loop-distribute-patternsโ performs loop distribution of patterns that can be code generated with calls to a library ๐ This flag is enabled by default at-O3, and by-fprofile-useand-fauto-profile๐
This pass distributes the initialization loops and generates a call to memset zero. For example, this loop:
DO I = 1, N
A(I) = 0
B(I) = A(I) + I
ENDDO
gets split into this:
DO I = 1, N
A(I) = 0
ENDDO
DO I = 1, N
B(I) = A(I) + I
ENDDO
and the initialization loop gets turned into a call to memset zero ๐งน This flag is enabled by default at -O3. It's also enabled by -fprofile-use and -fauto-profile ๐ธ
-floop-interchangeโ loop interchange outside of graphite ๐ This flag can improve cache performance on loop nests and let further loop optimizations, like vectorization, take place. For example, this nest:
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
for (int k = 0; k < N; k++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
gets swapped into this:
for (int i = 0; i < N; i++)
for (int k = 0; k < N; k++)
for (int j = 0; j < N; j++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
This flag is enabled by default at -O3. It's also enabled by -fprofile-use and -fauto-profile ๐ซถ
-floop-unroll-and-jamโ applies unroll and jam transformations on feasible loops ๐ฅช In a loop nest, it unrolls the outer loop by some factor and fuses the resulting multiple inner loops together. Enabled by default at-O3. It's also enabled by-fprofile-useand-fauto-profile๐ฅ-ftree-loop-imโ loop invariant motion on trees ๐ This pass only moves the invariants that are hard to handle at the RTL level (function calls, operations that expand to nontrivial sequences of insns) ๐ง With-funswitch-loopsit also moves operands of conditions that are invariant out of the loop, so we can use just trivial invariantness analysis in loop unswitching ๐ช The pass also includes store motion ๐-ftree-loop-ivcanonโ creates a canonical counter for the number of iterations in loops where figuring out the iteration count takes complicated analysis ๐ข Later optimizations can then determine the number easily. It's especially useful together with unrolling ๐-ftree-scev-cpropโ performs final value replacement ๐ If a variable is modified in a loop in such a way that its value when exiting can be determined using only its initial value and the number of loop iterations, the 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โ induction variable optimizations (strength reduction, induction variable merging and induction variable elimination) on trees ๐งฎ-ftree-parallelize-loops=nโ parallelizes loops, meaning it splits their iteration space to run in n threads ๐งต This is only possible for loops whose iterations are independent and can be arbitrarily reordered. The optimization is only profitable on multiprocessor machines, and only for CPU-intensive loops rather than ones constrained by things like memory bandwidth ๐ช This option implies-pthread, so it's only supported on targets that have support for-pthread๐งต-ftree-ptaโ function-local points-to analysis on trees ๐ฏ Enabled by default at-O1and higher, except for-Og๐-ftree-sraโ scalar replacement of aggregates ๐งฉ This pass swaps structure references out for scalars so structures don't get committed to memory too early ๐ง Enabled by default at-O1and higher, except for-Og๐-fstore-mergingโ merges narrow stores to consecutive memory addresses ๐ซง It combines contiguous stores of immediate values that are narrower than a word into fewer, wider stores, which cuts down on the number of instructions ๐ Enabled by default at-O2and higher, as well as-Os๐ธ-ftree-terโ temporary expression replacement during the SSA->normal phase ๐ช Single use/single def temporaries get replaced at their use location with their defining expression. This results in non-GIMPLE code, but it gives the expanders much more complex trees to work on, which leads to better RTL generation ๐ค Enabled by default at-Oand higher.-ftree-slsrโ straight-line strength reduction on trees ๐ It recognizes related expressions involving multiplications and replaces them with cheaper calculations when possible โจ Enabled by default at-Oand higher.-ftree-vectorizeโ vectorization on trees ๐ This flag enables-ftree-loop-vectorizeand-ftree-slp-vectorizeif they aren't explicitly specified ๐ซถ-ftree-loop-vectorizeโ loop vectorization on trees ๐ Enabled by default at-O3, and by-ftree-vectorize,-fprofile-use, and-fauto-profile๐-ftree-slp-vectorizeโ 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 gets enabled for iteration counts that will likely run faster than the original scalar loop ๐งcheapโ disables vectorization of loops where doing so would be cost-prohibitive, for example because of required runtime checks for data dependence or alignment. Otherwise it's equal todynamic๐ซง
The default cost model depends on other optimization flags and is either dynamic or cheap ๐คทโโ๏ธ
-fsimd-cost-model=modelโ alters the cost model used for vectorization of loops marked with the OpenMPsimddirective ๐ The model argument should be one ofunlimited,dynamic, orcheap. All values of model have the same meaning as described in-fvect-cost-model, and by default a cost model defined with-fvect-cost-modelis used ๐ฆ-ftree-vrp: okay so this one does Value Range Propagation on trees ๐ณ๐ It's giving constant propagation vibes, except instead of tracking single values, it tracks whole ranges of values ๐ฆ That lets the optimizers delete unnecessary range checks like array bound checks and null pointer checks ๐ It's on by default at-O2and higher โจ
Heads up tho: null pointer check elimination only happens if -fdelete-null-pointer-checks is enabled ๐
-fsplit-paths: this one splits the paths leading to loop backedges ๐ค๏ธ It can level up dead code elimination and common subexpression elimination ๐งน It's enabled by default at-O3and above ๐-fsplit-ivs-in-unroller: this lets the compiler express the values of induction variables in later iterations of an unrolled loop using the value from the first iteration ๐ง That breaks up long dependency chains, which makes the scheduling passes more efficient ๐
Using -fweb and CSE together is often enough to get the same effect ๐ซถ But that's not reliable when the loop body is more complicated than a single basic block ๐ It also doesn't work at all on some architectures because of restrictions in the CSE pass ๐ญ
This optimization is enabled by default ๐
-fvariable-expansion-in-unroller: with this on, the compiler makes multiple copies of some local variables when it unrolls a loop, and that can lead to superior code ๐-fpartial-inlining: inlines parts of functions ๐งฉ This only has an effect when inlining itself is turned on by-finline-functionsor-finline-small-functions๐
Enabled at levels -O2, -O3, -Os โจ
-fpredictive-commoning: this performs predictive commoning, which means reusing computations (especially memory loads and stores) from previous iterations of loops ๐๐
It's enabled at level -O3, and it's also enabled by -fprofile-use and -fauto-profile ๐ฅ
-fprefetch-loop-arrays: if the target machine supports it, the compiler generates instructions to prefetch memory, which can boost loops that access large arrays ๐โโ๏ธ
Fair warning: this might produce better code or worse code ๐คทโโ๏ธ The results are highly dependent on the structure of the loops in your source code ๐ธ
Disabled at level -Os ๐
โโ๏ธ
-fno-printf-return-value: okay this one is kinda wild ๐คฏ It stops GCC from substituting constants for the known return value of formatted output functions likesprintf,snprintf,vsprintf, andvsnprintf(but notprintforfprintf) ๐ซ
The transformation is what lets GCC optimize or even eliminate branches based on the known return value of these functions, as long as the arguments are either constant or have values known to be in a range that makes the exact return value figurable out ๐ฎ For example, when -fprintf-return-value is in effect, both the branch and the body of the if statement (but not the call to snprint) can be optimized away when i is a 32-bit or smaller integer, because the return value is guaranteed to be at most 8 ๐
char buf[9];
if (snprintf (buf, "%08x", i) >= sizeof buf)
...
The -fprintf-return-value option relies on other optimizations and gives the best results with -O2 and above ๐ It works in tandem with -Wformat-overflow and -Wformat-truncation ๐ซถ The -fprintf-return-value option is enabled by default ๐
-fno-peephole,-fno-peephole2: these disable any machine-specific peephole optimizations ๐ โโ๏ธ The difference between-fno-peepholeand-fno-peephole2is in how they're implemented in the compiler ๐ ๏ธ Some targets use one, some use the other, and a few use both ๐ฆ
-fpeephole is enabled by default โจ -fpeephole2 is enabled at levels -O2, -O3, -Os ๐
-fno-guess-branch-probability: do not guess branch probabilities using heuristics ๐ง ๐ซ
GCC uses heuristics to guess branch probabilities when they aren't provided by profiling feedback (-fprofile-arcs) ๐ These heuristics are based on the control flow graph ๐บ๏ธ If some branch probabilities are specified by __builtin_expect, the heuristics guess the rest of the control flow graph while taking the __builtin_expect info into account ๐ฏ The interactions between the heuristics and __builtin_expect can get messy ๐ตโ๐ซ so in some cases it's useful to turn the heuristics off, so the effects of __builtin_expect are easier to understand ๐ซถ
You can also specify the expected probability of an expression with the __builtin_expect_with_probability built-in function ๐ฎ
The default is -fguess-branch-probability at levels -O, -O2, -O3, -Os ๐
-freorder-blocks: reorders basic blocks in the compiled function to reduce the number of taken branches and improve code locality ๐งบ
Enabled at levels -O, -O2, -O3, -Os โจ
-freorder-blocks-algorithm=algorithm: picks the algorithm used for basic block reordering ๐งฉ Thealgorithmargument can besimple, which doesn't increase code size (except sometimes because of secondary effects like alignment) ๐งโโ๏ธ orstc, the "software trace cache" algorithm ๐ That one puts all the often-executed code together and minimizes the number of branches executed by making extra copies of code ๐ฅ
The default is simple at levels -O, -Os, and stc at levels -O2, -O3 ๐
-freorder-blocks-and-partition: on top of reordering basic blocks to cut down on taken branches, this one partitions hot and cold basic blocks into separate sections of the assembly and.ofiles ๐ฅ๐ง That helps paging and cache locality performance ๐
This optimization is automatically turned off when there's exception handling or unwind tables (on targets using setjump/longjump or a target specific scheme), for linkonce sections, for functions with a user-defined section attribute, and on any architecture that doesn't support named sections ๐
โโ๏ธ When -fsplit-stack is used, this option isn't enabled by default (to avoid linker errors), but you can enable it explicitly if you're using a working linker ๐ง
Enabled for x86 at levels -O2, -O3, -Os ๐
-freorder-functions: reorders functions in the object file to improve code locality ๐๏ธ This is done with special subsections,.text.hotfor the most frequently executed functions and.text.unlikelyfor 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-arcs for details) or manually annotate functions with hot or cold attributes ๐
Enabled at levels -O2, -O3, -Os โจ
-fstrict-aliasing: this lets the compiler assume the strictest aliasing rules that apply to the language being compiled ๐ง For C (and C++), it turns on optimizations based on the type of expressions ๐ง An object of one type is assumed never to live at the same address as an object of a different type, unless the types are almost the same ๐ For example, anunsigned intcan alias anint, but not avoid*or adouble๐ซ A character type may alias any other type ๐
Pay special attention to code like this ๐
union a_union {
int i;
double d;
};
int f() {
union a_union t;
t.d = 3.0;
return t.i;
}
Reading from a different union member than the one most recently written to (called "type-punning") is super common ๐ซ Even with -fstrict-aliasing, type-punning is allowed, as long as the memory is accessed through the union type ๐ So the code above works as expected ๐
However, this code might not ๐ฌ
int f() {
union a_union t;
int* ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}
Similarly, accessing by taking the address, casting the resulting pointer, and dereferencing the result has undefined behavior ๐จ๐ฑ even if the cast uses a union type, e.g.:
int f() {
double d = 3.0;
return ((union a_union *) &d)->i;
}
The -fstrict-aliasing option is enabled at levels -O2, -O3, -Os ๐
-falign-functions,-falign-functions=n,-falign-functions=n:m,-falign-functions=n:m:n2,-falign-functions=n:m:n2:m2: this aligns the start of functions to the next power-of-two greater thann, skipping up tom-1bytes ๐ That makes sure at least the firstmbytes of the function can be fetched by the CPU without crossing ann-byte alignment boundary ๐โโ๏ธ
If m isn't specified, it defaults to n ๐ซถ
Examples: -falign-functions=32 aligns functions to the next 32-byte boundary, -falign-functions=24 aligns to the next 32-byte boundary only if this can be done by skipping 23 bytes or less, and -falign-functions=32:7 aligns to the next 32-byte boundary only if this can be done by skipping 6 bytes or less ๐งฎ
The second pair of n2:m2 values lets you specify a secondary alignment: -falign-functions=64:7:32:3 aligns to the next 64-byte boundary if this can be done by skipping 6 bytes or less, otherwise it aligns to the next 32-byte boundary if this can be done by skipping 2 bytes or less ๐ช If m2 isn't specified, it defaults to n2 ๐
Some assemblers only support this flag when n is a power of two; in that case, it gets rounded up ๐ผ
-fno-align-functions and -falign-functions=1 are equivalent and mean that functions are not aligned ๐
โโ๏ธ
If n isn't specified or is zero, the compiler uses a machine-dependent default ๐ฅ๏ธ The maximum allowed n value is 65536 ๐ฏ
Enabled at levels -O2, -O3 โจ
-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 it won't skip more bytes than the size of the function ๐ not overdoing it, iconic ๐-falign-labels,-falign-labels=n,-falign-labels=n:m,-falign-labels=n:m:n2,-falign-labels=n:m:n2:m2: this aligns all branch targets to a power-of-two boundary ๐ฏ
The parameters of this option are analogous to the -falign-functions option ๐ช -fno-align-labels and -falign-labels=1 are equivalent and mean that labels are not aligned ๐
If -falign-loops or -falign-jumps apply and their values are greater than this one, then those get used instead, bestie ๐
If n is not specified or is zero, the machine picks its own default, which is very likely 1 (aka no alignment at all) ๐ The maximum allowed n option value is 65536 โจ
Enabled at levels -O2, -O3 ๐ธ
-falign-loops
-falign-loops
-falign-loops=n
-falign-loops=n:m
-falign-loops=n:m:n2
-falign-loops=n:m:n2:m2
Okay so this one aligns loops to a power-of-two boundary ๐ฆ If the loops run a ton of times, the dummy padding instructions are totally worth it, because the speedup makes up for them ๐ฅ
The parameters work exactly like the ones for -falign-functions, so it's giving dรฉjร vu ๐ -fno-align-loops and -falign-loops=1 are equivalent and mean that loops are not aligned. The maximum allowed n option value is 65536.
If n is not specified or is zero, the machine-dependent default takes over ๐ง
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 ๐ It's specifically for branch targets that can only be reached by jumping. Since they're only reached by jumping, no dummy operations need to run, which is so efficient ๐ญ
Again, the parameters are analogous to -falign-functions ๐ -fno-align-jumps and -falign-jumps=1 are equivalent and mean that loops are not aligned.
If n is not specified or is zero, the machine-dependent default is used. The maximum allowed n option value is 65536.
Enabled at levels -O2, -O3 ๐
-funit-at-a-time
This one is kept around purely for compatibility reasons, so it's basically a legacy icon ๐ -funit-at-a-time has no effect ๐ Meanwhile, -fno-unit-at-a-time implies -fno-toplevel-reorder and -fno-section-anchors.
Enabled by default ๐
-fno-toplevel-reorder
Do not reorder top-level functions, variables, and asm statements. Everything comes out in the same order it appeared in the input file ๐ When this is used, unreferenced static variables are not removed.
This one exists to support existing code that relies on a specific ordering. For new code, it's better to use attributes when possible ๐ฆ
-ftoplevel-reorder is the default at -O1 and higher, and also at -O0 if -fsection-anchors is explicitly requested. Additionally, -fno-toplevel-reorder implies -fno-section-anchors ๐งฉ
-fweb
This constructs webs, which are commonly used for register allocation purposes, and assigns each web its own individual pseudo register ๐ง That lets the register allocation pass operate on pseudos directly, and it also strengthens several other optimization passes, like CSE, the loop optimizer, and the trivial dead code remover โญ
It can, however, make debugging impossible, since variables no longer stay in a "home register" ๐
Enabled by default with -funroll-loops ๐ธ
-fwhole-program
Okay this one assumes that the current compilation unit is the whole program being compiled ๐ All public functions and variables, except main and those merged by the attribute externally_visible, become static functions. Because of that, the interprocedural optimizers can go way harder on them ๐ฅ
This option should not be used in combination with -flto. Instead, relying on a linker plugin should provide safer and more precise information ๐จ
-flto[=n]
This runs the standard link-time optimizer, and it's honestly iconic ๐ When you invoke it with source code, it generates GIMPLE (one of GCC's internal representations) and writes it to special ELF sections in the object file. When the object files get linked together, all the function bodies are read from those ELF sections and instantiated as if they had been 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 participating 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 into one image, all the interprocedural analyses and optimizations in GCC work across the two files as if they were a single one. So, for example, the inliner can inline functions in bar.o into functions in foo.o and vice-versa. Main character energy ๐
Another (simpler) way to enable link-time optimization is:
gcc -o myprog -flto -O2 foo.c bar.c
This generates bytecode for foo.c and bar.c, merges them together into a single GIMPLE representation, and optimizes them as usual to produce myprog โจ
The important thing to keep in mind is that to enable link-time optimizations, you need to use the GCC driver to perform the link step. GCC automatically performs link-time optimization if any of the objects involved were compiled with the -flto command-line option. You can always override the automatic decision to do link-time optimization by passing -fno-lto to the link command ๐ซถ
To make whole program optimization effective, it's necessary to make certain whole program assumptions. The compiler needs to know what functions and variables can be accessed by libraries and runtime outside of the link-time optimized unit. When the linker supports it, the linker plugin (see -fuse-linker-plugin) passes information to the compiler about used and externally visible symbols. When the linker plugin isn't available, -fwhole-program should be used so the compiler can make these assumptions, which leads to more aggressive optimization decisions ๐ฅ
When a file is compiled with -flto without -fuse-linker-plugin, the generated object file is larger than a regular object file, because it contains GIMPLE bytecodes and the usual final code (see -ffat-lto-objects). This means object files with LTO information can be linked as normal object files. If -fno-lto is passed to the linker, no interprocedural optimizations are applied. Note that when -fno-fat-lto-objects is enabled, the compile stage is faster, but you cannot perform a regular, non-LTO link on them ๐ญ
When producing the final binary, GCC only applies link-time optimizations to those files that contain bytecode. So you can mix and match object files and libraries with GIMPLE bytecodes and final object code. GCC automatically selects which files to optimize in LTO mode and which files to link without further processing ๐ฆ
Generally, options specified at link time override those specified at compile time, although in some cases GCC attempts to infer link-time options from the settings used to compile the input files.
If you do not specify an optimization level option -O at link time, GCC uses the highest optimization level used when compiling the object files. Note that it's generally ineffective to specify an optimization level option only at link time and not at compile time, for two reasons. First, compiling without optimization suppresses the compiler passes that gather information needed for effective optimization at link time. Second, some early optimization passes can only be performed at compile time and 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: -fPIC, -fpic, -fpie, -fcommon, -fexceptions, -fnon-call-exceptions, -fgnu-tm, and all the -m target flags ๐
Certain ABI-changing flags are required to match in all compilation units. Trying to override this at link time with a conflicting value is ignored. This includes options such as -freg-struct-return and -fpcc-struct-return ๐ซ
Other options such as -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 ๐
When you need to pass options to the assembler via -Wa or -Xassembler, make sure to either compile such translation units with -fno-lto, or consistently use the same assembler options on all translation units. You can alternatively also specify assembler options at LTO link time ๐งฉ
To enable debug info generation, you need to supply -g at compile time. If any of the input files at link time were built with debug info generation enabled, the link will enable debug info generation as well. Any elaborate debug info settings, like the DWARF level -gdwarf-5, need to be explicitly repeated on the linker command line, and mixing different settings in different translation units is discouraged ๐
If LTO encounters objects with C linkage declared with incompatible types in separate translation units to be linked together, that's undefined behavior according to ISO C99 6.2.7. A non-fatal diagnostic may be issued, but the behavior is still undefined at run time. Similar diagnostics may be raised for other languages ๐
Undefined behavior means the program can do literally anything, so please don't mix incompatible C linkage declarations and expect it to be fine ๐ญ
Another feature of LTO is that it's possible to apply interprocedural optimizations on files written in different languages:
gcc -c -flto foo.c
g++ -c -flto bar.cc
gfortran -c -flto baz.f90
g++ -o myprog -flto -O3 foo.o bar.o baz.o -lgfortran
Notice that the final link is done with g++ to get the C++ runtime libraries, and -lgfortran is added to get the Fortran runtime libraries. In general, when mixing languages in LTO mode, you should use the same link command options as when mixing languages in a regular (non-LTO) compilation ๐ธ
Okay so, if you've got object files holding GIMPLE bytecode stashed in a library archive (say libfoo.a), you can totally pull them out for an LTO link, as long as your linker has plugin support ๐
. To make static libraries that vibe with LTO, use gcc-ar and gcc-ranlib instead of ar and ranlib. If you wanna peek at the symbols in object files with GIMPLE bytecode, gcc-nm is your bestie ๐. Those tools need ar, ranlib and nm to be built with plugin support too, or it's a no-go ๐. When you link, slap on -fuse-linker-plugin so the library actually joins the LTO party ๐ฆ:
gcc -o myprog -O2 -flto -fuse-linker-plugin a.o b.o -lfoo
With the linker plugin on, the linker grabs the GIMPLE files it needs out of libfoo.a and hands them to the running GCC, so they become part of the big combined GIMPLE image that gets optimized โจ.
If you're not using a linker with plugin support, or you just didn't turn the linker plugin on, no drama ๐ฅฒ. The objects inside libfoo.a still get extracted and linked like normal, they just don't join the LTO optimization process. If you want a static library that works for both LTO and regular linking, compile its object files with -flto -ffat-lto-objects ๐ซถ.
LTO doesn't need the whole program to be present to work ๐. If your program doesn't need any symbols exported, you can combine -flto and -fwhole-program. That lets the interprocedural optimizers make more aggressive assumptions, which may lead to improved optimization opportunities ๐ฅ. You don't need -fwhole-program when the linker plugin is active (see -fuse-linker-plugin) ๐.
The current LTO implementation makes no attempt to generate bytecode that's portable between different types of hosts ๐ โโ๏ธ. The bytecode files are versioned with a strict version check, so bytecode generated by one GCC version won't work with an older or newer GCC. Not a vibe ๐ญ.
Link-time optimization doesn't play nice with debugging information on systems other than those using a combo of ELF and DWARF ๐.
If you specify the optional n, the optimization and code generation done at link time runs in parallel using n jobs, with an installed make program doing the heavy lifting ๐โโ๏ธ. 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 figure out how many parallel jobs to run. 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.
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โ This picks the partitioning algorithm the link-time optimizer uses. The value is either1to1, which mirrors the original source files, orbalanced, which splits things into equally sized chunks whenever possible, ormax, which makes a new partition for every symbol where possible. Specifyingnoneas the algorithm turns partitioning and streaming off completely. The default isbalanced.1to1can be used as a workaround for various code ordering issues, butmaxpartitioning is intended for internal testing only ๐งช. The valueonemeans exactly one partition gets used, whilenoneskips partitioning and runs the link-time optimization step straight from the WPA phase.-flto-odr-type-mergingโ Turns on streaming of the mangled type names of C++ types, plus their unification at link time. It makes LTO object files bigger, but you get diagnostics about One Definition Rule violations in return ๐.-flto-compression-level=nโ This sets how much compression is used for the intermediate language written to LTO object files. It only matters with LTO mode (-flto). Valid values are0(no compression) to9(maximum compression). Values outside that range get clamped to either0or9. If you don't give the option, a default balanced compression setting is used ๐๏ธ.-fuse-linker-pluginโ Enables a linker plugin during link-time optimization. This relies on plugin support in the linker, which is available ingoldor in GNU ld 2.21 or newer. It also enables extracting object files with GIMPLE bytecode out of library archives, which improves optimization quality by exposing more code to the link-time optimizer ๐ฆ. The plugin tells the optimizer which symbols can be accessed externally (by non-LTO objects or during dynamic linking). The code quality gains on binaries (and on 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 turned on and GCC was configured for 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 works when you're compiling with-flto, and it gets ignored at link time.
-fno-fat-lto-objects speeds up compilation compared to plain LTO, but the whole toolchain has to be LTO-aware. It needs a linker with linker plugin support for basic functionality ๐. On top of that, nm, ar and ranlib need to support linker plugins so you get a full-featured build environment (one that can build static libraries and all that). GCC provides the gcc-ar, gcc-nm and gcc-ranlib wrappers to pass the right options to these tools. With non-fat LTO, makefiles need to be modified to use them.
Modern binutils has 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.
Enabled at levels -O, -O2, -O3, -Os.
-fcprop-registersโ After register allocation and post-register allocation instruction splitting, this does a copy-propagation pass to try to reduce scheduling dependencies and occasionally eliminate the copy. ๐
Enabled at levels -O, -O2, -O3, -Os.
-fprofile-correctionโ Profiles collected from an instrumented binary for multi-threaded programs can be inconsistent because some counter updates get missed. When you specify this option, GCC uses heuristics to correct or smooth out those inconsistencies ๐ฉน. By default, GCC emits an error message when it detects an inconsistent profile.
This option is enabled by -fauto-profile.
-fprofile-use,-fprofile-use=pathโ Enables profile feedback-directed optimizations, plus the following optimizations, many of which are only really profitable when profile feedback is available:
-fbranch-probabilities, -fprofile-values, -funroll-loops, -fpeel-loops, -ftracer, -fvpt, -finline-functions, -fipa-cp, -fipa-cp-clone, -fipa-bit-cp, -fpredictive-commoning, -fsplit-loops, -funswitch-loops, -fgcse-after-reload, -ftree-loop-vectorize, -ftree-slp-vectorize, -fvect-cost-model=dynamic, -ftree-loop-distribute-patterns, -fprofile-reorder-functions
Before you can use this option, you must first generate profiling information ๐.
By default, GCC emits an error message if the feedback profiles don't match the source code. You can turn that error into a warning with -Wno-error=coverage-mismatch. Just know this may result in poorly optimized code ๐ฌ. Also by default, GCC emits a warning message if the feedback profiles don't exist (see -Wmissing-profile).
If path is specified, GCC looks at that path to find the profile feedback data files. See -fprofile-dir.
-fauto-profile,-fauto-profile=pathโ Enables sampling-based feedback-directed optimizations, plus the following optimizations, many of which are only really profitable when profile feedback is available: ๐
-fbranch-probabilities, -fprofile-values, -funroll-loops, -fpeel-loops, -ftracer, -fvpt, -finline-functions, -fipa-cp, -fipa-cp-clone, -fipa-bit-cp, -fpredictive-commoning, -fsplit-loops, -funswitch-loops, -fgcse-after-reload, -ftree-loop-vectorize, -ftree-slp-vectorize, -fvect-cost-model=dynamic, -ftree-loop-distribute-patterns, -fprofile-correction
path is the name of a file containing AutoFDO profile information. If you leave it off, it defaults to fbdata.afdo in the current directory ๐.
Producing an AutoFDO profile data file means running your program with the perf utility on a supported GNU/Linux target system. For more info, check out https://perf.wiki.kernel.org/ ๐.
E.g.
perf record -e br_inst_retired:near_taken -b -o perf.data \
-- your_program
Then use the create_gcov tool to convert the raw profile data into a format GCC can use. You also have to supply the unstripped binary for your program to this tool. See https://github.com/google/autofdo ๐ ๏ธ.
E.g.
create_gcov --binary=your_program.unstripped --profile=perf.data \
--gcov=profile.afdo
The following options control compiler behavior regarding floating-point arithmetic ๐งฎ. They trade off between speed and correctness, so think about which one you want. All of them must be specifically enabled.
-ffloat-storeโ Don't store floating-point variables in registers, and inhibit other options that might change whether a floating-point value gets taken from a register or from memory. ๐
Okay so, this one's about -ffloat-store ๐ง It stops the sneaky extra precision on machines like the 68000, where the floating registers (on the 68881) hold more precision than a double is supposed to have. x86 has the same issue ๐
For most programs that extra precision is a total win, but some programs rely on the exact IEEE floating-point definition. Those programs can use -ffloat-store, but first you have to edit them so every pertinent intermediate computation gets stored into a variable ๐ซถ
-fexcess-precision=styleโ Okay, this is the more precise control panel for excess precision ๐ It applies to machines where floating-point operations happen in a format with more precision or range than the IEEE standard and interchange floating-point types. By default,-fexcess-precision=fastis in effect โจ That means operations can run in a wider precision than the source types if it makes the code faster, and it's unpredictable when rounding to the source types actually happens.- When you compile C with
-fexcess-precision=standard, excess precision follows the ISO C99 rules ๐ Casts and assignments both cause values to be rounded to their semantic types. (Compare that to-ffloat-store, which only affects assignments.) This option is enabled 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=standardis not implemented for languages other than C. On the x86, it does nothing if-mfpmath=sseor-mfpmath=sse+387is specified. With the former, IEEE semantics apply without excess precision. With the latter, rounding is unpredictable ๐
- When you compile C with
-ffast-mathโ This one is a whole vibe ๐๏ธ It sets-fno-math-errno,-funsafe-math-optimizations,-ffinite-math-only,-fno-rounding-math,-fno-signaling-nans,-fcx-limited-rangeand-fexcess-precision=fastall at once. It also causes the preprocessor macro__FAST_MATH__to be defined ๐- Only
-Ofastturns this on. No other-Ooption does ๐
- Only
This can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It may, however, yield faster code for programs that don't need the guarantees of those specifications.
-fno-math-errnoโ Don't seterrnoafter calling math functions that run in a single instruction, likesqrt๐ฆ A program that handles math errors through IEEE exceptions might want this for speed while still keeping IEEE arithmetic compatibility ๐ธ- Not turned on by any
-Ooption, 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 may, however, be faster for programs that don't need those guarantees. - The default is
-fmath-errno. - On Darwin systems, the math library never sets
errno. So the compiler has no reason to consider that it might, and-fno-math-errnois the default there โจ
- Not turned on by any
-funsafe-math-optimizationsโ Allows floating-point optimizations that (a) assume arguments and results are valid and (b) may violate IEEE or ANSI standards ๐ฅ When used at link time, it may pull in libraries or startup files that change the default FPU control word or do other similar optimizations.- Not turned on by any
-Ooption, same reason as before: incorrect output is possible for programs that depend on exact IEEE or ISO math rules. It may still be faster for programs that don't need those guarantees. - Enables
-fno-signed-zeros,-fno-trapping-math,-fassociative-mathand-freciprocal-math. - The default is
-fno-unsafe-math-optimizations.
- Not turned on by any
-fassociative-mathโ Allows re-association of operands in a series of floating-point operations ๐ This violates the ISO C and C++ standard because it can change the computation result.
NOTE: Re-ordering may change the sign of zero, ignore NaNs, and inhibit or create underflow or overflow. That means it can't be used on code that relies on rounding behavior like (x + 2**52) - 2**52. It may also reorder floating-point comparisons, so don't use it where ordered comparisons are required ๐ญ
- This option requires that both
-fno-signed-zerosand-fno-trapping-mathbe in effect. - It doesn't make much sense with
-frounding-math. - For Fortran, the option is automatically enabled when both
-fno-signed-zerosand-fno-trapping-mathare in effect. - The default is
-fno-associative-math.
-freciprocal-mathโ Lets the reciprocal of a value be used instead of dividing by that value, if it enables optimizations ๐ For example,x / ycan be replaced withx * (1/y), which is handy when(1/y)is subject to common subexpression elimination. Heads up: this loses precision and increases the number of flops operating on the value.- The default is
-fno-reciprocal-math.
- The default is
-ffinite-math-onlyโ Allows optimizations that assume arguments and results are never NaNs or+-Infs๐ซง- Not turned on by any
-Ooption, 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 may still be faster for programs that don't need those guarantees. - The default is
-fno-finite-math-only.
- Not turned on by any
-fno-signed-zerosโ Allows optimizations that ignore the signedness of zero ๐ง IEEE arithmetic gives distinct+0.0and-0.0values with their own behavior, and that blocks simplifications of expressions likex+0.0or0.0*x(even with-ffinite-math-only). This option says the sign of a zero result doesn't matter.- The default is
-fsigned-zeros.
- The default is
-fno-trapping-mathโ Compiles code assuming 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 may allow faster code if you rely on "non-stop" IEEE arithmetic, for example.
This option should never be turned on by any -O option, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions.
- The default is
-ftrapping-math.
-frounding-mathโ Turns off transformations and optimizations that assume the default floating-point rounding behavior ๐ That default is round-to-zero for all floating-point to integer conversions, and round-to-nearest for all other arithmetic truncations. Use this for programs that change the FP rounding mode dynamically, or that might run with a non-default rounding mode ๐ It also disables compile-time constant folding of floating-point expressions (which rounding mode can affect), plus 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 that every GCC optimization affected by rounding mode gets disabled ๐งช
- Future GCC versions may offer finer control using C99's
FENV_ACCESSpragma. This command-line option will be used to set the default state forFENV_ACCESS.
- The default is
-fsignaling-nansโ Compiles code assuming IEEE signaling NaNs may generate user-visible traps during floating-point operations ๐ Turning this on disables optimizations that might change the number of exceptions visible with signaling NaNs. It implies-ftrapping-math.- This option causes the preprocessor macro
__SUPPORT_SNAN__to be defined. - The default is
-fno-signaling-nans. - This option is experimental and doesn't currently guarantee that every GCC optimization affecting signaling NaN behavior gets disabled.
- This option causes the preprocessor macro
-fno-fp-int-builtin-inexactโ Stops the built-in functionsceil,floor,roundandtrunc(plus theirfloatandlong doublevariants) from generating code that raises theinexactfloating-point exception for noninteger arguments ๐ ISO C99 and C11 let these functions raiseinexact, but ISO/IEC TS 18661-1:2014, the C bindings to IEEE 754-2008, does not.- The default is
-ffp-int-builtin-inexact, which allows the exception to be raised. - This option does nothing unless
-ftrapping-mathis in effect. - Even with
-fno-fp-int-builtin-inexact, if these functions end up calling a library function, theinexactexception may still be raised if the library implementation doesn't follow TS 18661.
- The default is
-fsingle-precision-constantโ Treats floating-point constants as single precision, instead of implicitly converting them to double-precision constants ๐ฆ-fcx-limited-rangeโ When enabled, this says a range reduction step isn't needed for complex division ๐ง It also means there's no check on whether a complex multiplication or division result isNaN + I*NaN, so no attempt to rescue that situation.- The default is
-fno-cx-limited-range, but-ffast-mathenables it. - This option controls the default setting of the ISO C99
CX_LIMITED_RANGEpragma. Even so, it applies to all languages ๐ท
- The default is
-fcx-fortran-rulesโ Complex multiplication and division follow Fortran rules ๐ Range reduction is done as part of complex division, but there's no check on whether the result isNaN + I*NaN, and no attempt to rescue it in that case.- The default is
-fno-cx-fortran-rules.
- The default is
The following options control optimizations that may improve performance, but none of them are enabled by any -O option. This section also includes experimental options that may produce broken code ๐๐ซถ
-fbranch-probabilitiesโ ๐ฆ okay so, after you run a program built with-fprofile-arcs, you compile it again with-fbranch-probabilitiesand the optimizer gets smarter about which branches actually get taken. When that profiled program exits, it saves arc execution counts to a file calledsourcename.gcdafor each source file. That data is super dependent on the structure of the generated code, so you must use the same source code and the same optimization options for both compiles, bestie. With this flag, GCC attaches aREG_BR_PROBnote to eachJUMP_INSNandCALL_INSN. Right now those notes only get used in one spot,reorg.c, where instead of guessing the likely path, GCC uses theREG_BR_PROBvalues to know exactly which path gets taken more often. โจ Enabled by-fprofile-useand-fauto-profile.-fprofile-valuesโ ๐ when you combine this with-fprofile-arcs, the compiler adds code that gathers data about the values of expressions in your program. Add-fbranch-probabilitiesand it reads that data back and uses it for optimizations. โจ Enabled by-fprofile-generate,-fprofile-use, and-fauto-profile.-fprofile-reorder-functionsโ ๐ง function reordering based on profile instrumentation records the first time each function runs, then sorts the functions in ascending order. โจ Enabled with-fprofile-use.-fvptโ ๐ฅ with-fprofile-arcs, this tells the compiler to add code that collects info about expression values. Then with-fbranch-probabilities, it reads that info back and actually does the optimizing. Right now that includes specializing division operations based on what the denominator's value is, which is so clever. โจ Enabled with-fprofile-useand-fauto-profile.-frename-registersโ ๐ธ this tries to dodge false dependencies in scheduled code by using registers that get left over after register allocation. It's most helpful on processors with lots of registers. > Heads up: depending on the debug information format your target uses, this 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 groups instructions of the same type together, since some machines run them more efficiently when they're sitting next to each other. โจ Enabled at levels-O2,-O3,-Os.-ftracerโ ๐ this does tail duplication to enlarge superblock size. It simplifies the function's control flow so other optimizations can do a better job. โจ Enabled by-fprofile-useand-fauto-profile.-funroll-loopsโ ๐ซถ unrolls loops whose number of iterations can be figured out at compile time or when the loop is entered. It implies-frerun-cse-after-loop,-fweband-frename-registers, and it also turns on complete loop peeling (fully removing loops with a small constant number of iterations). โ ๏ธ This makes your code bigger, and it may or may not make it run faster, so it's not a guarantee, babe. โจ Enabled by-fprofile-useand-fauto-profile.-funroll-all-loopsโ ๐ unrolls every loop, even if the iteration count is uncertain when the loop is entered. > Warning: this usually makes programs run more slowly. It implies the same options as-funroll-loops.-fpeel-loopsโ ๐ peels loops that the compiler has enough info about to know they won't roll much (from profile feedback or static analysis). It also turns on complete loop peeling, which fully removes loops with a small constant number of iterations. โจ Enabled by-O3,-fprofile-use, and-fauto-profile.-fmove-loop-invariantsโ ๐ turns on the loop invariant motion pass in the RTL loop optimizer, which moves stuff that doesn't change inside a loop out of it. โจ Enabled at level-O1and higher, except for-Og.-fsplit-loopsโ ๐ฆ splits a loop into two if it has a condition that's always true for one side of the iteration space and always false for the other. โจ Enabled by-fprofile-useand-fauto-profile.-funswitch-loopsโ ๐ moves branches with loop-invariant conditions out of the loop. You get duplicate copies of the loop on both branches, each modified according to what the condition came out to be. โจ Enabled by-fprofile-useand-fauto-profile.-fversion-loops-for-stridesโ ๐งโโ๏ธ if a loop walks through an array with a variable stride, the compiler makes a second 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 clutch for assumed-shape arrays in Fortran, since it lets the compiler vectorize better by assuming the accesses are contiguous. ๐ญ This flag is enabled by default at -O3, and it's also enabled by -fprofile-use and -fauto-profile.
-ffunction-sections,-fdata-sectionsโ ๐ธ these put each function or data item into its own section in the output file, if the target supports arbitrary sections. The function's name or the data item's name decides the section's name in the output file. Use these on systems where the linker can optimize 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. The performance impact varies, fr. Together with linker garbage collection (the linker--gc-sectionsoption), these may 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, though. โ ๏ธ Only use these when there are significant benefits, because when you turn them on, the assembler and linker make larger object and executable files and everything gets slower. They also affect code generation: they stop the compiler and assembler from using relative locations inside a translation unit, since those locations aren't known until link time. An example of an optimization that gets blocked is relaxing calls to short call instructions.-fbranch-target-load-optimizeโ ๐ performs branch target register load optimization before prologue/epilogue threading. The use of target registers usually only shows up during reload, so hoisting loads out of loops and doing inter-block scheduling needs its own separate optimization pass.-fbranch-target-load-optimize2โ ๐ performs that same branch target register load optimization, but after prologue/epilogue threading.-fbtr-bb-exclusiveโ ๐ when doing branch target register load optimization, this stops the compiler from reusing branch target registers within any basic block.-fstdarg-optโ ๐ optimizes the prologue of variadic argument functions based on how those arguments actually get used.
NOTE: In Ubuntu 14.10 and later versions,-fstack-protector-strongis enabled by default for C, C++, ObjC, ObjC++, if none of-fno-stack-protector,-nostdlib, nor-ffreestandingare found.
-fsection-anchorsโ ๐ฆ tries to cut down on symbolic address calculations by using shared "anchor" symbols to address nearby objects. On some targets this can reduce the number of GOT entries and GOT accesses. For example, say you have this functionfoo:
static int a, b, c;
int foo (void) { return a + b + c; }
Normally it calculates the addresses of all three variables, but if you compile it with -fsection-anchors, it accesses the variables from a common anchor point instead. The effect is similar to this pseudocode (which isn't valid C):
int foo (void)
{
register int *xr = &x;
return xr[&a - &x] + xr[&b - &x] + xr[&c - &x];
}
๐ Not all targets support this option.
--param name=valueโ ๐ GCC uses various constants to decide how much optimization to do. For example, it won't inline functions that contain more than a certain number of instructions. You can tweak some of these constants on the command line with--param. โ ๏ธ The names of specific parameters, and what the values mean, are tied to the compiler's internals and can change without notice in future releases. To find the minimal, maximal, and default value of a parameter, use--help=param -Q. In every case, the value is an integer. The allowable choices fornameare:predictable-branch-outcomeโ ๐ when a branch is predicted to be taken with a probability lower than this threshold (in percent), it's considered well predictable.max-rtl-if-conversion-insnsโ โจ RTL if-conversion tries to remove conditional branches around a block and swap them for conditionally executed instructions. This parameter sets the maximum number of instructions in a block that should be considered for if-conversion. The compiler also uses other heuristics to decide whether if-conversion is likely to be profitable.max-rtl-if-conversion-predictable-cost,max-rtl-if-conversion-unpredictable-costโ ๐ง RTL if-conversion will try to remove conditional branches around a block and replace them with conditionally executed instructions. These parameters give the maximum permissible cost for the sequence that would be generated by if-conversion, depending on whether the branch is statically determined to be predictable or not. The units are the same as the GCC internalseq_costmetric. The compiler will try to provide a reasonable default for this parameter using theBRANCH_COSTtarget macro.
max-crossjump-edgesโ okay so this is the max number of incoming edges cross-jumping will consider ๐-fcrossjumpingis O(N^2) in the edges coming into each block, so cranking this up means more aggressive optimization, longer compile times, and probably only a small shrink in executable size ๐min-crossjump-insnsโ the minimum number of instructions that have to match at the end of two blocks before cross-jumping happens on them ๐ฆ This one gets ignored if every instruction in the block being cross-jumped from already matches โจmax-grow-copy-bb-insnsโ the max code size expansion factor when copying basic blocks instead of jumping ๐ธ The expansion is measured relative to a jump instruction ๐max-goto-duplication-insnsโ the max number of instructions that can be duplicated into a block that jumps to a computed goto ๐ง GCC factors computed gotos early to dodge O(N^2) behavior in a bunch of passes, then unfactors them as late as possible ๐ Only computed jumps at the end of a basic block with no more thanmax-goto-duplication-insnsinstructions get unfactored ๐ซถmax-delay-slot-insn-searchโ the max number of instructions to look at while hunting for something to fill a delay slot ๐ Once you've searched past this arbitrary number, the time saved by filling the slot is basically nothing, so GCC just stops ๐ Bigger values mean more aggressive optimization, longer compile times, and probably a small win in execution time ๐max-delay-slot-live-searchโ when filling delay slots, this is the max number of instructions to check while looking for a block with valid live register information โจ Raising this arbitrarily chosen value means more aggressive optimization and more compile time ๐ญ This parameter should be removed once the delay slot code gets rewritten to maintain the control-flow graph ๐max-gcse-memoryโ the approximate max memory that can be allocated for global common subexpression elimination ๐ง If the optimization needs more than this, it just doesn't happen ๐max-gcse-insertion-ratioโ if the ratio of expression insertions to deletions is bigger than this for any expression, RTL PRE inserts or removes the expression instead ๐ฆ That means it leaves partially redundant computations sitting in the instruction stream, which is giving messy ๐ซmax-pending-list-lengthโ the max number of pending dependencies scheduling allows before it flushes the current state and starts over ๐ Big functions with few branches or calls can build up way too-large lists that waste memory and resources, so this keeps things in check ๐max-modulo-backtrack-attemptsโ the max number of backtrack attempts the scheduler makes when modulo scheduling a loop ๐ Bigger values can exponentially increase compilation time so don't go wild ๐max-inline-insns-singleโ several parameters control the tree inliner, and this one is the max number of instructions (counted in GCC's internal representation) in a single function that the tree inliner will consider for inlining ๐ It only affects functions declaredinlineand methods implemented in a class declaration (C++) ๐max-inline-insns-autoโ when you use-finline-functions(which is included in-O3), a whole lot of functions that would normally get skipped for inlining get investigated ๐ต๏ธโโ๏ธ For those, a different and more restrictive limit applies than the one for functions declared inline ๐ธmax-inline-insns-smallโ this bound applies to calls that count as relevant with-finline-small-functions๐max-inline-insns-sizeโ this bound applies to calls that get optimized for size ๐ A little growth can be desirable here, since it helps anticipate optimization opportunities that inlining exposes โจuninlined-function-insnsโ the number of instructions the inliner counts as function overhead, like the function prologue and epilogue ๐งuninlined-function-timeโ the extra time the inliner counts as function overhead, like the time it takes to run the function's prologue and epilogue โฑ๏ธuninlined-thunk-insns,uninlined-thunk-timeโ same thing as--param uninlined-function-insnsand--param uninlined-function-time, but these apply to function thunks ๐ฆinline-min-speedupโ when the estimated performance improvement of caller + callee runtime goes over this threshold (in percent), the function can be inlined no matter what the limits on--param max-inline-insns-singleand--param max-inline-insns-autosay ๐ Main character moment ๐large-function-insnsโ the limit that defines really large functions ๐ For functions bigger than this after inlining, inlining gets constrained by--param large-function-growth๐ It's mainly there to avoid extreme compile times caused by the non-linear algorithms the back end uses ๐ซlarge-function-growthโ the max growth of a large function caused by inlining, in percent ๐ For example, a value of100limits large function growth to 2.0 times the original size ๐large-unit-insnsโ the limit that defines a large translation unit ๐ฆ Growth from inlining units bigger than this is limited by--param inline-unit-growth, and for small units that might be way too tight ๐ฅฒ Picture a unit with function A that's inline and function B that just calls A three times ๐ If B is small compared to A, the unit's growth is 300% and yet that inlining is totally sane โจ But for really big units made of tiny inlineable functions, the overall unit growth limit is needed to stop an exponential explosion of code size ๐ So for smaller units, the size gets bumped up to--param large-unit-insnsbefore--param inline-unit-growthis applied ๐งinline-unit-growthโ the max overall growth of the compilation unit caused by inlining ๐ For example, a value of20limits unit growth to 1.2 times the original size ๐ Cold functions (marked cold with an attribute or by profile feedback) don't count toward the unit size ๐งipcp-unit-growthโ the max overall growth of the compilation unit caused by interprocedural constant propagation ๐ฎ For example, a value of10limits unit growth to 1.1 times the original size ๐ซถlarge-stack-frameโ the limit that defines large stack frames ๐ฅ While inlining, the algorithm tries not to grow past this limit too much ๐large-stack-frame-growthโ the max growth of large stack frames caused by inlining, in percent ๐ For example, a value of1000limits large stack frame growth to 11 times the original size ๐คฏmax-inline-insns-recursive,max-inline-insns-recursive-autoโ the max number of instructions an out-of-line copy of a self-recursive inline function can grow into by doing recursive inlining ๐--param max-inline-insns-recursiveapplies to functions declaredinline๐ For functions not declaredinline, recursive inlining only happens when-finline-functions(included in-O3) is enabled, and--param max-inline-insns-recursive-autoapplies instead ๐ฆmax-inline-recursive-depth,max-inline-recursive-depth-autoโ the max recursion depth used for recursive inlining ๐--param max-inline-recursive-depthapplies to functions declaredinline๐ For functions not declaredinline, recursive inlining only happens when-finline-functions(included in-O3) is enabled, and--param max-inline-recursive-depth-autoapplies instead โจmin-inline-recursive-probabilityโ recursive inlining is only worth it for functions that recurse deeply on average ๐ For functions with a little recursion depth, it can hurt by bloating the prologue size or making the function body more complicated for other optimizers ๐ฌ
When profile feedback is available (see -fprofile-generate), the actual recursion depth can be guessed from the probability that a function recurses via a given call expression ๐ฎ This parameter limits inlining to only those call expressions whose probability goes over the threshold (in percent) ๐ฏ
early-inlining-insnsโ the growth the early inliner is allowed to make ๐ฃ Basically, it boosts the amount of inlining for code that has a large abstraction penalty ๐max-early-inliner-iterationsโ the limit on iterations of the early inliner ๐ This roughly bounds how many nested indirect calls the early inliner can resolve ๐ธ๏ธ Deeper chains still get handled by late inlining ๐ซถcomdat-sharing-probabilityโ the probability (in percent) that C++ inline functions with comdat visibility get shared across multiple compilation units ๐คprofile-func-internal-idโ a parameter that 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 min number of iterations under which loops won't get vectorized when-ftree-vectorizeis used ๐ The number of iterations after vectorization has to be greater than the value set by this option for vectorization to happen ๐ ๐ฅgcse-cost-distance-ratio: okay so this is the scaling factor for how far GCSE is allowed to shove an expression around ๐ฆ It only works in the code hoisting pass, ngl. The bigger the ratio, the more aggressive the hoisting gets for simple expressions (the ones costing less thangcse-unrestricted-cost). Set it to0and simple expressions stop getting hoisted entirely ๐gcse-unrestricted-cost: this is the cost, roughly one typical machine instruction, where GCSE stops putting a leash on how far an expression can travel ๐ Also only in the code hoisting pass. The lesser the cost, the more aggressive the hoisting. Set it to0and every expression gets to roam free, no limits โจmax-hoist-depth: how deep the search goes into the dominator tree when hunting for expressions to hoist ๐ณ It exists to keep the hoisting algorithm from going quadratic. A value of0means there's no limit on the search, but it may slow down compiling huge functions ๐ญmax-tail-merge-comparisons: the max number of similar basic blocks (bbs) a block gets compared against. It keeps tree tail merging from going quadratic ๐max-tail-merge-iterations: the max number of passes over the function. It's there to cap compile time during tree tail merging โฑ๏ธstore-merging-allow-unaligned: lets the store merging pass sneak in unaligned stores, but only when that's legal ๐ฆmax-stores-to-merge: the max number of stores the store merging pass will try to squish into wider stores ๐max-unrolled-insns: the max number of instructions a loop can have and still get unrolled ๐ If it does get unrolled, this same number also decides how many times the loop code gets unrolled.max-average-unrolled-insns: the max number of instructions, weighted by how likely they are to execute, that a loop can have and still get unrolled ๐ Same deal as above: this also sets how many times the loop code gets unrolled.max-unroll-times: the max number of unrollings for a single loop ๐max-peeled-insns: the max number of instructions a loop can have and still get peeled ๐ If it does get peeled, this value also decides how many times the loop code gets 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 loop iterations for a loop to still be a good candidate 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 that can get unswitched in a single loop ๐lim-expensive: the minimum cost for an expression to count as "expensive" during loop invariant motion ๐iv-consider-all-candidates-bound: a bound on how many candidates there are for induction variables. Below this number, every candidate gets considered for each use in the induction variable optimizations. Above it, only the most relevant ones get considered, so things don't go quadratic on time complexity ๐งฎiv-max-considered-uses: the induction variable optimizations give up on any loop that has more induction variable uses than this โiv-always-prune-cand-set-bound: if the candidate set is smaller than this value, GCC always tries to remove unnecessary ivs from the set whenever it adds a new one ๐งนavg-loop-niter: the average number of iterations of a loop ๐dse-max-object-size: the max size, in bytes, of objects that dead store elimination tracks bytewise ๐ฆ Bigger values may mean bigger compile times.dse-max-alias-queries-per-store: the max number of queries into the alias oracle per store ๐ Bigger values mean longer compile times, but may also remove more dead stores.scev-max-expr-size: a bound on the size of expressions used in the scalar evolutions (SCEV) analyzer. Big expressions slow the analyzer down ๐ขscev-max-expr-complexity: a bound on how complex the expressions in the SCEV analyzer can get. Complicated expressions slow it down too ๐max-tree-if-conversion-phi-args: the max number of arguments in a PHI that tree if conversion supports, unless the loop is marked with thesimdpragma ๐ฏvect-max-version-for-alignment-checks: the max number of run-time checks allowed when the vectorizer does loop versioning for alignment ๐vect-max-version-for-alias-checks: the max number of run-time checks allowed when the vectorizer does loop versioning for alias ๐ชvect-max-peeling-for-alignment: the max number of loop peels the vectorizer can do to improve access alignment. A value of-1means no limit ๐ซถmax-iterations-to-track: the max number of loop iterations the brute-force algorithm tries to evaluate when it's figuring out how many iterations a loop does ๐ต๏ธโโ๏ธhot-bb-count-ws-permille: a basic block's profile count counts as "hot" if it contributes to the given permillage (0...1000) of the entire profiled execution ๐ฅhot-bb-frequency-fraction: the fraction of the entry block's execution frequency a basic block in the function needs to hit to be considered hot ๐ก๏ธmax-predicted-iterations: the max number of loop iterations GCC predicts statically. This matters when a function has one loop with a known bound and another with an unknown one. The known count gets predicted correctly, but the unknown count averages out to roughly 10, which makes the unbounded loop look artificially cold next to the other one ๐ฅถbuiltin-expect-probability: controls how likely the expression is to have the specified value. It takes a percentage (0 ... 100) as input ๐ฒbuiltin-string-cmp-inline-length: the max length of a constant string for a builtin string cmp call to be eligible for inlining ๐งตalign-threshold: the fraction of the maximal execution frequency of a basic block in a function that's needed before GCC aligns that block ๐align-loop-iterations: a loop that's expected to iterate at least this many times gets aligned ๐งญtracer-dynamic-coverage,tracer-dynamic-coverage-feedback: these limit superblock formation once the given percentage of executed instructions is covered, which keeps code size from ballooning ๐ The-feedbackversion is only used when profile feedback is available. Real profiles are way less balanced than the estimated ones, so the threshold can be set to a larger value ๐งtracer-max-code-growth: stops tail duplication once code growth reaches the given percentage. Honestly it's a pretty artificial limit, since most of the duplicates get cleaned up later in cross jumping, so it can be set way higher than the code growth you actually want ๐ฑtracer-min-branch-ratio: stops reverse growth when the reverse probability of the best edge drops below this threshold (in percent) โฉ๏ธtracer-min-branch-probability,tracer-min-branch-probability-feedback: stops forward growth if the best edge has a probability lower than this threshold. Liketracer-dynamic-coverage, there are two versions.tracer-min-branch-probability-feedbackis for compiling with profile feedback, andtracer-min-branch-probabilityis for compiling without it. The feedback value needs to be more conservative (higher) to make the tracer effective ๐stack-clash-protection-guard-size: sets the size of the operating system's stack guard as 2 raised to num bytes ๐ก๏ธ Higher values may reduce the number of explicit probes. But if the value is bigger than the operating system's guard, your code is left open to stack clash style attacks ๐จstack-clash-protection-probe-interval: stack clash protection probes stack space as it gets allocated. This param sets the max distance between those probes as 2 raised to num bytes ๐ก Higher values may cut down on explicit probes, but a value bigger than the operating system's guard leaves the code open to stack clash style attacks ๐ฌmax-cse-path-length: the max number of basic blocks on a path that CSE considers ๐ค๏ธmax-cse-insns: the max number of instructions CSE processes before it flushes ๐ฝggc-min-expand: GCC uses a garbage collector to manage its own memory allocation ๐งน This param sets the minimum percentage the garbage collector's heap is allowed to expand between collections. Tuning it may improve compilation speed, but it has no effect on code generation ๐
The default is 30% + 70% * (RAM/1GB), with an upper bound of 100% when RAM is >= 1GB ๐งฎ If getrlimit is available, "RAM" means the smallest of actual RAM and RLIMIT_DATA or RLIMIT_AS. If GCC can't calculate RAM on a particular platform, the lower bound of 30% is used ๐ฅน Setting this param and ggc-min-heapsize to zero causes a full collection to happen at every opportunity. It's extremely slow, but it can be useful for debugging ๐๐
ggc-min-heapsizeโ okay so this is the minimum size the garbage collector's heap has to reach before it even bothers collecting garbage ๐๏ธโจ The first collection happens once the heap grows byggc-min-expand%beyondggc-min-heapsize. Tuning this can speed up compilation, but it has zero effect on code generation ๐- Default: the smaller of
RAM/8,RLIMIT_RSS, or a limit that tries to make sureRLIMIT_DATAorRLIMIT_ASdon't get exceeded, but with a lower bound of4096(four megabytes) and an upper bound of131072(128 megabytes) ๐ - If GCC can't figure out the RAM on a platform, the lower bound is used ๐คท
- Setting this super large effectively turns garbage collection off ๐
- Setting this and
ggc-min-expandto zero makes a full collection happen at every opportunity ๐
- Default: the smaller of
max-reload-search-insnsโ how far back reload is allowed to look for an equivalent register ๐ Bigger numbers mean more aggressive optimization, which makes compilation take longer for probably slightly better performance โณmax-cselib-memory-locationsโ the max number of memory locationscselibwill keep in mind ๐ง Same deal: higher means more aggressive optimization and longer compile times, for probably slightly better performance ๐ฆmax-sched-ready-insnsโ the max number of instructions ready to be issued that the scheduler will look at any one time during the first scheduling pass ๐ Higher values mean more thorough searches, so compilation time goes up for probably very little benefit ๐ญmax-sched-region-blocksโ the max number of blocks in a region that can be considered for interblock scheduling ๐งฉmax-pipeline-region-blocksโ the max number of blocks in a region that can be considered for pipelining in the selective scheduler ๐ธmax-sched-region-insnsโ the max number of insns in a region that can be considered for interblock scheduling ๐งฉmax-pipeline-region-insnsโ the max number of insns in a region that can be 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 trips through the CFG when extending regions โจ A value of0turns region extensions off ๐ซmax-sched-insn-conflict-delayโ the max conflict delay an insn can have and still be considered for speculative motion ๐โโ๏ธsched-spec-prob-cutoffโ the minimal probability of speculation success (in percents) needed before speculative insns actually get scheduled ๐sched-state-edge-prob-cutoffโ the minimum probability an edge needs before the scheduler saves its state across it ๐ค๏ธsched-mem-true-dep-costโ the minimal distance (in CPU cycles) between a store and a load that target the same memory locations โฑ๏ธselsched-max-lookaheadโ the max size of the lookahead window for selective scheduling ๐ It's basically how deep the search for available instructions goes ๐selsched-max-sched-timesโ the max number of times an instruction gets scheduled during selective scheduling ๐ This is the cap on how many iterations the instruction is allowed to be pipelined through ๐ซถselsched-insns-to-renameโ the max number of best instructions on the ready list that get considered for renaming in the selective scheduler โ๏ธsms-min-scโ the minimum stage count that the swing modulo scheduler will generate ๐ฆขmax-last-value-rtlโ the max size, counted in RTLs, that the combiner can record in an expression as the last known value of a pseudo register ๐งพmax-combine-insnsโ the max number of instructions the RTL combiner tries to combine together ๐งinteger-share-limitโ small integer constants can use a shared data structure, which saves memory and speeds things up ๐ This sets the biggest value a shared integer constant can have ๐
ssp-buffer-sizeโ the minimum size of buffers (aka arrays) that get stack smashing protection when-fstack-protectionis used ๐ก๏ธ- Before Ubuntu 10.10 this default was "8" ๐ฐ๏ธ Right now it's "4", so more functions get protected by the stack protector ๐
min-size-for-stack-sharingโ the minimum size of variables that take part in stack slot sharing when you're not optimizing ๐ฆmax-jump-thread-duplication-stmtsโ the max number of statements allowed in a block that has to be duplicated when threading jumps ๐งตmax-fields-for-field-sensitiveโ the max number of fields in a structure that get treated in a field sensitive manner during pointer analysis ๐ฌprefetch-latencyโ an estimate of how many instructions, on average, run before a prefetch finishes โณ The distance prefetched ahead scales with this number ๐ Increasing it might also mean fewer streams get prefetched (seesimultaneous-prefetches) ๐simultaneous-prefetchesโ the max number of prefetches that can run at the same time ๐โโ๏ธ๐จl1-cache-line-sizeโ the size of a cache line in the L1 data cache, in bytes ๐งl1-cache-sizeโ the size of the L1 data cache, in kilobytes ๐l2-cache-sizeโ the size of the L2 data cache, in kilobytes ๐prefetch-dynamic-stridesโ whether the loop array prefetch pass should issue software prefetch hints for strides that aren't constant ๐ฆ This can be beneficial, but a non-constant stride can make it really hard to tell when the hints will clearly help ๐ค- Set to
1if prefetch hints should be issued for non-constant strides โ - Set to
0if prefetch hints should only be issued for strides that are known to be constant and belowprefetch-minimum-strideโ
- Set to
prefetch-minimum-strideโ the minimum constant stride, in bytes, before prefetch hints kick in ๐ท If the stride is below this threshold, no prefetch hints get issued ๐ โโ๏ธ- This is super handy for processors with hardware prefetchers ๐ฅ๏ธ Those and the software prefetchers can step on each other's toes, so if the hardware prefetchers have a maximum stride they can handle, that number belongs here to get the software prefetchers working well ๐ซถ
- A value of
-1means there's no threshold, so prefetch hints can be issued for any constant stride โพ๏ธ - This only matters for strides that are known and constant ๐
loop-interchange-max-num-stmtsโ the max number of stmts in a loop that can be interchanged ๐loop-interchange-stride-ratioโ the minimum ratio between the strides of two loops for interchange to be profitable ๐min-insn-to-prefetch-ratioโ the minimum ratio between the number of instructions and the number of prefetches needed to enable prefetching in a loop ๐งฎprefetch-min-insn-to-mem-ratioโ the minimum ratio between the number of instructions and the number of memory references needed to enable prefetching in a loop ๐งฎuse-canonical-typesโ whether the compiler uses the "canonical" type system ๐ It should always be1, since that uses a more efficient internal mechanism for comparing types in C++ and Objective-C++ ๐ But if bugs in the canonical type system are causing compilation failures, set this to0to turn canonical types off ๐switch-conversion-max-branch-ratioโ switch initialization conversion won't create arrays bigger thanswitch-conversion-max-branch-ratiotimes the number of branches in the switch ๐
max-partial-antic-lengthโ the max length of the partial antic set computed during tree partial redundancy elimination (-ftree-pre) when you're optimizing at-O3and up ๐ช๏ธ For some source code, the enhanced partial redundancy elimination can run away and eat all the memory on the host machine ๐ฑ This parameter caps the length of those sets to stop the runaway behavior ๐ Setting it to0allows an unlimited set length ๐rpo-vn-max-loop-depthโ the 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 get value-numbered optimistically, and the remaining ones don't ๐ซsccvn-max-alias-queries-per-accessโ the max number of alias-oracle queries performed when hunting for redundancies in loads and stores ๐ต๏ธโโ๏ธ If this limit is hit, the search is aborted and the load or store isn't considered redundant โ The number of queries is algorithmically limited to the number of stores on all paths from the load to the function entry ๐ira-max-loops-numโ IRA uses regional register allocation by default ๐งฉ If a function has more loops than this parameter's number, only that many of the most frequently executed loops form regions for regional register allocation ๐ira-max-conflict-table-sizeโ IRA uses a sophisticated algorithm to compress the conflict table, but for huge functions the table can still eat excessive memory ๐ฉ If a function's conflict table could be bigger than the size in MB given by this parameter, the register allocator switches to a faster, simpler, lower-quality algorithm that doesn't need to build a pseudo-register conflict table ๐โโ๏ธ๐จira-loop-reserved-regsโ okay so IRA can give a more accurate read on register pressure inside loops, which helps it decide whether to move loop invariants out (see-O3) ๐. This parameter sets how many available registers get saved aside for other purposes. The default is the best value from a ton of experiments, so trust it bestie ๐ .lra-inheritance-ebb-probability-cutoffโ LRA tries to reuse values it already reloaded into registers in the insns that come after, and this trick is called inheritance ๐ฆ. The EBB is the region it uses for this. The parameter is the minimum fall-through edge probability, as a percentage, needed before a BB gets added to the inheritance EBB in LRA. The default was picked from numerous runs of SPEC2000 on x86-64, so it's been tested to death ๐ฅ.loop-invariant-max-bbs-in-loopโ loop invariant motion can be super expensive in compile time and in how much compile-time memory it eats, especially with really huge loops ๐. Any loop with more basic blocks than this parameter just won't get loop invariant motion applied to it ๐.loop-max-datarefs-for-datadepsโ building data dependencies gets pricey for very large loops ๐ญ. This parameter caps how many data references in a loop get considered for data dependence analysis. The really big loops don't get handled by the optimizations that rely on loop data dependencies, so they just get skipped ๐ธ.max-vartrack-sizeโ this sets the max number of hash table slots that can be used during variable tracking dataflow analysis for any function ๐ง. If you go over the limit while variable tracking at assignments is turned on, the analysis gets retried without it, after all the debug insns are removed from the function. If it's still over the limit even 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 number of recursion levels when the compiler tries to map variable names or debug temporaries to value expressions ๐. It's basically trading compile time for more complete debug info. If you set it too low, value expressions that could be in the debug info might not get used at all ๐. Setting it higher lets the compiler find fancier debug expressions, but compile time and memory use can grow ๐.max-debug-marker-countโ a cap on the number of debug markers (like begin stmt markers) so things don't get too complicated during inlining or expanding to RTL ๐. If a function has more of these gimple stmts than the limit, those stmts get dropped from the inlined copy of the function and from its RTL expansion ๐ .min-nondebug-insn-uidโ uids starting at this value are used for nondebug insns โญ. The range below it is reserved exclusively 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 out for one or more new parameters when their cumulative size is less than or equal toipa-sra-ptr-growth-factortimes the size of the original pointer parameter ๐ฆ.sra-max-scalarization-size-Ospeedandsra-max-scalarization-size-Osizeโ the two Scalar Reduction of Aggregates passes (SRA and IPA-SRA) are all about swapping the 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 even considered for replacement.sra-max-scalarization-size-Ospeedis for when you're compiling for speed, andsra-max-scalarization-size-Osizeis for when you're compiling for size ๐ฅ.sra-max-propagationsโ the max number of artificial accesses that SRA will track for one 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 the save/restore code sequence pairs ๐ธ. This option only applies when you're using-fgnu-tm๐ง.graphite-max-nb-scop-paramsโ to avoid exponential chaos in the Graphite loop transforms, the number of parameters in a Static Control Part (SCoP) is capped ๐. A value of zero lifts the cap. A variable whose value isn't known at compile time and is defined outside a SCoP counts as a parameter of the SCoP โจ.loop-block-tile-sizeโ loop blocking or strip mining (turned on with-floop-blockor-floop-strip-mine) strip mines each loop in the loop nest by a set number of iterations ๐. You can change the strip length with this parameter ๐.ipa-cp-value-list-sizeโ IPA-CP tries to track every possible value and type passed to a function's parameter so it can propagate them and do devirtualization ๐ง . This is the max number of values and types it stores for each formal parameter of a function ๐.ipa-cp-eval-thresholdโ IPA-CP calculates its own score for how profitable cloning is, and it goes ahead and does the cloning for any opportunity whose score is aboveipa-cp-eval-threshold๐ฅ.ipa-cp-recursion-penaltyโ the percentage penalty that recursive functions get when they're being evaluated for cloning ๐.ipa-cp-single-call-penaltyโ the percentage penalty that functions with a single call to another function get when they're being evaluated for cloning ๐.ipa-max-agg-itemsโ IPA-CP can also propagate a bunch of scalar values passed inside an aggregate ๐ซถ. This controls the max number of those values for each parameter ๐ .ipa-cp-loop-hint-bonusโ if IPA-CP figures out that a cloning candidate would make a loop's iteration count known, it adds a bonus ofipa-cp-loop-hint-bonusto that candidate's profitability score โญ.ipa-cp-array-index-hint-bonusโ same vibe as the loop one! If a cloning candidate would make the index of an array access known, IPA-CP adds a bonus ofipa-cp-array-index-hint-bonusto the candidate's profitability score ๐ฆ.ipa-max-aa-stepsโ while it analyzes function bodies, IPA-CP uses alias analysis to track values pointed to by function parameters ๐ง. So it doesn't spend forever on huge functions, it gives up and considers all memory clobbered after examiningipa-max-aa-stepsstatements that modify memory ๐ญ.lto-partitionsโ the desired number of partitions made during WHOPR compilation ๐. It should be more than the number of CPUs used for compilation ๐.lto-min-partitionโ the size of the smallest partition for WHOPR (in estimated instructions) ๐ธ. This stops tiny programs from being chopped into way too many partitions ๐.lto-max-partitionโ the size of the biggest partition for WHOPR (in estimated instructions) ๐. It gives an upper bound on how big any single partition can be โจ. It's only meant to be used with balanced partitioning ๐ซถ.lto-max-streaming-parallelismโ the max number of parallel processes used for LTO streaming ๐ฅ.cxx-max-namespaces-for-diagnostic-helpโ the max number of namespaces the compiler checks for suggestions when a C++ name lookup fails for an identifier ๐ง .sink-frequency-thresholdโ the max relative execution frequency (in percent) of the target block, compared to the statement's original block, that still allows statement sinking ๐. Bigger numbers mean more aggressive statement sinking ๐. A small positive adjustment gets applied to statements with memory operands, since those are even more profitable to sink ๐ .max-stores-to-sinkโ the max number of conditional store pairs that can be sunk ๐. Set it to 0 if either vectorization (-ftree-vectorize) or if-conversion (-ftree-loop-if-convert) is disabled ๐.allow-store-data-racesโ lets optimizers introduce new data races on stores โ ๏ธ. Set it to1to allow that, or0to not ๐ฆ. (Be careful with this one, bestie, because races can be a total disaster ๐.)case-values-thresholdโ the smallest number of different values where a jump-table is better than a tree of conditional branches ๐ง. If the value is0, the default for the machine gets used โจ.tree-reassoc-widthโ sets the max number of instructions that run 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โ lets you choose between the two implementations of-fsched-pressure๐. Algorithm 1 is the original, and it's more likely to stop instructions from getting reordered ๐. Algorithm 2 was designed as a compromise between the pretty conservative approach of algorithm 1 and the aggressive approach of the default scheduler ๐ธ. It leans harder on having a regular register file and accurate register pressure classes ๐ซถ. Seehaifa-sched.cin the GCC sources for more details ๐. The default depends on the target ๐ง.max-slsr-cand-scanโ sets the max number of existing candidates that get considered when looking 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 object protection, use--param asan-globals=0๐.asan-stackโ turns on buffer overflow detection for stack objects ๐. This protection is also on by default when using-fsanitize=address. To turn off stack protection, use--param asan-stack=0option ๐ .asan-instrument-readsโ okay so this one turns on buffer overflow detection for memory reads ๐ It's already on by default when you use-fsanitize=address. If you want to turn reads protection off, use--param asan-instrument-reads=0.asan-instrument-writesโ same energy, but for memory writes โ๏ธ Also on by default with-fsanitize=address. To disable writes protection, use--param asan-instrument-writes=0option.asan-memintrinโ detection for built-in functions ๐งฉ This is on by default with-fsanitize=address. To turn built-in functions protection off, use--param asan-memintrin=0.asan-use-after-returnโ detects use-after-return ๐ฐ๏ธ It's on by default when you use the-fsanitize=addressoption. To disable it, use--param asan-use-after-return=0.
Note: By default the check is disabled at run time ๐ To turn it on, add"detect_stack_use_after_return=1"to the environment variableASAN_OPTIONS.
asan-instrumentation-with-call-thresholdโ if the number of memory accesses in the function being instrumented is greater or equal to this number, GCC uses callbacks instead of inline checks ๐ง E.g. to skip the inline code entirely, use--param asan-instrumentation-with-call-threshold=0.use-after-scope-direct-emission-thresholdโ if a local variable's size in bytes is smaller or equal to this number, shadow memory gets poisoned (or unpoisoned) directly, instead of going through run-time callbacks โกmax-fsm-thread-path-insnsโ the max number of instructions to copy when duplicating blocks on a finite state automaton jump thread path ๐งตmax-fsm-thread-lengthโ the max number of basic blocks on a finite state automaton jump thread path ๐งตmax-fsm-thread-pathsโ the max number of new jump thread paths to create for a finite state automaton ๐งตparloops-chunk-sizeโ the chunk size of the omp schedule for loops parallelized by parloops ๐ธparloops-scheduleโ the schedule type of the omp schedule for loops parallelized by parloops ๐ธ Pick fromstatic,dynamic,guided,auto, orruntime.parloops-min-per-threadโ this is the minimum number of iterations per thread of an innermost parallelized loop where the parallel version is preferred over the single threaded one ๐ Heads up: for a parallelized loop nest, the minimum number of iterations of the outermost loop per thread is two.max-ssa-name-query-depthโ the max recursion depth when querying properties of SSA names in things like fold routines ๐ One level of recursion means following one use-def chain.hsa-gen-debug-storesโ enables special debug stores inside HSA kernels, which the libgomp plugin then reads and reports ๐ ๏ธ These stores are disabled by default, so use--param hsa-gen-debug-stores=1to turn them on.max-speculative-devirt-maydefsโ the max number of may-defs we analyze while hunting for a must-def that tells us the dynamic type of an object making a virtual call we might be able to speculatively devirtualize ๐max-vrp-switch-assertionsโ the max number of assertions to add along the default edge of a switch statement during VRP ๐unroll-jam-min-percentโ the minimum percentage of memory references that must get optimized away for unroll-and-jam to count as profitable ๐ฐunroll-jam-max-unrollโ the max number of times the outer loop can be unrolled by the unroll-and-jam transformation ๐max-rtl-if-conversion-unpredictable-costโ the max permissible cost for the sequence the RTL if-conversion pass would generate for a branch that's considered unpredictable ๐ฒmax-variable-expansions-in-unrollerโ if-fvariable-expansion-in-unrolleris used, this is the max number of times one individual variable gets expanded during loop unrolling ๐tracer-min-branch-probability-feedbackโ stop forward growth if the probability of the best edge is less than this threshold (in percent) ๐ This one is used when profile feedback is available.partial-inlining-entry-probabilityโ the max probability of the entry BB of a split region (in percent, relative to the entry BB of the function) that still lets partial inlining happen ๐งฉmax-tracked-strlensโ the max number of strings the strlen optimization pass will track string lengths for ๐งถgcse-after-reload-partial-fractionโ the threshold ratio for performing partial redundancy elimination after reload ๐ซgcse-after-reload-critical-fractionโ the threshold ratio of critical edges' execution count that allows redundancy elimination after reload โจmax-loop-header-insnsโ the max number of insns in a loop header duplicated by the copy loop headers pass ๐ซถvect-epilogues-nomaskโ enables loop epilogue vectorization using a smaller vector size ๐ฆslp-max-insns-in-bbโ the max number of instructions in a basic block that gets considered for SLP vectorization ๐avoid-fma-max-bitsโ the max number of bits for which we avoid creating FMAs ๐ โโ๏ธsms-loop-average-count-thresholdโ a threshold on the average loop count that the swing modulo scheduler considers ๐sms-dfa-historyโ the number of cycles the swing modulo scheduler looks at when checking for conflicts using DFA ๐ฐ๏ธhot-bb-count-fractionโ the fraction of the max count of repetitions of a basic block in the program that a given basic block needs to hit to be considered hot ๐ฅ This one is used in non-LTO mode.max-inline-insns-recursive-autoโ the max number of instructions a non-inline function can grow to via 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 scheduling a loop ๐๏ธlra-max-considered-reload-pseudosโ the max number of reload pseudos considered while spilling a non-reload pseudo ๐ทmax-pow-sqrt-depthโ the max depth of sqrt chains to use 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โ enables asan allocas/VLAs protection ๐ก๏ธ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, where0means unlimited โพ๏ธgraphite-max-arrays-per-scopโ the max number of arrays per scop ๐ฆmax-vartrack-reverse-op-sizeโ the max size of a loc list for which reverse ops should be added ๐งทunlikely-bb-count-fractionโ the minimum fraction of profile runs a given basic block's execution count has to be in order to not be considered unlikely ๐tracer-dynamic-coverage-feedbackโ the percentage of a function, weighted by execution frequency, that trace formation must cover ๐ 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 comparing against the number of (scaled) blocks โ๏ธfsm-maximum-phi-argumentsโ the max number of arguments a PHI can have before the FSM threader gives up on threading through its block ๐ซuninit-control-dep-attemptsโ the max number of nested calls to search for control dependencies during uninitialized variable analysis ๐indir-call-topn-profileโ tracks the top N target addresses in the indirect-call profile ๐max-once-peeled-insnsโ the max number of insns in a peeled loop that only rolls once ๐ขsra-max-scalarization-size-Osizeโ the max size, in storage units, of an aggregate that gets 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 comparing against the number of (scaled) statements ๐ปsched-autopref-queue-depthโ a hardware autoprefetcher scheduler model control flag ๐ง It sets the number of 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, not counting any instructions in inner loops that directly benefit from versioning ๐ssa-name-def-chain-limitโ the max number ofSSA_NAMEassignments to follow when figuring out a property of a variable, like its value ๐ This caps the iterations or recursive calls GCC makes while optimizing certain statements or checking whether they're valid before it issues diagnostics.
โจ Program Instrumentation Options โจ
GCC supports a bunch of command-line options that control adding run-time instrumentation to the code it normally generates ๐ For example, one purpose of instrumentation is collecting profiling statistics for finding program hot spots, doing code coverage analysis, or running 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 to build other forms of tracing or function-level instrumentation for debug or program analysis purposes ๐ฆ
-p,-pgโ okay bestie, these two make GCC sneak extra profiling code into your program ๐-pis for theprofanalysis tool and-pgis forgprof. You have to pass the option when you compile the source files you want stats on, and when you link, no skipping ๐ You can also slap the function attributeno_instrument_functionon a specific function to stop it from being profiled when you compile with these options ๐ฆ-fprofile-arcsโ this one instruments the program flow arcs โจ While your program runs, it keeps count of how many times each branch and call happens, and how many times each one is taken or returns. On targets that support constructors with priority, profiling handles constructors, destructors, and C++ constructors (and destructors) of classes used as the type of a global variable properly ๐
When the compiled program exits, it saves that data to a file called auxname.gcda for each source file. The data can be used for profile-directed optimizations (-fbranch-probabilities) or for test coverage analysis (-ftest-coverage). Each object file's auxname comes from the output file's name if you explicitly specified one and it isn't the final executable. Otherwise it's the basename of the source file. Either way, any suffix gets chopped off (so you get foo.gcda for input dir/foo.c, or dir/foo.gcda for output specified as -o dir/foo.o) ๐ธ
--coverageโ the ultimate combo ๐ It's a synonym for-fprofile-arcs-ftest-coveragewhen compiling, and for-lgcovwhen linking. Check the docs for those options for more details. Here's the whole glow-up:- Compile the source files with
-fprofile-arcsplus optimization and code generation options. For test coverage analysis, add the extra-ftest-coverageoption. You don't need to profile every single 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 as many times as you want ๐ You can even run concurrent instances of your program, and as long as the file system supports locking, the data files will update 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. Refer to the gcov documentation for further info ๐
- Compile the source files with
With -fprofile-arcs, GCC builds a program flow graph for each function in your program, then finds a spanning tree for that graph. Only the arcs that aren't on the spanning tree need instrumenting. 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 right into that block. Otherwise, a new basic block has to be created to hold it ๐ง
-ftest-coverageโ this makes a notes file that the gcov code-coverage utility uses to show your program's coverage ๐ Each source file's notes file is calledauxname.gcno. Check out the-fprofile-arcsentry above for what auxname means and how to generate test coverage data. Heads up: coverage data matches your source more closely if you don't optimize ๐-fprofile-abs-pathโ this automatically converts relative source file names into absolute path names in the.gcnofiles. That way gcov can find the right sources in projects where compilations happen with different working directories ๐ฆ-fprofile-dir=pathโ sets the directory where the profile data files get searched for, to path ๐ This only affects profile data generated by-fprofile-generate,-ftest-coverage, and-fprofile-arcs, and used by-fprofile-useand-fbranch-probabilitiesand its related options. Absolute and relative paths both work. By default GCC uses the current directory, so the profile data file lands in the same directory as the object file. To avoid file name clashes, if the object file name isn't an absolute path, GCC mangles the absolute path of the sourcename.gcdafile and uses that as the name of the.gcdafile ๐งฉ
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โ turns on the options that instrument your app so it produces a profile for later recompilation with profile feedback based optimization ๐ฎ You must use-fprofile-generateboth when compiling and when linking. 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 information, use-fprofile-use๐-fprofile-update=methodโ changes the update method for an app instrumented for profile feedback based optimization โ๏ธ The method argument should be one ofsingle,atomicorprefer-atomic. The first one is useful for single-threaded apps, and the second one prevents profile corruption by emitting thread-safe code ๐งต
โ ๏ธ Warning: if an application doesn't properly join all of its threads (or creates a detached thread), a profile file can still get corrupted. Be careful, bestie ๐
Using prefer-atomic gets transformed either to atomic, when a target supports it, or to single otherwise. The GCC driver automatically selects prefer-atomic when -pthread is present on the command line โจ
-fprofile-filter-files=regexโ only instruments functions from files whose names match any regular expression (separated by a semicolon) ๐ฏ For example,-fprofile-filter-files=main.c;module.*.cwill instrument onlymain.cand all C files starting withmodule๐-fprofile-exclude-files=regexโ only instruments functions from files whose names do not match all of the regular expressions (separated by a semicolon) ๐ซ For example,-fprofile-exclude-files=/usr/*prevents instrumentation of every file located in the/usr/folder ๐ โโ๏ธ
-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 athttps://github.com/google/sanitizers/wiki/AddressSanitizer. The run-time behavior can be influenced with theASAN_OPTIONSenvironment variable. When it's set to"help=1", the available options get shown at startup of the instrumented program. You can find the supported options athttps://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags. This option cannot be combined with-fsanitize=thread๐จ-fsanitize=kernel-addressโ enables AddressSanitizer for the Linux kernel ๐ง More details athttps://github.com/google/kasan/wiki.-fsanitize=pointer-compareโ instruments comparison operations (<,<=,>,>=) with pointer operands ๐ This option must be combined with either-fsanitize=kernel-addressor-fsanitize=address. It cannot be combined with-fsanitize=thread. Note: by default the check is disabled at run time. To turn it on, add"detect_invalid_pointer_pairs=2"to theASAN_OPTIONSenvironment variable. Using"detect_invalid_pointer_pairs=1"only detects invalid operations when both pointers are non-null ๐ซถ-fsanitize=pointer-subtractโ instruments subtraction with pointer operands ๐งฎ This option must be combined with either-fsanitize=kernel-addressor-fsanitize=address. It cannot be combined with-fsanitize=thread. Note: by default the check is disabled at run time. To enable it, add"detect_invalid_pointer_pairs=2"to theASAN_OPTIONSenvironment variable. Using"detect_invalid_pointer_pairs=1"detects invalid operations only 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. More details athttps://github.com/google/sanitizers/wiki#threadsanitizer. The run-time behavior can be influenced with theTSAN_OPTIONSenvironment variable. Seehttps://github.com/google/sanitizers/wiki/ThreadSanitizerFlagsfor a list of supported options. This option cannot be combined with-fsanitize=addressor-fsanitize=leakโ
Heads up: 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 for linking executables, and the executable has to be linked against a library that overridesmallocand other allocator functions. More details athttps://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer. The run-time behavior can be influenced with theLSAN_OPTIONSenvironment variable. This option cannot be combined with-fsanitize=thread๐ซ-fsanitize=undefinedโ enables UndefinedBehaviorSanitizer, a fast undefined behavior detector ๐ Various computations get instrumented to detect undefined behavior at runtime. Seehttps://clang.llvm.org/docs/UndefinedBehaviorSanitizer.htmlfor more details. The run-time behavior can be influenced with theUBSAN_OPTIONSenvironment variable. The current suboptions are:-fsanitize=shiftโ ๐ okay so this one checks that the result of a shift operation isn't undefined. Ngl, what counts as undefined is slightly different between C and C++, and between ISO C90 and C99, etc. It has two suboptions:-fsanitize=shift-baseand-fsanitize=shift-exponent. ๐-fsanitize=shift-exponentโ ๐ฆ checks that the second argument of a shift is not negative and is smaller than the precision of the promoted first argument. Literally the bouncer for shifts. ๐ช-fsanitize=shift-baseโ ๐ if the second argument of a shift is within range, this checks that the result of the shift is not undefined. Same vibe as above: the rules for what's undefined differ a bit between C and C++, and between ISO C90 and C99, etc. ๐ธ-fsanitize=integer-divide-by-zeroโ โจ detects integer division by zero, plusINT_MIN / -1division. ๐-fsanitize=unreachableโ ๐ฅ with this on, the compiler turns the__builtin_unreachablecall into a diagnostics message call instead. When you actually reach__builtin_unreachable, the behavior is undefined. ๐-fsanitize=vla-boundโ ๐ makes the compiler check that the size of a variable length array is positive.-fsanitize=nullโ ๐ซถ pointer checking! An app built with this will issue an error message when it tries to dereference a NULL pointer, when a reference (possibly an rvalue reference) gets bound to a NULL pointer, or when a method is invoked on an object pointed to by a NULL pointer. โ-fsanitize=returnโ ๐ return statement checking. Programs built with this will issue an error message when the end of a non-void function is reached without actually returning a value. This one works in C++ only. ๐-fsanitize=signed-integer-overflowโ ๐ checks signed integer overflow. We check that the result of+,*, and both unary and binary-doesn't overflow in signed arithmetic. Integer promotion rules totally count here! Like, this one is not an overflow:
signed char a = SCHAR_MAX;
a++;
-fsanitize=boundsโ ๐ง turns on array bounds instrumentation, so various out of bounds accesses get detected. Flexible array members, flexible array member-like arrays, and initializers of variables with static storage are not instrumented. ๐-fsanitize=bounds-strictโ ๐ the stricter array bounds check! Most out of bounds accesses get caught, 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 whenever 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 enabled by-fsanitize=undefined, since floating-point division by zero can be a totally legit way to get infinities and NaNs. ๐ซถ-fsanitize=float-cast-overflowโ ๐ enables floating-point to integer conversion checking. We check that the result of the conversion doesn't overflow. Unlike other similar options, this is not enabled by-fsanitize=undefined. Also, it does not work well withFE_INVALIDexceptions enabled. ๐ญ-fsanitize=nonnull-attributeโ ๐ instruments calls, checking whether null values are 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 detect null values being returned from those functions. ๐ต๏ธ-fsanitize=boolโ ๐ instruments loads frombool. If a value other than 0/1 gets loaded, a run-time error is issued. ๐จ-fsanitize=enumโ ๐ง instruments loads from an enum type. If a value outside the range of values for that enum type gets loaded, a run-time error is issued. ๐-fsanitize=vptrโ ๐ 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, a run-time error is issued. ๐ฅ-fsanitize=builtinโ โจ instruments arguments to selected builtin functions. If an invalid value is passed to those arguments, a run-time error is issued. E.g. passing 0 as the argument to__builtin_ctzor__builtin_clzinvokes undefined behavior and gets diagnosed by this option. ๐ง
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=allis not allowed, as some sanitizers cannot be used together. ๐ โโ๏ธ-fasan-shadow-offset=numberโ ๐งช forces GCC to use a custom shadow offset in AddressSanitizer checks. It's useful for experimenting with different shadow memory layouts in Kernel AddressSanitizer. ๐ฌ-fsanitize-sections=s1,s2,...โ ๐๏ธ sanitizes global variables in selected user-defined sections.simay contain wildcards. โจ-fsanitize-recover[=opts]โ ๐-fsanitize-recover=controls the error recovery mode for the sanitizers listed in the comma-separated list ofopts. Turn it on for a sanitizer and it tries to keep the program running as if no error happened. That means multiple runtime errors can be reported in a single run, and the exit code might say success even when errors were reported. ๐คท
The -fno-sanitize-recover= option changes this: only the first detected error is reported, and then the program exits with a non-zero exit code. ๐
Right now this feature only works for -fsanitize=undefined (and its suboptions, except -fsanitize=unreachable and -fsanitize=return), -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero, -fsanitize=bounds-strict, -fsanitize=kernel-address and -fsanitize=address. For these sanitizers, error recovery is turned on by default, except -fsanitize=address, where this feature is experimental. ๐งซ -fsanitize-recover=all and -fno-sanitize-recover=all are also accepted: the former enables recovery for all sanitizers that support it, and the latter disables recovery for all sanitizers that support it. ๐
Even if a recovery mode is turned on at the compiler side, it also needs to be enabled on the runtime library side, otherwise the failures are still fatal. ๐ The runtime library defaults to halt_on_error=0 for ThreadSanitizer and UndefinedBehaviorSanitizer, while the default value for AddressSanitizer is halt_on_error=1. 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 equivalent to specifying an opts list of:
undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
-fsanitize-address-use-after-scopeโ ๐ enables sanitization of local variables to detect use-after-scope bugs. This option sets-fstack-reusetonone. ๐ง-fsanitize-undefined-trap-on-errorโ ๐ชค instructs the compiler to report undefined behavior using__builtin_traprather than alibubsanlibrary routine. The advantage is that thelibubsanlibrary is not needed and is not 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 a call to__sanitizer_cov_trace_cmp1,__sanitizer_cov_trace_cmp2,__sanitizer_cov_trace_cmp4or__sanitizer_cov_trace_cmp8for integral comparisons with both operands variable, or__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, and__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 prevents diverting the flow of control to an unexpected target. It's intended to protect against threats like Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP). ๐โจ
Okay so the value branch tells the compiler to check that control-flow transfers are valid at indirect branch instructions (aka call/jmp instructions) ๐
. The value return checks validity when a function returns ๐. full is an alias for specifying both branch and return โจ, and none turns off the instrumentation entirely ๐
โโ๏ธ.
The value check is for the final link with link-time optimization (LTO) ๐. An error gets issued if LTO object files were compiled with different -fcf-protection values ๐จ. And check is ignored at compile time ๐.
The macro __CET__ gets defined whenever -fcf-protection is used ๐ง. Its first bit is set to 1 for the value branch, and its second bit is set to 1 for return ๐.
You can also use the nocf_check attribute to pick out which functions and calls should be skipped from instrumentation ๐.
Currently the x86 GNU/Linux target has an implementation based on Intel Control-flow Enforcement Technology (CET), which works for i686 processors or newer ๐.
๐ฃ 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โ Emit extra code to check for buffer overflows ๐ก๏ธ, like stack smashing attacks ๐ฅ. It adds a guard variable to functions with vulnerable objects, which includes functions that callallocaand functions with buffers larger than 8 bytes ๐งธ. The guards get initialized when a function is entered and then checked when it exits ๐. If a guard check fails, an error message is printed and the program exits ๐ญ.-fstack-protector-allโ Same energy as-fstack-protector, except that every single function gets protected ๐.-fstack-protector-strongโ Like-fstack-protectorbut with extra functions added to the protected list ๐ช: those that have local array definitions, or have references to local frame addresses ๐งฉ.-fstack-protector-explicitโ Like-fstack-protectorbut only protects the functions that have thestack_protectattribute ๐ฏ.-fstack-checkโ Generates code to verify that you don't go beyond the boundary of the stack ๐งฑ. You should specify this if you're running in an environment with multiple threads ๐งต, but you only rarely need it in a single-threaded environment, since stack overflow is automatically detected on nearly all systems when there's only one stack ๐.
Quick heads up, though: this switch doesn't do the checking itself ๐ . The operating system or the language runtime has to do that. The switch just makes the code that ensures they see the stack being extended ๐ซง.
You can also give it a string parameter: no means no checking, generic forces the old-style checking, and specific uses the best checking method and is equivalent to bare -fstack-check ๐.
Old-style checking is a generic mechanism that needs no 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 exceeds a fixed threshold. Note this may change the semantics of some code.
- Fixed limit on the size of the static frame of functions: when it's topped by a particular function, stack checking isn't reliable and the compiler issues a warning.
- Inefficiency: because of both the modified allocation strategy and the generic implementation, code performance gets hampered.
Old-style stack checking is also the fallback method for specific if no target support has been added in the compiler ๐.
-fstack-check= is designed for Ada's needs to detect infinite recursion and stack overflows ๐ธ. specific is an excellent choice when compiling Ada code ๐. It'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 on, the compiler only allocates one page of stack space at a time, and each page is accessed right after allocation ๐. That way, allocations can't jump over any stack guard page the operating system provides ๐ง.
Most targets don't fully support stack clash protection ๐
. On those targets, -fstack-clash-protection protects dynamic stack allocations ๐ช. It may also give limited protection for static stack allocations if the target supports -fstack-check=specific ๐ง .
๐ฃ NOTE: In Ubuntu 19.10 and later versions,-fstack-clash-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โ Generates code to make sure the stack doesn't grow beyond a certain value ๐ฆ, either the value of a register or the address of a symbol. If a bigger stack is needed, a signal gets raised at run time โก. For most targets, the signal is raised before the stack overruns the boundary, so you can catch it without taking 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 is unable to allocate any more memory ๐งฉ. This is most useful with threaded programs, since you no longer have to calculate a good stack size 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 it, there may not be much stack space available for the latter code to run ๐ฌ. If compiling all code, including library code, with -fsplit-stack isn't an option, the linker can fix up these calls so that code compiled without -fsplit-stack always has a large stack ๐ง. Support for this is implemented in the gold linker in GNU binutils release 2.21 and later ๐.
-fvtable-verify=[std|preinit|none]โ This is only available when compiling C++ code ๐. It turns on (or off, if you use-fvtable-verify=none) the security feature that checks at run time, for every virtual call, that the vtable pointer used for the call is valid for the object's type and hasn't been corrupted or overwritten ๐ต๏ธ. If an invalid vtable pointer is detected at run time, an error is reported and execution of the program is immediately halted ๐.
This option builds run-time data structures at program startup, and those are used to verify the vtable pointers ๐๏ธ. The options std and preinit control when these data structures get built โฐ. In both cases, they're built before execution reaches main ๐ช. -fvtable-verify=std builds them after shared libraries have been loaded and initialized ๐, while -fvtable-verify=preinit builds them before shared libraries have been loaded and initialized ๐ฃ.
If this option appears multiple times on the command line with different values specified, none takes highest priority over both std and preinit, and preinit takes priority over std ๐.
-fvtv-debugโ When used with-fvtable-verify=stdor-fvtable-verify=preinit, it causes debug versions of the runtime functions for the vtable verification feature to be 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 is defined, or the current working directory otherwise ๐.
Note: This feature appends data to the log file. If you want a fresh log file, be sure to delete any existing one ๐๏ธ.
-fvtv-countsโ This is a debugging flag ๐. When used with-fvtable-verify=stdor-fvtable-verify=preinit, the compiler keeps track of the total number of virtual calls it encounters and the number of verifications it inserts ๐ข. It also counts the 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 by the environment variableVTV_LOGS_DIRif that is defined, or the current working directory otherwise ๐๏ธ. It also counts the size of the vtable pointer sets for each class and writes that tovtv_class_set_sizes.login the same directory ๐.
Note: This feature appends data to the log files. To get fresh log files, be sure to delete any existing ones ๐งน.
-finstrument-functionsโ Generates instrumentation calls for function entry and exit ๐. Just after function entry and just before function exit, the following profiling functions are called with the address of the current function and its call site ๐ญ. (On some platforms,__builtin_return_addressdoesn't work beyond the current function, so the call site information may not be available to the profiling functions otherwise ๐.)
void __cyg_profile_func_enter (void *this_fn,
void *call_site);
void __cyg_profile_func_exit (void *this_fn,
void *call_site);
The first argument is the address of the start of the current function ๐, which may be looked up exactly in the symbol table ๐.
This instrumentation also happens for functions that get expanded inline inside other functions ๐
The profiling calls basically mark where the inline function is conceptually entered and exited, so addressable versions of those functions have to exist ๐ฅบ If all your uses of a function get expanded inline, that can mean extra code size ๐ And if you use extern inline in your C code, you have to provide an addressable version of the function ๐ (This is normally the case anyway, but if you get lucky and the optimizer always expands the function inline, you might have gotten away without providing static copies ๐)
A function can be given the attribute no_instrument_function, and then this instrumentation just isn't done ๐
โโ๏ธ That's super handy for things like the profiling functions listed above ๐, high-priority interrupt routines โก, and any functions the profiling functions can't safely be called from ๐ฌ (think signal handlers, if the profiling routines generate output or allocate memory ๐ซ ).
-finstrument-functions-exclude-file-list=file,file,...โ okay this one is a filter, and it's giving precision ๐ต๏ธโโ๏ธ It sets the list of functions that get excluded from instrumentation (see-finstrument-functionsfor the deets). If the file that contains a function definition matches one of thefileentries, that function is not instrumented. The match is done on substrings, so if yourfileparameter is a substring of the file name, it counts as a match ๐ฏ
For example:
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
That excludes any inline function defined in files whose pathnames contain /bits/stl or include/sys ๐งน
If, for some reason, you want to include the letter , in one of sym, write ,,. For example, -finstrument-functions-exclude-file-list=',,tmp' (note the single quote surrounding the option) โจ
-finstrument-functions-exclude-function-list=sym,sym,...โ this is basically the same energy as the file list, except this one takes function names instead ๐ฆ The name that gets matched is the user-visible one, likevector<int> blah(const vector<int> &), NOT the internal mangled name (e.g.,_Z4blahRSt6vectorIiSaIiEE) ๐ Matching is substring-based too: if sym is a substring of the function name, it's a match. For C99 and C++ extended identifiers, the function name has to be given in UTF-8, not using universal character names ๐ธ-fpatchable-function-entry=N[,M]โ okay this one is so cool ๐ง It generates N NOPs right at the beginning of each function, with the function entry point sitting before the Mth NOP. If M is omitted, it defaults to0, so the entry point lands right at the first NOP ๐ Those NOPs reserve extra space you can use to patch in any instrumentation you want at run time, provided the code segment is writable ๐ฅ You control the amount of space indirectly, through the number of NOPs ๐ The NOP instruction used corresponds to the instruction emitted by the internal GCC back-end interfacegen_nop๐ค This behavior is target-specific and may also depend on the architecture variant and/or other compilation options ๐
For run-time identification, the starting addresses of these areas (which correspond to their respective function entries minus M) are additionally collected in the __patchable_function_entries section of the resulting binary ๐๏ธ
Note that the value of __attribute__ ((patchable_function_entry (N,M))) takes precedence over the command-line option -fpatchable-function-entry=N,M. This can be used to increase the area size or to remove it completely on a single function. If N=0, no pad location is recorded ๐
The NOP instructions are inserted atโand maybe before, depending on *M*โthe function entry address, even before the prologue ๐
โจ Options Controlling the Preprocessor โจ
These options control the C preprocessor, which runs on each C source file before the actual compilation ๐งผ
If you use the -E option, nothing is done except preprocessing ๐ Some of these options only make sense together with -E, because they make the preprocessor output unsuitable for actual compilation ๐
In addition to the options listed here, there are a bunch of options to control search paths for include files, documented in Directory Options ๐บ๏ธ Options to control preprocessor diagnostics are listed in Warning Options ๐จ
-D nameโ predefine name as a macro, with definition1๐-D name=definitionโ the contents of definition get tokenized and processed as if they appeared during translation phase three in a#definedirective ๐ง In particular, the definition gets truncated by embedded newline characters โ๏ธ
If you're invoking the preprocessor from a shell or shell-like program, you may need to use the shell's quoting syntax to protect characters like spaces that have a meaning in shell syntax ๐
If you wish to define a function-like macro on the command line, write its argument list with surrounding parentheses before the equals sign (if any). 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 are given on the command line. All -imacros file and -include file options are processed after all -D and -U options โญ
-U nameโ cancel any previous definition of name, either built in or provided with a-Doption ๐งน-include fileโ processes file as if#include "file"appeared as the first line of the primary source file ๐ The first directory searched for file is the preprocessor's working directory instead of the directory containing the main source file. If it's not found there, it's 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 scanning file is thrown away ๐๏ธ The macros it defines stay defined, which lets you grab all the macros from a header without also processing its declarations ๐ซง
All files specified by -imacros are processed before all files specified by -include ๐ฅ
-undefโ do not predefine any system-specific or GCC-specific macros ๐ โโ๏ธ The standard predefined macros remain 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โ main character energy ๐ Instead of outputting the result of preprocessing, it outputs a rule suitable formakethat describes the dependencies of the main source file ๐ The preprocessor outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from-includeor-imacroscommand-line options ๐งฉ
Unless you specify it explicitly (with -MT or -MQ), the object file name 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 is 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, you should explicitly specify the dependency output file with -MF, or use an environment variable like DEPENDENCIES_OUTPUT. Debug output is still sent to the regular output stream as normal ๐ค
Passing -M to the driver implies -E, and suppresses warnings with an implicit -w ๐คซ
-MMโ like-M, but do not 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 in itself determine whether that header appears in -MM dependency output ๐ง
-MF fileโ when used with-Mor-MM, specifies a file to write the dependencies to ๐ If no-MFswitch is given, the preprocessor sends the rules to the same place it would send preprocessed output ๐
When used with the driver options -MD or -MMD, -MF overrides the default dependency output file ๐
If file is -, 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 renders that useless ๐ซ
This feature is used in automatic updating of makefiles ๐ ๏ธ
-MPโ this option tells CPP to add a phony target for each dependency other than the main file, causing each one to depend on nothing ๐ป These dummy rules work around the errorsmakegives if you remove header files without updating the Makefile to match ๐ฉน
This is typical output:
test.o: test.c test.h
test.h:
-MT targetโ changes the target of the rule emitted by dependency generation ๐ฏ By default, CPP takes the name of the main input file, deletes any directory components and any file suffix such as.c, and appends the platform's usual object suffix. The 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 ๐
Okay bestie, let's talk about the -MD flag ๐ It's giving dependency-file energy ๐
-MDโ basically-M -MF filewith a glow-up, except it does not imply-Eโจ The driver figures out thefilename like this:- If you've got an
-ooption, the driver takes that name and tacks on a.dsuffix ๐ฆ - If there's no
-o, it grabs the input file's name, strips off any directory components and the suffix, then adds.d๐ธ
- If you've got an
Lowkey the most iconic part: if you use -MD together with -E, any -o switch is understood to specify the dependency output file ๐ซถ But if you use it without -E, each -o is understood to specify a target object file instead ๐
Since -E isn't implied, -MD can make a dependency output file as a side effect of the compilation process. Main character behavior, no cap ๐
-MMDโ same vibe as-MD, but it only mentions user header files and skips system header files ๐ง-fpreprocessedโ tells the preprocessor that the input file is already preprocessed ๐ It skips macro expansion, trigraph conversion, escaped newline splicing, and processing of most directives, so it's all "already done, don't redo" ๐ The preprocessor still recognizes and removes comments, so you can pass a file preprocessed with-Cto the compiler without problems ๐ญ In this mode the integrated preprocessor is little more than a tokenizer for the front ends ๐-fpreprocessedis implicit if the input file has one of the extensions.i,.iior.mi๐ Those are the extensions GCC uses for preprocessed files created by-save-temps.
-fdirectives-onlyโ when preprocessing, handle directives but don't expand macros ๐ How it acts depends on-Eand-fpreprocessed:- With
-E, preprocessing is limited to directives like"#define","#ifdef", and"#error". Other stuff like macro expansion and trigraph conversion doesn't happen. Also,-dDgets implicitly enabled ๐ - With
-fpreprocessed, predefinition of command line and most builtin macros is disabled. Contextual macros like"__LINE__"are handled normally, which lets you compile files previously preprocessed with"-E -fdirectives-only"๐ - With both
-Eand-fpreprocessed, the-fpreprocessedrules take precedence ๐ That lets you fully preprocess files that were previously preprocessed with"-E -fdirectives-only"โจ
- With
-fdollars-in-identifiersโ accept$in identifiers ๐ฒ-fextended-identifiersโ accept universal character names in identifiers ๐ This is enabled by default for C99 (and later C standard versions) and C++ ๐ซถ-fno-canonical-system-headersโ when preprocessing, don't shorten system header paths with canonicalization ๐-ftabstop=widthโ sets the distance between tab stops ๐ This helps the preprocessor report correct column numbers in warnings or errors, even if tabs show up on the line. If the value is less than 1 or greater than 100, the option is ignored. The default is 8.-ftrack-macro-expansion[=level]โ tracks token locations across macro expansions, so the compiler can show the current macro expansion stack when an error happens inside a macro ๐ Heads up: using it makes the preprocessor and the compiler consume more memory ๐ Thelevelparameter lets you pick how precise the tracking is, so you can dial down the memory use 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 one ๐- If you give it no argument, the default parameter value is 2.
Note that -ftrack-macro-expansion=2 is activated by default ๐ฅน
-fmacro-prefix-map=old=newโ when preprocessing files residing in directoryold, expands the"__FILE__"and"__BASE_FILE__"macros as if the files lived in directorynewinstead ๐บ๏ธ You can use this to turn an absolute path into a relative one by using.fornew, which 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 is UTF-8.charsetcan be any encoding supported by the system'siconvlibrary routine ๐ธ-fwide-exec-charset=charsetโ sets the wide execution character set, used for wide string and character constants ๐ The default is UTF-32 or UTF-16, whichever matches the width ofwchar_t. Just like-fexec-charset,charsetcan be any encoding the system'siconvroutine supports, but you'll have problems with encodings that don't fit exactly inwchar_t๐ฌ-finput-charset=charsetโ sets the input character set, which is used for translating from the input file's charset to the source character set GCC uses ๐ฅ If the locale doesn't specify it, or GCC can't get that info from the locale, the default is UTF-8. The locale or this command-line option can override it, but right now the command-line option wins if there's a conflict.charsetcan be any encoding supported by the system'siconvlibrary routine ๐ฆ-fpch-depsโ when you're using precompiled headers, this makes the dependency-output flags also list the files from the precompiled header's dependencies ๐ง If you don't specify it, only the precompiled header gets listed, not the files used to create it, because those files aren't consulted when a precompiled header is used.-fpch-preprocessโ lets you use a precompiled header together with-E๐ It inserts a special#pragma,#pragma GCC pch_preprocess "filename", into the output to mark the spot 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, since the resulting preprocessed output is only really suitable as input to GCC. It gets switched on by
-save-temps. - You should never 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 may be absolute, or it may be relative to GCC's current directory.
- This option is off by default, since the resulting preprocessed output is only really 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 current working directory at the time of preprocessing ๐ With this on, the preprocessor emits, after the initial linemarker, a second linemarker with the current working directory followed by two slashes. GCC uses that directory, when it's present in the preprocessed input, as the directory emitted as the current working directory in some debugging information formats ๐ง This is implicitly enabled if debugging information is enabled, but you can inhibit it with the negated form-fno-working-directory. If the-Pflag is in the command line, this option has no effect, since no#linedirectives are emitted whatsoever ๐-A predicate=answerโ makes an assertion with the predicatepredicateand 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 answeranswer๐ซ-Cโ don't discard comments ๐ฌ All comments are passed through to the output file, except for comments in processed directives, which get deleted along with the directive.- You should be prepared for side effects when using
-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#.
- You should be prepared for side effects when using
-CCโ don't discard comments, including during macro expansion โจ This is like-C, except comments contained within macros also get passed through to the output file where the macro is expanded.- Besides the side effects of
-C,-CCconverts all C++-style comments inside a macro into C-style comments ๐ก๏ธ This stops later uses of that macro from accidentally commenting out the rest of the source line. -CCis generally used to support lint comments ๐งน
- Besides the side effects of
-Pโ inhibits generation of linemarkers in the output from the preprocessor ๐ This might be useful when you're running the preprocessor on something that isn't C code and will be sent to a program that might get confused by the linemarkers.-traditional,-traditional-cppโ try to imitate the behavior of pre-standard C preprocessors, as opposed to ISO C preprocessors ๐ฐ๏ธ See the GNU CPP manual for details.- Note that GCC doesn't otherwise attempt to emulate a pre-standard C compiler, and these options are only supported with the
-Eswitch, or when invoking CPP explicitly.
- Note that GCC doesn't otherwise attempt 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 other normal activities ๐ Each name is indented to show how deep it is in the#includestack. Precompiled header files are also printed, even if they're found to be invalid. An invalid precompiled header file is printed with...x, and a valid one with...!.
โจ OPTIONS โจ
-dlettersโ okay so this one lets you ask for debug dumps while compiling, and the letters you pass decide what gets dumped ๐ . These letters are for the preprocessor. Anything else is handled by the compiler proper or saved for future GCC versions, so it gets quietly ignored ๐ซฅ. If you mix letters that clash, the result is undefined, so... don't do that bestie ๐ญ.-dMโ instead of the usual output, you get a list of#definedirectives for every macro defined while the preprocessor runs, predefined ones included ๐ฎ. It's the best way to see what your version of the preprocessor already has baked in โจ. If you don't have a file calledfoo.h, this command shows all the predefined macros:
touch foo.h; cpp -dM foo.h
If you use -dM without -E, it's treated as a synonym for -fdump-rtl-mach ๐ค.
-dDโ basically-dM, but with two twists ๐ฆ. It skips the predefined macros, and it outputs both the#definedirectives and the preprocessed result. Both go to the standard output file ๐.-dNโ like-dD, but only the macro names show up, not their expansions ๐ธ.-dIโ adds#includedirectives to the preprocessed result ๐ง.-dUโ like-dD, but only macros that get expanded, or whose definedness gets tested in preprocessor directives, make the cut ๐. The output is delayed until that macro is used or tested, and#undefdirectives also show up for macros that were tested but were undefined at that moment ๐ซถ.-fdebug-cppโ this one is only useful if you're debugging GCC itself, so it's a niche moment ๐. When it's used from CPP or with-E, it dumps debugging info about location maps, and every token in the output gets the dump of the map its location belongs to ๐บ๏ธ. Used from GCC without-E, it does absolutely nothing ๐.-Wp,optionโ this lets you skip the compiler driver and pass option straight through to the preprocessor ๐. If option has commas, it gets split into multiple options at each comma. Here's the tea though: lots of options get modified, translated, or interpreted by the driver first, and-Wpforcibly skips that step โ ๏ธ. The preprocessor's direct interface is undocumented and can change, so whenever possible, let the driver handle your options instead ๐ซ .-Xpreprocessor optionโ passes option along to the preprocessor ๐. Use this for system-specific preprocessor options that GCC doesn't recognize.
If the option you're passing needs an argument, you have to use -Xpreprocessor twice: once for the option and once for the argument ๐.
-no-integrated-cppโ normally GCC preprocesses as part of tokenizing and parsing the input, which is the integrated way ๐งฉ. With this flag, preprocessing becomes its own separate pass before compilation. The right language front end (cc1for C,cc1plusfor C++, orcc1objfor Objective-C) gets invoked twice: once for preprocessing only, and once for compiling the preprocessed input ๐. This can come in handy with the-Bor-wrapperoptions if you want an alternate preprocessor, or extra processing of the source between preprocessing and compilation ๐.
โจ Passing Options to the Assembler โจ
You can pass options to the assembler ๐งต.
-Wa,optionโ passes option to the assembler ๐ . If option has commas, it gets split into multiple options at each comma.-Xassembler optionโ also passes option to the assembler ๐ซถ. Use it for system-specific assembler options that GCC doesn't recognize.
If the option needs an argument, 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 bother ๐ โโ๏ธ.
object-file-nameโ any file name that doesn't end in a special recognized suffix is treated as an object file or library ๐ฆ. (The linker tells object files and libraries apart by checking the file contents.) If linking happens, these object files get fed into the linker as input.-c,-S,-Eโ if you use any of these, the linker doesn't run, so don't pass object file names as arguments ๐ซ.-flinker-output=typeโ this controls the code generation of the link time optimizer โก. By default, the linker plugin picks the linker output automatically ๐ค. If you're debugging the compiler, or you want incremental linking to a non-LTO object file, it can be useful to set the type yourself ๐ ๏ธ.execโ generates a static binary, and both-fpicand-fpieget disabled ๐ง.dynโ generates a shared library.-fpicor-fPICgets preserved, but not turned on automatically ๐ฆ. This lets you build shared libraries without position independent code on architectures where that's possible, like x86.pieโ generates a-fpieexecutable ๐. You get similar optimizations asexec, except-fpieisn't disabled if you specified it at compile time.relโ assumes incremental linking is happening ๐งฉ. The sections holding intermediate LTO code get merged, pre-optimized, and written to the resulting object file. If you also pass-ffat-lto-objects, binary code gets produced for future non-LTO linking ๐ซง. The object file from an incremental link ends up smaller than a static library made from the same object files, and at link time it loads faster for the compiler than a static library, as long as most of the library's objects are used ๐โโ๏ธ.nolto-relโ configures the compiler for incremental linking where code generation is forced ๐ช. A final binary gets produced, and the intermediate code for later LTO gets stripped out ๐๏ธ. When several object files are linked together, the code comes out better optimized than with LTO disabled (cross-module inlining will happen, for example), but most of the whole program optimization benefits are lost ๐ค.
During an incremental link (with -r), the linker plugin defaults to rel ๐. Right now, GNU Binutils doesn't let you incrementally link LTO objects and non-LTO objects into a single mixed object file ๐
. If any object in an incremental link can't be used for link-time optimization, the linker plugin prints a warning and uses nolto-rel โ ๏ธ. To keep whole program optimization, it's recommended to link those objects into a static library instead ๐. Or you can use H.J. Lu's binutils, which supports mixed objects ๐.
-fuse-ld=bfdโ uses the bfd linker instead of the default one ๐ง.-fuse-ld=goldโ uses the gold linker instead of the default one ๐ช.-fuse-ld=lldโ uses the LLVM lld linker instead of the default one ๐.-llibrary,-l libraryโ searches the library named library when linking ๐. (The second form, with the library as a separate argument, is only there for POSIX compliance, and it's not recommended ๐.)
GCC passes -l straight to the linker, so check your linker's docs for the exact details ๐. The general description below applies to the GNU linker.
The linker searches a standard list of directories for the library ๐๏ธ. That list includes several standard system directories, plus any you add with -L.
Static libraries are archives of object files, with names like liblibrary.a. Some targets also support shared libraries, which usually have names like liblibrary.so ๐ฆ. If the linker finds both kinds, it prefers the shared library unless you use the -static option ๐
.
Where you put this option in the command matters ๐. The linker processes libraries and object files in the order you specify them. So foo.o -lz bar.o searches library z after foo.o but before bar.o. If bar.o calls functions in z, those functions might not get loaded ๐ญ.
-lobjcโ you need this special case of-lto link an Objective-C or Objective-C++ program ๐.-nostartfilesโ skips the standard system startup files when linking ๐ช. The standard system libraries still get used normally, unless-nostdlib,-nolibc, or-nodefaultlibsis used.-nodefaultlibsโ skips the standard system libraries when linking ๐ โโ๏ธ. Only the libraries you name get passed to the linker, and options that set linkage for system libraries, like-static-libgccor-shared-libgcc, get ignored. The standard startup files still get used normally, unless-nostartfilesis used.
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". These are usually resolved by entries in libc. When you use this option, you have to supply those entry points some other way ๐จ.
-nolibcโ skips the C library and the system libraries that are tightly coupled with it ๐ง. It still links the startup files, libgcc, and toolchain-provided language support libraries like libgnat, libgfortran, or libstdc++, unless other options stop their inclusion too ๐. This usually removes-lcfrom the link command line, along with system libraries that normally go with it and stop making sense without a C library, like-lpthreador-lmin some configurations ๐ซง. It's meant for bare-board targets where there's genuinely no C library available ๐ค.-nostdlibโ skips the standard system startup files and libraries when linking ๐. No startup files get used, and only the libraries you name get passed to the linker. Options that set linkage for system libraries, like-static-libgccor-shared-libgcc, get ignored too ๐ฅน.
okay so the compiler is lowkey going to make calls to memcmp, memset, memcpy and memmove on its own ๐ซถ Usually libc has those covered, but when you use this option, those entry points need to be supplied some other way ๐ญ
One of the standard libraries that -nostdlib and -nodefaultlibs bypass is libgcc.a ๐ง It's a library of internal subroutines that GCC uses to work around quirks of particular machines or special needs for some languages.
In most cases you still need libgcc.a even when you want to skip the other standard libraries, so when you pass -nostdlib or -nodefaultlibs, you should usually pass -lgcc as well โจ That way you don't end up with unresolved references to internal GCC library subroutines. (An example is __main, which makes sure C++ constructors get called ๐
)
-e entry,--entry=entryโ Sets the program entry point to entry. The linker is the one that reads this value, and the GNU linker will take either a symbol name or an address ๐ฆ-pieโ Makes a dynamically linked position independent executable on targets that support it ๐ For predictable results, you also need to use the same set of options you used for compilation (-fpie,-fPIE, or model suboptions) when you pass this linker option.-no-pieโ Don't make a dynamically linked position independent executable. Not me skipping the PIE ๐-static-pieโ Makes a static position independent executable on targets that support it ๐ธ It's basically like a static executable, except it can be loaded at any address without a dynamic linker. Same deal as-pie: for predictable results, match your compile options (-fpie,-fPIE, or model suboptions) when you use this linker option.-pthreadโ Links with the POSIX threads library ๐งต This works on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets. On some targets it also sets flags for the preprocessor, so you should use it consistently for both compiling and linking.-rโ Produces a relocatable object as the output. This is also called partial linking.-rdynamicโ Passes the flag-export-dynamicto the ELF linker on targets that support it ๐ฅ This tells the linker to add all symbols, not just the ones that get used, to the dynamic symbol table. It's needed for some uses ofdlopen, or if you want backtraces from inside a program.-sโ Removes all symbol table and relocation information from the executable ๐ซง-staticโ On systems that support dynamic linking, this overrides-pieand stops linking with the shared libraries. On other systems it does absolutely nothing ๐-sharedโ Produces a shared object that can be linked with other objects to form an executable. Not every system supports this one. For predictable results, you also need to use the same set of options you used for compilation (-fpic,-fPIC, or model suboptions) when you pass this linker option.[1]-shared-libgcc,-static-libgccโ On systems that provide libgcc as a shared library, these force the use of the shared or static version, respectively ๐ If no shared version of libgcc was built when the compiler was configured, these options do nothing.
There are a few situations where an application should use the shared libgcc instead of the static version. The biggest one is when the app wants to throw and catch exceptions across different shared libraries ๐ In that case, each of the libraries and the application itself should use the shared libgcc.
So the G++ driver automatically adds -shared-libgcc whenever you build a shared library or a main executable ๐ C++ programs usually use exceptions, so this is the right thing to do.
If you use the GCC driver to create shared libraries instead, you might notice they don't 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 adding relocation costs at library load time โจ
However, if a library or main executable is supposed to throw or catch exceptions, you must link it using the G++ driver, or use the option -shared-libgcc, so that it's linked with the shared libgcc. Don't skip this one bestie ๐ญ
-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 the shared version. This option tells the GCC driver to link libasan statically, without necessarily linking other libraries statically.-static-libtsanโ When-fsanitize=threadis used to link a program, the GCC driver automatically links against libtsan ๐งต If libtsan is available as a shared library and-staticisn't used, it links the shared version. This option tells the GCC driver to link libtsan statically, without necessarily linking other libraries statically.-static-liblsanโ When-fsanitize=leakis used to link a program, the GCC driver automatically links against liblsan ๐ซง If liblsan is available as a shared library and-staticisn't used, it links the shared version. This option tells the GCC driver to link liblsan statically, without necessarily linking other libraries statically.-static-libubsanโ When-fsanitize=undefinedis used to link a program, the GCC driver automatically links against libubsan ๐ธ If libubsan is available as a shared library and-staticisn't used, it links the shared version. This option tells the GCC driver to link libubsan statically, without necessarily linking other libraries statically.-static-libstdc++โ When the g++ 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 the shared version, which is normally fine. Sometimes, though, you want to freeze the version of libstdc++ your program uses without going all the way to a fully static link. This option tells the g++ driver to link libstdc++ statically, without necessarily linking other libraries statically.-symbolicโ Binds references to global symbols when building a shared object ๐ฆ It warns about any unresolved references (unless you override that with the link editor option-Xlinker -z -Xlinker defs). Only a few systems support this one.-T scriptโ Uses script as the linker script ๐ Most systems using the GNU linker support this. On some targets, like bare-board targets without an operating system, you may need-Twhen 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 have to 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 that passes the whole string as a single argument, which isn't what the linker expects ๐
โโ๏ธ
When you're using the GNU linker, it's usually way more convenient to pass arguments with the option=value syntax instead of as separate arguments ๐ For example, you can write -Xlinker -Map=output.map instead of -Xlinker -Map -Xlinker output.map. Other linkers might 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 those commas. You can use this syntax to pass an argument to the option. For example,-Wl,-Map,output.mappasses-Map output.mapto the linker. When you're using the GNU linker, you can get the same effect with-Wl,-Map=output.map.
NOTE: In Ubuntu 8.10 and later versions, for LDFLAGS, the option-Wl,-z,relrois used. To disable it, use-Wl,-z,norelro.
-u symbolโ Pretends the symbol symbol is undefined, which forces the linking of library modules that define it ๐ง You can use-umultiple times with different symbols to force loading of additional library modules.-z keywordโ-zgets passed straight 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 tell GCC which directories to search for header files, libraries, and parts of the compiler ๐
-I dir,-iquote dir,-isystem dir,-idirafter dirโ Adds the directory dir to the list of directories searched for header files during preprocessing ๐ If dir begins with=or$SYSROOT, then that=or$SYSROOTgets replaced by the sysroot prefix. See--sysrootand-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 the 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 at once ๐ The lookup order goes like this:
- For the quote form of the include directive, the directory of the current file is searched first โจ
- For the quote form of the include directive (
#include "file"), the-iquotedirectories get searched left-to-right, in the exact order they show up on the command line. ๐ - Next up are the
-Idirectories, also scanned left-to-right. ๐ธ - Then the
-isystemdirectories, scanned left-to-right too. ๐ - Now the standard system directories get their turn. ๐๏ธ
- Last but not least, the
-idirafterdirectories, scanned left-to-right. ๐ฆ
Want to swap out a system header for your own version? -I is your girl, since those directories get searched before the standard system header directories. BUT bestie, ๐จ don't use -I to add directories full of vendor-supplied system headers. Use -isystem for that. ๐ซถ
Both -isystem and -idirafter also tag their directory as a system directory, so it gets the same VIP treatment as the standard system ones. โจ
Heads up: if a standard system include directory (or one you gave to -isystem) also shows up as a -I, the -I gets ignored ๐. That directory still gets searched, just as a system directory in its normal spot in the system include chain. The whole point is so GCC's procedure for fixing buggy system headers and the ordering for the "#include_next" directive don't get messed up by accident. If you truly need to shuffle the search order for system directories, reach for -nostdinc and/or -isystem. ๐
-I-โ Splits the include path. This one is deprecated, so please don't be attached ๐- Swap to
-iquotefor any-Idirectories that come before-I-, then delete the-I-entirely. -Idirectories placed before-I-only get searched for#include "file". They are NOT searched for#include <file>.-Idirectories placed after-I-get searched for every#includedirective.- Also,
-I-stops the current file's directory from being the first place searched for#include "file". There's no way to undo that effect of-I-. ๐ญ
- Swap to
-iprefix prefixโ Setsprefixas the prefix for later-iwithprefixoptions. If the prefix is a directory, make sure you include the final/. ๐-iwithprefix dir,-iwithprefixbefore dirโ Tacksdironto the prefix you set with-iprefix, then adds the result to the include search path.-iwithprefixbeforeputs it in the same spot-Iwould, while-iwithprefixputs it where-idirafterwould. ๐ง-isysroot dirโ This is basically--sysroot, but it only applies to header files (except on Darwin targets, where it covers both headers and libraries). Check out--sysrootfor the full scoop. ๐-imultilib dirโ Usesdiras a subdirectory of the directory that holds the target-specific C++ headers. ๐-nostdincโ Skips the standard system directories when hunting for headers. Only the directories you explicitly give through-I,-iquote,-isystem, and/or-idirafterget searched, plus the current file's directory if that's appropriate. ๐ โโ๏ธ-nostdinc++โ Skips the C++-specific standard directories but still searches the other standard ones. (This one is used when building the C++ library, so it's pretty niche. ๐ค)-iplugindir=dirโ Sets the directory to search for plugins that get passed with-fplugin=nameinstead of-fplugin=path/name.so. This is NOT meant for you to use directly. Only the driver should pass it. ๐ซ-Ldirโ Addsdirto the list of directories searched for-l. ๐-Bprefixโ This is where you tell the compiler to find its own executables, libraries, include files, and data files. โจ- The compiler driver runs one or more of the subprograms
cpp,cc1,asandld. It triesprefixas a prefix for each program it attempts to run, both with and withoutmachine/version/for the corresponding target machine and compiler version. - For each subprogram, the driver tries the
-Bprefix first (if you gave one). If that name isn't found, or if-Bwasn't specified, it tries two standard prefixes:/usr/lib/gcc/and/usr/local/lib/gcc/. If neither of those turns up a file, the unmodified program name gets searched for in the directories listed in yourPATHenvironment variable. - The compiler checks whether the path given by
-Bis a directory, and if needed, it adds a directory separator character at the end of the path. -Bprefixes that effectively specify directory names also apply to libraries in the linker, because the compiler translates these options into-Loptions for the linker. They also apply to include files in the preprocessor, because the compiler translates these options into-isystemoptions for the preprocessor. In that case, the compiler appendsincludeto the prefix.- The runtime support file
libgcc.acan also be searched for using the-Bprefix, if needed. If it isn't found there, the two standard prefixes above get tried, and that's it. The file is left out of the link if those means don't find it. - Another way to specify a prefix, much like the
-Bprefix, is the environment variableGCC_EXEC_PREFIX. - As a special kludge, if the path given by
-Bis[dir/]stageN/, where N is a number in the range 0 to 9, then it gets replaced by[dir/]include. This helps with boot-strapping the compiler. ๐ฅพ
- The compiler driver runs one or more of the subprograms
-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 will instead searchdir/usr/includeanddir/usr/lib. ๐- If you use both this option and
-isysroot, then--sysrootapplies to libraries, but-isysrootapplies to header files. - The GNU linker (beginning with version 2.16) has the necessary support for this option. If your linker doesn't support it, the header file part of
--sysrootstill works, but the library part does not. ๐ฅฒ
- If you use both this option and
--no-sysroot-suffixโ For some targets, a suffix gets added to the root directory you specify with--sysroot, depending on the other options you used. That means headers might be found indir/suffix/usr/includeinstead ofdir/usr/include. This option turns off that suffix. ๐
๐ Options for Code Generation Conventions ๐
These machine-independent options control the interface conventions used in code generation. ๐
Most of them come in both positive and negative forms. The negative form of -ffoo is -fno-foo. Below, only one of the forms is listed, the one that is not the default. You can figure out the other form by removing no- or adding it. ๐ง
-fstack-reuse=reuse-level
This option controls stack space reuse for user-declared local/auto variables and compiler-generated temporaries. reuse_level can be all, named_vars, or none. all enables stack reuse for all local variables and temporaries, named_vars enables reuse only for user-defined local variables that have names, and none disables stack reuse completely. The default value is all. This option is needed when the program extends the lifetime of a scoped local variable or a compiler-generated temporary beyond the end point defined by the language. When a variable's lifetime ends and it lives in memory, the optimizing compiler has the freedom to reuse its stack space with other temporaries or scoped local variables whose live range doesn't overlap with it. Legacy code that extends local lifetime is likely to break with stack reuse optimization. ๐
For example,
int *p;
{
int local1;
p = &local1;
local1 = 10;
....
}
{
int local2;
local2 = 20;
...
}
if (*p == 10) // out of scope use of local1
{
}
Another example:
struct A
{
A(int k) : i(k), j(k) { }
int i;
int j;
};
A *ap;
void foo(const A& ar)
{
ap = &ar;
}
void bar()
{
foo(A(10)); // temp object's lifetime ends when foo returns
{
A a(20);
....
}
ap->i+= 10; // ap references out of scope temp whose space
// is reused with a. What is the value of ap->i?
}
The lifetime of a compiler-generated temporary is well defined by the C++ standard. When a temporary's lifetime ends and it lives in memory, the optimizing compiler has the freedom to reuse its stack space with other temporaries or scoped local variables whose live range doesn't overlap with it. However, some legacy code relies on the behavior of older compilers, where temporaries' stack space wasn't reused, so aggressive stack reuse can lead to runtime errors. This option is used to control the temporary stack reuse optimization. ๐งฏ
-ftrapv
This option generates traps for signed overflow on addition, subtraction, and multiplication operations. -ftrapv and -fwrapv override each other, so using -ftrapv -fwrapv on the command-line results in -fwrapv being effective. Only active options override, though, so using -ftrapv -fwrapv -fno-wrapv on the command-line results in -ftrapv being effective. โก
-fwrapvโ okay so this one tells the compiler to assume signed arithmetic overflow from addition, subtraction, and multiplication just wraps around, usingtwos-complementrepresentation ๐. It turns some optimizations on and others off, so it's a whole vibe โจ.-ftrapvand-fwrapvoverride each other, so-ftrapv -fwrapvon the command line means-fwrapvis the one that's effective ๐. Only active options override, though, so-ftrapv -fwrapv -fno-wrapvmeans-ftrapvwins ๐ .-fwrapv-pointerโ same energy, but for pointers ๐ฆ. This tells the compiler to assume pointer arithmetic overflow on addition and subtraction wraps around usingtwos-complementrepresentation. It also switches off some optimizations that assume pointer overflow is invalid ๐.-fstrict-overflowโ this one flips the switch the other way ๐. It implies-fno-wrapv -fno-wrapv-pointer, and when negated it implies-fwrapv -fwrapv-pointer๐ซถ.-fexceptionsโ enable exception handling ๐. GCC generates the extra code needed to propagate exceptions. On some targets this also means GCC generates frame unwind information for all functions, which can cause significant data size overhead, but it doesn't affect execution, so no panic ๐ธ. 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 may still need to enable it when compiling C code that has to interoperate properly 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 only lets trapping instructions throw exceptions, meaning memory references or floating-point instructions. It does not let exceptions get thrown from arbitrary signal handlers such as"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 front end, as the Ada language specification permits. Optimization passes that remove dead exceptions are enabled 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 normally don't need to turn this on yourself, because a language processor that needs this handling enables it on your behalf ๐ซถ.-fasynchronous-unwind-tablesโ generates an unwind table in DWARF format, if the target machine supports it ๐. The table is exact at each instruction boundary, so it can be used for stack unwinding from asynchronous events, like a debugger or a garbage collector ๐.-fno-gnu-uniqueโ okay this one is a little deep ๐ค. With a recent GNU assembler and C library, the C++ compiler uses the"STB_GNU_UNIQUE"binding so that template static data members and static local variables in inline functions stay unique, even with"RTLD_LOCAL". That's needed to avoid problems where a library used by two different"RTLD_LOCAL"plugins depends on a definition in one of them and then disagrees with the other about the binding of the symbol. The catch is that this makesdlcloseget ignored for affected DSOs. So if your program relies on reinitializing a DSO viadlcloseanddlopen, you can use-fno-gnu-unique๐.-fpcc-struct-returnโ returns"short" "struct"and"union"values in memory, just like the longer ones, instead of in registers ๐งบ. It's less efficient, but it lets GCC-compiled files play nicely with files compiled by other compilers, especially the Portable C Compiler (pcc) ๐ค.
The exact convention for returning structures in memory depends on the target configuration macros ๐ฏ.
Short structures and unions are the ones whose size and alignment match that of some integer type ๐.
๐จ Warning: code compiled with the-fpcc-struct-returnswitch is not binary compatible with code compiled with the-freg-struct-returnswitch. Only use it to conform to a non-default application binary interface.
-freg-struct-returnโ returns"struct"and"union"values in registers when possible ๐โโ๏ธ. This is more efficient for small structures than-fpcc-struct-returnโก.
If you specify neither -fpcc-struct-return nor -freg-struct-return, GCC defaults to whichever convention is standard for the target ๐. If there's no standard convention, GCC defaults to -fpcc-struct-return, except on targets where GCC is the principal compiler. In those cases, GCC gets to choose the standard, and it picked the more efficient register return alternative ๐.
๐จ Warning: code compiled with the-freg-struct-returnswitch is not binary compatible with code compiled with the-fpcc-struct-returnswitch. Only use it to conform to a non-default application binary interface.
-fshort-enumsโ allocates to an"enum"type only as many bytes as it needs for the declared range of possible values ๐ข. The"enum"type ends up equivalent to the smallest integer type that has enough room ๐งธ.
๐จ Warning: the -fshort-enums switch causes GCC to generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface.
-fshort-wcharโ overrides the underlying type for"wchar_t"to be"short unsigned int"instead of the target's default ๐ช. This one is super useful for building programs that run under WINE ๐ท.
๐จ Warning: the -fshort-wchar switch causes GCC to generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface.
-fno-commonโ in C code, this option controls where global variables defined without an initializer get placed. These are called tentative definitions in the C standard ๐. Tentative definitions are different from declarations of a variable with the"extern"keyword, which don't allocate any storage ๐ซง.
Unix C compilers have traditionally put storage for uninitialized global variables in a common block ๐งฑ. That lets the linker resolve all the tentative definitions of the same variable across different compilation units into the same object, or into a non-tentative definition ๐. This is the behavior -fcommon specifies, and it's the default for GCC on most targets ๐. It isn't required by ISO C though, and on some targets it can carry a speed or code size penalty on variable references ๐.
-fno-common tells the compiler to put uninitialized global variables in the BSS section of the object file instead ๐๏ธ. This stops the linker from merging tentative definitions, so you'll get a multiple-definition error if the same variable is defined in more than one compilation unit ๐ซ. Compiling with -fno-common is useful on targets where it gives better performance, or if you want to check that your program will work on other systems that always treat uninitialized variable definitions this way ๐.
-fno-identโ ignores the"#ident"directive ๐.-finhibit-size-directiveโ don't output a.sizeassembler directive, or anything else that would cause trouble if the function gets split in the middle and the two halves end up placed far apart in memory ๐งฉ. This is used when compilingcrtstuff.c, so you shouldn't need it for anything else ๐ โโ๏ธ.-fverbose-asmโ puts extra commentary into the generated assembly code to make it more readable ๐. 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 want to compare two assembler files ๐.
The added comments include:
- information on the compiler version and command-line options,
- the source code lines associated with the assembly instructions, in the form
FILENAME:LINENUMBER:CONTENT OF LINE, - hints on which high-level expressions correspond to the various assembly instruction operands.
For example, here's a C source file:
int test (int n)
{
int i;
int total = 0;
for (i = 0; i < n; i++)
total += i * i;
return total;
}
If you compile it to (x86_64) assembly via -S and emit the result straight to stdout via -o -:
gcc -S test.c -fverbose-asm -Os -o -
you'll get output similar to this ๐ฅน:
.file "test.c"
# GNU C11 (GCC) version 7.0.0 20160809 (experimental) (x86_64-pc-linux-gnu)
[...snip...]
# options passed:
[...snip...]
Okay so, we're picking up right where the -fverbose-asm stuff left off, and this is what the assembly looks like with all the comments in it ๐โจ
.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, not machines, bestie, so the exact format of those comments can change whenever. Don't build your whole life around them ๐ซถ
๐ -frecord-gcc-switches
This switch makes GCC record the command line you used to invoke the compiler into the object file it's creating. ๐
It's only implemented on some targets, and the exact format of the recording depends on both the target and the binary file format, but it usually shows up as a section full of ASCII text. It's related to -fverbose-asm, except that one only drops info into the assembler output as comments, so it never actually makes it into the object file. If you want another way to stash compiler options in the object file, check out -grecord-gcc-switches. ๐ง
๐ฆ -fpic
Generate position-independent code (PIC), which is perfect for a shared library, as long as your target machine supports it. ๐ This code reaches every constant address through a global offset table (GOT). The dynamic loader fills in the GOT entries when the program starts up. (The dynamic loader isn't part of GCC, it's part of the operating system, so no, GCC isn't doing that part, bestie ๐)
If the GOT size for your linked executable goes over a machine-specific maximum, the linker will throw an error saying that -fpic doesn't work. When that happens, just recompile with -fPIC instead. ๐ญ The maximums are 8k on the SPARC, 28k on AArch64, and 32k on the m68k and RS/6000. The x86 has no such limit, so it's giving freedom ๐ฆ
Position-independent code needs special support, so it only works on certain machines. For x86, GCC supports PIC for System V, but not for the Sun 386i. Code generated for the IBM RS/6000 is always position-independent โจ
When this flag is set, the macros __pic__ and __PIC__ are defined to 1. ๐
๐ธ -fPIC
If the target machine supports it, this emits position-independent code that's suitable for dynamic linking, and it avoids any limit on the size of the global offset table. This option makes a difference on AArch64, m68k, PowerPC, and SPARC. ๐ฅ
Same as before, this needs special support, so it only works on certain machines.
When this flag is set, the macros __pic__ and __PIC__ are defined to 2. Note the 2, not the 1 from -fpic ๐
๐ง -fpie, -fPIE
These are basically cousins of -fpic and -fPIC, but the position-independent code they generate can only be linked into executables, not shared libraries. ๐ You'll usually use them when compiling code that's getting linked with the -pie GCC 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
Do not use the PLT for external function calls in position-independent code. Instead, load the callee address at call sites from the GOT and branch to it. โจ This is 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, which is so iconic. ๐
Lazy binding needs the PLT. With -fno-plt, all external symbols get resolved at load time, so no lazy binding for you, babe ๐ญ
Alternatively, the function attribute noplt can be used to avoid calls through the PLT for specific external functions. Very targeted, very cute ๐ฏ
In position-dependent code, a few targets also convert calls to functions marked to not use the PLT so they use the GOT instead. ๐
๐ซง -fno-jump-tables
Don't use jump tables for switch statements, even where they'd be more efficient than other code generation strategies. ๐ This one is useful alongside -fpic or -fPIC when you're building code that's part of a dynamic linker and can't reference the address of a jump table. On some targets, jump tables don't require a GOT, so this option isn't needed there. ๐
๐ -ffixed-reg
Treat the register named reg as a fixed register. 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 they're defined in the REGISTER_NAMES macro in the machine description macro file. ๐ง
This flag doesn't have a negative form, because it's a three-way choice. ๐ฆ
๐ -fcall-used-reg
Treat the register named reg as an allocable register that gets clobbered by function calls. It can 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 on other registers with fixed, pervasive roles in the machine's execution model produces disastrous results. ๐ Not the vibe.
This flag doesn't have a negative form, because it's a three-way choice. ๐ฆ
๐ท -fcall-saved-reg
Treat the register named reg as an allocable register that's saved by functions. It may be allocated even for temporaries or variables that live across a call. Functions compiled this way save and restore the register reg if they use it. ๐ซถ
It is an error to use this flag with the frame pointer or stack pointer. Using it on other registers with fixed, pervasive roles in the machine's execution model produces disastrous results. ๐ญ
A different kind of disaster happens if you use this flag on a register where function values may be returned. ๐ฅ Please don't.
This flag doesn't have a negative form, because it's a three-way choice. ๐ฆ
๐ -fpack-struct[=n]
Without a value, this packs all structure members together with no holes. ๐งฉ When you give it a value, which has to be a small power of two, structure members get packed according to that value, which is treated as the maximum alignment. Objects with default alignment requirements larger than this are output potentially unaligned at the next fitting location. ๐
Warning: the -fpack-struct switch makes GCC generate code that is not binary compatible with code generated without that switch. It also makes the code suboptimal. Only use it to conform to a non-default application binary interface. โ ๏ธ
๐ -fleading-underscore
This option, and its counterpart -fno-leading-underscore, forcibly change how C symbols are represented in the object file. One use is to help link with legacy assembly code. ๐ฐ๏ธ
Warning: the -fleading-underscore switch makes GCC generate code that is not binary compatible with code generated without that switch. Only use it to conform to a non-default application binary interface. Not all targets provide complete support for this switch. ๐จ
๐งต -ftls-model=model
This alters the thread-local storage model. The model argument should be one of global-dynamic, local-dynamic, initial-exec, or local-exec. โจ Heads up, the choice is subject to optimization. The compiler might use a more efficient model for symbols that aren't visible outside of the translation unit, or if -fpic isn't given on the command line. ๐ง
The default without -fpic 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 created at run time on the stack when the address of a nested function is taken. It's used to call the nested function indirectly. Because of that, the stack has to be made executable for the program to work properly. ๐ณ
-fno-trampolines is enabled by default on a language-by-language basis, so the compiler can skip generating trampolines when it figures out that's safe, and replace them with descriptors instead. Descriptors are made up of data only, but the generated code has to be prepared to deal with them. As of this writing, -fno-trampolines is enabled by default only for Ada. ๐
Code compiled with -ftrampolines and code compiled with -fno-trampolines are not binary compatible if nested functions are present. So this option must be used on a program-wide basis and handled with extreme care ๐
๐ -fvisibility=[default|internal|hidden|protected]
This sets the default ELF image symbol visibility to the option you specify. All symbols get marked with this unless they're overridden within the code. ๐ Using this feature can massively improve linking and load times for shared object libraries, produce more optimized code, give you near-perfect API export, and prevent symbol clashes. It's strongly recommended that you use it in any shared objects you distribute. ๐ซถ
Despite the name, default always means public, meaning it's 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, which makes every symbol public. ๐ฆ
A good explanation of why ELF symbols should have the correct visibility is "How To Write Shared Libraries" by Ulrich Drepper ๐ (you can find it at https://www.akkadia.org/drepper/). But the real main character move this option unlocks is making the default hidden and marking the stuff you want public ๐ That's 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 total boon for cross-platform projects ๐
For those adding visibility support to existing code, #pragma GCC visibility is giving ๐ง You wrap the declarations you want to set visibility for with, for example, #pragma GCC visibility push(hidden) and #pragma GCC visibility pop. Bear in mind that symbol visibility should be treated as part of the API interface contract, so all new code should always specify visibility when it isn't the default ๐
That means declarations only used inside the local DSO should always be marked explicitly as hidden, so you avoid PLT indirection overheads. Making this super clear also helps readability and self-documentation, bestie ๐
Note that, due to ISO C++ specification requirements,operator newandoperator deletemust always be of default visibility. No exceptions, no cap ๐ โโ๏ธ
Be aware that headers from outside your project, especially system headers and headers from any other library you use, may not be expecting to be compiled with visibility other than the default ๐ You may need to explicitly say #pragma GCC visibility push(default) before including any of those headers.
extern declarations are not affected by -fvisibility, so a lot of code can be recompiled with -fvisibility=hidden with zero modifications โจ However, calls to extern functions with no explicit visibility go through the PLT, so it's more effective to use __attribute ((visibility)) and/or #pragma GCC visibility to tell the compiler which extern declarations should be treated as hidden ๐ฆ
Note that -fvisibility does affect C++ vague linkage entities. This means, for instance, that an exception class to be thrown between DSOs must be explicitly marked with default visibility, so the type_info nodes get unified between the DSOs ๐
An overview of these techniques, their benefits, and how to use them lives at http://gcc.gnu.org/wiki/Visibility ๐ธ
โจ -fstrict-volatile-bitfields โจ
This option should be used if accesses to volatile bit-fields (or other structure fields, although the compiler usually honors those types anyway) should use a single access of the width of the field's type, aligned to a natural alignment if possible. Lowkey very specific, but super important ๐ For example, targets with memory-mapped peripheral registers might require all such accesses to be 16 bits wide. With this flag, you can declare all peripheral bit-fields as unsigned short (assuming short is 16 bits on these targets) to force GCC to use 16-bit accesses instead of, perhaps, a more efficient 32-bit access ๐ฅ
If this option is disabled, the compiler uses the most efficient instruction. In the previous example, that might be a 32-bit load instruction, even though it accesses bytes that don't contain any portion of the bit-field, or memory-mapped registers unrelated to the one being updated ๐ญ
In some cases, such as when the packed attribute is applied to a structure field, it may not be possible to access the field with a single read or write that is correctly aligned for the target machine. In that case, GCC falls back to generating multiple accesses, rather than code that will fault or truncate the result at run time ๐ซถ
Note: Due to restrictions of the C/C++11 memory model, write accesses are not allowed to touch non bit-field members. It is therefore recommended to define all bits of the field's type as bit-field members ๐
The default value of this option is determined by the application binary interface for the target processor ๐ง
โจ -fsync-libcalls โจ
This option controls whether any out-of-line instance of the __sync family of functions may be used to implement the C++11 __atomic family of functions ๐
The default value of this option is enabled, so the only useful form of the option is -fno-sync-libcalls. This option is used in the implementation of the libatomic runtime library ๐
๐งช GCC Developer Options ๐งช
This section is for command-line options that are mainly of interest to GCC developers, including options that support compiler testing and investigation of compiler bugs and compile-time performance problems ๐ It covers 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, such as where it searches for libraries ๐ You should rarely need any of these for ordinary compilation and linking tasks, so don't stress ๐
Many developer options that make GCC dump output to a file take an optional =filename suffix. You can specify stdout or - to dump to standard output, and stderr for standard error ๐
If =filename is omitted, a default dump file name gets built by concatenating the base dump file name, a pass number, a phase letter, and a pass name ๐งฉ The base dump file name is the name of the output file the compiler produces if it's explicitly specified and isn't an executable. Otherwise, it's the source file name. The pass number is determined by the order passes are registered with the compiler's pass manager. This is generally the same as the order of execution, but passes registered by plugins, target-specific passes, or passes that are otherwise registered late get numbered higher than the pass named final, even if they run earlier ๐คฏ The phase letter is one of i (inter-procedural analysis), l (language-specific), r (RTL), or t (tree). The files get created in the directory of the output file ๐
-dletters,-fdump-rtl-pass,-fdump-rtl-pass=filenameโ Makes debugging dumps during compilation at the times specified by letters. This is how you debug the RTL-based passes of the compiler ๐
Some -dletters switches mean something different 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 for the pass and letters, and what each one means ๐
-fdump-rtl-alignmentsโ dumps after branch alignments have been computed ๐-fdump-rtl-asmconsโ dumps after fixing RTL statements that have unsatisfied in/out constraints ๐ ๏ธ-fdump-rtl-auto_inc_decโ dumps after auto-inc-dec discovery. This pass 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โ dump 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โ dump 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โ dump 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โ dump 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โ dump after the two forward propagation passes โก๏ธ-fdump-rtl-gcse1,-fdump-rtl-gcse2โ dump 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โ dumps 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โ dump after the basic block scheduling passes ๐-fdump-rtl-reeโ dumps after sign/zero extension elimination โ-fdump-rtl-seqabstrโ dumps after common sequence discovery ๐งพ-fdump-rtl-shortenโ โ๏ธ okay so this one dumps the RTL after shortening branches, bestie.-fdump-rtl-siblingโ ๐ง dumps the RTL after sibling call optimizations.-fdump-rtl-split1,-fdump-rtl-split2,-fdump-rtl-split3,-fdump-rtl-split4,-fdump-rtl-split5โ ๐ these five enable dumping after each of five rounds of instruction splitting. Five whole rounds, periodt.-fdump-rtl-smsโ ๐ dumps after modulo scheduling. Heads up, this pass only runs on some architectures, so don't be surprised if it's missing on yours ๐.-fdump-rtl-stackโ ๐ dumps after the conversion from GCC's "flat register file" registers to the x87's stack-like registers. This pass is only run on x86 variants, so it's very much an x86 moment โจ.-fdump-rtl-subreg1,-fdump-rtl-subreg2โ ๐ฆ these enable dumping after the two subreg expansion passes, one for each of the passes. Two passes, two dumps, zero drama.-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 converted to hard registers.-fdump-rtl-webโ ๐ธ๏ธ dumps after live range splitting.-fdump-rtl-regclass,-fdump-rtl-subregs_of_mode_init,-fdump-rtl-subregs_of_mode_finish,-fdump-rtl-dfinit,-fdump-rtl-dfinishโ ๐ these are defined, but they always produce empty files. Not a bug in your code, bestie, it's just how these ones are. Don't cry over blank files ๐ญ.-da,-fdump-rtl-allโ ๐ produce all the dumps listed above, all at once. Full send energy.-dAโ ๐ annotates the assembler output with miscellaneous debugging information.-dDโ ๐ธ dumps all macro definitions at the end of preprocessing, in addition to the normal output.-dHโ โญ produces a core dump whenever an error occurs. Be prepared for a core dump every time something goes sideways.-dpโ ๐ annotates the assembler output with a comment indicating which pattern and alternative is used. The length and cost of each instruction get printed too.-dPโ ๐ง dumps the RTL in the assembler output as a comment before each instruction. This also turns on-dpannotation, so you get both vibes at once.-dxโ ๐ช just generates RTL for a function instead of compiling it. This is usually used with-fdump-rtl-expand, so pair them up, iykyk.
-fdump-debugโ ๐ dumps the debugging information generated during the debug generation phase.-fdump-earlydebugโ โฐ dumps the debugging information generated during the early debug generation phase.-fdump-noaddrโ ๐ when doing debugging dumps, this suppresses address output. That makes it way more feasible todiffdebugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations. Lowkey a lifesaver.-freport-bugโ ๐จ collects and dumps debug information into a temporary file if an internal compiler error (ICE) occurs. Your ICE gets receipts, no cap.-fdump-unnumberedโ ๐ข when doing debugging dumps, this suppresses instruction numbers and address output. That makes it more feasible todiffdebugging dumps for compiler invocations with different options, especially with and without-g. Very useful, very main character.-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 generated by appending a switch-specific suffix to the source file name, and the file is created in the same directory as the output file. These dumps are possible:allโ enables all inter-procedural analysis dumps.cgraphโ dumps information about call-graph optimization, unused function removal, and inlining decisions.inlineโ dumps after function inlining.
Additionally, the options -optimized, -missed, -note, and -all can be provided, with the same meaning as for -fopt-info, defaulting to -optimized.
For example, -fdump-ipa-inline-optimized-missed will emit information on callsites that were inlined, along with callsites that were not inlined. Bestie, this is the one to reach for when you want the full tea โ.
By default, the dump will contain messages about successful optimizations (equivalent to -optimized) together with low-level details about the analysis.
-fdump-lang-all,-fdump-lang-switch,-fdump-lang-switch-options,-fdump-lang-switch-options=filenameโ ๐๏ธ these control the dumping of language-specific information. Theoptionsandfilenameparts behave exactly as described in the-fdump-treeoption. These switch values are accepted:allโ enables all language-specific dumps.classโ dumps class hierarchy information. Virtual table information is emitted unlessslimis specified. This one is C++ only, so it's a C++ girlie moment ๐.rawโ dumps the raw internal tree data. Also C++ only.
-fdump-passesโ ๐ prints on stderr the list of optimization passes that are turned on and off by the current command-line options. A little roll call for your compiler ๐ซก.-fdump-statistics-optionโ ๐ enables and controls dumping of pass statistics in a separate file. The file name is generated by appending a suffix ending in.statisticsto the source file name, and the file is created in the same directory as the output file. If the-optionform is used,-statscauses counters to be summed over the whole compilation unit, while-detailsdumps every event as the passes generate them. The default with no option is to sum counters for each function compiled.
-fdump-tree-all,-fdump-tree-switch,-fdump-tree-switch-options,-fdump-tree-switch-options=filenameโ ๐ณ these control the dumping at various stages of processing the intermediate language tree to a file. If the-optionsform is used,optionsis a list of-separated options that control the details of the dump. Not all options apply to all dumps, and any that aren't meaningful for a dump are ignored. The following options are available:addressโ prints the address of each node. Usually this isn't meaningful, since it changes according to the environment and source file. Its main use is tying up a dump file with a debug environment ๐.asmnameโ ifDECL_ASSEMBLER_NAMEhas been set for a given decl, uses that in the dump instead ofDECL_NAME. Its main use is making it easier to work backward from mangled names in the assembly file.slimโ when dumping front-end intermediate representations, inhibits dumping of members of a scope or body of a function merely because that scope has been reached. Only dumps such items when they are directly reachable by some other path. When dumping pretty-printed trees, this option inhibits dumping the bodies of control structures. When dumping RTL, 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 are pretty-printed into a C-like representation.detailsโ enables more detailed dumps (not honored by every dump option). Also includes information from the optimization passes.statsโ enables dumping various statistics about the pass (not honored by every dump option).blocksโ enables showing basic block boundaries (disabled in raw dumps).graphโ for each of the other indicated dump files (-fdump-rtl-pass), dumps a representation of the control flow graph suitable for viewing with GraphViz tofile.passid.pass.dot. Each function in the file is pretty-printed as a subgraph, so GraphViz can render them all in a single plot ๐. This option currently only works for RTL dumps, and the RTL is always dumped in slim 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.
Wanna know which tree dumps exist or find the dump for a pass you care about? Follow these steps, it's giving treasure map ๐บ๏ธ:
- Invoke GCC with
-fdump-passesand, in the stderr output, look for a code that corresponds to 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 distinguishes distinct invocations of the same pass. - To enable the creation of the dump file, append the pass code to the
-fdump-option prefix and invoke GCC with it. For example, to enable the dump from the Early Value Range Propagation pass, invoke GCC with the-fdump-tree-evrpoption. Optionally, you may specify the name of the dump file. If you don't specify one, GCC creates it as described below. - Find the pass dump in a file whose name is composed of three components separated by a period: the name of the source file GCC was invoked to compile, a numeric suffix indicating the pass number followed by the letter
tfor tree passes (and the letterrfor RTL passes), and finally the pass code. For example, the Early VRP pass dump might be in a file namedmyfile.c.038t.evrpin the current working directory. Note that the numeric codes are not stable and may change from one version of GCC to another ๐ฅบ.
-fopt-info,-fopt-info-options,-fopt-info-options=filenameโ ๐ control optimization dumps from various optimization passes. If the-optionsform is used,optionsis a list of-separated option keywords that select the dump details and optimizations. Okay so the options can be divided into three groups:
You know how -fopt-info lets you pick your optimization drama? Here's the rest of the tea โโจ
Okay so there are three buckets you can mix and match ๐
- what kinds of messages get printed ๐ฌ
- how verbose the dump is ๐
- which optimizations get included ๐ฏ
You can freely mix options from each bucket because they don't overlap ๐ซถ If things do clash, though, the later option on the command line wins. Main character energy, literally ๐
The message kinds ๐ธ
optimizedโ Prints info when an optimization is successfully applied ๐ฅ Each pass gets to decide what counts as relevant. For example, the vectorizer passes print the source location of loops that got successfully vectorized โจmissedโ Prints info about optimizations that didn't happen ๐ Each pass controls what details show up here.noteโ Prints verbose info about optimizations, like certain transformations and more detailed messages about decisions ๐งallโ Prints detailed optimization info, and this includesoptimized,missed, andnote๐
The verbosity dial ๐๏ธ
internalsโ By default, only "high-level" messages come through. This turns on extra, more detailed messages that are probably only interesting to GCC developers ๐ค (not us, bestie, we're just here to vibe ๐ญ)
The optimization groups ๐ง
You can add one or more of these keywords to pick a whole 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 groups above ๐
If you leave options out, it defaults to optimized-optall, which means dumping messages about successful optimizations from all the passes, skipping anything treated as "internals" ๐ซ
Where the output goes ๐
If you give a filename, the dumps from all the applicable optimizations get concatenated into that file. If you don't, the dump goes to stderr. You're allowed to use multiple -fopt-info options, but only one of them can include a filename. If other filenames show up, all but the first such option get ignored ๐
โโ๏ธ
Heads up, bestie: the output filename gets overwritten when you have multiple translation units ๐ฑ If you want one combined output from several translation units, use stderr instead.
Here are some examples, because examples are everything ๐ฅน This one sends the optimization info to stderr:
gcc -O3 -fopt-info
This one dumps the missed optimization report from all the passes into missed.all:
gcc -O3 -fopt-info-missed=missed.all
And this one prints info about missed optimization opportunities from the vectorization passes on stderr. Also, -fopt-info-vec-missed is equivalent to -fopt-info-missed-vec, so the order of the group names and message types after -fopt-info doesn't matter ๐ซถ
gcc -O2 -ftree-vectorize -fopt-info-vec-missed
Here's one that outputs info about missed optimizations and optimized locations from all the inlining passes into inline.txt:
gcc -O3 -fopt-info-inline-optimized-missed=inline.txt
Finally, the plot twist ๐
gcc -fopt-info-vec-missed=vec.miss -fopt-info-loop-optimized=loop.opt
Here, the two output filenames vec.miss and loop.opt clash, since only one output file is allowed. So only the first option takes effect and the rest get ignored. That means only vec.miss gets produced, and it holds the vectorizer's dumps about missed opportunities ๐
-fsave-optimization-record
Okay this one is giving machine-readable ๐ค๐ It writes a SRCFILE.opt-record.json.gz file detailing what optimizations were performed, for the ones that support -fopt-info.
This option is experimental, and the format of the data inside the compressed JSON file is subject to change. Don't build your whole life on it yet ๐
Roughly speaking, it's like 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 places (which might themselves be inlined), you can tell the copies apart ๐ช
- objects identifying the parts of the message that refer to expressions, statements, or symbol-table nodes, which of those categories they are, and, when available, their source code location ๐
- the GCC pass that emitted the message ๐ง
- the location in GCC's own code from which the message was emitted ๐ซฃ
Also, some messages are logically nested inside other messages, which reflects the implementation details of the optimization passes. Wild, I know ๐
-fsched-verbose=n
On targets that use instruction scheduling, this option controls how much debugging output the scheduler prints to the dump files ๐
- For
ngreater than zero,-fsched-verboseoutputs the same info as-fdump-rtl-sched1and-fdump-rtl-sched2. - For
ngreater than one, it also outputs basic block probabilities, detailed ready list information, and unit/insn info. - For
ngreater than two, it includes the RTL at the abort point, plus control-flow and regions info. - For
nover four,-fsched-verbosealso includes dependence info. That's a lot of info, bestie ๐ตโ๐ซ
-fenable-kind-pass and -fdisable-kind-pass=range-list
These are a set of options for explicitly disabling and enabling optimization passes ๐ง They're intended for debugging GCC itself.
Compiler users should stick to the regular options for enabling and disabling passes instead. These are for GCC devs only, so don't mess with them unless you're debugging the compiler ๐ โโ๏ธ
-fdisable-ipa-passโ Disables the IPA passpass, wherepassis the pass name. If the same pass gets statically invoked in the compiler multiple times, append a sequential number to the pass name, starting from 1 ๐ข-fdisable-rtl-passand-fdisable-rtl-pass=range-listโ Disables the RTL passpass, wherepassis the pass name. The same numbering rule applies if the pass runs more than once.range-listis 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, you can simplify the number pair to a single number. If a function's call graph node uid falls inside one of the specified ranges, the pass gets disabled for that function. The uid shows up in the function header of a dump file, and you can dump the pass names with-fdump-passes๐ง-fdisable-tree-passand-fdisable-tree-pass=range-listโ Disables the tree passpass. Check out-fdisable-rtlfor the description of the option arguments ๐ณ-fenable-ipa-passโ Enables the IPA passpass, wherepassis the pass name. Same numbering rule as above if it's invoked multiple times ๐ฆ-fenable-rtl-passand-fenable-rtl-pass=range-listโ Enables the RTL passpass. See-fdisable-rtlfor the option argument description and examples โจ-fenable-tree-passand-fenable-tree-pass=range-listโ Enables the tree passpass. See-fdisable-rtlfor the description of the option arguments ๐ธ
Here are some examples so you can see these in action ๐
# disable ccp1 for all functions
-fdisable-tree-ccp1
# disable complete unroll for function whose cgraph node uid is 1
-fenable-tree-cunroll=1
# disable gcse2 for functions at the following ranges [1,1],
# [300,400], and [400,1000]
# disable gcse2 for functions foo and foo2
-fdisable-rtl-gcse2=foo,foo2
# disable early inlining
-fdisable-tree-einline
# disable ipa inlining
-fdisable-ipa-inline
# enable tree full unroll
-fenable-tree-unroll
-fchecking and -fchecking=n
Enables internal consistency checking ๐ต๏ธโโ๏ธ The default depends on how the compiler was configured. -fchecking=2 turns on further internal consistency checking that might affect code generation, so be careful with that one ๐
-frandom-seed=string
This option 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 in the object files that produce them. Use -frandom-seed if you want reproducibly identical object files ๐ซถ
The string can be a number (decimal, octal, or hex) or an arbitrary string. If it's an arbitrary string, it gets converted to a number by computing CRC32 ๐งฎ
The string should be different for every file you compile ๐
-save-temps and -save-temps=cwd
These store the usual "temporary" intermediate files permanently ๐ They go in the current directory and get named after the source file. So compiling foo.c with -c -save-temps produces foo.i and foo.s, as well as foo.o. This makes a preprocessed foo.i output file even though the compiler now normally uses an integrated preprocessor, which is so extra but also very useful ๐ง
When you use -save-temps with the -x command-line option, it's smart enough to avoid overwriting an input source file that has the same extension as an intermediate file ๐ง If you want the intermediate file, you can rename the source file before using -save-temps ๐
Okay so bestie, running GCC in parallel is fun until it absolutely isn't ๐ญ If you compile several source files that share a base name (in different subdirectories), or the same source file for multiple output destinations, the parallel compilers are super likely to interfere with each other and overwrite each other's temporary files. Chaos ๐ For instance:
gcc -save-temps -o outdir1/foo.o indir1/foo.c&
gcc -save-temps -o outdir2/foo.o indir2/foo.c&
This can end with foo.i and foo.o being written to at the same time by both compilers. Not it ๐
-save-temps=objโ okay this one is so good โจ It stores the usual "temporary" intermediate files permanently. If the-ooption is used, the temp files are based on the object file. If-ois not used,-save-temps=objjust behaves like-save-temps.
For example:
gcc -save-temps=obj -c foo.c
gcc -save-temps=obj -c bar.c -o dir/xbar.o
gcc -save-temps=obj foobar.c -o dir2/yfoobar
Those create foo.i, foo.s, dir/xbar.i, dir/xbar.s, dir2/yfoobar.i, dir2/yfoobar.s, and dir2/yfoobar.o ๐ง
-time[=file]โ main character energy ๐ It reports the CPU time taken by each subprocess in the compilation sequence. For C source files, that's the compiler proper and the assembler (plus the linker if linking is done).
Without an output file specified, the output looks like this:
# cc1 0.12 0.01
# as 0.00 0.01
The first number on each line is the "user time," which is the time spent executing the program itself. The second number is the "system time," the time spent executing operating system routines on behalf of the program. Both numbers are in seconds โฑ๏ธ
With an output file specified, 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 displayed too, so you can later tell what file was being compiled and with which options ๐
-fdump-final-insns[=file]โ dumps the final internal representation (RTL) to file. If the optional argument is omitted (or if file is.), the dump file name is determined by appending.gkdto the compilation output file name ๐ธ-fcompare-debug[=opts]โ okay this one is giving science experiment ๐งช If no error occurs during compilation, the compiler runs a second time, adding opts and-fcompare-debug-secondto the arguments passed to the second compilation. It dumps the final internal representation in both compilations and prints an error if they differ.
If the equal sign is omitted, the default -gtoggle is used.
The environment variable GCC_COMPARE_DEBUG, if it's defined, non-empty, and nonzero, implicitly enables -fcompare-debug. If GCC_COMPARE_DEBUG is defined to a string starting with a dash, then 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 say -fcompare-debug-not-overridden. GCC rejects that as an invalid option in any actual compilation (rather than preprocessing, assembly, or linking). To get just a warning instead, setting GCC_COMPARE_DEBUG to -w%n-fcompare-debug not overridden will do ๐ซถ
-fcompare-debug-secondโ this one gets passed to the compiler implicitly for the second compilation requested by-fcompare-debug. It comes along with options to silence warnings, and it leaves out any other options that would make the compiler produce output to files or to standard output as a side effect. Dump files and preserved temporary files get renamed so they contain the additional.gkextension during the second compilation, so they don't overwrite the ones from the first ๐ฆ
When this option is passed to the compiler driver, it causes the first compilation to be skipped. That makes it useful for little other than debugging the compiler proper, so don't be surprised if it's a whole vibe check ๐
-gtoggleโ turns off generation of debug info if leaving out this option generates it, or turns it on at level 2 otherwise. Its position in the command line does not matter. It takes effect after all other options are processed, and it does so only once, no matter how many times it is given. It's mainly intended to be used with-fcompare-debug๐-fvar-tracking-assignments-toggleโ toggles-fvar-tracking-assignments, in the same way that-gtoggletoggles-gโจ-Qโ makes the compiler print out each function name as it is 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 the verbosity of the dump file for the integrated register allocator. The default value is5. If the value n is greater than or equal to10, the dump output is sent tostderrusing the same format as n minus10๐-flto-reportโ prints a report with internal details on the workings of the link-time optimizer. 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).
Disabled by default ๐
-flto-report-wpaโ like-flto-report, but only prints for the WPA phase of Link Time Optimization ๐ง-fmem-reportโ makes the compiler print some statistics about permanent memory allocation when it finishes ๐ง-fmem-report-wpaโ makes the compiler print some statistics about permanent memory allocation for the WPA phase only ๐-fpre-ipa-mem-report,-fpost-ipa-mem-reportโ make the compiler print some statistics about permanent memory allocation before or after interprocedural optimization ๐-fprofile-reportโ makes the compiler print some statistics about consistency of the (estimated) profile and the effect of individual passes ๐-fstack-usageโ okay this one is so detailed it's literally iconic ๐ 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 one is explicitly specified and it is not an executable. Otherwise, it's the basename of the source file.
Each entry is made up of 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 are allocated for the frame on function entry and released on function exit, and no stack adjustments are otherwise made in the function. The second field is this fixed number of bytes ๐ชต
The qualifier "dynamic" means the function manipulates the stack dynamically. In addition to the static allocation described above, stack adjustments are 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 of the total amount of stack used by the function. If it's not present, the amount of these adjustments is not bounded at compile time, and the second field only represents the bounded part ๐ซ
-fstatsโ emits statistics about front-end processing at the end of the compilation. This option is supported only by the C++ front end, and the information 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 bound. counter-value-list is a comma-separated list ofname:lower_bound:upper_boundtuples, which sets the lower and the upper bound of each debug counter name. Thelower_boundis optional and is zero initialized if not set. All debug counters have the initial upper bound of"UINT_MAX", sodbg_cntreturns true always unless the upper bound is set by this option.
For example, with -fdbg-cnt=dce:2:4,tail_call:10, "dbg_cnt(dce)" returns true only for the third and fourth invocation. For "dbg_cnt(tail_call)", true is returned for the first 10 invocations ๐ฏ
-print-file-name=libraryโ prints the full absolute name of the library file library that would be used when linking, and then doesn't do anything else. With this option, GCC does not compile or link anything. It just prints the file name ๐จ๏ธ-print-multi-directoryโ prints the directory name corresponding to the multilib selected by any other switches present in the command line. This directory is supposed to exist inGCC_EXEC_PREFIX๐-print-multi-libโ prints the mapping from multilib directory names to the compiler switches that enable them. The directory name is separated from the switches by;, and each switch starts with an@instead of the-, without spaces between multiple switches. This is supposed to ease shell processing ๐-print-multi-os-directoryโ prints the path to OS libraries for the selected multilib, relative to somelibsubdirectory. If OS libraries are present in thelibsubdirectory and no multilibs are used, this is usually just.. If OS libraries are present in libsuffix sibling directories, it prints something like../lib64,../lib, or../lib32. Or, if OS libraries are present inlib/subdirsubdirectories, it prints something likeamd64,sparcv9, orev6๐ธ-print-multiarchโ prints the path to OS libraries for the selected multiarch, relative to somelibsubdirectory ๐ฆ-print-prog-name=programโ like-print-file-name, but searches for a program such ascpp๐-print-libgcc-file-nameโ same as-print-file-name=libgcc.a. This is useful when you use-nostdlibor-nodefaultlibsbut you still want to link withlibgcc.a. You can do:
gcc -nostdlib <files>... `gcc -print-libgcc-file-name`
-print-search-dirsโ okay so this one prints the name of the configured installation directory and a list of the program and library directories gcc searches, and then it stops. It doesn't do anything else ๐
This is SO useful when gcc throws installation problem, cannot exec cpp0: No such file or directory. ๐ญ To fix that, you either put cpp0 and the other compiler components where gcc expects to find them, or you set the environment variable GCC_EXEC_PREFIX to the directory where you installed them. Don't forget the trailing / ๐ซถ
-print-sysrootโ prints the target sysroot directory used during compilation. This is the target sysroot set either at configure time or with the--sysrootoption, and it might have an extra suffix that depends on your compilation options. If no target sysroot is set, this prints nothing ๐ธ-print-sysroot-headers-suffixโ prints the suffix added to the target sysroot when searching for headers. If the compiler wasn't configured with one, you'll get an error instead. Then it's done, and it doesn't do anything else โจ-dumpmachineโ prints the compiler's target machine, likei686-pc-linux-gnu. Then it stops ๐ฆ-dumpversionโ prints the compiler version, like3.0,6.3.0or7, and then it's done ๐ This is the version used in filesystem paths and specs. Depending on how the compiler was configured, it can be one number (major version), two numbers split by a dot (major and minor), or three numbers split 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 ๐ฅ-dumpspecsโ prints the compiler's built-in specs and then stops. (This one is used when GCC itself is being built ๐ง)
โจ Machine-Dependent Options โจ
Every target machine GCC supports can have its own options. Think: compiling for a specific processor variant or ABI, or tweaking optimizations for that exact machine ๐ By convention, machine-specific option names start with -m.
Some compiler configurations also support extra target-specific options, usually so they match other compilers on the same platform ๐
๐ AArch64 Options ๐
These options are defined for AArch64 implementations:
-mabi=nameโ generates code for the data model you pick.ilp32is the SysV-like model whereint,long intand pointers are 32 bits.lp64is the SysV-like model whereintis 32 bits, butlong intand pointers are 64 bits.
The default depends on your specific target configuration. Heads up, bestie: the LP64 and ILP32 ABIs are not link-compatible. You have to compile your whole program with the same ABI and link it with a compatible set of libraries ๐
-mbig-endianโ generates big-endian code. This is the default when GCC is configured for anaarch64_be-*-*target ๐-mgeneral-regs-onlyโ generates code that only uses the general-purpose registers. This stops the compiler from 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-*-*target ๐-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. This is the default code model ๐ธ-mcmodel=largeโ generates code for the large code model. It makes no assumptions about addresses and section sizes. Programs can only be statically linked ๐ฅ-mstrict-align,-mno-strict-alignโ avoids or allows generating memory accesses that might not be aligned on a natural object boundary, as described in the architecture specification โจ-momit-leaf-frame-pointer,-mno-omit-leaf-frame-pointerโ omits or keeps the frame pointer in leaf functions. The first one, omitting it, is the default ๐-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ generates stack protection code using a canary atguard. The supported locations areglobalfor a global canary, orsysregfor a canary in an appropriate system register ๐ก๏ธ
With the sysreg choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset also tell it which system register to use as the base register for reading the canary, and what offset from that base register to read from. There's no default register or offset, because this is entirely for use within the Linux kernel ๐ง
-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ generates stack protection code using a canary atguard. The supported locations areglobalfor a global canary, orsysregfor a canary in an appropriate system register ๐ก๏ธ
With the sysreg choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset also tell it which system register to use as the base register for reading the canary, and what offset from that base register to read from. There's no default register or offset, because this is entirely for use within the Linux kernel ๐ง
-mtls-dialect=descโ uses TLS descriptors as the thread-local storage mechanism for dynamic accesses of TLS variables. This is the default ๐-mtls-dialect=traditionalโ uses traditional TLS as the thread-local storage mechanism for dynamic accesses of TLS variables ๐-mtls-size=sizeโ specifies the bit size of immediate TLS offsets. 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. It works by 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 workaround happens at link time, so this option only passes the matching flag to the linker ๐-mlow-precision-recip-sqrt,-mno-low-precision-recip-sqrtโ enables or disables the reciprocal square root approximation. This only does something if-ffast-mathor-funsafe-math-optimizationsis used too. Turning it on drops the precision of reciprocal square root results to about 16 bits for single precision and about 32 bits for double precision ๐ซ-mlow-precision-sqrt,-mno-low-precision-sqrtโ enables or disables the square root approximation. This only does something if-ffast-mathor-funsafe-math-optimizationsis used too. Turning it on drops square root precision to about 16 bits for single precision and about 32 bits for double precision. If you enable it, it also implies-mlow-precision-recip-sqrt๐-mlow-precision-div,-mno-low-precision-divโ enables or disables the division approximation. This only does something if-ffast-mathor-funsafe-math-optimizationsis used too. Turning it on drops division precision to about 16 bits for single precision and about 32 bits for double precision โญ-mtrack-speculation,-mno-track-speculationโ enables or disables generating extra code that tracks speculative execution through conditional branches. The tracking state can then be used by the compiler when it expands calls to"__builtin_speculation_safe_copy", so it can produce a more efficient code sequence ๐ง-moutline-atomics,-mno-outline-atomicsโ enables or disables calls to out-of-line helpers that implement atomic operations. At runtime, these helpers figure out whether the LSE instructions from ARMv8.1-A can be used. If not, they fall back to the load/store-exclusive instructions that are in the base ARMv8.0 ISA ๐ซ
This option only applies when compiling for the base ARMv8.0 instruction set. If you use a later revision, like -march=armv8.1-a or -march=armv8-a+lse, the ARMv8.1-Atomics instructions get used directly. The same goes for -mcpu= when the selected CPU supports the lse feature ๐
-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 permissible values for arch are armv8-a, armv8.1-a, armv8.2-a, armv8.3-a, armv8.4-a, armv8.5-a or native.
The value armv8.5-a implies armv8.4-a and enables compiler support for the ARMv8.5-A architecture extensions.
The value armv8.4-a implies armv8.3-a and enables compiler support for the ARMv8.4-A architecture extensions.
The value armv8.3-a implies armv8.2-a and enables compiler support for the ARMv8.3-A architecture extensions.
The value armv8.2-a implies armv8.1-a and enables compiler support for the ARMv8.2-A architecture extensions.
The value armv8.1-a implies armv8-a and enables compiler support for the ARMv8.1-A architecture extension. In particular, it enables the +crc, +lse, and +rdma features ๐ฅ
The value native is available on native AArch64 GNU/Linux and makes the compiler pick the architecture of the host system. This option has no effect if the compiler can't recognize the architecture of the host system,
The permissible values for feature are listed in the sub-section on aarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. If you specify conflicting feature modifiers, the right-most feature is used ๐
GCC uses name to decide what kind of instructions it can emit when generating assembly code. If -march is specified without -mtune or -mcpu also being specified, the code is tuned to perform well across a range of target processors that implement the target architecture ๐ธ
-mtune=nameโ okay bestie, this one tells GCC which target processor to tune your code's performance for ๐ The permissible values are:generic,cortex-a35,cortex-a53,cortex-a55,cortex-a57,cortex-a72,cortex-a73,cortex-a75,cortex-a76,ares,exynos-m1,emag,falkor,neoverse-e1,neoverse-n1,neoverse-n2,neoverse-v1,neoverse-512tvb,qdf24xx,saphira,phecda,xgene1,vulcan,octeontx,octeontx81,octeontx83,a64fx,thunderx,thunderxt88,thunderxt88p1,thunderxt81,tsv110,thunderxt83,thunderx2t99,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, andnative.
The big.LITTLE combos are lowkey the cutest ๐ฆ cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55, and cortex-a76.cortex-a55 tell GCC to tune for a big.LITTLE system.
neoverse-512tvb is giving very specific energy ๐ฅ It means GCC should tune for Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits per cycle. In other words, GCC tunes 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.
Also, on native AArch64 GNU/Linux systems, native tunes performance to the host system โจ If the compiler can't recognize the host's processor, this option has no effect.
Where none of -mtune=, -mcpu= or -march= are specified, the code gets 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 attached ๐ The form is-mcpu=cpu{+[no]feature}*, wherecputakes the same values as-mtune. The allowedfeaturevalues are documented in the sub-sectionaarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. If you specify conflicting feature modifiers, the right-most one wins.
GCC uses name to decide what kind of instructions it can emit when generating assembly (as if by -march), and which processor to tune performance for (as if by -mtune). If you use this option together with -march or -mtune, those take precedence over the matching part of -mcpu.
-mcpu=neoverse-512tvb is special ๐ It doesn't refer to one specific core, but to all Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits a cycle. Unless you override it with -march, -mcpu=neoverse-512tvb generates code that can run on a Neoverse V1 core, since Neoverse V1 is the first Neoverse core with these properties. Unless you override it with -mtune, -mcpu=neoverse-512tvb tunes code the same way as -mtune=neoverse-512tvb.
-moverride=stringโ lets you override 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 ๐ง
-mverbose-cost-dumpโ turns on verbose cost model dumping in the debug dump files ๐ This one's for debugging the compiler itself.-mpc-relative-literal-loads,-mno-pc-relative-literal-loadsโ enable or disable 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 where return address signing gets applied ๐ The permissible values arenone, which turns return address signing off,non-leaf, which enables pointer signing for functions that aren't leaf functions, andall, which enables pointer signing for all functions. The default value isnone.
This option has been deprecated by -mbranch-protection ๐
-mbranch-protection=none|standard|pac-ret[+leaf]|btiโ picks which branch protection features to use ๐ก๏ธnoneis the default and turns off all types of branch protection.standardturns on all types of branch protection features, and if a feature has extra tuning options,standardsets it to its standard level.pac-ret[+leaf]turns on return address signing to its standard level: it signs 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.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
On top of that, -mharden-sls=all enables all SLS hardening, while -mharden-sls=none disables all of it.
-msve-vector-bits=bitsโ sets the number of bits 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 that works with any size of vector register, and "vector-length specific" output that lets GCC make assumptions about the vector length when that's useful for optimization. The possible values of bits are: scalable, 128, 256, 512, 1024 and 2048. Specifying scalable selects vector-length agnostic output. At present, -msve-vector-bits=128 also generates vector-length agnostic output. All other values generate vector-length specific code. The behavior of these values may change in future releases, and no value except scalable should be relied on for producing code that's portable across different hardware SVE vector lengths ๐ฅบ
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 their inverses nofeature ๐
crcโ Enable CRC extension. This is on by default for-march=armv8.1-a.cryptoโ Enable Crypto extension. This also enables Advanced SIMD and floating-point instructions.fpโ Enable floating-point instructions. This is on by default for all possible values for options-marchand-mcpu.simdโ Enable Advanced SIMD instructions. This also enables floating-point instructions. This is on by default for all possible values for options-marchand-mcpu.sveโ Enable Scalable Vector Extension instructions. This also enables Advanced SIMD and floating-point instructions.lseโ Enable Large System Extension instructions. This is on by default for-march=armv8.1-a.rdmaโ Enable Round Double Multiply Accumulate instructions. This is on by default for-march=armv8.1-a.fp16โ Enable FP16 extension. This also enables floating-point instructions.fp16fmlโ Enable FP16 fmla extension. This also enables FP16 extensions and floating-point instructions. This option is enabled by default for-march=armv8.4-a. Use of this option with architectures prior to Armv8.2-A is not supported ๐rcpcโ Enable the RcPc extension. This doesn't change code generation from GCC, but it is passed on to the assembler, enabling inline asm statements to use instructions from the RcPc extension.dotprodโ Enable the Dot Product extension. This also enables Advanced SIMD instructions.aesโ Enable the Armv8-aaesandpmullcrypto extension. This also enables Advanced SIMD instructions.sha2โ Enable the Armv8-asha2crypto extension. This also enables Advanced SIMD instructions.sha3โ Enable thesha512andsha3crypto extension. This also enables Advanced SIMD instructions. Use of this option with architectures prior to Armv8.2-A is not supported ๐sm4โ Enable thesm3andsm4crypto extension. This also enables Advanced SIMD instructions. Use of this option with architectures prior to Armv8.2-A is not supported ๐profileโ Enable the Statistical Profiling extension. This option is only to enable the extension at the assembler level and does not affect code generation.rngโ Enable the Armv8.5-a Random Number instructions. This option is only to enable the extension at the assembler level and does not affect code generation.memtagโ Enable the Armv8.5-a Memory Tagging Extensions. This option is only to enable the extension at the assembler level and does not affect code generation.sbโ Enable the Armv8-a Speculation Barrier instruction. This option is only to enable the extension at the assembler level and does not affect code generation. This option is enabled by default for-march=armv8.5-a.ssbsโ Enable the Armv8-a Speculative Store Bypass Safe instruction. This option is only to enable the extension at the assembler level and does not affect code generation. This option is enabled by default for-march=armv8.5-a.predresโ Enable the Armv8-a Execution and Data Prediction Restriction instructions. This option is only to enable the extension at the assembler level and does not affect code generation. This option is enabled by default for-march=armv8.5-a.
Feature crypto implies aes, sha2, and simd, which implies fp. Conversely, nofp implies nosimd, which implies nocrypto, noaes and nosha2 ๐
๐ธ Adapteva Epiphany Options
These -m options are defined for Adapteva Epiphany ๐
-mhalf-reg-fileโ Don't allocate any register in the range"r32"..."r63". That lets code run on hardware variants that lack these registers ๐ง-mprefer-short-insn-regsโ Preferentially allocate registers that allow short instruction generation. This can result in increased instruction count, so it may either reduce or increase overall code size ๐คทโโ๏ธ-mbranch-cost=numโ okay so this sets how pricey branches are, roughly likenum"simple" instructions ๐ง. It's only a heuristic though, so don't expect the exact same results across releases ๐.-mcmoveโ turns on the generation of conditional moves โจ-mnops=numโ emitsnumNOPs before every other instruction it generates ๐ฆ-mno-soft-cmpsfโ for single-precision floating-point comparisons, this emits anfsubinstruction and tests the flags ๐ฅ It's faster than a software comparison, BUT it can give wrong results with NaNs, or when two different small numbers subtract to zero ๐ญ The default is-msoft-cmpsf, which is slower but IEEE-compliant, so it's the safe bestie choice ๐ซถ-mstack-offset=numโ sets the offset between the top of the stack and the stack pointer ๐ฅ E.g., a value of8means the eight bytes in the range"sp+0...sp+7"can be used by leaf functions without stack allocation. Values other than8or16are untested and unlikely to work ๐
Heads up: this option changes the ABI, so compiling a program with a different stack offset than the libraries were built with generally does not work ๐ซ
This one is useful if you want to evaluate whether a different stack offset gives you better code. But to actually build working programs with a different stack offset, it's recommended to configure the toolchain with the appropriate --with-stack-offset=num option.
-mno-round-nearestโ makes the scheduler assume the rounding mode has been set to truncating. The default is-mround-nearest๐-mlong-callsโ if no attribute says otherwise, 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 (otherwise direct) call ๐ This is the default.-mshort-callsโ if no attribute says otherwise, this assumes all direct calls are in range of the"b"/"bl"instructions, so it uses those for direct calls ๐โโ๏ธ The default is-mlong-calls.-msmall16โ assumes addresses can be loaded as 16-bit unsigned values ๐ This does not 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 it to the mode you mostly need at function start can make your programs smaller and faster by avoiding unnecessary mode switches ๐
mode can be set to one of the following values:
callerโ any mode at function entry is valid, and it gets retained or restored when the function returns and when it calls other functions. This is useful for compiling libraries or other compilation units you might want to drop into different programs with different prevailing FPU modes. Being able to use a single object file can outweigh the size and speed overhead of any extra mode switching you'd need with a more specific choice ๐งtruncateโ the mode used for floating-point calculations with truncating (i.e. round towards zero) rounding mode. That includes conversion from floating point to integer โ๏ธround-nearestโ the mode used for floating-point calculations with round-to-nearest-or-even rounding mode ๐ฏintโ the mode used to perform integer calculations in the FPU, e.g. integer multiply, or integer multiply-and-accumulate ๐ข
The default is -mfp-mode=caller โจ
-mno-split-lohi,-mno-postinc,-mno-postmodifyโ code generation tweaks that disable, respectively, splitting of 32-bit loads, generation of post-increment addresses, and generation of post-modify addresses ๐งฉ The defaults aremsplit-lohi,-mpost-inc, and-mpost-modify.-mnovect-doubleโ changes the preferred SIMD mode to SImode ๐ The default is-mvect-double, which uses DImode as the preferred SIMD mode.-max-vect-align=numโ the maximum alignment for SIMD vector mode types ๐nummay be4or8, and the default is8. Note that this is an ABI change, even though many library function interfaces are unaffected if they don't use SIMD vector modes in places that affect the size and/or alignment of relevant types ๐-msplit-vecmove-earlyโ splits vector moves into single word moves before reload ๐ช In theory this can give better register allocation, but so far the reverse seems to be generally the case ๐-m1reg-regโ specifies a register to hold the constant-1, which makes loading small negative constants and certain bitmasks faster โก Allowable values forregarer43andr63, which specify use of that register as a fixed register, andnone, which means no register is used for this purpose. The default is-m1reg-none.
๐ธ AMD GCN Options ๐ธ
These options are defined specifically for the AMD GCN port ๐
-march=gpu,-mtune=gpuโ sets the architecture type or tuning forgpu๐ฎ Supported values forgpuare:fijiโ compile for GCN3 Fiji devices (gfx803).gfx900โ compile for GCN5 Vega 10 devices (gfx900).
-mstack-size=bytesโ specifies how many bytes of stack space will be requested for each GPU thread (wave-front) ๐งต Beware, because there may be many threads and limited memory available ๐ญ The size of the stack allocation may also have an impact on run-time performance. The default is32KBwhen using OpenACC or OpenMP, and1MBotherwise.
๐ฆ ARC Options ๐ฆ
The following options control the architecture variant that code is being compiled for ๐ง
-mbarrel-shifterโ generates instructions supported by the barrel shifter ๐ This is the default unless-mcpu=ARC601or-mcpu=ARCEMis in effect.-mjli-alwaysโ forces a function call to use thejli_sinstruction ๐ฃ This option is valid only for the ARCv2 architecture.-mcpu=cpuโ sets the architecture type, register usage, and instruction scheduling parameters forcpu๐ง There are also shortcut alias options available for backward compatibility and convenience. Supported values forcpuare:arc600โ compile for ARC600. Aliases:-mA6,-mARC600.arc601โ compile for ARC601. Alias:-mARC601.arc700โ compile for ARC700. Aliases:-mA7,-mARC700. This is the default when configured with--with-cpu=arc700.arcemโ compile for ARC EM.archsโ compile for ARC HS.emโ compile for ARC EM CPU with no hardware extensions.em4โ compile for ARC EM4 CPU.em4_dmipsโ compile for ARC EM4 DMIPS CPU.em4_fpusโ compile for ARC EM4 DMIPS CPU with the single-precision floating-point extension.em4_fpudaโ compile for ARC EM4 DMIPS CPU with single-precision floating-point and double assist instructions.hsโ compile for ARC HS CPU with no hardware extensions except the atomic instructions.hs34โ compile for ARC HS34 CPU.hs38โ compile for ARC HS38 CPU.hs38_linuxโ compile for ARC HS38 CPU with all hardware extensions on.arc600_normโ compile for ARC 600 CPU with "norm" instructions enabled.arc600_mul32x16โ compile for ARC 600 CPU with "norm" and 32x16-bit multiply instructions enabled.arc600_mul64โ compile for ARC 600 CPU with "norm" and "mul64"-family instructions enabled.arc601_normโ compile for ARC 601 CPU with "norm" instructions enabled.arc601_mul32x16โ compile for ARC 601 CPU with "norm" and 32x16-bit multiply instructions enabled.arc601_mul64โ compile for ARC 601 CPU with "norm" and "mul64"-family instructions enabled.nps400โ compile for ARC 700 on NPS400 chip.em_miniโ compile for ARC EM minimalist configuration featuring a reduced register set.
-mdpfp,-mdpfp-compactโ generates double-precision FPX instructions, tuned for the compact implementation ๐ท-mdpfp-fastโ generates double-precision FPX instructions, tuned for the fast implementation ๐๏ธ-mno-dpfp-lrsrโ disables "lr" and "sr" instructions from using FPX extension aux registers ๐ซ-meaโ generates extended arithmetic instructions ๐งฎ Currently only "divaw", "adds", "subs", and "sat16" are supported. This is always enabled for-mcpu=ARC700.-mno-mpyโ does not generate "mpy"-family instructions for ARC700 ๐ฅ This option is deprecated.-mmul32x16โ generates 32x16-bit multiply and multiply-accumulate instructions โ๏ธ-mmul64โ generates "mul64" and "mulu64" instructions ๐ฅ Only valid for-mcpu=ARC600.-mnormโ generates "norm" instructions ๐ This is the default if-mcpu=ARC700is in effect.-mspfp,-mspfp-compactโ generates single-precision FPX instructions, tuned for the compact implementation ๐ผ-mspfp-fastโ generates single-precision FPX instructions, tuned for the fast implementation โก-msimdโ enables generation of ARC SIMD instructions via target-specific builtins ๐ Only valid for-mcpu=ARC700.-msoft-floatโ this option is ignored; it's provided for compatibility purposes only ๐ซ Software floating-point code is emitted by default, and this default can be overridden by FPX options:-mspfp,-mspfp-compact, or-mspfp-fastfor single precision, and-mdpfp,-mdpfp-compact, or-mdpfp-fastfor double precision.-mswapโ generates "swap" instructions ๐-matomicโ enables use of the locked load/store conditional extension to implement atomic memory built-in functions ๐ Not available for ARC 6xx or ARC EM cores.-mdiv-remโ enables "div" and "rem" instructions for ARCv2 cores โ-mcode-densityโ enables code density instructions for ARC EM ๐ฐ This option is on by default for ARC HS.-mll64โ enables double load/store operations for ARC HS cores ๐-mtp-regno=regnoโ specifies the thread pointer register number ๐งต-mmpy-option=multoโ โจ pick your multiplier design! You can passmultoas a string or a number.wlh1is the default, and these are the options:0ornoneโ No multiplier at all ๐1orwโ A 16x16 multiplier that's fully pipelined. It turns on"mpyw"and"mpyuw".2orwlh1โ A 32x32 multiplier that's fully pipelined (1 stage) ๐ฅ. It also unlocks"mpy","mpyu","mpym","mpymu", and"mpy_s". This is the default ๐.3orwlh2โ Also a 32x32 multiplier that's fully pipelined, but with 2 stages. It also unlocks"mpy","mpyu","mpym","mpymu", and"mpy_s".4orwlh3โ Two 16x16 multipliers that are blocking and sequential. It also unlocks"mpy","mpyu","mpym","mpymu", and"mpy_s".5orwlh4โ One 16x16 multiplier that's blocking and sequential. It also unlocks"mpy","mpyu","mpym","mpymu", and"mpy_s".6orwlh5โ One 32x4 multiplier that's blocking and sequential. It also unlocks"mpy","mpyu","mpym","mpymu", and"mpy_s".7orplus_dmpyโ ARC HS SIMD support ๐ฆ.8orplus_macdโ ARC HS SIMD support ๐ฆ.9orplus_qmacwโ ARC HS SIMD support ๐ฆ.
This option is only available for ARCv2 cores ๐ซถ.
-mfpu=fpuโ โจ turns on specific floating-point hardware extensions for ARCv2 cores. These are thefpuvalues you can use:fpusโ Single-precision floating-point hardware extensions ๐ธ.fpudโ Double-precision floating-point hardware extensions. The single-precision extension comes along too. Not available for ARC EM ๐.fpudaโ Double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision extension is on too. This option is only available for ARC EM.fpuda_divโ Double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision floating-point, square-root, and divide extensions are on as well. This option is only available for ARC EM.fpuda_fmaโ Double-precision floating-point hardware extensions using double-precision assist instructions. The single-precision floating-point and fused multiply and add extensions are on too. This option is only available for ARC EM.fpuda_allโ Double-precision floating-point hardware extensions using double-precision assist instructions. Every single-precision floating-point hardware extension is on too. This option is only available for ARC EM.fpus_divโ Single-precision floating-point, square-root, and divide hardware extensions ๐ง.fpud_divโ Double-precision floating-point, square-root, and divide hardware extensions. This option includesfpus_div. Not available for ARC EM.fpus_fmaโ Single-precision floating-point and fused multiply and add hardware extensions ๐.fpud_fmaโ Double-precision floating-point and fused multiply and add hardware extensions. This option includesfpus_fma. Not available for ARC EM.fpus_allโ Every single-precision floating-point hardware extension ๐.fpud_allโ Every single- and double-precision floating-point hardware extension. Not available for ARC EM ๐ .
-mirq-ctrl-saved=register-range, blink, lp_countโ tells the processor which general-purpose registers to automatically save and restore on interrupt entry and exit โจ. Theregister-rangeis two registers separated by a dash. It always starts with"r0", and the upper limit is the"fp"register.blinkandlp_countare optional. This option is only valid for ARC EM and ARC HS cores.-mrgf-banked-regs=numberโ sets how many registers get copied into the second register bank when a fast interrupt starts. Fast interrupts are the ones with the highest priority level,P0โก. They only save thePCandSTATUS32registers, so they skip memory transactions during entry and exit. Use this when you're using fast interrupts on an ARC V2 family processor. Permitted values are4,8,16, and32.-mlpc-width=widthโ sets the width of the"lp_count"register ๐ข. Valid values forwidthare8,16,20,24,28, and32bits. The default is locked at 32 bits. If the width is less than 32, the compiler won't try to turn your loops into the zero-delay loop mechanism unless it knows that"lp_count"can hold the loop-counter value. Depending on the width, the compiler and run-time library might still use the loop mechanism for various needs. This option defines the"__ARC_LPC_WIDTH__"macro with the value ofwidth.-mrf16โ makes the compiler generate code for a 16-entry register file ๐. This option defines the"__ARC_RF16__"preprocessor macro.-mbranch-indexโ turns onbiorbihinstructions to implement jump tables ๐ฆ.
The following options are passed through to the assembler, and they also define preprocessor macro symbols ๐.
-mdsp-packaโ passed down to the assembler to enable the DSP Pack A extensions. It also sets the"__Xdsp_packa"preprocessor symbol. This option is deprecated. ๐-mdvbfโ passed down to the assembler to enable the dual Viterbi butterfly extension. It also sets the"__Xdvbf"preprocessor symbol. This option is deprecated. ๐-mlockโ passed down to the assembler to enable the locked load/store conditional extension. It also sets the"__Xlock"preprocessor symbol ๐.-mmac-d16โ passed down to the assembler. It also sets the"__Xxmac_d16"preprocessor symbol. This option is deprecated. ๐-mmac-24โ passed down to the assembler. It also sets the"__Xxmac_24"preprocessor symbol. This option is deprecated. ๐-mrtscโ passed down to the assembler to enable the 64-bit time-stamp counter extension instruction. It also sets the"__Xrtsc"preprocessor symbol. This option is deprecated. ๐-mswapeโ passed down to the assembler to enable the swap byte ordering extension instruction. It also sets the"__Xswape"preprocessor symbol ๐.-mtelephonyโ passed down to the assembler to enable dual- and single-operand instructions for telephony. It also sets the"__Xtelephony"preprocessor symbol. This option is deprecated. ๐-mxyโ passed down to the assembler to enable the XY memory extension. It also sets the"__Xxy"preprocessor symbol ๐.
The following options control how the assembly code is annotated ๐.
-misizeโ annotates assembler instructions with estimated addresses ๐.-mannotate-alignโ explains which alignment considerations led to the decision to make an instruction short or long ๐ง.
The following options are passed through to the linker ๐.
-marclinuxโ passed through to the linker to specify use of the"arclinux"emulation. This option is enabled by default in tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets when profiling is not requested โจ.-marclinux_profโ passed through to the linker to specify use of the"arclinux_prof"emulation. This option is enabled by default in tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets when profiling is requested ๐.
The following options control the semantics of the 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 go below 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 a conditional branch-and-link. This is the default for tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets ๐.-G numโ puts definitions of externally-visible data in a small data section, as long as that data is no bigger thannumbytes. The default value ofnumis4for any ARC configuration, or8when there are double load/store operations ๐ฆ.-mno-sdataโ doesn't generate sdata references. This is the default for tool chains built for"arc-linux-uclibc"and"arceb-linux-uclibc"targets ๐ซ.-mvolatile-cacheโ uses ordinarily cached memory accesses for volatile references. This is the default ๐๏ธ.-mno-volatile-cacheโ enables cache bypass for volatile references ๐โโ๏ธ.
The following options fine tune code generation ๐จ.
-malign-callโ does alignment optimizations for call instructions ๐.-mauto-modify-regโ enables the use of pre/post modify with register displacement ๐ฆ.-mbbit-peepholeโ enables bbit peephole2 ๐.-mno-brccโ disables a target-specific pass inarc_reorgthat generates compare-and-branch ("brcc") instructions. It has no effect on the generation of these instructions when they're driven by the combiner pass ๐ โโ๏ธ.-mcase-vector-pcrelโ uses PC-relative switch case tables to enable case table shortening. This is the default for-Os๐ง.-mcompact-casesiโ enables the compact"casesi"pattern. This is the default for-Os, and it's only available for ARCv1 cores. This option is deprecated. ๐-mno-cond-execโ disables the ARCompact-specific pass that generates conditional execution instructions ๐ง.
Okay so the ARC port has its own special pass ๐
The regular conditional-execution pass kinda struggles, because delay slot scheduling, operand numbers, literal sizes, instruction lengths, and conditional execution support all get tangled together ๐. So ARC keeps a separate pass that goes hunting for more conditional execution chances after register allocation, branch shortening, and delay slot scheduling are done โจ. It usually (not always!) improves performance and code size, but it costs extra compile time, which is why there's an option to switch it off ๐ซถ. If your call instructions are blowing past their allowed offset range because they got conditionalized ๐ญ, bestie, consider -mmedium-calls instead ๐ฆ.
-mearly-cbranchsiโ Turns on pre-reload use of thecbranchsipattern ๐ธ-mexpand-adddiโ Expandsadddi3andsubdi3at RTL generation time intoadd.f,adcetc. โ ๏ธ This one is deprecated, so maybe don't build your whole vibe around it ๐-mindexed-loadsโ Enables indexed loads ๐ Be careful though, because some optimizers then assume indexed stores exist, and they don't on ARC, so it can get messy ๐-mlraโ Enables Local Register Allocation ๐ง It's still experimental for ARC, so by default the compiler uses standard reload (i.e.-mno-lra) ๐-mlra-priority-noneโ Doesn't indicate any priority for target registers ๐-mlra-priority-compactโ Indicates target register priority forr0..r3/r12..r15๐-mlra-priority-noncompactโ Reduces target register priority forr0..r3/r12..r15๐ฅ-mmillicodeโ When you're optimizing for size (using-Os), prologues and epilogues that have to save or restore a big pile of registers often get shortened by calling a special function in libgcc, and that's called a millicode call โจ Since these calls can cause performance issues, and/or linking issues when you link in a nonstandard way, this option lets you turn millicode call generation on or off ๐-mcode-density-frameโ Lets the compiler emitenterandleaveinstructions ๐ฆ These are only valid for CPUs with the code-density feature, so check your CPU first, babe ๐-mmixed-codeโ Tweaks register allocation to help 16-bit instruction generation โจ The general vibe is shorter average instruction size, but a higher instruction count ๐ธ-mq-classโ Enables q instruction alternatives ๐ This is the default for-Os.-mRcqโ Enables Rcq constraint handling ๐ซถ Most short code generation depends on this, and it's the default ๐-mRcwโ Enables Rcw constraint handling ๐ฅ Most ccfsm condexec mostly depends on this, and yep, it's the default too โญ-msize-level=levelโ Fine-tunes size optimization with regards to instruction lengths and alignment ๐ The recognized values forlevelare:0โ No size optimization. This level is deprecated and treated like1๐ฅ1โ Short instructions are used opportunistically ๐ท2โ On top of that, alignment of loops and of code after barriers gets dropped ๐งธ3โ On top of that, optional data alignment gets dropped, and theOsoption 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=๐ฏ Supported values forcpuare:ARC600โ Tunes for the ARC600 CPU ๐ธARC601โ Tunes for the ARC601 CPU ๐ทARC700โ Tunes for the ARC700 CPU with the standard multiplier block ๐ARC700-xmacโ Tunes for the ARC700 CPU with the XMAC block ๐ฅARC725Dโ Tunes for the ARC725D CPU ๐งARC750Dโ Tunes for the ARC750D CPU โจ
-mmultcost=numโ Sets the cost to assume for a multiply instruction, with4being equal to a normal instruction ๐งฎ-munalign-prob-threshold=probabilityโ Sets the probability threshold for unaligning branches ๐ When tuning for ARC700 and optimizing for speed, branches without a filled delay slot are preferably emitted unaligned and long, unless profiling shows the probability of the branch being taken is belowprobability๐ The default is(REG_BR_PROB_BASE/2), i.e.5000๐
The following options are maintained for backward compatibility, but they're now deprecated and will be removed in a future release ๐ Use them at your own risk, bestie ๐ญ
-margonautโ Obsolete FPX ๐ฅ-mbig-endian,-EBโ Compiles code for big-endian targets ๐ Using these is now deprecated ๐ Big-endian code is supported by configuring GCC to buildarceb-elf32andarceb-linux-uclibctargets instead, where big endian is the default ๐ซถ-mlittle-endian,-ELโ Compiles code for little-endian targets ๐ธ Using these is now deprecated ๐ Little-endian code is supported by configuring GCC to buildarc-elf32andarc-linux-uclibctargets instead, 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 ๐ Permissible values are:apcs-gnu,atpcs,aapcs,aapcs-linuxandiwmmxt๐งธ-mapcs-frameโ Generates a stack frame that's compliant with the ARM Procedure Call Standard for all functions, even if it isn't strictly necessary for the code to run correctly ๐งฑ Specifying-fomit-frame-pointerwith this option causes stack frames not to be generated for leaf functions ๐ The default is-mno-apcs-frame๐ This option is deprecated ๐-mapcsโ A synonym for-mapcs-frame, and it's deprecated too ๐-mthumb-interworkโ Generates code that supports calling between the ARM and Thumb instruction sets ๐ Without this option, on pre-v5 architectures, the two instruction sets can't be reliably used inside one program ๐ฌ The default is-mno-thumb-interwork, since slightly larger code is generated when-mthumb-interworkis specified ๐ In AAPCS configurations this option is meaningless ๐คทโโ๏ธ-mno-sched-prologโ Prevents the reordering of instructions in the function prologue, or the merging of those instructions with the instructions in the function's body ๐ This means all functions start with a recognizable set of instructions (or in fact one of a choice from a small set of different function prologues), and that info can be used to locate the start of functions inside an executable piece of code ๐ The default is-msched-prologโจ-mfloat-abi=nameโ Specifies which floating-point ABI to use ๐งฎ Permissible values are:soft,softfpandhard๐ธsoftmakes GCC generate output containing library calls for floating-point operations ๐softfpallows code using hardware floating-point instructions, but still uses the soft-float calling conventions ๐คhardallows floating-point instructions and uses FPU-specific calling conventions ๐ฅ
The default depends on the specific target configuration ๐ฏ Note that the hard-float and soft-float ABIs are not link-compatible; you must compile your entire program with the same ABI, and link with a compatible set of libraries ๐ซ
-mgeneral-regs-onlyโ Generates code that uses only the general-purpose registers ๐ท This stops the compiler from using floating-point and Advanced SIMD registers, but it won't impose any restrictions on the assembler ๐ซถ-mlittle-endianโ Generates code for a processor running in little-endian mode ๐ This is the default for all standard configurations ๐-mbig-endianโ Generates code for a processor running in big-endian mode ๐ The default is to compile code for a little-endian processor ๐-mbe8,-mbe32โ When linking a big-endian image, selects between BE8 and BE32 formats ๐ This option has no effect on little-endian images and is ignored there ๐ The default depends on the selected target architecture: for ARMv6 and later architectures it's BE8, and for older architectures it's BE32 ๐งญ BE32 format has been deprecated by ARM ๐-march=name[+extension...]โ Specifies the name of the target ARM architecture ๐ฏ GCC uses this name to determine what kind of instructions it can emit when generating assembly code ๐ง This option can be used in conjunction with, or instead of, the-mcpu=option ๐ค
Permissible names are: armv4t, armv5t, armv5te, armv6, armv6j, armv6k, armv6kz, armv6t2, armv6z, armv6zk, armv7, armv7-a, armv7ve, armv8-a, armv8.1-a, armv8.2-a, armv8.3-a, armv8.4-a, armv8.5-a, armv7-r, armv8-r, armv6-m, armv6s-m, armv7-m, armv7e-m, armv8-m.base, armv8-m.main, iwmmxt and iwmmxt2 ๐
Additionally, the following architectures, which lack support for the Thumb execution state, are recognized but support is deprecated: armv4 ๐ฅ
Many of the architectures support extensions ๐งฉ These can be added by appending +extension to the architecture name ๐
Extension options are processed in order, and capabilities accumulate โ An extension will also enable any necessary base extensions it depends on ๐ซถ For example, the +crypto extension will always enable the +simd extension ๐ The exception to the additive construction is for extensions prefixed with +no...: these extensions disable the specified option, and any other extensions that may depend on the presence of that extension ๐ซ
For example, -march=armv7-a+simd+nofp+vfpv4 is equivalent to writing -march=armv7-a+vfpv4, since the +simd option is entirely disabled by the +nofp option that follows it ๐โจ
Okay so extension names are super generic ๐ซถ but what they actually do depends on which architecture you slap them onto โจ Like, +simd works on both armv7-a and armv8-a, but on armv7-a it switches on the original ARMv7-A Advanced SIMD (Neon) stuff, and on armv8-a it's the ARMv8-A version ๐
Here's the tea on what each architecture supports ๐ Anything not mentioned doesn't support any extensions at all, so no cap, skip those ๐
armv5te, armv6, armv6j, armv6k, armv6kz, armv6t2, armv6z, armv6zk
These all share the same two extensions ๐ธ
+fpโ The VFPv2 floating-point instructions ๐ฆ You can also call it+vfpv2, since that's an alias for this extension.+nofpโ Turns off 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 alias+vfpv3-d16works here too. Heads up, though: floating-point isn't supported by the base ARMv7-M architecture, but it is compatible with both ARMv7-A and ARMv7-R โ ๏ธ+nofpโ Disables the floating-point instructions ๐
armv7-a
+mpโ The multiprocessing extension โจ+secโ The security extension ๐+fpโ The VFPv3 floating-point instructions, with 16 double-precision registers ๐ The alias+vfpv3-d16works for this one as well.+simdโ The Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions ๐ฅ The aliases+neonand+neon-vfpv3can be used instead of this one.+vfpv3โ The VFPv3 floating-point instructions, with 32 double-precision registers ๐+vfpv3-d16-fp16โ The VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐+vfpv3-fp16โ The VFPv3 floating-point instructions with 32 double-precision registers, plus the half-precision floating-point conversion operations ๐+vfpv4-d16โ The VFPv4 floating-point instructions, with 16 double-precision registers ๐ฆ+vfpv4โ The VFPv4 floating-point instructions, with 32 double-precision registers ๐ฆ+neon-fp16โ The Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions, with the half-precision floating-point conversion operations ๐+neon-vfpv4โ The Advanced SIMD (Neon) v2 plus the VFPv4 floating-point instructions ๐+nosimdโ Disables the Advanced SIMD instructions. Floating point stays on, though ๐ซถ+nofpโ Disables the floating-point and Advanced SIMD instructions ๐
armv7ve
The extended version of the ARMv7-A architecture, with support for virtualization ๐ง
+fpโ The VFPv4 floating-point instructions, with 16 double-precision registers ๐ฆ The alias+vfpv4-d16can be used for this one.+simdโ The Advanced SIMD (Neon) v2 plus the VFPv4 floating-point instructions ๐ฅ The alias+neon-vfpv4can be used for this one.+vfpv3-d16โ The VFPv3 floating-point instructions, with 16 double-precision registers ๐+vfpv3โ The VFPv3 floating-point instructions, with 32 double-precision registers ๐+vfpv3-d16-fp16โ The VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐+vfpv3-fp16โ The VFPv3 floating-point instructions with 32 double-precision registers, plus the half-precision floating-point conversion operations ๐+vfpv4-d16โ The VFPv4 floating-point instructions, with 16 double-precision registers ๐ฆ+vfpv4โ The VFPv4 floating-point instructions, with 32 double-precision registers ๐ฆ+neonโ The Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions ๐ฅ The alias+neon-vfpv3can be used for this one.+neon-fp16โ The Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions, with the half-precision floating-point conversion operations ๐+nosimdโ Disables the Advanced SIMD instructions. Floating point is still on ๐ซถ+nofpโ Disables the floating-point and Advanced SIMD instructions ๐
armv8-a
+crcโ The Cyclic Redundancy Check (CRC) instructions โจ+simdโ The ARMv8-A Advanced SIMD and floating-point instructions ๐ฅ+cryptoโ The cryptographic instructions ๐+nocryptoโ Disables the cryptographic instructions ๐+nofpโ Disables the floating-point, Advanced SIMD and cryptographic instructions ๐+sbโ The Speculation Barrier Instruction ๐ก๏ธ+predresโ The Execution and Data Prediction Restriction Instructions ๐ง
armv8.1-a
+simdโ The ARMv8.1-A Advanced SIMD and floating-point instructions ๐ฅ+cryptoโ The cryptographic instructions ๐ This also turns on the Advanced SIMD and floating-point instructions.+nocryptoโ Disables the cryptographic instructions ๐+nofpโ Disables the floating-point, Advanced SIMD and cryptographic instructions ๐+sbโ The Speculation Barrier Instruction ๐ก๏ธ+predresโ The Execution and Data Prediction Restriction Instructions ๐ง
armv8.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, plus the Advanced SIMD and floating-point instructions.+simdโ The ARMv8.1-A Advanced SIMD and floating-point instructions ๐ฅ+cryptoโ The cryptographic instructions ๐ This also enables the Advanced SIMD and floating-point instructions.+dotprodโ Enables the Dot Product extension ๐ธ This also enables Advanced SIMD instructions.+nocryptoโ Disables the cryptographic extension ๐+nofpโ Disables the floating-point, Advanced SIMD and cryptographic instructions ๐+sbโ The Speculation Barrier Instruction ๐ก๏ธ+predresโ The Execution and Data Prediction Restriction Instructions ๐ง
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โ Disables the cryptographic extension ๐+nofpโ Disables the floating-point, Advanced SIMD and cryptographic instructions ๐+sbโ The Speculation Barrier Instruction ๐ก๏ธ+predresโ The Execution and Data Prediction Restriction Instructions ๐ง
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โ 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โ Disables the cryptographic extension ๐+nofpโ Disables the floating-point, Advanced SIMD and cryptographic instructions ๐
armv7-r
+fp.spโ The single-precision VFPv3 floating-point instructions ๐ The alias+vfpv3xdcan be used for this one.+fpโ The VFPv3 floating-point instructions with 16 double-precision registers ๐ The alias+vfpv3-d16can be used for this one.+vfpv3xd-d16-fp16โ The single-precision VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐+vfpv3-d16-fp16โ The VFPv3 floating-point instructions with 16 double-precision registers, 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 ๐
Okay so the -march list is still going, and the ARMv8-M and ARMv8-R crew are iconic ๐
armv8-m.main๐ธ: the ARMv8-M main architecture, with these extensions:+dsp: the DSP instructions ๐+nodsp: disable the DSP extension ๐+fp: the single-precision floating-point instructions โจ+fp.dp: the single- and double-precision floating-point instructions ๐ฅ+nofp: disable the floating-point extension ๐
armv8-r๐ฆ: the ARMv8-R architecture, with these extensions:+crc: the Cyclic Redundancy Check (CRC) instructions ๐งฎ+fp.sp: the single-precision FPv5 floating-point instructions+simd: the ARMv8-A Advanced SIMD and floating-point instructions+crypto: the cryptographic instructions ๐+nocrypto: disable the cryptographic instructions+nofp: disable the floating-point, Advanced SIMD and cryptographic instructions ๐ญ
-march=native makes the compiler auto-detect the architecture of the build computer, bestie ๐ซถ Right now this only works on GNU/Linux, and not every architecture gets recognized. If the auto-detect fails, the option has no effect.
-mtune=name
This one tells GCC which target ARM processor to tune the performance of the code for. Some ARM implementations get better performance when you use this option โจ The permissible names are:
arm7tdmi, arm7tdmi-s, arm710t,
arm720t, arm740t, strongarm, strongarm110, strongarm1100,
0strongarm1110, arm8, arm810, arm9, arm9e, arm920, arm920t, arm922t,
arm946e-s, arm966e-s, arm968e-s, arm926ej-s, arm940t, arm9tdmi,
arm10tdmi, arm1020t, arm1026ej-s, arm10e, arm1020e, arm1022e,
arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1156t2-s,
arm1156t2f-s, arm1176jz-s, arm1176jzf-s, generic-armv7-a, cortex-a5,
cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17,
cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57,
cortex-a72, cortex-a73, cortex-a75, cortex-a76, 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-m1.small-multiply,
cortex-m0.small-multiply, cortex-m0plus.small-multiply, exynos-m1,
marvell-pj4, neoverse-n1, neoverse-n2, neoverse-v1, xscale, iwmmxt,
iwmmxt2, ep9312, fa526, fa626, fa606te, fa626te, fmp626, fa726te,
xgene1.
It can also tune for a big.LITTLE system ๐ง Here are the permissible big.LITTLE names:
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 tunes for a blend of processors within the architecture arch ๐ The goal is code that runs well on the most popular current processors, balancing optimizations that help some CPUs in the range while avoiding performance pitfalls on the others. Heads up: the effects of this option may shift in future GCC versions as CPU models come and go ๐
-mtune takes the same extension options as -mcpu, but the extensions don't change how the generated code gets tuned, okay? ๐
-mtune=native auto-detects the CPU of the build computer ๐ Same deal as before: GNU/Linux only for now, not every architecture is recognized, and if the auto-detect fails the option does nothing.
-mcpu=name[+extension...]
This one names the target ARM processor ๐ GCC uses that name to figure out the target ARM architecture (like -march would) and the processor type to tune for (like -mtune would). If you use this alongside -march or -mtune, those win for their own part of the job ๐
A bunch of the supported CPUs have optional architectural extensions, and those are usually enabled by default. If some versions of a CPU don't have an extension, you can use the extension syntax to switch off the ones that are missing ๐
Floating-point and Advanced SIMD (Neon) are a little extra, so -mfloat-abi and -mfpu matter here too. Floating-point and Advanced SIMD instructions only get used if -mfloat-abi is not 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 SIMD and floating-point instructions.
The permissible names for this option are the same as the ones for -mtune ๐
These extension options are common to the listed CPUs:
+nodsp: disables the DSP instructions oncortex-m33.+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-m7andcortex-m33. 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 not the floating-point ones) ongeneric-armv7-a,cortex-a5,cortex-a7andcortex-a9.+crypto: enables the cryptographic instructions oncortex-a32,cortex-a35,cortex-a53,cortex-a55,cortex-a57,cortex-a72,cortex-a73,cortex-a75,exynos-m1,xgene1,cortex-a57.cortex-a53,cortex-a72.cortex-a53,cortex-a73.cortex-a35,cortex-a73.cortex-a53andcortex-a75.cortex-a55. ๐
The generic-armv7-a pseudo target defaults to VFPv3 with 16 double-precision registers โจ It supports these extension options: mp, sec, vfpv3-d16, vfpv3, vfpv3-d16-fp16, vfpv3-fp16, vfpv4-d16, vfpv4, neon, neon-vfpv3, neon-fp16 and neon-vfpv4. They mean the same thing as the extensions to -march=armv7-a.
-mcpu=generic-arch is also allowed, and it's equivalent to -march=arch -mtune=generic-arch. Check out -mtune for more info ๐ง
-mcpu=native auto-detects the CPU of the build computer ๐ Once again: GNU/Linux only for now, not every architecture is recognized, and if the auto-detect fails the option has no effect.
-mfpu=name
This tells GCC 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-armv8 and
crypto-neon-fp-armv8.
Note that neon is an alias for neon-vfpv3, and vfp is an alias for vfpv2 ๐
The setting auto is the default and it's special ๐ It makes the compiler pick the floating-point and Advanced SIMD instructions based on the settings of -mcpu and -march.
If the selected floating-point hardware includes the NEON extension (e.g. -mfpu=neon), GCC's auto-vectorization pass won't generate floating-point operations unless you also specify -funsafe-math-optimizations. This is because NEON hardware doesn't fully implement the IEEE 754 standard for floating-point arithmetic. In particular, denormal values are treated as zero, so using NEON instructions can lead to a loss of precision ๐ญ
Heads up: NEON doesn't fully follow IEEE 754, so denormal values get treated as zero. Using NEON can lose precision, so only add -funsafe-math-optimizations if you're okay with that trade-off.
You can also set the fpu name at function level with the target("fpu=") function attributes or pragmas ๐
-mfp16-format=name
This specifies the format of the "__fp16" half-precision floating-point type ๐ The permissible names are none, ieee and alternative. The default is none, and in that case the "__fp16" type is not defined.
-mstructure-size-boundary=n
The sizes of all structures and unions get rounded up to a multiple of the number of bits set by this option ๐ The permissible values are 8, 32 and 64. The default varies between toolchains. For the COFF targeted toolchain, the default is 8. A value of 64 is only allowed if the underlying ABI supports it.
A bigger number can give you 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 pass information through structures or unions.
This option is deprecated. ๐ Don't build new stuff around it.
-mabort-on-noreturn
This generates a call to the function "abort" at the end of a "noreturn" function ๐งฏ It runs if the function tries to return.
-mlong-calls and -mno-long-calls
These tell 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 switch if the target function lives outside the 64-megabyte addressing range of the offset-based subroutine call instruction.
Even with this switch on, not every call becomes a long call ๐ The heuristic is that these calls are not turned into long calls: 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.
The exceptions are the ones that are always turned into long calls: weak function definitions, functions with the "long_call" attribute or the "section" attribute, and functions inside the scope of a "#pragma long_calls" directive ๐
This one's off by default, bestie ๐ Passing -mno-long-calls puts you back on the default path, and so does wrapping the calls in a #pragma long_calls_off directive ๐. Just know these switches do nothing to calls made through function pointers ๐.
-msingle-pic-baseโ This one treats the PIC addressing register as read-only โจ instead of loading it in the prologue of every function. The runtime system has to set that register to the right value before execution starts, so it's on you (or your runtime) ๐ซถ.-mpic-register=regโ Pick the register used for PIC addressing ๐ธ. With the standard PIC base, the compiler picks any suitable register on its own. With the single PIC base, the default isR9if the target is EABI based or stack-checking is enabled, and otherwise it'sR10๐.-mpic-data-is-text-relativeโ Assumes the gap between the text and data segments is locked in at static link time ๐ฆ. That means PC-relative addressing can reach data you know lives in the data segment. On non-VxWorks RTP targets this is on by default ๐. If you turn it off on those targets,-msingle-pic-basegets turned on by default instead ๐ง.-mpoke-function-nameโ This writes each function's name into the text section, sitting right before the function prologue ๐. The generated code looks roughly 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, you can look at the pc value stored at fp + 0 ๐. If the trace function checks pc - 12 and the top 8 bits are set, then the function name is embedded right before that spot, and its length is ((pc[-3]) & 0xff000000) โจ. Iykyk, it's giving detective energy ๐ต๏ธโโ๏ธ.
-mthumb,-marmโ Pick whether the code runs in ARM state or Thumb state ๐. Most configurations default to ARM state, but you can change that by configuring GCC with the--with-mode=stateconfigure option ๐. You can also override ARM or Thumb mode for each function with thetarget("thumb")andtarget("arm")function attributes or pragmas ๐ .-mflip-thumbโ Flips ARM and Thumb modes on alternating functions ๐. This is only here for regression testing of mixed Thumb/ARM code generation, so do not use it for ordinary compiling ๐ซ.-mtpcs-frameโ Generates a stack frame that follows the Thumb Procedure Call Standard for all non-leaf functions ๐งฑ. (A leaf function is one that doesn't call any other functions ๐.) The default is-mno-tpcs-frame.-mtpcs-leaf-frameโ Same deal, but for all leaf functions ๐. The default is-mno-apcs-leaf-frame.-mcallee-super-interworkingโ Gives every externally visible function in the file being compiled an ARM instruction set header ๐. That header switches to Thumb mode before the rest of the function runs, so these functions can be called from non-interworking code โจ. This option is not valid in AAPCS configurations, since interworking is already enabled by default ๐.-mcaller-super-interworkingโ Lets calls through function pointers (including virtual functions) work correctly no matter whether the target code was compiled for interworking ๐ฆ. Heads up, there's a small overhead when running a function pointer if you turn this on ๐ข. Also not valid in AAPCS configurations, same reason as above โ.-mtp=nameโ Picks the access model for the thread local storage pointer ๐งต. The valid models are:softโ generates calls to__aeabi_read_tpcp15โ fetches the thread pointer fromcp15directly (supported in thearm6karchitecture)autoโ uses the best available method for the processor you picked
The default is auto ๐.
-mtls-dialect=dialectโ Chooses the dialect for accessing thread local storage ๐ท. There are two:gnuandgnu2. Thegnuone is the original GNU scheme for local and global dynamic TLS models ๐. Thegnu2one is the GNU descriptor scheme, which performs better for shared libraries ๐. The descriptor scheme is compatible with the original, but it needs new assembler, linker and library support, so check your toolchain first ๐ ๏ธ. Initial and local exec TLS models ignore this option and always use the original scheme ๐ โโ๏ธ.-mword-relocationsโ Only generates absolute relocations on word-sized values, meaningR_ARM_ABS32๐งฉ. This is on by default on targets like uClinux and SymbianOS, where the runtime loader enforces this restriction, and whenever-fpicor-fPICis specified ๐. It conflicts with-mslow-flash-dataโ ๏ธ.-mfix-cortex-m3-ldrdโ Some Cortex-M3 cores can corrupt data whenldrdinstructions have overlapping destination and base registers ๐ญ. This option stops the compiler from generating those instructions ๐ก๏ธ. It's on by default when-mcpu=cortex-m3is specified ๐ .-munaligned-access,-mno-unaligned-accessโ These turn on (or off) 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 ARMv8-M Baseline architectures, and enabled for all other architectures ๐ง. If unaligned access isn't enabled, words in packed data structures get accessed one byte at a time ๐.
The ARM attribute Tag_CPU_unaligned_access gets set in the generated object file to either true or false, depending on this option ๐ท๏ธ. If unaligned access is enabled, the preprocessor symbol __ARM_FEATURE_UNALIGNED is defined too โจ.
-mneon-for-64bitsโ Lets Neon handle scalar 64-bit operations ๐ถ. It's disabled by default because moving data from core registers over to Neon is expensive ๐ธ.-mslow-flash-dataโ Assumes loading data from flash is slower than fetching instructions ๐ข, so the compiler minimizes literal loads for better performance ๐๏ธ. This is only supported when compiling for ARMv7 M-profile, and it's off by default ๐ซ. It conflicts with-mword-relocationsโ ๏ธ.-masm-syntax-unifiedโ Assumes inline assembler uses unified asm syntax ๐. The default is currently off, which means divided syntax ๐ช. This option has no impact on Thumb2, although that could change in future GCC releases ๐. Divided syntax should be considered deprecated ๐, so please don't start new code with it ๐.-mrestrict-itโ Restricts IT block generation so it follows the ARMv8-A rules ๐. IT blocks can only contain a single 16-bit instruction from a select set of instructions ๐ฏ. This is on by default for ARMv8-A Thumb mode ๐.-mprint-tune-infoโ Prints CPU tuning info as a comment in the assembler file ๐๏ธ. This is only for regression testing of the compiler and isn't meant for ordinary code compiling ๐ซ. It's disabled by default ๐ค.-mverbose-cost-dumpโ Turns on verbose cost model dumping in the debug dump files ๐. It's provided for debugging the compiler itself ๐งโ๐ป.-mpure-codeโ Stops constant data from being placed in code sections ๐ง. When you compile for ELF object format, it also gives all text sections the ELF processor-specific section attributeSHF_ARM_PURECODEโจ. This option is only available when generating non-PIC code for M-profile targets ๐ .-mcmseโ Generates secure code according to the "ARMv8-M Security Extensions: Requirements on Development Tools Engineering Specification" ๐. You can find that spec athttps://developer.arm.com/documentation/ecm0359818/latest/๐.
๐ฆ AVR Options ๐ฆ
These options are defined for AVR implementations ๐ธ.
-mmcu=mcuโ Picks 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 ๐.- MCUs:
attiny22,attiny26,at90s2313,at90s2323,at90s2333,at90s2343,at90s4414,at90s4433,at90s4434,at90c8534,at90s8515,at90s8535
- MCUs:
avr25โ "Classic" devices with up to 8 KiB of program memory and with theMOVWinstruction ๐ฆ.- MCUs:
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
- MCUs:
avr3โ "Classic" devices with 16 KiB up to 64 KiB of program memory ๐.- MCUs:
at76c711,at43usb355
- MCUs:
avr31โ "Classic" devices with 128 KiB of program memory ๐ง.- MCUs:
atmega103,at43usb320
- MCUs:
avr35โ "Classic" devices with 16 KiB up to 64 KiB of program memory and with theMOVWinstruction ๐.- MCUs:
attiny167,attiny1634,atmega8u2,atmega16u2,atmega32u2,ata5505,ata6617c,ata664251,at90usb82,at90usb162
- MCUs:
avr4โ "Enhanced" devices with up to 8 KiB of program memory ๐ฅ.- MCUs:
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
- MCUs:
"avr5"โ the "Enhanced" squad 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".
- mcu =
"avr51"โ more "Enhanced" devices, this time with 128 KiB of program memory ๐ฆ- mcu =
"atmega128", "atmega128a", "atmega128rfa1", "atmega128rfr2", "atmega1280", "atmega1281", "atmega1284", "atmega1284p", "atmega1284rfr2", "at90can128", "at90usb1286", "at90usb1287".
- mcu =
"avr6"โ the "Enhanced" devices with a 3-byte PC, so anything with more than 128 KiB of program memory ๐- mcu =
"atmega256rfr2", "atmega2560", "atmega2561", "atmega2564rfr2".
- mcu =
"avrxmega2"โ XMEGA devices with more than 8 KiB and up to 64 KiB of program memory โจ- mcu =
"atxmega8e5", "atxmega16a4", "atxmega16a4u", "atxmega16c4", "atxmega16d4", "atxmega16e5", "atxmega32a4", "atxmega32a4u", "atxmega32c3", "atxmega32c4", "atxmega32d3", "atxmega32d4", "atxmega32e5".
- mcu =
"avrxmega3"โ XMEGA devices with up to 64 KiB of combined program memory and RAM, where the program memory is visible in the RAM address space ๐ง- mcu =
"attiny202", "attiny204", "attiny212", "attiny214", "attiny402", "attiny404", "attiny406", "attiny412", "attiny414", "attiny416", "attiny417", "attiny804", "attiny806", "attiny807", "attiny814", "attiny816", "attiny817", "attiny1604", "attiny1606", "attiny1607", "attiny1614", "attiny1616", "attiny1617", "attiny3214", "attiny3216", "attiny3217", "atmega808", "atmega809", "atmega1608", "atmega1609", "atmega3208", "atmega3209", "atmega4808", "atmega4809".
- mcu =
"avrxmega4"โ XMEGA devices with more than 64 KiB and up to 128 KiB of program memory ๐- mcu =
"atxmega64a3", "atxmega64a3u", "atxmega64a4u", "atxmega64b1", "atxmega64b3", "atxmega64c3", "atxmega64d3", "atxmega64d4".
- mcu =
"avrxmega5"โ XMEGA devices with more than 64 KiB and up to 128 KiB of program memory, plus more than 64 KiB of RAM ๐- mcu =
"atxmega64a1", "atxmega64a1u".
- mcu =
"avrxmega6"โ XMEGA devices with more than 128 KiB of program memory, the big-brain ones ๐ง- mcu =
"atxmega128a3", "atxmega128a3u", "atxmega128b1", "atxmega128b3", "atxmega128c3", "atxmega128d3", "atxmega128d4", "atxmega192a3", "atxmega192a3u", "atxmega192c3", "atxmega192d3", "atxmega256a3", "atxmega256a3b", "atxmega256a3bu", "atxmega256a3u", "atxmega256c3", "atxmega256d3", "atxmega384c3", "atxmega384d3".
- mcu =
"avrxmega7"โ XMEGA devices with more than 128 KiB of program memory and more than 64 KiB of RAM ๐ฅ- mcu =
"atxmega128a1", "atxmega128a1u", "atxmega128a4u".
- mcu =
"avrtiny"โ the "TINY" Tiny core devices with 512 B up to 4 KiB of program memory ๐ธ- mcu =
"attiny4", "attiny5", "attiny9", "attiny10", "attiny20", "attiny40".
- mcu =
"avr1"โ this ISA is the minimal AVR core, and it's only supported for the assembler, so no C for these bestie ๐ฅบ- mcu =
"attiny11", "attiny12", "attiny15", "attiny28", "at90s1200".
- mcu =
-mabsdataโ assumes all data in static storage can be reached withLDS/STSinstructions. This only does anything on reduced Tiny devices like ATtiny40. See also the "absdata" AVR Variable Attributes, variable attribute ๐-maccumulate-argsโ collects outgoing function arguments and grabs or drops the needed stack space once, in the function prologue and epilogue. Without this, arguments get pushed before a call and popped after it โจ
Popping arguments after a call can be pricey on AVR, so accumulating the stack space can give you smaller executables, since the arguments never have to come off the stack after each call ๐
This can shrink code for functions that make several calls to functions taking stack arguments, like printf-style functions ๐ซถ
-mbranch-cost=costโ sets the branch costs for conditional branch instructions tocost. Sensible values are small, non-negative integers. The default branch cost is0๐-mcall-prologuesโ function prologues and epilogues get expanded as calls to the right subroutines, so the code size is smaller ๐ง-mgas-isr-prologuesโ interrupt service routines (ISRs) can use the__gcc_isrpseudo instruction that GNU Binutils supports. If this is on, you can still turn it off for individual ISRs with theno_gccisrfunction attribute (see AVR Function Attributes). This is turned on by default when optimization is on, but not with-Og(see Optimize Options), and when GNU Binutils supports PR21683 athttps://sourceware.org/PR21683๐-mint8โ treatsintas an 8-bit integer. This changes the size of every type: acharis 1 byte, anintis 1 byte, alongis 2 bytes, and along longis 4 bytes ๐
Heads up bestie: this option does NOT conform to the C standards. It does give you smaller code size though, so it's a trade-off ๐
-mmain-is-OS_taskโ stopsmainfrom saving registers. It does the same thing as putting theOS_taskattribute (see AVR Function Attributes) onmain. This is turned on by default when optimization is on ๐-mn-flash=numโ assumes the flash memory isnumtimes 64 KiB in size ๐ธ-mno-interruptsโ the generated code doesn't play nicely with hardware interrupts
Careful, this one isn't compatible with hardware interrupts at all. The upside is smaller code size ๐ญ
-mrelaxโ tries to swap aCALLorJMPinstruction for the shorterRCALLorRJMPinstruction when it applies. Setting-mrelaxjust adds the--mlink-relaxoption to the assembler's command line and the--relaxoption to the linker's command line ๐ฆ
Jump relaxing happens in the linker, since jump offsets aren't known until the code gets placed. So the assembler code the compiler makes stays the same, but the instructions in the executable might look different from what's in the assembler code ๐
Relaxing has to be on if linker stubs are needed. Check the section on "EIND" and linker stubs below for more ๐
-mrmwโ assumes the device supports the Read-Modify-Write instructionsXCH,LAC,LASandLAT๐ฅ-mshort-callsโ assumesRJMPandRCALLcan reach the whole program memory
This one is used internally for multilib selection. It's not an optimization option, so you don't need to set it by hand ๐ โโ๏ธ
-msp8โ treats the stack pointer register as an 8-bit register, so the high byte of the stack pointer is assumed to be zero. Generally you don't need to set this by hand ๐ง
The compiler uses this internally to pick and build multilibs for the avr2 and avr25 architectures, which 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, since the compiler already knows whether the device has an 8-bit stack pointer and no SPH register ๐
-mstrict-Xโ uses the address registerXthe way the hardware intends. That meansXis only used for indirect, post-increment or pre-decrement addressing ๐ซถ
Without this option, X can be used just like Y or Z, but then it gets emulated with extra instructions. For example, loading a value with X+const addressing, where const is small and non-negative (const < 64), into a register Rn looks like this:
adiw r26, const ; X += const
ld <Rn>, X ; <Rn> = *X
sbiw r26, const ; X -= const
-mtiny-stackโ only changes the lower 8 bits of the stack pointer โจ-mfract-convert-truncateโ lets fractional fixed-point types use truncation instead of rounding towards zero ๐-nodevicelibโ don't link against AVR-LibC's device specific librarylib<mcu>.a๐-nodevicespecsโ don't add-specs=device-specs/specs-<mcu>to the compiler driver's command line. You're on the hook for giving the subprocesses (compiler proper, assembler and linker) the right command line options yourself ๐-Waddr-space-convertโ warns about conversions between address spaces when the resulting address space isn't contained in the incoming one โญ-Wmisspelled-isrโ warns if an ISR is misspelled, meaning it's missing the__vectorprefix. This one's 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 gets represented as a word address, so indirect jumps and calls can target any code address in the range of 64 Ki words ๐ฆ
In order to facilitate indirect jump on devices with more than 128 Ki bytes of program memory space, there is a special function register called EIND ๐ It's the most significant part of the target address when EICALL or EIJMP instructions are used, and it's giving very specific rules, so let's go โจ
Indirect jumps and calls on these devices are handled like this by the compiler, and they come with some limitations. Read these, bestie, they matter ๐ซถ
- The compiler never sets
EIND. - The compiler uses
EINDimplicitly inEICALL/EIJMPinstructions or might readEINDdirectly in order to emulate an indirect call/jump by means of aRETinstruction. - The compiler assumes that
EINDnever changes during the startup code or during the application. In particular,EINDis not saved/restored in function or interrupt service routine prologue/epilogue. - For indirect calls to functions and computed goto, the linker generates stubs ๐ง Stubs are jump pads, sometimes also called trampolines. So the indirect call/jump lands on such a stub, and the stub contains a direct jump to the desired address.
- Linker relaxation must be turned on so that the linker generates the stubs correctly in all situations. See the compiler option
-mrelaxand the linker option--relax.
There are corner cases where the linker is supposed to generate stubs but aborts without relaxation and without a helpful error message. Yikes ๐
- 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 start 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 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 address of a label is taken by means of the
LDI r24, lo8(gs(<func>))
LDI r25, hi8(gs(<func>))
- The final location of that label is in a code segment outside the segment where the stubs are located.
- The compiler emits such
gsmodifiers for code labels in the following situations:- Taking address of a function or code label.
- Computed goto.
- If prologue-save function is used, see
-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 ๐ธ
Some AVR devices support memories larger than the 64 KiB range that can be accessed with 16-bit pointers. To reach memory locations outside this 64 KiB range, the content of a RAMP register is used as the high part of the address. The X, Y, Z address register is concatenated with the RAMPX, RAMPY, RAMPZ special function register, respectively, to get a wide address. Similarly, RAMPD is used together with direct addressing ๐ฆ
- The startup code initializes the
RAMPspecial function registers with zero. - If a AVR Named Address Spaces, named address space other than generic or
__flashis used, thenRAMPZis set as needed before the operation. - If the device supports RAM larger than 64 KiB and the compiler needs to change
RAMPZto accomplish an operation,RAMPZis reset to zero after the operation. - If the device comes with a specific
RAMPregister, the ISR prologue/epilogue saves/restores that SFR and initializes it with zero in case the ISR code might (implicitly) use it. - RAM larger than 64 KiB is not supported by GCC for AVR targets.
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, periodt ๐ญ
โจ AVR Built-in Macros ๐
GCC defines several built-in macros so that the user 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__โ A built-in macro that resolves to a decimal number identifying the architecture. It depends on the-mmcu=mcuoption. Possible values are:2, 25, 3, 31, 35, 4, 5, 51, 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=devicedefines this built-in macro, which reflects the device's name. For example,-mmcu=atmega8defines the built-in macro__AVR_ATmega8__,-mmcu=attiny261adefines__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=devicedefines this built-in macro to the device's name. For example, with-mmcu=atmega8the macro is defined to"atmega8".
If device is not a device but only a core architecture like avr51, this macro is not defined.
__AVR_XMEGA__โ The device / architecture belongs to the XMEGA family of devices.__AVR_HAVE_ELPM__โ The device has theELPMinstruction.__AVR_HAVE_ELPMX__โ The device has theELPM Rn,ZandELPM Rn,Z+instructions.__AVR_HAVE_MOVW__โ The device has theMOVWinstruction to perform 16-bit register-register moves.__AVR_HAVE_LPMX__โ The device has theLPM Rn,ZandLPM Rn,Z+instructions.__AVR_HAVE_MUL__โ The device has a hardware multiplier.__AVR_HAVE_JMP_CALL__โ The device has theJMPandCALLinstructions. This is the case for devices with more than 8 KiB of program memory.__AVR_HAVE_EIJMP_EICALL__and__AVR_3_BYTE_PC__โ The device has theEIJMPandEICALLinstructions. This is the case for devices with more than 128 KiB of program memory. This also means 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 an 8-bit or 16-bit register by the compiler, respectively. The definition of these macros is affected by-mtiny-stack.__AVR_HAVE_SPH__and__AVR_SP8__โ The device has the SPH (high part of stack pointer) special function register, or has an 8-bit stack pointer, respectively. The definition of these macros is affected by-mmcu=and, in the cases of-mmcu=avr2and-mmcu=avr25, also by-msp8.__AVR_HAVE_RAMPD__,__AVR_HAVE_RAMPX__,__AVR_HAVE_RAMPY__and__AVR_HAVE_RAMPZ__โ The device has theRAMPD,RAMPX,RAMPY,RAMPZspecial function register, respectively.__NO_INTERRUPTS__โ This macro reflects the-mno-interruptscommand-line option.__AVR_ERRATA_SKIP__and__AVR_ERRATA_SKIP_JMP_CALL__โ Some AVR devices (AT90S8515, ATmega103) must not skip 32-bit instructions because of a hardware erratum. Skip instructions areSBRS,SBRC,SBIS,SBICandCPSE. The second macro is only defined if__AVR_HAVE_JMP_CALL__is also set. ๐__AVR_ISA_RMW__โ The device has Read-Modify-Write instructions (XCH,LAC,LASandLAT). ๐__AVR_SFR_OFFSET__=offsetโ Instructions that can address I/O special function registers directly, likeIN,OUT,SBI, etc., may use a different address than an instruction accessing RAM, likeLDorSTS. This offset depends on the device architecture and has to be subtracted from the RAM address in order to get the respective I/O address.__AVR_SHORT_CALLS__โ The-mshort-callscommand line option is set. ๐
"__AVR_PM_BASE_ADDRESS__=addr"
Okay so some AVR devices can read from flash memory with LD* instructions ๐ง The flash shows up in the data address space at an offset of __AVR_PM_BASE_ADDRESS__. If this macro isn't defined, the feature just isn't available ๐ If it is defined, the address space is linear and you don't need to shove .rodata into RAM. The default linker description file handles that, and it's currently available for avrtiny and avrxmega3 โจ It's even more convenient bc you don't need address spaces like __flash or stuff like the progmem attribute and pgm_read_* ๐
"__WITH_AVRLIBC__"
This one's giving "the compiler was set up to play nicely with AVR-Libc" ๐ Check the --with-avrlibc configure option if you want the details ๐ซถ
โจ Blackfin Options โจ
-mcpu=cpu[-sirevision]โ This is how you name your target Blackfin processor ๐ The cpu can be any of these, and I'm not kidding, it's a whole list:bf512, bf514, bf516, bf518, bf522, bf523, bf524, bf525, bf526, bf527, bf531, bf532, bf533, bf534, bf536, bf537, bf538, bf539, bf542, bf544, bf547, bf548, bf549, bf542m, bf544m, bf547m, bf548m, bf549m, bf561, bf592. The optional sirevision tells GCC which silicon revision you're on, and any workarounds for that revision get turned on ๐ฅ If you writenone, no workarounds are enabled. If you writeany, every workaround for that processor is enabled. The__SILICON_REVISION__macro gets defined as two hex digits, one for the major number and one for the minor number, of the silicon revision. Withnone,__SILICON_REVISION__isn't defined at all. Withany, it's defined as0xffff. If you skip the optional sirevision completely, GCC assumes the latest silicon revision it knows about for your processor ๐ GCC also defines a preprocessor macro for whatever cpu you picked. On thebfin-elftoolchain, this option makes the hardware BSP from libgloss get linked in, as long as you didn't also pass-msimโจ Without this option,bf532is the default processor ๐
Note that support for bf561 is incomplete. For bf561, only the preprocessor macro gets defined, so don't expect the rest to be there ๐
-msimโ Tells the compiler your program is running on the simulator, so the simulator BSP from libgloss gets linked in ๐ง This only does something on thebfin-elftoolchain. Some other options, like-mid-shared-libraryand-mfdpic, imply-msimon their own ๐-momit-leaf-frame-pointerโ Don't keep the frame pointer in a register for leaf functions ๐ฆ That skips the instructions that save, set up, and restore frame pointers, and it frees up an extra register in leaf functions ๐ฅ-mspecld-anomalyโ When this is on, the compiler makes sure the generated code doesn't have speculative loads right after jump instructions ๐ If you use this option,__WORKAROUND_SPECULATIVE_LOADSgets defined ๐-mno-specld-anomalyโ Don't generate the extra code that stops speculative loads from happening ๐ซถ-mcsync-anomalyโ When this is on, the compiler makes sure the generated code doesn't have CSYNC or SSYNC instructions too soon after conditional branches ๐ธ If you use this option,__WORKAROUND_SPECULATIVE_SYNCSgets defined โจ-mno-csync-anomalyโ Don't generate the extra code that keeps CSYNC or SSYNC instructions from popping up too soon after a conditional branch ๐-mlow64kโ The compiler is allowed to take advantage of the fact that the whole program fits in the low 64k of memory ๐-mno-low64kโ Assume the program is arbitrarily large. This is the default ๐-mstack-check-l1โ Does stack checking using information the uClinux kernel puts into L1 scratchpad memory ๐ง-mid-shared-libraryโ Generates code that supports shared libraries through the library ID method โจ This lets you do execute in place and shared libraries in an environment with no virtual memory management ๐ฆ This option 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 being used. This is the default ๐ธ-mleaf-id-shared-libraryโ Generates code that supports shared libraries through the library ID method, but assumes this library or executable won't link against any other ID shared libraries. That lets the compiler use faster code for jumps and calls ๐ฅ-mno-leaf-id-shared-libraryโ Don't assume the code you're compiling won't link against any ID shared libraries. This makes slower code for jump and call instructions ๐-mshared-library-id=nโ Sets the identification number of the ID-based shared library you're compiling ๐ซถ A value of0makes more compact code. Other values force that number onto the current library, but that'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 allows 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โ-mlong-callstells the compiler to call functions by first loading the function's address into a register, then doing a subroutine call on that register ๐ฆ You need this switch if the target function is outside the 24-bit addressing range of the offset-based subroutine call instruction ๐ This feature isn't enabled by default, and-mno-long-callsputs the default behavior back ๐ These switches don't change how the compiler handles function calls through function pointers, so keep that in mind ๐-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), in the name of performance ๐ฅ-minline-pltโ Enables inlining of PLT entries in function calls to functions that aren't known to bind locally โจ It does nothing without-mfdpic๐-mmulticoreโ Builds a standalone application for multicore Blackfin processors ๐ This option makes sure the proper start files and link scripts for multicore get used, and it defines the macro__BFIN_MULTICORE. It can only be used with-mcpu=bf561[-sirevision]๐
This option can be paired with -mcorea or -mcoreb, which pick the one-application-per-core programming model ๐ซถ Without either of those, the single-application/dual-core model gets used, and in that model the main function of Core B should be named coreb_main ๐ง
If you don't use this option, you get the single-core application programming model ๐ธ
-mcoreaโ Builds a standalone application for Core A of BF561 when you're using the one-application-per-core model ๐ The proper start files and link scripts for Core A get used, and the macro__BFIN_COREAgets defined. This option can only be used together with-mmulticore๐-mcorebโ Builds a standalone application for Core B of BF561 when you're using the one-application-per-core model ๐ฆ The proper start files and link scripts for Core B get used, and the macro__BFIN_COREBgets defined. When you use this option,coreb_mainshould be used instead ofmain๐ It can only be used together with-mmulticore๐ฅ-msdramโ Builds a standalone application for SDRAM ๐ Proper start files and link scripts put the application into SDRAM, and the macro__BFIN_SDRAMgets defined. Your loader needs to initialize 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. For standalone applications, the default is off โจ
โจ C6X Options โจ
-march=nameโ Specifies the name of the target architecture ๐ GCC uses this name to figure out what kinds of instructions it 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 work with the simulator ๐ซถ-msdata=defaultโ Puts small global and static data in the.neardatasection, which is pointed to by registerB14๐ง Small uninitialized global and static data goes in the.bsssection, which sits right next to.neardata๐ฆ Small read-only data goes in the.rodatasection ๐ The sections for large pieces of data are.fardata,.far, and.const๐-msdata=allโ Puts all data, not just small objects, into the sections reserved for small data, and uses addressing relative to theB14register to get to them โจ-msdata=noneโ Makes no use of the sections reserved for small data, and uses absolute addresses to access all data ๐ All initialized global and static data goes in the.fardatasection, and all uninitialized data goes in the.farsection ๐ฅ All constant data goes in the.constsection ๐
โจ CRIS Options โจ
These options are defined specifically for the CRIS ports ๐ฆ
-march=architecture-type,-mcpu=architecture-typeโ Generates code for the architecture you specify ๐ The choices for architecture-type arev3,v8, andv10, which are ETRAX 4, ETRAX 100, and ETRAX 100 LX respectively ๐ The default isv0, except forcris-axis-linux-gnu, where the default isv10๐ง-mtune=architecture-typeโ Tunes everything that applies to the generated code for architecture-type, except for the ABI and the set of available instructions ๐ธ The choices for architecture-type 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โ-metrax4and-metrax100are synonyms for-march=v3and-march=v8respectively ๐ซถ-mmul-bug-workaround,-mno-mul-bug-workaroundโ okay so these patch up a bug in themulsandmuluinstructions on the CPU models where it actually shows up ๐ง. It's on by default, so you literally don't have to lift a finger โจ-mpdebugโ turns on CRIS-specific verbose debug info in the assembly code ๐. It also switches off the#NO_APPformatted-code indicator at the very top of the assembly file ๐-mcc-initโ don't reuse condition-code results from earlier instructions. Always throw in compare and test instructions before you touch the condition codes ๐-mno-side-effectsโ no instructions with side effects in addressing modes, except post-increment ๐ฆ-mstack-align,-mno-stack-align,-mdata-align,-mno-data-align,-mconst-align,-mno-const-alignโ these make the stack frame, individual data, and constants line up to the biggest single data access size for your chosen CPU model ๐ Theno-versions undo that alignment. The default is 32-bit alignment, and ABI stuff like structure layout is not affected by any of these ๐ซถ-m32-bit,-m16-bit,-m8-bitโ same vibe as the stack, data, and const align options, but these make the stack frame, writable data, and constants 32-bit, 16-bit, or 8-bit aligned. 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 get skipped, and no return instructions or return sequences get generated ๐ญ Only do this if you're checking the compiled code by eye. No warnings or errors show up when call-saved registers need saving or local variable storage needs allocating ๐-mno-gotplt,-mgotpltโ with-fpicand-fPIC,-mno-gotpltskips the instruction sequences that load function addresses from the PLT part of the GOT.-mgotplt(the default) does generate them, instead of making traditional calls to the PLT like other architectures do ๐ง-melfโ a legacy no-op. It's only recognized with thecris-axis-elfandcris-axis-linux-gnutargets ๐ฆ-mlinuxโ another legacy no-op, only recognized with thecris-axis-linux-gnutarget ๐ฆ-simโ recognized forcris-axis-elf. It links with input-output functions from a simulator library. Code, initialized data, and zero-initialized data get allocated consecutively ๐-sim2โ basically-sim, but it also passes linker options so initialized data lands at0x40000000and zero-initialized data lands at0x80000000๐
โจ CR16 Options โจ
These are defined specifically for the CR16 ports, so they're the CR16 crew's vibe ๐
-mmacโ enables the multiply-accumulate instructions. Off by default. ๐ฅ-mcr16cplus,-mcr16cโ generates code for the CR16C or CR16C+ architecture. CR16C+ is the default. โญ-msimโ links the librarylibsim.a, which is compatible with the simulator. Only applies to the ELF compiler. ๐ง-mint32โ makes the integer type 32-bit wide ๐-mbit-opsโ generatessbitandcbitinstructions for bit manipulations ๐ฆ-mdata-model=modelโ picks a data model. The choices arenear,far, ormedium, andmediumis the default. Heads up:faris not valid with-mcr16c, because the CR16C architecture doesn't support the far data model ๐
โจ C-SKY Options โจ
GCC supports these options when compiling for C-SKY V2 processors ๐ซถ
-march=archโ specifies the C-SKY target architecture. Valid values forarchareck801,ck802,ck803,ck807, andck810. The default isck810. ๐-mcpu=cpuโ specifies the C-SKY target processor. Valid values forcpuareck801,ck801t,ck802,ck802t,ck802j,ck803,ck803h,ck803t,ck803ht,ck803f,ck803fh,ck803e,ck803eh,ck803et,ck803eht,ck803ef,ck803efh,ck803ft,ck803eft,ck803efht,ck803r1,ck803hr1,ck803tr1,ck803htr1,ck803fr1,ck803fhr1,ck803er1,ck803ehr1,ck803etr1,ck803ehtr1,ck803efr1,ck803efhr1,ck803ftr1,ck803eftr1,ck803efhtr1,ck803s,ck803st,ck803se,ck803sf,ck803sef,ck803seft,ck807e,ck807ef,ck807,ck807f,ck810e,ck810et,ck810ef,ck810eft,ck810,ck810v,ck810f,ck810t,ck810fv,ck810tv,ck810ft, andck810ftv. The whole list is a lot, bestie, but it's all there ๐-mbig-endian,-EB,-mlittle-endian,-ELโ picks big-endian or little-endian code. Little-endian is the default. ๐-mhard-float,-msoft-floatโ picks hardware or software floating-point. Soft float is the default. ๐ง-mdouble-float,-mno-double-floatโ when-mhard-floatis in effect,-mdouble-floatenables double-precision float instructions. This is the default except when compiling for CK803 โจ-mfdivdu,-mno-fdivduโ when-mhard-floatis in effect,-mfdivduenablesfrecipd,fsqrtd, andfdivdinstructions. Also the default except when compiling for CK803 ๐-mfpu=fpuโ selects the floating-point processor. This only works with-mhard-float. The values forfpuarefpv2_sf(equivalent to-mno-double-float -mno-fdivdu),fpv2(-mdouble-float -mno-divdu), andfpv2_divd(-mdouble-float -mdivdu) ๐ฆ-melrw,-mno-elrwโ enables the extendedlrwinstruction. Defaults to on for CK801 and off otherwise. ๐-mistack,-mno-istackโ enables interrupt stack instructions. The default is off. ๐ซถ
The-mistackoption is required to handle theinterruptandisrfunction attributes. Don't skip it, bestie ๐จ
-mmpโ enables multiprocessor instructions. Default is off. ๐ธ-mcpโ enables coprocessor instructions. Default is off. ๐ง-mcacheโ enables coprocessor instructions. Default is off. ๐-msecurityโ enables C-SKY security instructions. Default is off. ๐-mtrustโ enables C-SKY trust instructions. Default is off. ๐-mdsp,-medsp,-mvdspโ enables C-SKY DSP, Enhanced DSP, or Vector DSP instructions, respectively. All of these default to off. ๐ถ-mdiv,-mno-divโ generates divide instructions. Default is off. โ-msmart,-mno-smartโ generates code for Smart Mode, which only uses registers numbered 0-7 so you can use 16-bit instructions. This is ignored for CK801, where this is the required behavior, and it defaults to on for CK802. For other targets, the default is off. ๐-mhigh-registers,-mno-high-registersโ generates code that uses the high registers numbered 16-31. This isn't supported on CK801, CK802, or CK803, and it's enabled by default for other processors ๐-manchor,-mno-anchorโ generates code using global anchor symbol addresses โ-mpushpop,-mno-pushpopโ generates code usingpushandpopinstructions. This option defaults to on. ๐ง-mmultiple-stld,-mstm,-mno-multiple-stld,-mno-stmโ generates code usingstmandldminstructions. This isn't supported on CK801, but it's enabled by default on other processors ๐-mconstpool,-mno-constpoolโ creates constant pools in the compiler instead of handing that job off to the assembler. This is the default and is required for correct code generation on CK801 and CK802. It's optional on other processors ๐ซถ-mstack-size,-mno-stack-sizeโ emits.stack_sizedirectives for each function in the assembly output. This option defaults to off. ๐-mccrt,-mno-ccrtโ generates code for the C-SKY compiler runtime instead oflibgcc. This option defaults to off. ๐ง-mbranch-cost=nโ sets the branch costs to roughlyninstructions. The default is 1. ๐-msched-prolog,-mno-sched-prologโ permits scheduling of function prologue and epilogue sequences. Here's the drama: using this can result in code that isn't compliant with the C-SKY V2 ABI prologue requirements, and that code can't be debugged or backtraced ๐ฑ It's disabled by default.
โจ Darwin Options โจ
These options are defined for all architectures running the Darwin operating system ๐
FSF GCC on Darwin doesn't make "fat" object files. It makes an object file for the single architecture GCC was built to target ๐ฏ Apple's GCC on Darwin does make "fat" files if you use multiple -arch options. It does that by running the compiler or linker multiple times and then joining the results together with lipo ๐งฉ
The subtype of the file (like ppc7400, ppc970, or i686) is decided by the flags that specify the ISA GCC is targeting, like -mcpu or -march. If you want to override that, the -force_cpusubtype_ALL option is your friend ๐
The Darwin tools act differently when they hit an ISA mismatch. The assembler, as, only lets you use instructions that are valid for the subtype of the file it's generating. So you can't put 64-bit instructions in a ppc750 object file ๐
The linker for shared libraries, /usr/bin/libtool, fails and prints an error if you ask it to make a shared library with a less restrictive subtype than its input files. For example, trying to put a ppc970 object file in a ppc7400 library is a no-go ๐ The linker for executables, ld, quietly gives the executable the most restrictive subtype of any of its input files ๐คซ
-Fdirโ adds the framework directorydirto the head of the list of directories searched for header files. These directories are interleaved with the ones from-Ioptions, and they're scanned in a left-to-right order ๐ฆ
Okay bestie, so a framework directory is just a directory that's full of frameworks ๐โจ A framework is a directory with a Headers and/or PrivateHeaders directory sitting directly inside it, and its name has to end in .framework. The framework's name is the directory name minus the .framework part ๐ Its headers live in one of those two folders, and Headers gets searched first. ๐
A subframework is a framework directory that lives inside a framework's Frameworks directory ๐ฆ Includes of subframework headers are only allowed in a header of the framework that contains the subframework, or in a sibling subframework header. Two subframeworks are siblings if they're in the same framework ๐ฏโโ๏ธ A subframework should not share a name with a framework, and if it does, GCC issues a warning. Right now subframeworks can't have subframeworks of their own, but that could change later ๐ธ
The standard frameworks are in /System/Library/Frameworks and /Library/Frameworks ๐ An example include looks like #include <Framework/header.h>, where Framework is the framework's name and header.h is found in the PrivateHeaders or Headers directory.
-iframeworkdirโ This is basically-F, except the directory gets treated as a system directory ๐ง The big difference is that with-iframework, the compiler won't warn you about stuff inside header files found through that directory. This option only works for the C family of languages.-gusedโ Emits debugging info for symbols that are used ๐ For stabs debugging format, this turns on-feliminate-unused-debug-symbols. It's ON by default, so you basically get it for free โจ-gfullโ Emits debugging info for all symbols and types, no exceptions ๐-mmacosx-version-min=versionโ This sets the earliest version of macOS X your executable will run on ๐ Typical values are10.1,10.2, and10.3.9.
If the compiler was built to use the system's headers by default, the default for this option is whatever system version the compiler is running on. Otherwise, it makes choices that play nicest with as many systems and codebases 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-weakand-fno-rttiwhere applicable. It also sets-mno-altivec,-msoft-float,-fno-builtinand-mlong-branchfor PowerPC targets ๐-mone-byte-boolโ Overrides the defaults for"bool"so that"sizeof(bool)==1"๐ By default,"sizeof(bool)"is 4 when compiling for Darwin/PowerPC and 1 when compiling for Darwin/x86, so this option does nothing on x86.
Warning: The -mone-byte-bool switch makes GCC generate code that is NOT binary compatible with code generated without it ๐ญ You may have to recompile all the other modules in your program, including system libraries. Only use this switch when you need to match a non-default data model.
-mfix-and-continue,-ffix-and-continue,-findirect-dataโ These generate code built for fast turnaround development, like letting GDB dynamically load.ofiles into programs that are already running ๐ฆ-findirect-dataand-ffix-and-continueare only here for backwards compatibility.-all_loadโ Loads all members of static archive libraries ๐ Seeman ld(1)for more info.-arch_errors_fatalโ Makes errors about files with the wrong architecture fatal ๐-bind_at_loadโ Marks the output file so the dynamic linker binds all undefined references when the file is loaded or launched โจ-bundleโ Produces a Mach-o bundle format file ๐งบ Seeman ld(1)for more info.-bundle_loader executableโ Specifies the executable that will load the build output file being linked ๐ Seeman ld(1)for more info.-dynamiclibโ When you pass this, GCC produces a dynamic library instead of an executable when linking, using the Darwinlibtoolcommand ๐-force_cpusubtype_ALLโ Gives GCC's output file the ALL subtype, instead of one controlled by-mcpuor-march๐
These options are passed to the Darwin linker, and the Darwin linker man page describes every single one in detail ๐ Here's the whole squad:
-allowable_client client_name-client_name-compatibility_version-current_version-dead_strip-dependency-file-dylib_file-dylinker_install_name-dynamic-exported_symbols_list-filelist-flat_namespace-force_flat_namespace-headerpad_max_install_names-image_base-init-install_name-keep_private_externs-multi_module-multiply_defined-multiply_defined_unused-noall_load-no_dead_strip_inits_and_terms-nofixprebinding-nomultidefs-noprebind-noseglinkedit-pagezero_size-prebind-prebind_all_twolevel_modules-private_bundle-read_only_relocs-sectalign-sectobjectsymbols-whyload-seg1addr-sectcreate-sectobjectsymbols-sectorder-segaddr-segs_read_only_addr-segs_read_write_addr-seg_addr_table-seg_addr_table_filename-seglinkedit-segprot-segs_read_only_addr-segs_read_write_addr-single_module-static-sub_library-sub_umbrella-twolevel_namespace-umbrella-undefined-unexported_symbols_list-weak_reference_mismatches-whatsloaded
๐ DEC Alpha Options ๐
These -m options are defined for the DEC Alpha implementations ๐ฆ
-mno-soft-float,-msoft-floatโ Use (or don't use) the hardware floating-point instructions for floating-point operations ๐ง With-msoft-float, functions inlibgcc.ado the floating-point work instead. Unless they've been replaced by routines that emulate those operations, or compiled to call such emulation routines, these routines issue floating-point operations. If you're compiling for an Alpha without floating-point operations, you have to make sure the library is built so it doesn't call them ๐ญ
Note that 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 register set isn't used, floating-point operands get passed in integer registers as if they were integers, and floating-point results are passed in$0instead of$f0. This is a non-standard calling sequence, so any function with a floating-point argument or return value that's called by code compiled with-mno-fp-regsmust also be compiled with that option ๐
A typical use is building a kernel that doesn't use, and so doesn't need to save and restore, any floating-point registers ๐
-mieeeโ The Alpha architecture has floating-point hardware optimized for maximum performance, and it's mostly IEEE compliant, but full compliance needs some software help ๐ซถ This option generates code that's fully IEEE-compliant, except the inexact-flag isn't maintained (more on that below). When it's 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 like not-a-number and plus/minus infinity. Other Alpha compilers call this option-ieee_with_no_inexact.
DEBIAN SPECIFIC: This option is on by default for alpha-linux-gnu, unless -ffinite-math-only (which is part of the -ffast-math set) is specified ๐ธ The reason: the software functions in the GNU libc math libraries generate denormalized numbers, NaNs, and infs, and all of those will cause a program to SIGFPE when it tries to use the results without -mieee.
-mieee-with-inexactโ This is like-mieee, except the generated code also maintains the IEEE inexact-flag ๐ Turning it on makes the generated code fully-compliant IEEE math. In addition to"_IEEE_FP", the preprocessor macro"_IEEE_FP_EXACT"is defined. On some Alpha implementations, the code may run significantly slower than the default code. Since very little code 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 (for example, the 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 the Alpha architecture manual for details) ๐ก๏ธsuiโ Likesu, but inexact traps are enabled as well โจ
-mfp-rounding-mode=rounding-modeโ Selects the IEEE rounding mode ๐ฏ Other Alpha compilers call this option-fprm rounding-mode. Therounding-modecan be one of:nโ Normal IEEE rounding mode. Floating-point numbers are rounded towards the nearest machine number, or towards the even machine number in case of a tie ๐mโ Rounds towards minus infinity โฌ๏ธcโ Chopped rounding mode. Floating-point numbers are rounded towards zero โ๏ธdโ Dynamic rounding mode. A field in the floating-point control register (fpcr, see the Alpha architecture reference manual) controls the rounding mode in effect. The C library initializes this register for rounding towards plus infinity, so unless your program modifies thefpcr,dcorresponds to rounding towards plus infinity โฌ๏ธ
-mtrap-precision=trap-precisionโ okay so on the Alpha, floating-point traps are imprecise ๐ญ That means without software help you basically can't recover from a float trap, and the program normally has to be terminated ๐ GCC can generate code that helps OS trap handlers figure out the exact spot that caused a floating-point trap โจ Pick your precision based on what your app needs:pโ Program precision ๐ธ This is the default. The trap handler can only tell which program caused the floating-point exception.fโ Function precision ๐ The trap handler can find the function that caused the floating-point exception.iโ Instruction precision ๐ The trap handler can pinpoint the exact instruction that caused the floating-point exception.
Other Alpha compilers have the same idea under the names -scope_safe and -resumption_safe ๐ซถ
-mieee-conformantโ this marks the generated code as IEEE conformant ๐ฆ Its only effect is to emit the line.eflag 48in the function prologue of the generated assembly file.
Careful, bestie โ ๏ธ You must not use this unless you also specify-mtrap-precision=iand either-mfp-trap-mode=suor-mfp-trap-mode=sui. Don't skip the pairing or it's giving chaos ๐
-mbuild-constantsโ normally GCC looks at a 32- or 64-bit integer constant and checks if it can build it from smaller constants in two or three instructions ๐ง If it can't, it outputs the constant as a literal and generates code to load it from the data segment at run time.
Use this option to make GCC build all integer constants with code, even if that takes more instructions (the maximum is six) ๐
You typically use this when building a shared library dynamic loader ๐ It's a shared library itself, so it has to relocate itself in memory before it can find the variables and constants in its own data segment. Lowkey wild, iykyk ๐ญ
-mbwx,-mno-bwx,-mcix,-mno-cix,-mfix,-mno-fix,-mmax,-mno-maxโ these decide whether GCC generates code using the optional BWX, CIX, FIX and MAX instruction sets โจ By default it uses whatever instruction sets the CPU type from-mcpu=supports, or the CPU GCC was built on if you don't specify one ๐ธ-mfloat-vax,-mfloat-ieeeโ-mfloat-vaxgenerates code that uses VAX F and G floating-point arithmetic, and-mfloat-ieeegenerates code that does not use it, so you get IEEE single and double precision instead ๐-mexplicit-relocs,-mno-explicit-relocsโ okay this one is a little nerdy ๐ค Older Alpha assemblers had no way to make symbol relocations except through assembler macros, and those macros don't allow optimal instruction scheduling ๐ค GNU binutils as of version 2.12 has a new syntax that lets the compiler explicitly mark which relocations apply to which instructions ๐ This option is mostly useful for debugging, since GCC detects the assembler's capabilities when it's built and sets the default to match โจ-msmall-data,-mlarge-dataโ when-mexplicit-relocsis in effect, static data is accessed through gp-relative relocations ๐ง With-msmall-data, objects 8 bytes long or smaller go into a small data area (the.sdataand.sbsssections) and get accessed through 16-bit relocations off the$gpregister. This caps the small data area at 64KB, but the variables can be accessed with a single instruction, which is so efficient ๐ฅ
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 that data on the heap instead of in the program's data segment ๐ซถ
When generating code for shared libraries, -fpic implies -msmall-data, and -fPIC implies -mlarge-data ๐ฆ
-msmall-text,-mlarge-textโ with-msmall-text, the compiler assumes the code for the whole program (or shared library) fits in 4MB, so it's reachable with a branch instruction ๐ When-msmall-datais also used, the compiler can assume all local symbols share the same$gpvalue, which cuts the instructions needed for a function call from 4 down to 1 ๐คฏ The default is-mlarge-text๐-mcpu=cpu_typeโ sets the instruction set and instruction scheduling parameters for the machine typecpu_typeโจ You can use either the EV style name or the matching chip number. GCC has scheduling parameters for the EV4, EV5 and EV6 families, and it picks the default instruction set values from the processor you name ๐ If you don't specify 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 the BWX extension.pca56,21164pc,21164PCโ schedules as an EV5 and supports the BWX and MAX extensions.ev6,21264โ schedules as an EV6 and supports the BWX, FIX, and MAX extensions.ev67,21264aโ schedules as an EV6 and supports the BWX, CIX, FIX, and MAX extensions.
Native toolchains also support the value native, which picks the best architecture option for the host processor ๐ -mcpu=native has no effect if GCC doesn't recognise the processor ๐
-mtune=cpu_typeโ sets only the instruction scheduling parameters forcpu_type. The instruction set doesn't change, so no vibe shift there ๐
Native toolchains also support native, which selects the best architecture option for the host processor โจ -mtune=native has no effect if GCC doesn't recognise the processor.
-mmemory-latency=timeโ sets the latency the scheduler should assume for typical memory references as seen by the application ๐ง This number depends a LOT on the application'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 & 3 caches (also called Dcache, Scache, and Bcache), plus main memory. Note thatL3is only valid for EV5 ๐ธ
๐ง 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 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 be run on the simulator ๐ฅ๏ธ This links in an alternate runtime startup and library.
Danger zone ๐จ 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โ don't usedivandmodinstructions ๐ โโ๏ธ-mft32bโ enables the extended instructions of the FT32B processor โจ-mcompressโ compresses all code using the Ft32B code compression scheme ๐๏ธ-mnopmโ don't generate code that reads program memory ๐ซถ
๐ FRV Options ๐
-mgpr-32โ only use the first 32 general-purpose registers ๐ธ-mgpr-64โ use all 64 general-purpose registers ๐-mfpr-32โ use only the first 32 floating-point registers ๐-mfpr-64โ use all 64 floating-point registers ๐-mhard-floatโ use hardware instructions for floating-point operations โก-msoft-floatโ use library routines for floating-point operations ๐-malloc-ccโ dynamically allocate condition code registers ๐ง-mfixed-ccโ don't try to dynamically allocate condition code registers; only useicc0andfcc0๐-mdwordโ changes the ABI to use double word instructions ๐ซ-mno-dwordโ don't use double word instructions ๐ โโ๏ธ-mdoubleโ use floating-point double instructions ๐ฆ-mno-doubleโ don't use floating-point double instructions ๐-mmediaโ use media instructions ๐ถ-mno-mediaโ don't use media instructions ๐ซฅ-mmuladdโ use multiply and add/subtract instructions โ๏ธ-mno-muladdโ don't use multiply and add/subtract instructions ๐-mfdpicโ selects the FDPIC ABI, which uses function descriptors to represent pointers to functions ๐งฉ Without any PIC/PIE-related options, it implies-fPIE. With-fpicor-fpie, it assumes GOT entries and small data are within a 12-bit range from the GOT base address. With-fPICor-fPIE, GOT offsets are computed with 32 bits ๐ With abfin-elftarget, this option implies-msim.-minline-pltโ enables inlining of PLT entries in function calls to functions that aren't known to bind locally โจ It has no effect without-mfdpic. It's enabled by default if you're optimizing for speed and compiling for shared libraries (i.e.,-fPICor-fpic), or when an optimization option such as-O3or above is on the command line ๐-mTLSโ assumes a large TLS segment when generating thread-local code ๐งต-mtlsโ does not assume a large TLS segment when generating thread-local code ๐ชก-mgprel-roโ enables the use ofGPRELrelocations in the FDPIC ABI for data known to be in read-only sections ๐ It's enabled by default, except for-fpicor-fpie: even though it may 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 needing 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โ okay so this one links with the (library, not FD) pic libraries ๐ธ. It's implied by-mlibrary-pic, and also by-fPICand-fpicwhen-mfdpicisn't in the mix. You should literally never have to type it yourself ๐ .-mlinked-fpโ the EABI says you always need a frame pointer whenever a stack frame gets allocated, and this is on by default ๐ฆ. If you want it gone, use-mno-linked-fp.-mlong-callsโ uses indirect addressing to call functions outside the current compilation unit ๐ง. The payoff is that those functions can be placed anywhere in the 32-bit address space โจ.-malign-labelsโ tries to align labels to an 8-byte boundary by sticking NOPs into the previous packet ๐ซถ. Only works when VLIW packing is enabled. It doesn't make new packets, it just adds NOPs to the ones that already exist ๐.-mlibrary-picโ generates position-independent EABI code ๐.-macc-4โ only uses the first four media accumulator registers ๐.-macc-8โ uses all eight media accumulator registers ๐.-mpackโ packs VLIW instructions ๐.-mno-packโ does NOT pack VLIW instructions ๐.-mno-eflagsโ doesn't mark ABI switches ine_flags๐ง.-mcond-moveโ enables conditional-move instructions, and this is the default ๐ .- Heads up bestie, this switch is mainly for debugging the compiler and will likely be removed in a future version ๐ฅบ.
-mno-cond-moveโ disables conditional-move instructions ๐.- This one is mainly for debugging the compiler too, and it'll likely be yeeted in a future version ๐ซ .
-msccโ enables conditional set instructions (default) โจ.- Mainly for compiler debugging, and likely to be removed in a future version ๐ฃ.
-mno-sccโ disables conditional set instructions ๐.- Also mainly for compiler debugging, and likely to be removed in a future version ๐.
-mcond-execโ enables conditional execution (default) ๐ฆ.- Mainly a debugging switch, and likely to be removed in a future version ๐ฅฒ.
-mno-cond-execโ disables conditional execution ๐ซฅ.- Mainly for debugging the compiler, and likely to be removed in a future version ๐ญ.
-mvliw-branchโ runs a pass to pack branches into VLIW instructions (default) ๐ธ.- Mainly a debugging switch, and likely to be removed in a future version ๐ซถ.
-mno-vliw-branchโ does NOT run a pass to pack branches into VLIW instructions ๐ .- Mainly for debugging, and likely to be removed in a future version ๐.
-mmulti-cond-execโ enables optimization of "&&" and "||" in conditional execution (default) ๐.- Mainly a debugging switch, and likely to be removed in a future version ๐ง.
-mno-multi-cond-execโ disables optimization of "&&" and "||" in conditional execution ๐.- Mainly for compiler debugging, and likely to be removed in a future version ๐ซ .
-mnested-cond-execโ enables nested conditional execution optimizations (default) ๐.- Mainly a debugging switch, and likely to be removed in a future version ๐ฅบ.
-mno-nested-cond-execโ disables nested conditional execution optimizations ๐ซฅ.- Mainly for debugging, and likely to be removed in a future version ๐ญ.
-moptimize-membarโ removes redundant "membar" instructions from the compiler-generated code โจ. It's enabled by default, so you get this one for free ๐.-mno-optimize-membarโ turns off the automatic removal of redundant "membar" instructions from the generated code ๐.-mtomcat-statsโ makes gas print out tomcat statistics ๐.-mcpu=cpuโ picks the processor type you want code generated for ๐ . The possible values arefrv,fr550,tomcat,fr500,fr450,fr405,fr400,fr300andsimple๐.
โจ GNU/Linux Options โจ
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, this option enables
-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default ๐. - When linking, this option makes the GCC driver pass Android-specific options to the linker ๐.
- Finally, this option causes the preprocessor macro "
__ANDROID__" to be defined ๐.
- When compiling, this option 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 it's possible ๐. It uses the linker option-relax.-mhโ generates code for the H8/300H ๐ซ.-msโ generates code for the H8S ๐.-mnโ generates code for the H8S and H8/300H in the normal mode ๐ซถ. This switch must be used either with-mhor-ms.-ms2600โ generates code for the H8S/2600 ๐ฆ. This switch must be used with-ms.-mexrโ stores extended registers on the stack before a function with the monitor attribute runs ๐. This is the default option. It's only valid for H8S targets.-mno-exrโ does NOT store extended registers on the stack before a function with the monitor attribute runs ๐. This option is the default one is-mno-exr, I mean, if you don't pick-mexr๐ . It's only valid for H8S targets.-mint32โ makes "int" data 32 bits by default ๐.-malign-300โ on the H8/300H and H8S, uses the same alignment rules as the H8/300 ๐ธ. The default for the H8/300H and H8S is to align longs and floats on 4-byte boundaries, but-malign-300moves them to 2-byte boundaries instead. This option has no effect on the H8/300.
๐ท HPPA Options
These -m options are defined for the HPPA family of computers ๐ป.
-march=architecture-typeโ generates code for the architecture you specify ๐๏ธ. The choices for architecture-type are1.0for PA 1.0,1.1for PA 1.1, and2.0for PA 2.0 processors. Refer to/usr/lib/sched.modelson an HP-UX system to find the right architecture option for your machine ๐. Code compiled for lower numbered architectures runs on higher numbered architectures, but not the other way around ๐ซ.-mpa-risc-1-0,-mpa-risc-1-1,-mpa-risc-2-0โ these are synonyms for-march=1.0,-march=1.1, and-march=2.0respectively ๐ฏ.-mcaller-copiesโ the caller copies function arguments that get passed by hidden reference ๐.
โ ๏ธ Use this one with care, bestie! It is not compatible with the default 32-bit runtime. However, only aggregates larger than eight bytes are passed by hidden reference, and this option gives 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. Literally dead.
-mdisable-indexingโ stops the compiler from using indexing address modes ๐ . This avoids some rather obscure problems when compiling MIG generated code under MACH ๐ค.-mno-space-regsโ generates code that assumes the target has no space registers ๐. This lets GCC make 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 does faster indirect calls.
โ ๏ธ This option does not work in the presence of shared libraries or nested functions. Don't say I didn't warn you ๐ญ.
-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers ๐งฑ. A fixed register is one the register allocator can't use, which is super useful when compiling kernel code ๐ ๏ธ. You specify a register range as two registers separated by a dash, and you can separate multiple ranges with a comma ๐.-mlong-load-storeโ generates 3-instruction load and store sequences, which the HP-UX 10 linker sometimes needs ๐ฆ. This is equivalent to the+koption on the HP compilers.-mportable-runtimeโ uses the portable calling conventions HP proposed for ELF systems ๐.-mgasโ enables the use of assembler directives that only GAS understands ๐ฃ.-mschedule=cpu-typeโ schedules code according to the constraints for the machine type cpu-type ๐๏ธ. The choices for cpu-type are700 7100,7100LC,7200,7300and8000. Refer to/usr/lib/sched.modelson an HP-UX system to 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: this makes symbolic debugging impossible. It also triggers a bug in the HP-UX 8 and HP-UX 9 linkers, where they give bogus error messages when linking some programs. Not it ๐.
-msoft-floatโ generates output containing library calls for floating point ๐งฎ.
โ ๏ธ The requisite libraries are not available for all HPPA targets. Normally the facilities of the machine's usual C compiler are used, but this cannot be done directly in cross-compilation. You must 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 your whole program with this option ๐ซถ. In particular, you need to compile libgcc.a, the library that comes with GCC, with -msoft-float for this to work ๐.
-msioโ generates the predefine "_SIO" for server IO ๐ง. The default is-mwsio. That one generates the predefines "__hp9000s700", "__hp9000s700__" and "_WSIO" for workstation IO ๐ฅ๏ธ. These options are available under HP-UX and HI-UX โจ.-mgnu-ldโ okay so this one tells GCC to use the GNU ld energy ๐ง It passes-sharedtoldwhen building a shared library. It's the default when GCC is configured, explicitly or implicitly, with the GNU linker. Heads up: this option does NOT decide whichldgets called, it only changes the parameters sent to it ๐ Theldthat gets called is picked by the--with-ldconfigure option, GCC's program search path, and finally the user's PATH. You can check which linker GCC is using with whichgcc -print-prog-name=ld. This is only available on the 64-bit HP-UX GCC, i.e. configured withhppa*64*-*-hpux*๐ซถ-mhp-ldโ the HP linker's turn to shine ๐ธ 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. Same deal as above: it doesn't change whichldis called, just the parameters. That's decided by the--with-ldconfigure option, GCC's program search path, and finally the user's PATH. The linker GCC uses can be printed with whichgcc -print-prog-name=ld. Also only available on the 64-bit HP-UX GCC, i.e. configured withhppa*64*-*-hpux*โจ-mlong-callsโ generates long call sequences, so a call can ALWAYS reach linker-generated stubs ๐ฆ By default, long calls only get generated when the distance from the call site to the beginning of the function or translation unit (depending on the case) goes past a predefined limit set by the branch type being used. The limits for normal calls are 7,600,000 and 240,000 bytes, respectively for the PA 2.0 and PA 1.X architectures. Sibcalls are always limited at 240,000 bytes.
Distances get measured from the beginning of functions when using the -ffunction-sections option, or when using the -mgas and -mno-portable-runtime options together under HP-UX with the SOM linker.
Real talk, it's normally not desirable to use this one because it degrades performance ๐ญ It might still be useful in large applications, especially when partial linking is used to build the application.
The types of long calls used depend on what the assembler and linker can do, plus the type of code being generated. On systems that support long absolute calls, and long pic symbol-difference or pc-relative calls, the impact should be relatively small. BUT an indirect call is used on 32-bit ELF systems in pic code, and it is quite long ๐
-munix=unix-stdโ picks a UNIX standard, and GCC generates compiler predefines and selects a startfile for it ๐ The choices forunix-stdare93,95and98.93works on all HP-UX versions.95is available on HP-UX 10.10 and later.98is available on HP-UX 11.11 and later. The defaults are93for HP-UX 10.00,95for HP-UX 10.10 through 11.00, and98for HP-UX 11.11 and later.
-munix=93 gives you the same predefines as GCC 3.3 and 3.4. -munix=95 adds predefines for "XOPEN_UNIX" and "_XOPEN_SOURCE_EXTENDED", plus the startfile unix95.o. -munix=98 adds predefines for "_XOPEN_UNIX", "_XOPEN_SOURCE_EXTENDED", "_INCLUDE__STDC_A1_SOURCE" and "_INCLUDE_XOPEN_SOURCE_500", plus the startfile unix98.o.
โ ๏ธ Be careful with this one, bestie! This option changes the interfaces for various library routines, and it also affects the operational behavior of the C library. Extreme care is needed when using it.
Library code that's meant to work with more than one UNIX standard has to test, set and restore the variable "__xpg4_extended_mask" as appropriate. Most GNU software doesn't provide this capability ๐
-nolibdldโ stops GCC from adding the link options that searchlibdld.slwhen-staticis specified on HP-UX 10 and later ๐-staticโ okay, this one has drama ๐ญ The HP-UX implementation ofsetlocalein libc depends onlibdld.sl. There isn't an archive version oflibdld.sl, so when-staticis specified, special link options are needed to resolve that dependency.
On HP-UX 10 and later, the GCC driver adds the necessary options to link with libdld.sl when -static is specified. This makes the resulting binary dynamic. On the 64-bit port, the linkers generate dynamic binaries by default anyway. If you don't want the GCC driver adding these link options, use -nolibdld ๐ซถ
-threadsโ adds support for multithreading with the dce thread library under HP-UX ๐งต This option sets flags for both the preprocessor and the linker.
โจ IA-64 Options โจ
These are the -m options defined for the Intel IA-64 architecture ๐
-mbig-endianโ generates code for a big-endian target. This is the default for HP-UX ๐-mlittle-endianโ generates code for a little-endian target. This is the default for AIX5 and GNU/Linux ๐ฃ-mgnu-as,-mno-gnu-asโ generates (or doesn't) code for the GNU assembler. 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 does NOT use a global pointer register. The result is not position independent code, and it violates the IA-64 ABI ๐-mvolatile-asm-stop,-mno-volatile-asm-stopโ generates (or doesn't) a stop bit immediately before and after volatileasmstatements ๐-mregister-names,-mno-register-namesโ generates (or doesn't)in,loc, andoutregister names for the stacked registers. This may make the assembler output more readable ๐-mno-sdata,-msdataโ disables (or enables) optimizations that use the small data section. This may be useful for working around optimizer bugs ๐-mconstant-gpโ generates code that uses a single constant global pointer value. This is useful when compiling kernel code ๐ฅ๏ธ-mauto-picโ generates code that is self-relocatable. This implies-mconstant-gp. It's useful when compiling firmware code ๐ง-minline-float-divide-min-latencyโ generates code for inline divides of floating-point values using the minimum latency algorithm โก-minline-float-divide-max-throughputโ generates code for inline divides of floating-point values using the maximum throughput algorithm ๐-mno-inline-float-divideโ does NOT generate inline code for divides of floating-point values ๐-minline-int-divide-min-latencyโ generates code for inline divides of integer values using the minimum latency algorithm โก-minline-int-divide-max-throughputโ generates code for inline divides of integer values using the maximum throughput algorithm ๐-mno-inline-int-divideโ does NOT generate inline code for divides of integer values ๐-minline-sqrt-min-latencyโ generates code for inline square roots using the minimum latency algorithm โก-minline-sqrt-max-throughputโ generates code for inline square roots using the maximum throughput algorithm ๐-mno-inline-sqrtโ does NOT generate inline code for"sqrt"๐-mfused-madd,-mno-fused-maddโ does (or doesn't) generate code that uses the fused multiply/add or multiply/subtract instructions. The default is to use these instructions ๐ฅ-mno-dwarf2-asm,-mdwarf2-asmโ doesn't (or does) generate assembler code for the DWARF line number debugging info. This may be useful when NOT using the GNU assembler ๐งฉ-mearly-stop-bits,-mno-early-stop-bitsโ allows stop bits to be placed earlier than immediately preceding the instruction that triggered the stop bit. This can improve instruction scheduling, but it doesn't always do so ๐-mfixed-range=register-rangeโ generates code treating the given register range as fixed registers. A fixed register is one the register allocator cannot use. This is useful when compiling kernel code. A register range is specified as two registers separated by a dash, and you can specify multiple register ranges separated by a comma ๐ธ-mtls-size=tls-sizeโ specifies the bit size of immediate TLS offsets. Valid values are14,22, and64๐-mtune=cpu-typeโ tunes the instruction scheduling for a particular CPU. Valid values areitanium,itanium1,merced,itanium2, andmckinley๐ฏ-milp32,-mlp64โ generates code for a 32-bit or 64-bit environment. The 32-bit environment setsint,longand pointer to 32 bits. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits. These are HP-UX specific flags ๐ฆ-mno-sched-br-data-spec,-msched-br-data-specโ disables (or enables) data speculative scheduling before reload. This results in generation ofld.ainstructions and the corresponding check instructions (ld.c/chk.a). The default setting is disabled ๐-msched-ar-data-spec,-mno-sched-ar-data-specโ enables (or disables) data speculative scheduling after reload. This results in generation ofld.ainstructions and the corresponding check instructions (ld.c/chk.a). The default setting is enabled ๐-mno-sched-control-spec,-msched-control-specโ disables (or enables) control speculative scheduling. This feature is available only during region scheduling (i.e. before reload). This results in generation of theld.sinstructions and the corresponding check instructionschk.s. The default setting is disabled ๐ซง-msched-br-in-data-spec,-mno-sched-br-in-data-specโ enables (or disables) speculative scheduling of the instructions that depend on the data speculative loads before reload. This is effective only with-msched-br-data-specenabled. The default setting is enabled ๐ท-msched-ar-in-data-spec,-mno-sched-ar-in-data-specโ enables (or disables) speculative scheduling of the instructions that depend on the data speculative loads after reload. This is effective only with-msched-ar-data-specenabled. The default setting is enabled ๐ญ-msched-in-control-spec,-mno-sched-in-control-specโ enables (or disables) speculative scheduling of the instructions that depend on the control speculative loads. This is effective only with-msched-control-specenabled. The default setting is enabled ๐-mno-sched-prefer-non-data-spec-insns,-msched-prefer-non-data-spec-insnsโ ๐ธ When this is on, data-speculative instructions only get picked for scheduling if there's literally nothing else available. It makes data speculation super conservative. It's off by default.-mno-sched-prefer-non-control-spec-insns,-msched-prefer-non-control-spec-insnsโ ๐ฆ Same vibe, but for control-speculative instructions. They only get chosen when there are no other options left, so control speculation gets very conservative. Off by default.-mno-sched-count-spec-in-critical-path,-msched-count-spec-in-critical-pathโ ๐ When enabled, speculative dependencies get counted when GCC works out instruction priorities. That makes speculation a bit more cautious. It's disabled by default.-msched-spec-ldcโ ๐ง Uses a simple data speculation check. This one is on by default, bestie.-msched-control-spec-ldcโ โจ Uses a simple check for control speculation. Also on by default.-msched-stop-bits-after-every-cycleโ ๐ Puts a stop bit after every cycle while scheduling. On by default.-msched-fp-mem-deps-zero-costโ ๐ Tells GCC to assume floating-point stores and loads aren't likely to clash when they land in the same instruction group. Disabled by default.-msel-sched-dont-check-control-specโ ๐ Generates checks for control speculation in selective scheduling. Heads up: this flag is disabled by default.-msched-max-memory-insns=max-insnsโ ๐ฅ Sets a limit on how many memory insns can go in one instruction group. Any extra memory insns trying to squeeze into that same group get lower priority. This is super handy for avoiding 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 many memory insns can ever show up in one instruction group. Without this, the limit is "soft": non-memory ops get preferred once you hit it, but memory ops can still sneak in if they need to.
๐ 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โ ๐ Picks the CPU you're generating code 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โ ๐ธ Says the program will run on the simulator. This links in an alternate runtime library that supports stuff like file I/O. > You must not use this option when generating programs for real hardware! For that you need to provide your own runtime library for whatever I/O functions you need, bestie. ๐-memregs=numberโ ๐ฅ Sets how many memory-based pseudo-registers GCC uses during code generation. They get used like real registers, so it's a tradeoff: fitting code into the available registers versus the performance hit from using memory instead. Every module in a program has to be compiled with the same value for this option. Because of that, you must not use this option with GCC's default runtime libraries.
๐ฆ M32R/D Options ๐ฆ
These -m options are defined for Renesas M32R/D architectures:
-m32r2โ โจ Generates code for the M32R/2.-m32rxโ ๐ Generates code for the M32R/X.-m32rโ ๐ Generates code for the M32R. This is the default.-mmodel=smallโ ๐ Assumes all objects live in the lower 16MB of memory, so their addresses can be loaded with the "ld24" instruction. It also assumes all subroutines are reachable with the "bl" instruction. This is the default.
The addressability of a particular object can be set with the "model" attribute.
-mmodel=mediumโ ๐ง Assumes objects may be anywhere in the 32-bit address space, so the compiler generates "seth/add3" instructions to load their addresses. It still assumes all subroutines are reachable with the "bl" instruction.-mmodel=largeโ ๐ฅ Assumes objects may be anywhere in the 32-bit address space (the compiler generates "seth/add3" instructions to load their addresses). It also assumes subroutines may not be reachable with the "bl" instruction, so the compiler generates the much slower "seth/add3/jl" instruction sequence. Slow but steady, periodt. ๐ข-msdata=noneโ ๐ Disables use of the small data area. Variables get put into one of ".data", ".bss", or ".rodata" (unless the "section" attribute has been specified). This is the default.
The small data area is made up of the ".sdata" and ".sbss" sections. You can explicitly put objects in the small data area with the "section" attribute using one of these sections.
-msdata=sdataโ ๐ธ Puts small global and static data in the small data area, but doesn't generate any special code to reference them.-msdata=useโ ๐ Puts small global and static data in the small data area and generates special instructions to reference them.-G numโ ๐ Puts global and static objects that are less than or equal tonumbytes into the small data or BSS sections instead of the normal data or BSS sections. The default value ofnumis8. The-msdataoption has to be set to eithersdataorusefor this option to do anything.
All modules should be compiled with the same -G num value. Compiling with different values of num may or may not work. If it doesn't, the linker throws an error message. Incorrect code is not generated, though, so no sneaky bugs. ๐ซถ
-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 be1or2.-mbranch-cost=numberโ ๐numbercan only be1or2. If it's1, branches are preferred over conditional code. If it's2, the opposite applies.-mflush-trap=numberโ ๐ Specifies the trap number to use to flush the cache. The default is12. Valid numbers are between0and15inclusive.-mno-flush-trapโ ๐ฆ Specifies that the cache cannot be flushed by using a trap.-mflush-func=nameโ ๐ง Specifies the name of the operating system function to call to flush the cache. The default is_flush_cache, but a function call is only used if a trap isn't available.-mno-flush-funcโ ๐ Indicates that there's 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. Valid values ofarchfor M680x0 architectures are:68000,68010,68020,68030,68040,68060andcpu32. ColdFire architectures are picked according to Freescale's ISA classification, and the valid values are:isaa,isaaplus,isabandisac.
GCC defines a macro __mcfarch__ whenever it's generating code for a ColdFire target. The arch in this macro is one of the -march arguments listed above.
When you use -march and -mtune together, you get code that runs on a family of similar processors but is optimized for one particular microarchitecture. ๐ซถ
-mcpu=cpuโ ๐ Generates code for a specific M680x0 or ColdFire processor. The M680x0 cpus are:68000,68010,68020,68030,68040,68060,68302,68332andcpu32. The ColdFire cpus are in the table below, which also sorts the CPUs into families:
Family : -mcpu arguments
51 : 51 51ac 51ag 51cn 51em 51je 51jf 51jg 51jm 51mm 51qe 51qm
5206 : 5202 5204 5206
5206e : 5206e
5208 : 5207 5208
5211a : 5210a 5211a
5213 : 5211 5212 5213
5216 : 5214 5216
52235 : 52230 52231 52232 52233 52234 52235
5225 : 5224 5225
52259 : 52252 52254 52255 52256 52258 52259
5235 : 5232 5233 5234 5235 523x
5249 : 5249
5250 : 5250
5271 : 5270 5271
5272 : 5272
5275 : 5274 5275
5282 : 5280 5281 5282 528x
53017 : 53011 53012 53013 53014 53015 53016 53017
5307 : 5307
5329 : 5327 5328 5329 532x
5373 : 5372 5373 537x
5407 : 5407
5475 : 5470 5471 5472 5473 5474 5475 547x 5480 5481 5482 5483 5484
5485
-mcpu=cpu overrides -march=arch if arch is compatible with cpu. Other combinations of -mcpu and -march get rejected, so watch out! โ ๏ธ
GCC defines the macro __mcf_cpu_cpu when a ColdFire target cpu is selected. It also defines __mcf_family_family, where the value of family comes from the table above. โจ
-mtune=tuneโ ๐ฅ Tunes the code for a particular microarchitecture, within the limits set by-marchand-mcpu. The M680x0 microarchitectures 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 pretty well on 68020, 68030 and 68040 targets. -mtune=68020-60 is similar, but it includes 68060 targets too. These two options pick the same tuning decisions as -m68020-40 and -m68020-60 respectively. ๐
GCC defines the macros __mcarch and __mcarch__ when tuning for 680x0 architecture arch. It also defines mcarch unless either -ansi or a non-GNU -std option is used. If GCC is tuning for a range of architectures, as selected by -mtune=68020-40 or -mtune=68020-60, it defines the macros for every architecture in the range. ๐
GCC also defines the macro __muarch__ when tuning for ColdFire microarchitecture uarch, where uarch is one of the arguments listed above. ๐ฆ
๐ OPTIONS, continued ๐
-m68000,-mc68000โ okay so this one is the 68000 output, and it's the default if your compiler was set up for 68000-based systems ๐ธ It's the same as-march=68000. Use it for microcontrollers with a 68000 or EC000 core, like the 68008, 68302, 68306, 68307, 68322, 68328 and 68356 ๐ซถ-m68010โ generates code for a 68010 ๐ฆ Default when you're configured for 68010 systems, and it's the same as-march=68010.-m68020,-mc68020โ the 68020 version โจ Default for 68020 configs, equal to-march=68020. Slay.-m68030โ a 68030 build ๐ Default for 68030 configs, same as-march=68030.-m68040โ the 68040 build ๐ Default for 68040 configs, and it's the same as-march=68040. Lowkey important bit: this one stops using the 68881/68882 instructions that the 68040 has to fake in software. Only use it if your 68040 doesn't have the code to emulate those, bestie ๐ญ-m68060โ 68060 output ๐ฅ Default for 68060 configs, same as-march=68060. It blocks the 68020 and 68881/68882 instructions that the 68060 has to emulate in software, so use it only if your 68060 lacks that emulation code ๐-mcpu32โ CPU32 output ๐ง Default for CPU32 configs, same as-march=cpu32. It's for microcontrollers with a CPU32 or CPU32+ core, including the 68330, 68331, 68332, 68333, 68334, 68336, 68340, 68341, 68349 and 68360 ๐-m5200โ a 520X ColdFire CPU ๐ Default for 520X configs. It's the same as-mcpu=5206, but it's deprecated now, so use-mcpu=5206instead. It's meant for microcontrollers with a 5200 core, like the MCF5202, MCF5203, MCF5204 and MCF5206.-m5206eโ a 5206e ColdFire CPU. Deprecated, so just switch to-mcpu=5206e๐-m528xโ a member of the ColdFire 528X family. Also deprecated, use-mcpu=528xinstead โจ-m5307โ a ColdFire 5307 CPU. Deprecated! Go with-mcpu=5307๐-m5407โ a ColdFire 5407 CPU. Deprecated too, so it's-mcpu=5407now ๐ฆ-mcfv4eโ ColdFire V4e family vibes (think 547x/548x) ๐ฅ This includes the hardware floating-point instructions. It's equal to-mcpu=547x, and yep, it's deprecated in favor of that.-m68020-40โ generates 68040 code without any of the new instructions ๐ The result runs pretty efficiently on a 68020/68881, a 68030, or a 68040. The generated code does use the 68881 instructions that the 68040 emulates. This is the same as-march=68020 -mtune=68020-40.-m68020-60โ same energy as above, but for 68060 code, still without any of the new instructions ๐ซถ It 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. Equivalent to-march=68020 -mtune=68020-60.-mhard-float,-m68881โ turns on floating-point instructions ๐ธ This is the default for the 68020 and up, and for ColdFire devices with an FPU. It defines the macro__HAVE_68881__on M680x0 targets and__mcffpu__on ColdFire targets.-msoft-floatโ no floating-point instructions here, bestie ๐ Library calls do the math instead. It's the default for 68000, 68010, and 68832 targets, and also for ColdFire devices that don't have an FPU.-mdiv,-mno-divโ-mdivturns on ColdFire hardware divide and remainder instructions, and-mno-divturns them off ๐งฎ If you use-marchwithout-mcpu, the default is "on" for ColdFire architectures and "off" for M680x0 architectures. Otherwise the default comes from the target CPU, either the default CPU or whichever one you picked with-mcpu. For example, it's "off" for-mcpu=5206but "on" for-mcpu=5206e. Also, GCC defines the macro__mcfhwdiv__when this is enabled, so you can check for it โจ-mshortโ this one treatsintas 16 bits wide, just likeshort int๐ On top of that, parameters passed on the stack get aligned to a 16-bit boundary, even on targets that are supposed to promote them to 32-bit.-mno-shortโintis not 16 bits wide. This is the default, so you're probably already here ๐-mnobitfield,-mno-bitfieldโ don't use the bit-field instructions ๐ Heads up,-m68000,-mcpu32and-m5200all imply-mnobitfield.-mbitfieldโ do use the bit-field instructions ๐ฅ-m68020implies this, and it's the default if you're using a configuration designed for a 68020.-mrtdโ okay this one is a whole vibe ๐ It switches to a different function-calling convention, where functions with a fixed number of arguments return with thertdinstruction, which pops their arguments on the way out. That saves one instruction in the caller since it doesn't have to pop anything. The default is-mno-rtd.
Warning, bestie: this calling convention is incompatible with the one normally used on Unix, so you can't use it if you need to call libraries compiled with the Unix compiler. You also must provide function prototypes for every function that takes a variable number of arguments (including printf), or the code generated for those calls will be incorrect. And if you call a function with too many arguments, you get seriously incorrect code. Normally extra arguments are harmlessly ignored, but not here ๐ญ
The rtd instruction is supported by the 68010, 68020, 68030, 68040, 68060 and CPU32 processors, but not by the 68000 or 5200.
-malign-int,-mno-align-intโ controls whether GCC alignsint,long,long long,float,double, andlong doublevariables on a 32-bit boundary (-malign-int) or a 16-bit boundary (-mno-align-int) ๐ Aligning on 32-bit boundaries makes code run a bit faster on processors with 32-bit busses, but it costs more memory.
Warning: if you use -malign-int, GCC aligns structures containing those types differently than most published application binary interface specifications for the m68k. Watch out for that one, bestie ๐ซฃ
-mpcrelโ uses the 68000's pc-relative addressing mode directly, instead of a global offset table ๐ฆ For now this option implies-fpic, which allows at most a 16-bit offset for pc-relative addressing.-fPICisn't supported with-mpcrelyet, although that could be supported for 68020 and higher processors.-mno-strict-align,-mstrict-alignโ-mno-strict-alignmeans GCC does not assume that unaligned memory references get handled by the system, and-mstrict-alignmeans it does assume that ๐ง-msep-dataโ generates code that lets the data segment sit in a different area of memory than the text segment ๐ This allows execute-in-place in an environment without virtual memory management. It implies-fPIC.-mno-sep-dataโ generates code that assumes the data segment follows the text segment. This is the default ๐ธ-mid-shared-libraryโ generates code that supports shared libraries through the library ID method โจ This allows execute-in-place and shared libraries in an environment without virtual memory management. It implies-fPIC.-mno-id-shared-libraryโ generates code that doesn't assume ID-based shared libraries are being used. This is the default ๐-mshared-library-id=nโ specifies the identification number of the ID-based shared library being compiled ๐ง Specifying0generates more compact code. Other values force that number onto the current library, but it's no more space- or time-efficient than leaving this option out.-mxgot,-mno-xgotโ when generating position-independent code for ColdFire,-mxgotmakes code that works even if the GOT has more than 8192 entries ๐ That code is larger and slower than the normal stuff. On M680x0 processors you don't need this one, since-fPICis enough.
Normally GCC uses a single instruction to load values from the GOT. That's pretty efficient, but it only works if the GOT is smaller than about 64k. Anything bigger makes the linker throw an error like this:
relocation truncated to fit: R_68K_GOT16O foobar
If that happens, recompile your code with -mxgot, and it should work with very large GOTs ๐ซถ Heads up though: code built with -mxgot is less efficient, since it takes 4 instructions to fetch the value of a global symbol.
Also, 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, so you're probably fine ๐
These options have no effect unless GCC is generating position-independent code.
-mlong-jump-table-offsetsโ uses 32-bit offsets inswitchtables ๐ The default is 16-bit offsets.
๐ MCore Options ๐
These are the -m options defined for the Motorola M*Core processors ๐ฆ
-mhardlit,-mno-hardlitโ-mhardlitinlines constants into the code stream if it can be done in two instructions or less โจ-mno-hardlitturns that off.-mdiv,-mno-divโ-mdivuses the divide instruction ๐งฎ It's enabled by default, so-mno-divis the one you'd have to ask for.-mrelax-immediate,-mno-relax-immediateโ-mrelax-immediateallows arbitrary-sized immediates in bit operations ๐ธ-mno-relax-immediateshuts that down.-mwide-bitfields,-mno-wide-bitfieldsโ-mwide-bitfieldsalways treats bit-fields asint-sized ๐-mno-wide-bitfieldsis the opposite.-m4byte-functions,-mno-4byte-functionsโ-m4byte-functionsforces all functions to be aligned to a 4-byte boundary ๐-mno-4byte-functionsdoesn't force that.-mcallgraph-data,-mno-callgraph-dataโ-mcallgraph-dataemits callgraph information ๐ธ๏ธ-mno-callgraph-datadoesn't.-mslow-bytes,-mno-slow-bytesโ-mslow-bytesprefers word access when reading byte quantities ๐-mno-slow-bytesturns that preference off.-mlittle-endian,-mbig-endianโ okay so these two share one description: generate code for a little-endian target ๐-m210,-m340โ generate code for the 210 processor โจ-mno-lsimโ assume the runtime support is already taken care of, so skip the simulator library (libsim.a) on the linker command line ๐ธ-mstack-increment=sizeโ sets the max amount for a single stack increment operation ๐ฆ Big values can speed up programs with functions that need a lot of stack space, but they can also trigger a segmentation fault if the stack gets extended too much. The default is0x1000.
๐ bestie, don't go too wild with size. A huge value can cause a segfault if the stack gets extended too far.
โจ MeP Options โจ
-mabsdiffโ ๐ enables theabsinstruction, which gives you the absolute difference between two registers.-mall-optsโ ๐ enables ALL the optional instructions: average, multiply, divide, bit operations, leading zero, absolute difference, min/max, clip, and saturation. Main character energy, no cap.-maverageโ โจ enables theaveinstruction, which computes the average of two registers.-mbased=nโ ๐ง variables of n bytes or smaller get placed in the.basedsection by default. Based variables use the$tpregister as their base register, and there's a 128-byte limit on the.basedsection.-mbitopsโ ๐ฅ enables the bit operation instructions: bit test (btstm), set (bsetm), clear (bclrm), invert (bnotm), and test-and-set (tas).-mc=nameโ ๐ picks which section constant data gets placed in. name can betiny,near, orfar.-mclipโ ๐ฆ enables theclipinstruction. Heads up:-mclipisn't useful unless you also pass-mminmax.-mconfig=nameโ ๐ picks 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 (not part of GCC) provides these configurations through this option, and using this option is the same as using all the corresponding command-line options. The default configuration isdefault.-mcopโ ๐ enables the coprocessor instructions. By default this is a 32-bit coprocessor. The coprocessor is normally enabled 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โ generate big-endian code.-melโ generate little-endian code.-mio-volatileโ tells the compiler that any variable marked with theioattribute is to be considered volatile.-mlโ causes variables to be assigned to the.farsection by default.-mleadzโ enables theleadz(leading zero) instruction.-mmโ causes variables to be assigned to the.nearsection by default.-mminmaxโ enables theminandmaxinstructions.-mmultโ enables the multiplication and multiply-accumulate instructions.-mno-optsโ disables all the optional instructions enabled by-mall-opts๐ โโ๏ธ-mrepeatโ enables therepeatanderepeatinstructions, which are used for low-overhead looping ๐-msโ causes all variables to default to the.tinysection. There's a 65536-byte limit to this section, and accesses to these variables use the%gpbase register.-msaturโ enables the saturation instructions. The compiler doesn't generate these itself right now, but this option is included for compatibility with other tools, likeas.-msdramโ links the SDRAM-based runtime instead of the default ROM-based runtime.-msimโ links the simulator run-time libraries.-msimnovecโ links the simulator runtime libraries, but leaves out built-in support for reset and exception vectors and tables.-mtfโ causes all functions to default to the.farsection. Without this option, functions default to the.nearsection.-mtiny=nโ variables that are n bytes or smaller get allocated to the.tinysection. These use the$gpbase register. The default for this option is4, but there's a 65536-byte limit to the.tinysection.
โจ MicroBlaze Options โจ
-msoft-floatโ use software emulation for floating point (default). ๐งธ-mhard-floatโ use hardware floating-point instructions.-mmemcpyโ don't optimize block moves, usememcpyinstead.-mno-clearbssโ deprecated, bestie. Use-fno-zero-initialized-in-bssinstead.-mcpu=cpu-typeโ use features of, and schedule code for, the given CPU. Supported values are in the formatvX.YY.Z, where X is a 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โ use software multiply emulation (default).-mxl-soft-divโ use software emulation for divides (default).-mxl-barrel-shiftโ use the hardware barrel shifter.-mxl-pattern-compareโ use pattern compare instructions.-msmall-dividesโ use table lookup optimization for small signed integer divisions.-mxl-stack-checkโ deprecated, so use-fstack-checkinstead.-mxl-gp-optโ use GP-relative.sdata/.sbsssections.-mxl-multiply-highโ use multiply high instructions for the high part of a 32x32 multiply.-mxl-float-convertโ use hardware floating-point conversion instructions.-mxl-float-sqrtโ use the hardware floating-point square root instruction.-mbig-endianโ generate code for a big-endian target.-mlittle-endianโ generate code for a little-endian target.-mxl-reorderโ use reorder instructions (swap and byte reversed load/store).-mxl-mode-app-modelโ select the application model app-model. Valid models are:executableโ normal executable (default), uses startup codecrt0.o.-mpic-data-is-text-relativeโ assume 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 calledxmdstub. This uses startup filecrt1.oand sets the start address of the program to0x800.bootstrapโ for applications that are loaded using a bootloader. This model uses startup filecrt2.o, which doesn't contain a processor reset vector handler. It's suitable for handing control to the bootloader on a processor reset rather than the application.novectorsโ for applications that don't require any of the MicroBlaze vectors. This can be useful for applications running within a monitoring application. This model usescrt3.oas a startup file.
๐ฅ Option-xl-mode-app-modelis a deprecated alias for-mxl-mode-app-model.
โจ MIPS Options โจ
-EBโ generate big-endian code.-ELโ generate little-endian code. This is the default formips*el-*-*configurations.-march=archโ ๐ธ generate code that runs on arch, which can be the name of a generic MIPS ISA or the name of a particular processor. The ISA names are:mips1,mips2,mips3,mips4,mips32,mips32r2,mips32r3,mips32r5,mips32r6,mips64,mips64r2,mips64r3,mips64r5andmips64r6. The processor names are:4kc,4km,4kp,4ksc,4kec,4kem,4kep,4ksd,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,24kec,24kef2_1,24kef1_1,34kc,34kf2_1,34kf1_1,34kn,74kc,74kf2_1,74kf1_1,74kf3_2,1004kc,1004kf2_1,1004kf1_1,i6400,i6500,interaptiv,loongson2e,loongson2f,loongson3a,gs464,gs464e,gs264e,m4k,m14k,m14kc,m14ke,m14kec,m5100,m5101,octeon,octeon+,octeon2,octeon3,orion,p5600,p6600,r2000,r3000,r3900,r4000,r4400,r4600,r4650,r4700,r5900,r6000,r8000,rm7000,rm9000,r10000,r12000,r14000,r16000,sb1,sr71000,vr4100,vr4111,vr4120,vr4130,vr4300,vr5000,vr5400,vr5500,xlrandxlp. The special valuefrom-abiselects the most compatible architecture for the selected ABI (that is,mips1for 32-bit ABIs andmips3for 64-bit ABIs).
The native Linux/GNU toolchain also supports the value native, which selects the best architecture option for the host processor. -march=native has no effect if GCC does not recognize the processor.
In processor names, a final 000 can be abbreviated as k (for example, -march=r2k). Prefixes are optional, and vr may be written r.
Names of the form nf2_1 refer to processors with FPUs clocked at half the rate of the core, names of the form nf1_1 refer to processors with FPUs clocked at the same rate as the core, and names of the form nf3_2 refer to processors with FPUs clocked at a ratio of 3:2 with respect to the core. For compatibility reasons, nf is accepted as a synonym for nf2_1, while nx and bfx are accepted as synonyms for nf1_1.
GCC defines two macros based on the value of this option. The first is "_MIPS_ARCH", which gives the name of the target architecture as a string. The second has the form "_MIPS_ARCH_foo", where foo is the capitalized value of "_MIPS_ARCH". For example, -march=r2000 sets "_MIPS_ARCH" to "r2000" and defines the macro "_MIPS_ARCH_R2000".
Note that the "_MIPS_ARCH" macro uses the processor names given above. In other words, it has the full prefix and 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โ ๐ optimize for arch. Among other things, this option controls the way instructions are scheduled, and the perceived cost of arithmetic operations. The list of arch values is the same as for-march.
When this option is not used, GCC optimizes for the processor specified by -march. By using -march and -mtune together, it's possible to generate code that runs on a family of processors, but optimize the code for one particular member of that family. iconic ๐
Okay so -mtune also sets up the macros _MIPS_TUNE and _MIPS_TUNE_foo ๐. They work exactly like the -march ones we just went over โจ
-mips1โ same as-march=mips1๐ธ-mips2โ same as-march=mips2๐ธ-mips3โ same as-march=mips3๐ธ-mips4โ same as-march=mips4๐ธ-mips32โ same as-march=mips32๐ธ-mips32r3โ same as-march=mips32r3๐ธ-mips32r5โ same as-march=mips32r5๐ธ-mips32r6โ same as-march=mips32r6๐ธ-mips64โ same as-march=mips64๐ธ-mips64r2โ same as-march=mips64r2๐ธ-mips64r3โ same as-march=mips64r3๐ธ-mips64r5โ same as-march=mips64r5๐ธ-mips64r6โ same as-march=mips64r6๐ธ
-mips16,-mno-mips16โ Turns MIPS16 code generation on (or off) ๐ง If GCC is targeting a MIPS32 or MIPS64 architecture, it uses the MIPS16e ASE.
You can also control MIPS16 on a per-function basis with the mips16 and nomips16 attributes ๐
-mflip-mips16โ Generates MIPS16 code on alternating functions ๐ฆ This one exists for regression testing of mixed MIPS16/non-MIPS16 code generation.
โ ๏ธ This is not meant for ordinary use when compiling your own code, bestie ๐
-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 the other way around ๐
Like, code using the standard ISA encoding can't jump straight into MIPS16 or microMIPS code ๐ It has to use a call or an indirect jump instead. So -minterlink-compressed turns off direct jumps unless GCC knows the jump target isn't compressed.
-minterlink-mips16,-mno-interlink-mips16โ These are just aliases of-minterlink-compressedand-mno-interlink-compressed๐ซถ They're older than the microMIPS ASE and only stuck around for backwards compatibility.
-mabi=32,-mabi=o64,-mabi=n32,-mabi=64,-mabi=eabiโ Generates code for the ABI you pick ๐
The EABI comes in a 32-bit and a 64-bit flavour ๐ GCC usually makes 64-bit code when you pick a 64-bit architecture, but you can use -mgp32 if you want 32-bit code instead.
For the O64 ABI deets, check out http://gcc.gnu.org/projects/mipso64-abi.html ๐
GCC also supports a version of the o32 ABI where the floating-point registers are 64 bits wide instead of 32 โจ You can get this combo with -mabi=32 -mfp64. It leans on the mthc1 and mfhc1 instructions, so it's only supported on MIPS32R2, MIPS32R3 and MIPS32R5 processors. Be careful with that one ๐
The argument and return value registers stay the same, but each scalar value gets passed in one 64-bit register instead of a pair of 32-bit ones. For example, scalar floating-point values come back in $f0 only, not a $f0/$f1 pair ๐ The call-saved registers are the same too, in that the even-numbered double-precision registers get saved.
Two more o32 variants exist to help you move from 32-bit to 64-bit registers ๐ฆ They're FPXX (-mfpxx) and FP64A (-mfp64 -mno-odd-spreg). The FPXX one means all code has to run correctly with either 32-bit or 64-bit registers ๐งฉ It can link with FP32 or FP64 code, but not both at once. FP64A is similar to FP64 but doesn't allow odd-numbered single-precision registers. It pairs well with the "FRE" mode of FPUs on MIPS32R5 processors, and lets FP32 and FP64A code link together and run in the same process without switching FPU modes ๐ฅ
-mabicalls,-mno-abicallsโ Generates (or doesn't generate) code that's suitable for SVR4-style dynamic objects ๐-mabicallsis the default on SVR4-based systems.-mshared,-mno-sharedโ Generates (or doesn't generate) code that's fully position-independent, so it can be linked into shared libraries ๐ This option only affects-mabicalls.
Traditionally all -mabicalls code has been position-independent, no matter what you pass like -fPIC or -fpic ๐ But as an extension, the GNU toolchain lets executables use absolute accesses for locally-binding symbols. It can also use shorter GP initialization sequences and generate direct calls to locally-defined functions. -mno-shared is how you turn that mode on ๐ง
โ ๏ธ-mno-sharedneeds binutils 2.16 or higher, and the objects it makes can only be linked by the GNU linker. The good news is it doesn't change the ABI of the final executable, only the ABI of relocatable objects. Using-mno-sharedusually makes executables both smaller and quicker ๐โโ๏ธ
-mshared is the default โจ
-mplt,-mno-pltโ Assumes (or doesn't assume) that the static and dynamic linkers support PLTs and copy relocations ๐ฏ This only affects-mno-shared -mabicalls. For the n64 ABI, this option does nothing without-msym32.
You can make -mplt the default by configuring GCC with --with-mips-plt. Otherwise the default is -mno-plt ๐
-mxgot,-mno-xgotโ Lifts (or doesn't lift) the usual size limits on the global offset table ๐ฆ
GCC normally uses a single instruction to load values from the GOT. 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 you see that, recompile your code with -mxgot ๐ซ It works with really huge GOTs, though the code is less efficient since it takes three instructions to fetch the value of a global symbol.
Some linkers can make multiple GOTs. If yours does, you should only need -mxgot when one object file accesses more than 64k's worth of GOT entries. Very few linkers do this ๐คทโโ๏ธ
These options do nothing unless GCC is generating position-independent code ๐
-mgp32โ Assumes general-purpose registers are 32 bits wide ๐-mgp64โ Assumes general-purpose registers are 64 bits wide ๐-mfp32โ Assumes floating-point registers are 32 bits wide ๐-mfp64โ Assumes floating-point registers are 64 bits wide ๐-mfpxxโ Doesn't assume anything about how wide the floating-point registers are ๐คทโโ๏ธ-mhard-floatโ Uses the floating-point coprocessor instructions ๐ฅ-msoft-floatโ Doesn't use the floating-point coprocessor instructions. Floating-point math is done with library calls instead ๐-mno-floatโ Same as-msoft-float, but it also promises that the program doesn't do any floating-point operations at all ๐ค This is only supported on some bare-metal MIPS configurations, where it might pick a special set of libraries with zero floating-point support. That includes stuff like the floating-pointprintfformats.
๐ If code compiled with -mno-float accidentally has floating-point operations in it, it'll probably crash with a link-time or run-time failure.
-msingle-floatโ Assumes the floating-point coprocessor only does single-precision operations ๐น-mdouble-floatโ Assumes the floating-point coprocessor does double-precision operations. This is the default ๐-modd-spreg,-mno-odd-spregโ Enables (or disables) using odd-numbered single-precision floating-point registers for the o32 ABI ๐งฉ Odd registers are the default on processors known to support them. When you use the o32 FPXX ABI,-mno-odd-spregis set by default.-mabs=2008,-mabs=legacyโ These control how special not-a-number (NaN) IEEE 754 floating-point data gets handled by theabs.fmtandneg.fmtmachine instructions ๐
By default, or with -mabs=legacy, you get the legacy treatment. Here those instructions count as arithmetic and get avoided wherever correct behaviour matters and the input might be a NaN ๐
โโ๏ธ Instead, a longer sequence of instructions that fiddles with the sign bit by hand gets used, unless -ffinite-math-only is also specified.
-mabs=2008 gives you the IEEE 754-2008 treatment. Now those instructions count as non-arithmetic, so they work correctly in every case, including when the input is a NaN. They get used for the matching operations every time ๐
-mnan=2008,-mnan=legacyโ These control how special not-a-number (NaN) IEEE 754 floating-point data is encoded ๐ธ
-mnan=legacy picks the legacy encoding. Here 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 picks the IEEE 754-2008 encoding. Now qNaNs have that first bit set to 1, and sNaNs have it set to 0.
The default is -mnan=legacy, unless GCC was configured with --with-nan=2008 ๐ง
-mllsc,-mno-llscโ Uses (or doesn't use) thell,sc, andsyncinstructions to build the atomic memory built-in functions โ๏ธ If you don't specify either, 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 help when you're compiling for nonstandard ISAs ๐งช You can make either one the default by configuring GCC with --with-llsc or --without-llsc. --with-llsc is already the default for some configurations, so check the installation docs for the details ๐
-mdsp,-mno-dspโ Uses (or doesn't use) revision 1 of the MIPS DSP ASE ๐ถ This defines the preprocessor macro__mips_dsp, and also sets__mips_dsp_revto 1.-mdspr2,-mno-dspr2โ Uses (or doesn't use) revision 2 of the MIPS DSP ASE ๐ถ This defines the preprocessor macros__mips_dspand__mips_dspr2, and also sets__mips_dsp_revto 2.
Okay bestie, the MIPS options keep going and they are a LOT ๐ ๐ธ Let's get into it.
-msmartmips,-mno-smartmipsโ โจ Turn the MIPS SmartMIPS ASE on or off.-msmartmipsuses it,-mno-smartmipsskips it ๐ง-mpaired-single,-mno-paired-singleโ ๐ฆ Use or skip the paired-single floating-point instructions. Heads up, this one needs hardware floating-point support turned on too, so it won't work without it ๐ญ-mdmx,-mno-mdmxโ ๐ Use or skip the MIPS Digital Media Extension instructions. Two things to know: it only works when you're generating 64-bit code, and it also needs hardware floating-point support enabled ๐-mips3d,-mno-mips3dโ ๐ Use or skip the MIPS-3D ASE. Fun fact,-mips3dautomatically implies-mpaired-single, so you're getting that one too ๐ซถ-mmicromips,-mno-micromipsโ ๐ Generate or don't generate microMIPS code. You can also control this one per function with the"micromips"and"nomicromips"attributes, which is so precise it's giving ๐-mmt,-mno-mtโ ๐งต Use or skip the MT Multithreading instructions โจ-mmcu,-mno-mcuโ ๐ง Use or skip the MIPS MCU ASE instructions ๐-meva,-mno-evaโ ๐บ๏ธ Use or skip the MIPS Enhanced Virtual Addressing instructions ๐ธ-mvirt,-mno-virtโ ๐ฅ๏ธ Use or skip the MIPS Virtualization (VZ) instructions ๐-mxpa,-mno-xpaโ ๐ Use or skip the MIPS eXtended Physical Address (XPA) instructions ๐ฆ-mcrc,-mno-crcโ ๐งฎ Use or skip the MIPS Cyclic Redundancy Check (CRC) instructions ๐-mginv,-mno-ginvโ ๐งน Use or skip the MIPS Global INValidate (GINV) instructions โจ-mloongson-mmi,-mno-loongson-mmiโ ๐ถ Use or skip the MIPS Loongson MultiMedia extensions Instructions (MMI) ๐ฉท-mloongson-ext,-mno-loongson-extโ ๐งฉ Use or skip the MIPS Loongson EXTensions (EXT) instructions ๐-mloongson-ext2,-mno-loongson-ext2โ ๐งฉ Use or skip the MIPS Loongson EXTensions r2 (EXT2) instructions. The r2 upgrade, obsessed ๐ญ
-mlong64โ ๐ Force"long"types to be 64 bits wide. Check out-mlong32for the full story on the default and how the pointer size gets decided ๐-mlong32โ ๐ Force"long","int", and pointer types to be 32 bits wide. Here's the default tea โ:- Every supported ABI uses 32-bit
"int"s. - The n64 ABI uses 64-bit
"long"s, and so does the 64-bit EABI. Everyone else uses 32-bit"long"s. - Pointers match the size of
"long"s, or the size of integer registers, whichever one is smaller ๐ง
- Every supported ABI uses 32-bit
-msym32,-mno-sym32โ ๐ฏ Assume (or don't assume) that all symbols have 32-bit values, no matter which ABI you picked. This is especially useful combined with-mabi=64and-mno-abicalls, because GCC can then make shorter, faster references to symbolic addresses ๐-G numโ ๐ฆ Stick externally-visible data definitions in a small data section, as long as the data is no bigger thannumbytes. This lets GCC access the data more efficiently. Peep-mgpoptfor the details ๐- The default
-Gvalue depends on your configuration ๐ธ
- The default
-mlocal-sdata,-mno-local-sdataโ ๐ Extend (or don't extend) the-Gbehaviour to local data too, like static variables in C.-mlocal-sdatais the default for every configuration ๐- If the linker starts complaining that your app is using too much small data, try rebuilding the less performance-critical parts with
-mno-local-sdata๐ญ - Building large libraries with
-mno-local-sdatais also a power move, since it leaves more room for the main program ๐
- If the linker starts complaining that your app is using too much small data, try rebuilding the less performance-critical parts with
-mextern-sdata,-mno-extern-sdataโ ๐ Assume (or don't assume) that externally-defined data sits in a small data section, as long as its size fits within the-Glimit.-mextern-sdatais the default for every configuration ๐ซถ
โ ๏ธ Okay, this part is serious. If you compile a moduleModwith-mextern-sdata -G num -mgpopt, andModreferences a variableVarno bigger thannumbytes, you MUST make sureVarlands in a small data section. If another module definesVar, either compile that module with a high-enough-Gsetting or attach a"section"attribute toVar's definition. IfVaris common, link the application with a high-enough-Gsetting. No skipping these rules, bestie ๐
- The easiest way to stay safe is to compile and link every module with the same
-Goption ๐ง - If you're building a library that has to support several different small data limits, compile it with the highest supported
-Gsetting. Then add-mno-extern-sdataso the library stops making assumptions about externally-defined data ๐ฆ
-mgpopt,-mno-gpoptโ ๐ฏ Use (or don't use) GP-relative accesses for symbols that are known to live in a small data section. See-G,-mlocal-sdataand-mextern-sdatafor the related stuff.-mgpoptis the default for every configuration ๐-mno-gpoptis clutch when the$gpregister might not hold the value of"_gp". For example, if your code is part of a library that might get used in a boot monitor, programs that call boot monitor routines pass an unknown value in$gp. (In those situations, the boot monitor itself is usually compiled with-G0.) ๐ฅ๏ธ-mno-gpoptimplies-mno-local-sdataand-mno-extern-sdataโจ
-membedded-data,-mno-embedded-dataโ ๐งธ Allocate variables to the read-only data section first if possible, then the small data section if possible, and otherwise to data. The code is slightly slower than the default, but it cuts down on the RAM needed while running, so some embedded systems might prefer it ๐-muninit-const-in-rodata,-mno-uninit-const-in-rodataโ ๐ Put uninitialized"const"variables in the read-only data section. This only means something when you're also using-membedded-data๐ฉท
-mcode-readable=settingโ ๐ Tell GCC whether it's allowed to generate code that reads from executable sections. There are three possible settings, and I've got all the tea:-mcode-readable=yesโ Instructions can freely access executable sections. This is the default ๐-mcode-readable=pcrelโ MIPS16 PC-relative load instructions can access executable sections, but other instructions must NOT. This one is handy on 4KSc and 4KSd processors when the code TLBs have the Read Inhibit bit set. It's also useful on processors that can be set up with a dual instruction/data SRAM interface and that, like the M4K, automatically redirect PC-relative loads to the instruction RAM ๐ฆ-mcode-readable=noโ Instructions must NOT access executable sections. This can help on targets configured with a dual instruction/data SRAM interface that (unlike the M4K) don't automatically redirect PC-relative loads to the instruction RAM ๐ฅ
-msplit-addresses,-mno-split-addressesโ โ๏ธ Enable (or disable) the use of the"%hi()"and"%lo()"assembler relocation operators. This has been superseded by-mexplicit-relocs, but it's kept around for backwards compatibility ๐ฐ๏ธ-mexplicit-relocs,-mno-explicit-relocsโ ๐ Use (or don't use) assembler relocation operators when handling symbolic addresses. The alternative, picked by-mno-explicit-relocs, is to use assembler macros instead ๐งฉ-mexplicit-relocsis the default if GCC was configured to use an assembler that supports relocation operators ๐ธ
-mcheck-zero-division,-mno-check-zero-divisionโ ๐ซ Trap (or don't trap) on integer division by zero. The default is-mcheck-zero-division๐ก๏ธ
-mdivide-traps,-mdivide-breaksโ โ MIPS systems check for division by zero by generating either a conditional trap or a break instruction. Traps give you smaller code, but they're only supported on MIPS II and later. Also, some versions of the Linux kernel have a bug that stops trap from generating the proper signal ("SIGFPE"). Use-mdivide-trapsto allow conditional traps on architectures that support them, and-mdivide-breaksto force the use of breaks ๐ญ- The default is usually
-mdivide-traps, but you can override that at configure time with--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โ ๐ฏ Enable (or disable) an optimization that pairs consecutive load or store instructions so they can do load/store bonding. It's on by default, but it only kicks in when the selected architecture is known to support bonding ๐-mmemcpy,-mno-memcpyโ ๐ Force (or don't force) the use of"memcpy"for non-trivial block moves. The default is-mno-memcpy, which lets GCC inline most constant-sized copies ๐-mlong-calls,-mno-long-callsโ ๐ Disable (or don't disable) the use of the"jal"instruction. Calling functions with"jal"is more efficient, but it requires the caller and callee to be in the same 256 megabyte segment. This option has no effect on abicalls code. The default is-mno-long-calls๐๏ธ
-mmad,-mno-madโ โ๏ธ Enable (or disable) the use of the"mad","madu"and"mul"instructions, as provided by the R4650 ISA ๐-mimadd,-mno-imaddโ โ Enable (or disable) the use of the"madd"and"msub"integer instructions. The default is-mimaddon architectures that support"madd"and"msub", except the 74k architecture, where it was found to generate slower code ๐ข-mfused-madd,-mno-fused-maddโ ๐ง Enable (or disable) the floating-point multiply-accumulate instructions when they're available. The default is-mfused-madd.- On the R8000 CPU, when multiply-accumulate instructions are used, the intermediate product gets calculated to infinite precision and is NOT subject to the FCSR Flush to Zero bit. That might be undesirable in some situations. On other processors, the result is numerically identical to the equivalent computation using separate multiply, add, subtract and negate instructions ๐ค
-nocppโ ๐ซ Tell the MIPS assembler to NOT run its preprocessor over user assembler files (with a.ssuffix) when assembling them ๐ โโ๏ธ-mfix-24k,-mno-fix-24kโ ๐ ๏ธ Work around the 24K E48 errata (lost data on stores during refill). The workarounds are implemented by the assembler rather than by GCC ๐ฉน-mfix-r4000,-mno-fix-r4000โ ๐ ๏ธ Work around certain R4000 CPU errata:- A double-word or a variable shift may give an incorrect result if it's executed immediately after starting an integer division. Be careful with that one, bestie ๐ญ
Okay so the R4000 errata list is still going, bestie ๐ธ there are two more gremlins to know about:
- A double-word or a variable shift can give a wrong answer if it runs while an integer multiplication is still in progress ๐
- An integer division can give a wrong answer if it starts in the delay slot of a taken branch or a jump ๐
-mfix-r4400,-mno-fix-r4400โ Works around some R4400 CPU errata ๐- A double-word or a variable shift can give a wrong answer if it runs right after an integer division starts ๐ญ
-mfix-r10000,-mno-fix-r10000โ Works around some R10000 errata ๐ll/scsequences might not behave atomically on revisions before 3.0. On revisions 2.6 and earlier, they can deadlock ๐
This option only works if the target architecture supports branch-likely instructions. -mfix-r10000 is the default when -march=r10000 is used, and -mno-fix-r10000 is the default otherwise โจ
-mfix-r5900,-mno-fix-r5900โ Stops GCC from scheduling the instruction before a branch into that branch's delay slot when the branch sits at the end of a short loop of six instructions or fewer. Instead, anopalways goes in there ๐ฆ The short loop bug can make loops run only once or twice because of a hardware bug in the R5900 chip. The assembler handles this workaround, not GCC ๐ง-mfix-rm7000,-mno-fix-rm7000โ Works around the RM7000dmult/dmultuerrata. The assembler does the workarounds, not GCC ๐ฅ-mfix-vr4120,-mno-fix-vr4120โ Works around some VR4120 errata ๐dmultudoesn't always give the correct result ๐ญdivandddivdon't always give the correct result if one of the operands is negative ๐
The division workarounds rely on special functions in libgcc.a. Right now, those functions only come with the mips64vr*-elf configurations ๐ซถ
The other VR4120 errata need a NOP inserted between certain pairs of instructions. The assembler takes care of those, not GCC itself ๐ธ
-mfix-vr4130โ Works around the VR4130mflo/mfhierrata. The assembler implements the workarounds rather than GCC, but GCC avoids usingmfloandmfhiwhen the VR4130macc,macchi,dmaccanddmacchiinstructions 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โ Decides whether GCC should insert cache barriers to avoid the side effects of speculation on R10K processors ๐
Okay, so the R10K is kind of a drama queen. Like many processors, it tries to guess how a conditional branch will go and speculatively runs instructions from the "taken" branch. If the guess was wrong, it aborts those instructions. But on the R10K, even aborted instructions can leave side effects behind ๐
This only affects kernel stores and, depending on the system, kernel loads. For example, a speculatively executed store might pull the target memory into cache and mark the cache line as dirty, even if the store itself gets aborted later. If a DMA operation writes to the same memory before that dirty line gets flushed, the cached data overwrites the DMA'd data ๐ญ The R10K processor manual has the full story, including other potential problems ๐
One workaround is to insert cache barrier instructions before every memory access that might be speculatively executed and might have side effects even if aborted. -mr10k-cache-barrier=setting controls how GCC implements this workaround. It assumes that aborted accesses to any byte in these 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 really are safe ๐ซถ
If the input program has a function declaration like this:
void foo (void);
then the implementation of foo must allow j foo and jal foo to run speculatively. GCC follows this rule for functions it compiles itself, and it expects non-GCC functions (like hand-written assembly) to do the same ๐
This 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 might have side effects even if aborted ๐ฆ-mr10k-cache-barrier=storeโ Inserts a cache barrier before a store that might be speculatively executed and might have side effects even if aborted ๐-mr10k-cache-barrier=noneโ Turns off cache barrier insertion. This is the default setting ๐
-mflush-func=func,-mno-flush-funcโ Picks the function to call to flush the I and D caches, or tells GCC to call no such function ๐ธ If one is called, it has to take the same arguments as the common_flush_func: the address of the memory range being flushed, the size of that range, and the number 3 (to flush both caches). The default depends on the target GCC was configured for, but it's commonly either_flush_funcor__cpu_flushโจmbranch-cost=numโ Sets the cost of branches to roughlynum"simple" instructions. This cost is only a heuristic, so it isn't guaranteed to give consistent results across releases ๐คทโโ๏ธ A zero cost just selects the default again, which is based on the-mtunesetting ๐ง-mbranch-likely,-mno-branch-likelyโ Turns Branch Likely instructions on or off, no matter what the selected architecture's default is ๐ฅ By default, Branch Likely instructions can 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 aren't generated by default, because MIPS32 and MIPS64 specifically deprecate their use ๐-mcompact-branches=neverโ Makes sure compact branch instructions are never generated ๐-mcompact-branches=optimalโ Uses a delay slot branch if one is available in the current ISA and the delay slot gets filled successfully. If the delay slot doesn't get filled, a compact branch is picked when one is available ๐ซถ-mcompact-branches=alwaysโ Makes sure a compact branch instruction is generated whenever one is available. If none is available, a delay slot form of the branch gets used instead ๐
The default is -mcompact-branches=optimal. This option is supported from MIPS Release 6 onwards ๐
-mfp-exceptions,-mno-fp-exceptionsโ Controls whether FP exceptions are enabled. This affects how FP instructions get scheduled on some processors. FP exceptions are enabled by default ๐
For instance, on the SB-1, if FP exceptions are disabled and GCC is emitting 64-bit code, both FP pipes can be used. Otherwise, only one FP pipe can be used ๐ฆ
-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 on, GCC aligns pairs of instructions it thinks should run in parallel ๐
This option only does something when optimizing for the VR4130. It usually makes code faster, but the tradeoff is that the code gets bigger ๐ It's turned on by default at optimization level -O3 โจ
-msynci,-mno-synciโ Enables or disables generatingsynciinstructions on architectures that support them. When enabled,synciinstructions are generated while__builtin___clear_cacheis compiled ๐ง
-mno-synci is the default, but you can change that by configuring GCC with --with-synci ๐ฅ
Using synci is generally safe on single processor systems. On many multi-core (SMP) systems, though, it doesn't invalidate the instruction caches on all cores and may lead to undefined behavior ๐
-mrelax-pic-calls,-mno-relax-pic-callsโ Tries to turn PIC calls that normally go through register$25into direct calls. This only works if the linker can resolve the destination at link time and the destination is within range for a direct call ๐ฆ
-mrelax-pic-calls is the default if GCC was configured to use an assembler and a linker that support the .reloc assembly directive and -mexplicit-relocs is in effect. With -mno-explicit-relocs, the assembler and linker can do this optimization on their own, without help from the compiler ๐ซถ
-mmcount-ra-address,-mno-mcount-ra-addressโ Emits (or doesn't emit) code that lets_mcountchange the calling function's return address ๐ธ When enabled, this option extends the usual_mcountinterface with a new ra-address parameter. It has typeintptr_t *and is passed in register$12._mcountcan then change the return address by doing both of the following:- Returning the new address in register
$31. - Storing the new address in
*ra-address, if ra-address is nonnull.
- Returning the new address in register
The default is -mno-mcount-ra-address ๐
-mframe-header-opt,-mno-frame-header-optโ Enables (or disables) frame header optimization in the o32 ABI. With 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 allocating 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) generatinglwxc1,swxc1,ldxc1, andsdxc1instructions. It's enabled by default โจ๐-mmadd4,-mno-madd4โ okay so when it's applicable,-mmadd4turns on the 4-operandmadd.s,madd.dand related instructions ๐.-mno-madd4turns them off. They're enabled by default โจ.
๐ MMIX Options ๐
These options are defined for the MMIX ๐ฆ:
-mlibfuncs,-mno-libfuncsโ bestie, this one is iconic ๐.-mlibfuncstells the compiler that intrinsic library functions are being compiled, so all values get passed in registers no matter how big they are.-mno-libfuncsturns that off.-mepsilon,-mno-epsilonโ-mepsilongenerates floating-point comparison instructions that compare with respect to therEepsilon register ๐ง.-mno-epsilonskips that.-mabi=mmixware,-mabi=gnuโ-mabi=mmixwaregenerates code where function parameters and return values are seen (in the called function) as registers$0and up.-mabi=gnugoes with the GNU ABI instead, which uses global registers$231and up ๐ .-mzero-extend,-mno-zero-extendโ when reading data from memory in sizes shorter than 64 bits,-mzero-extenduses zero-extending load instructions by default instead of sign-extending ones.-mno-zero-extenddoes not use them ๐ธ.-mknuthdiv,-mno-knuthdivโ-mknuthdivmakes the result of a division yielding a remainder have the same sign as the divisor. With the default,-mno-knuthdiv, the sign of the remainder follows the sign of the dividend. Both methods are arithmetically valid, but the latter is almost exclusively used ๐.-mtoplevel-symbols,-mno-toplevel-symbolsโ-mtoplevel-symbolsprepends a:to all global symbols, so the assembly code can be used with thePREFIXassembly directive.-mno-toplevel-symbolsdoes not prepend it โจ.-melfโ generates an executable in the ELF format, instead of the default mmo format used by the mmix simulator ๐ฆ.-mbranch-predict,-mno-branch-predictโ-mbranch-predictuses the probable-branch instructions when static branch prediction indicates a probable branch.-mno-branch-predictdoesn't use them ๐.-mbase-addresses,-mno-base-addressesโ-mbase-addressesgenerates code that uses base addresses, and-mno-base-addressesdoesn't. Using a base address automatically generates a request (handled by the assembler and the linker) for a constant to be set up in a global register. That register is used for one or more base address requests within the range 0 to 255 from the value held in the register. It 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โ-msingle-exitforces generated code to have a single exit point in each function.-mno-single-exitdoes not force that ๐.
๐ 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โ does not generate code to avoid those multiply bugs for the MN10300 processors.-mam33โ generates code using features specific to the AM33 processor ๐ฅ.-mno-am33โ does not generate code using AM33-specific features. This is the default.-mam33-2โ generates code using features specific to the AM33/2.0 processor โจ.-mam34โ generates code using features specific to the AM34 processor ๐ฆ.-mtune=cpu-typeโ uses the timing characteristics of the indicated CPU type when scheduling instructions. This does not change the targeted processor type, so it's just about timing ๐. The CPU type must be one ofmn10300,am33,am33-2oram34.-mreturn-pointer-on-d0โ when generating a function that returns a pointer, the pointer is returned in botha0andd0. Otherwise, the pointer is returned only ina0, and attempts to call such functions without a prototype result in errors ๐ญ. This option is on by default, so use-mno-return-pointer-on-d0to disable it.-mno-crt0โ does not link in the C run-time initialization object file ๐ง.-mrelaxโ tells the linker it should perform a relaxation optimization pass to shorten branches, calls and absolute memory addresses โญ. This option only has an effect when used on the command line for the final link step.
This option makes symbolic debugging impossible. ๐
-mliwโ allows the compiler to generate Long Instruction Word instructions if the target is the AM33 or later. This is the default. This option defines the preprocessor macro__LIW__๐ธ.-mno-liwโ does not allow the compiler to generate Long Instruction Word instructions. This option defines the preprocessor macro__NO_LIW__.-msetlbโ allows the compiler to generate the SETLB and Lcc instructions if the target is the AM33 or later. This is the default. This option defines the preprocessor macro__SETLB__๐.-mno-setlbโ does not allow the compiler to generate SETLB or Lcc instructions. This option defines the preprocessor macro__NO_SETLB__.
๐ฆ Moxie Options ๐ฆ
-mebโ generates big-endian code. This is the default formoxie-*-*configurations ๐.-melโ generates little-endian code ๐.-mmul.xโ generatesmul.xandumul.xinstructions. This is the default formoxiebox-*-*configurations โจ.-mno-crt0โ does not link in the C run-time initialization object file ๐ง.
๐ MSP430 Options ๐
These options are defined for the MSP430 ๐ธ:
-masm-hexโ forces assembly output to always use hex constants. Normally such constants are signed decimals, but this option is available for testsuite and/or aesthetic purposes ๐.-mmcu=โ selects the MCU to target. This is used to create a C preprocessor symbol based upon the MCU name, converted to upper case and pre- and post-fixed with__. That symbol in turn is used by themsp430.hheader file to select an MCU-specific supplementary header file ๐.
The option also sets the ISA to use. If the MCU name is one that is known to only support the 430 ISA, then that is selected. Otherwise the 430X ISA is selected. A generic MCU name of msp430 can also be used to select the 430 ISA. Similarly, the generic msp430x MCU name selects the 430X ISA.
An MCU-specific linker script is also added to the linker command line. The script's name is the name of the MCU with .ld appended. So specifying -mmcu=xxx on the gcc command line defines the C preprocessor symbol __XXX__ and causes the linker to search for a script called xxx.ld ๐ฅ. This option is also passed on to the assembler.
-mwarn-mcu,-mno-warn-mcuโ-mwarn-mcuenables warnings about conflicts between the MCU name specified by the-mmcuoption and the ISA set by the-mcpuoption and/or the hardware multiply support set by the-mhwmultoption. It also toggles warnings about unrecognized MCU names.-mno-warn-mcuturns those off. This option is on by default ๐.-mcpu=โ specifies the ISA to use. Accepted values aremsp430,msp430xandmsp430xv2. This option is deprecated ๐. The-mmcu=option should be used to select the ISA instead.-msimโ links to the simulator runtime libraries and linker script. It overrides any scripts that would be selected by the-mmcu=option ๐ง.-mlargeโ uses large-model addressing (20-bit pointers, 32-bitsize_t) ๐.-msmallโ uses small-model addressing (16-bit pointers, 16-bitsize_t) ๐ฆ.-mrelaxโ this option is passed to the assembler and linker, and allows the linker to perform certain optimizations that cannot be done until the final link โญ.mhwmult=โ describes the type of hardware multiply supported by the target ๐. 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. A value ofautocan also be given. This tells GCC to deduce the hardware multiply support based upon the MCU name provided by the-mmcuoption. If no-mmcuoption is specified, or if the MCU name is not recognized, then no hardware multiply support is assumed.autois the default setting ๐ซถ.
Hardware multiplies are normally performed by calling a library routine, which saves space in the generated code. When compiling at -O3 or higher, however, the hardware multiplier is invoked inline. That makes for bigger but faster code ๐ฅ.
The hardware multiply routines disable interrupts whilst running 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 the use of a minimum runtime environment, with no static initializers or constructors. This is intended for memory-constrained devices ๐ธ. The compiler includes special symbols in some objects that tell the linker and runtime which code fragments are required.-mcode-region=,-mdata-region=โ these options tell the compiler where to place functions and data that do not have one of thelower,upper,eitherorsectionattributes ๐. Possible values arelower,upper,eitherorany. The first three behave like the corresponding attribute. The fourth possible 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 on a request to the assembler to enable the fixes for the named silicon errata ๐ง.-msilicon-errata-warn=โ passes on a request to the assembler to enable warning messages when a silicon errata might need to be applied โ ๏ธ.
๐ง NDS32 Options ๐ง
These options are defined for NDS32 implementations โจ:
-mbig-endianโ generates code in big-endian mode ๐.-mlittle-endianโ generates code in little-endian mode ๐.-mreduced-regsโ uses reduced-set registers for register allocation ๐ธ.-mfull-regsโ uses full-set registers for register allocation ๐.-mcmovโ generates conditional move instructions ๐ฆ.-mno-cmovโ does not generate conditional move instructions.-mext-perfโ generates performance extension instructions ๐ฅ.-mno-ext-perfโ does not generate performance extension instructions.-mext-perf2โ generates performance extension 2 instructions ๐.-mno-ext-perf2โ does not generate performance extension 2 instructions.-mext-stringโ generates string extension instructions ๐.-mno-ext-stringโ does not generate string extension instructions.-mv3pushโ generates v3push25/pop25instructions ๐ .-mno-v3pushโ Bestie, this one is a hard pass ๐ โโ๏ธ It tells GCC not to generate the v3push25/pop25instructions. Ghosted ๐ป-m16-bitโ Main character move โจ This makes GCC generate 16-bit instructions.-mno-16-bitโ The opposite energy: GCC will not generate 16-bit instructions ๐-misr-vector-size=numโ You get to pick how big each interrupt vector is, and it has to be either4or16. Those are the only two options, no cap ๐ฅ-mcache-block-size=numโ Sets how big each cache block is. It has to be a power of 2 between 4 and 512 ๐ง-march=archโ This is where you name the target architecture ๐-mcmodel=code-modelโ Pick your code model. It has to be one of these:smallโ All the data and read-only data segments have to live within 512KB of addressing space. The text segment has to stay within 16MB of addressing space ๐ฆmediumโ The data segment has to be within 512KB, but the read-only data segment can stretch out to 4GB of addressing space. The text segment should still stay within 16MB of addressing space ๐ธlargeโ All the text and data segments can be within 4GB of addressing space. Anything goes ๐
-mctor-dtorโ Turns on the constructor/destructor feature ๐-mrelaxโ Tells the linker to relax instructions ๐ง
๐ฆ Nios II Options ๐ฆ
These are the options for the Altera Nios II processor, so if that's your chip, this section is literally your whole vibe ๐ฅ๏ธ
-G numโ Anything global or static that'snumbytes or smaller gets tucked into the small data or BSS sections instead of the normal data or BSS sections. The default value ofnumis8๐-mgpopt=option,-mgpopt,-mno-gpoptโ Okay, this one is a whole thing ๐ญ It lets you generate (or not generate) GP-relative accesses. These are the option names it recognizes:noneโ Don't generate GP-relative accesses at all.localโ Generate GP-relative accesses for small data objects that aren't external, weak, or uninitialized common symbols. You also get GP-relative addressing for objects you've explicitly placed in a small data section with asectionattribute.globalโ Same aslocal, but also generates GP-relative accesses for small data objects that are external, weak, or common. If you go this route, you must make sure every part of your program (including libraries) is compiled with the same-Gsetting โ ๏ธdataโ Generate 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 in 64K of memory, and you must use an appropriate linker script to allocate them within the addressable range of the global pointer.allโ Generate GP-relative addresses for function pointers as well as data pointers. If you use this, the entire text, data, and BSS segments of your program must fit in 64K of memory, and you must use an appropriate linker script to allocate them within the addressable range of the global pointer.
-mgpopt is equivalent to -mgpopt=local, and -mno-gpopt is equivalent to -mgpopt=none.
The default is -mgpopt except when -fpic or -fPIC is specified to generate position-independent code.
Note that the Nios II ABI does not permit GP-relative accesses from shared libraries.
You may need to specify -mno-gpopt explicitly when building programs that include large amounts of small data, including large GOT data sections. In this case, the 16-bit offset for GP-relative addressing may not be large enough to allow access to the entire small data section.
-mgprel-sec=regexpโ This one adds extra section names that can be reached via GP-relative addressing. It's most useful alongsidesectionattributes on variable declarations and a custom linker script. Theregexpis a POSIX Extended Regular Expression ๐ง
This option doesn't change how -G behaves. The sections you list are on top of the standard .sdata and .sbss small-data sections that -mgpopt already recognizes.
-mr0rel-sec=regexpโ This one names sections you can reach with a 16-bit offset fromr0, which means the low 32K or high 32K of the 32-bit address space. It's most useful withsectionattributes on variable declarations and a custom linker script, and theregexpis a POSIX Extended Regular Expression ๐
Unlike GP-relative addressing for small data, zero-based addressing is never generated by default, and there are no conventional section names used in standard linker scripts for sections in the low or high areas of memory.
-mel,-mebโ Generate little-endian (the default) or big-endian (experimental) code, respectively. Big-endian is still experimental, so be brave ๐ซถ-march=archโ This is the name of the target Nios II architecture. GCC uses this name to figure out what kinds of instructions it can emit when generating assembly code. Permissible names arer1andr2๐
The preprocessor macro __nios2_arch__ is available to your programs, with value 1 or 2, indicating the targeted ISA level.
-mbypass-cache,-mno-bypass-cacheโ Forces every load and store instruction 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 access bypasses the cache using the I/O variants of the load and store instructions. The default is not to bypass the cache โจ-mno-fast-sw-div,-mfast-sw-divโ 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โ Enable or disable the compiler emitting themul,mulx, anddivfamily of instructions. The default is to emitmuland not emitdivandmulx๐ฆ-mbmx,-mno-bmx,-mcdx,-mno-cdxโ Enable or disable generation of Nios II R2 BMX (bit manipulation) and CDX (code density) instructions. Enabling these also requires-march=r2. Since these are optional extensions to the R2 architecture, the default is not to emit them ๐ธ-mcustom-insn=N,-mno-custom-insnโ Each-mcustom-insn=Noption turns on a custom instruction with encodingNwhen generating code that uses insn. For example,-mcustom-fadds=253generates custom instruction 253 for single-precision floating-point add operations, instead of the default of making a library call ๐ง
The following values of insn are supported. Except as otherwise noted, floating-point operations are expected to be implemented with normal IEEE 754 semantics and 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 are only generated if-ffinite-math-onlyis specified.fsqrtsโ Unary square root operation.fcoss,fsins,ftans,fatans,fexps,flogsโ Floating-point trigonometric and exponential functions. These are only generated if-funsafe-math-optimizationsis also specified.
๐ฆ Double-precision floating point ๐ฆ
faddd,fsubd,fdivd,fmuldโ Binary arithmetic operations.fnegdโ Unary negation.fabsdโ Unary absolute value.fcmpeqd,fcmpged,fcmpgtd,fcmpled,fcmpltd,fcmpnedโ Comparison operations.fmind,fmaxdโ Double-precision minimum and maximum. These are only generated if-ffinite-math-onlyis specified.fsqrtdโ Unary square root operation.fcosd,fsind,ftand,fatand,fexpd,flogdโ Double-precision trigonometric and exponential functions. These are only generated if-funsafe-math-optimizationsis also specified.
๐ง Conversions ๐ง
fextsdโ Conversion from single precision to double precision.ftruncdsโ Conversion from double precision to single precision.fixsi,fixsu,fixdi,fixduโ Conversion from floating point to signed or unsigned integer types, with truncation towards zero.roundโ Conversion from single-precision floating point to signed integer, rounding to the nearest integer and ties away from zero. This corresponds to the__builtin_lroundffunction when-fno-math-errnois used.floatis,floatus,floatid,floatudโ Conversion from signed or unsigned integer types to floating-point types.
In addition, all of the following transfer instructions for internal registers X and Y must be provided to use any of the double-precision floating-point instructions.
Custom instructions taking two double-precision source operands expect the first operand in the 64-bit registerX. The other operand (or only operand of a unary operation) is given to the custom arithmetic instruction with the least significant half in source registersrc1and the most significant half insrc2. 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 registerY. GCC automatically generates the necessary code sequences to write registerXand/or read registerYwhen double-precision floating-point instructions are used.
fwrxโ Writesrc1into the least significant half ofXandsrc2into the most significant half ofX.fwryโ Writesrc1intoY.frdxhi,frdxloโ Read the most or least (respectively) significant half ofXand store it indest.frdyโ Read the value ofYand store it intodest.
Note that you can gain more local control over generation of Nios II custom instructions by using the target("custom-insn=N") and target("no-custom-insn") function attributes or pragmas. It's giving precision ๐
-mcustom-fpu-cfg=nameโ This enables a predefined, named set of custom instruction encodings (see-mcustom-insnabove). Currently, the following sets are defined:
-mcustom-fpu-cfg=60-1 is equivalent to: -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -fsingle-precision-constant ๐
-mcustom-fpu-cfg=60-2 is equivalent to: -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -mcustom-fdivs=255 -fsingle-precision-constant ๐ฆ
-mcustom-fpu-cfg=72-3 is equivalent to: -mcustom-floatus=243 -mcustom-fixsi=244 -mcustom-floatis=245 -mcustom-fcmpgts=246 -mcustom-fcmples=249 -mcustom-fcmpeqs=250 -mcustom-fcmpnes=251 -mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -mcustom-fdivs=255 -fsingle-precision-constant ๐คฏ
Okay, bestie, the individual -mcustom-insn= assignments always beat whatever -mcustom-fpu-cfg= hands out, no matter where they sit on the command line. Order doesn't matter, so don't stress ๐ซถ
Also, if you want local control over which FPU config a function uses, you can slap target("custom-fpu-cfg=name") on it as a function attribute or pragma. Main character energy ๐โจ
These additional -m options are available for the Altera Nios II ELF (bare-metal) target: ๐ง
-mhalโ Links with the HAL BSP. This skips the GCC-provided C runtime startup and termination code, and it's usually paired with-msys-crt0=so you can point at 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) to use while linking. This only does anything together with-mhal๐-msys-lib=systemlibโsystemlibis the library that provides the low-level system calls the C library needs, like"read"and"write". You'll usually use this to link with a library from a HAL BSP ๐ฅ
๐ Nvidia PTX Options ๐
These options are defined for Nvidia PTX: ๐
-m32,-m64โ Generates code for the 32-bit or 64-bit ABI ๐-misa=ISA-stringโ Generates code for the PTX ISA you specify (likesm_35). ISA strings have to be lower-case, and valid ones includesm_30andsm_35. The default ISA issm_30๐-mmainkernelโ Links in code for a__mainkernel. This is for stand-alone execution instead of offloading ๐ง-moptimizeโ Applies partitioned execution optimizations. This is the default whenever any level of optimization is selected โจ-msoft-stackโ Generates code that doesn't use".local"memory directly for stack storage. Instead, a per-warp stack pointer gets maintained explicitly. This unlocks variable-length stack allocation (with variable-length arrays or"alloca"), and when global memory is the underlying storage, it makes it possible to access automatic variables from other threads, or with atomic instructions. OpenMP offloading uses this code generation variant, but the option is exposed on its own so you can test the compiler. If you want code that's suitable for linking into programs using OpenMP offloading, use-mgompinstead ๐ฆ-muniform-simtโ Switches to a code generation variant that lets every thread in each warp execute, while keeping memory state and side effects the same as if only one thread in each warp was active outside of OpenMP SIMD regions. All atomic operations and calls to the runtime (malloc,free,vprintf) run conditionally (iff the current lane index equals the master lane index), and the register being assigned gets copied from the master lane via a shuffle instruction. Outside of SIMD regions, lane 0 is the master. Inside them, each thread sees itself as the master. The shared memory array"int __nvptx_uni[]"stores all-zeros or all-ones bitmasks for each warp, which tells you the current mode (0 outside of 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 enables-msoft-stackand-muniform-simt, and selects 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โ For compatibility, it's always newlib for elf now ๐-mhard-divโ Generates code for hardware that supports divide instructions. This is the default โจ-mhard-mulโ Generates code for hardware that supports multiply instructions. This is also the default ๐ฅ-mcmovโ Generates code for hardware that supports the conditional move (l.cmov) instruction ๐ฆ-mrorโ Generates code for hardware that supports rotate right instructions ๐-msextโ Generates code for hardware that supports sign-extension instructions ๐-msfimmโ Generates code for hardware that supports set flag immediate (l.sf*i) instructions ๐ง-mshftimmโ Generates code for hardware that supports shift-immediate-related instructions (i.e."l.srai","l.srli","l.slli","1.rori"). Heads up: to get thel.roriinstruction generated, you also need-mror๐-msoft-divโ Generates code for hardware that needs divide instruction emulation ๐-msoft-mulโ Generates code for hardware that needs multiply instruction emulation ๐
๐ PDP-11 Options ๐
These options are defined for the PDP-11: ๐ธ
-mfpuโ Uses hardware FPP floating point. This is the default. (FIS floating point on the PDP-11/40 is not supported.) Implies-m45๐-msoft-floatโ Doesn't use hardware floating point ๐ซถ-mac0โ Returns floating-point results inac0(fr0in Unix assembler syntax) โจ-mno-ac0โ Returns floating-point results in memory. This is the default ๐-m40โ Generates code for a PDP-11/40. Implies-msoft-float -mno-split๐ฆ-m45โ Generates code for a PDP-11/45. This is the default ๐-m10โ Generates code for a PDP-11/10. Implies-msoft-float -mno-split๐-mint16,-mno-int32โ Uses 16-bit"int". This is the default ๐ง-mint32,-mno-int16โ Uses 32-bit"int"๐ฅ-msplitโ 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=ANY selects 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 types of operation (e.g., multiplication) don't work properly on all types of AE ๐ญ
-mae=MUL selects a MUL AE type. This is the most useful AE type for compiled code, and it's the default โจ
-mae=MAC selects a DSP-style MAC AE. Code compiled with this option may suffer from poor performance of byte (char) manipulation, since the DSP AE doesn't provide 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 than without the option. The results vary from program to program, though, so it's left as a user option instead of being permanently enabled ๐ง-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 necessary hardware support. This option turns those warnings off ๐
๐ PowerPC Options ๐
These are listed under
๐ RISC-V Options ๐
These command-line options are defined for RISC-V targets: ๐ซถ
-mbranch-cost=nโ Sets the cost of branches to roughlyninstructions ๐-mplt,-mno-pltโ When generating PIC code, these control whether PLTs are allowed. They're ignored for non-PIC. The default is-mplt๐ฆ-mabi=ABI-stringโ Specifies the integer and floating-point calling convention.ABI-stringhas two parts: the size of integer types, and the registers used for floating-point types. For example,-march=rv64ifd -mabi=lp64dmeans thatlongand pointers are 64-bit (implicitly makingint32-bit), and that 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 allows floating-point values up to 32 bits long to be passed in registers. Or-march=rv64ifd -mabi=lp64, where no floating-point arguments get passed in registers at all ๐ง
The default for this argument is system dependent, so users who want a specific calling convention should specify one explicitly. The valid calling conventions are: ilp32, ilp32f, ilp32d, lp64, lp64f, and lp64d. Some calling conventions are impossible to implement on some ISAs. For example, -march=rv32if -mabi=ilp32d is invalid, because the ABI requires 64-bit values to be passed in F registers, but F registers are only 32 bits wide ๐ญ There's also the ilp32e ABI, which can only be used with the rv32e architecture. This ABI isn't well specified at present, and it's subject to change ๐ฅบ
-mfdiv,-mno-fdivโ Do or don't use hardware floating-point divide and square root instructions. This requires the F or D extensions for floating-point registers. The default is to use them if the specified architecture has these instructions ๐
โจ RISC-V Options โจ
-mdiv,-mno-divโ okay bestie, these decide whether hardware instructions get used for integer division ๐งฎ.-mdivsays yes,-mno-divsays nah. This one needs the M extension. By default it uses them if the architecture you picked actually has them ๐-march=ISA-stringโ tell GCC which RISC-V ISA to generate code for, likerv64im. ISA strings have to be lower-case (no caps, no cap ๐งข). Examples arerv64i,rv32g,rv32e, andrv32imaf๐ฆ-mtune=processor-stringโ optimize the output for a specific processor, named by its microarchitecture. The allowed values arerocket,sifive-3-series,sifive-5-series,sifive-7-series, andsize๐
If you don't specify -mtune=, the default is rocket ๐
Okay, the size choice is not really meant for end-users, so don't go picking it for fun ๐ It gets used when -Os is specified. It overrides the instruction cost info from -mtune=, but it does not override the pipeline info. The vibe is smaller code that still performs well โจ
-mpreferred-stack-boundary=numโ tries to keep the stack boundary aligned to a 2 raised to num byte boundary ๐ If you don't specify this, the default is4, which is 16 bytes or 128-bits.
๐จ Warning: if you use this switch, you have to build all modules with the same value, libraries included. That means the system libraries and startup modules too. No exceptions, bestie ๐ญ
-msmall-data-limit=nโ puts global and static data smaller than n bytes into a special section (on some targets). Small data, special treatment ๐-msave-restore,-mno-save-restoreโ-msave-restoreuses smaller prologue and epilogue code that calls library functions. It's smaller but slower, so it's giving "tiny but sluggish" ๐ข-mno-save-restoreis the opposite. By default you get fast inline prologues and epilogues โก-mstrict-align,-mno-strict-alignโ-mstrict-alignmeans no unaligned memory accesses, and-mno-strict-alignmeans you're allowed to do them. The default depends on whether your target processor supports fast unaligned access ๐ง-mcmodel=medlowโ generates code for the medium-low code model ๐ Your program and its statically defined symbols have to fit inside a single 2 GiB address range, 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 ๐ Your program and its statically defined symbols just need to fit in any single 2 GiB address range. Static or dynamic linking both work โจ-mexplicit-relocs,-mno-exlicit-relocsโ-mexplicit-relocsuses assembler relocation operators when dealing with symbolic addresses.-mno-exlicit-relocsskips those and uses assembler macros instead, which can limit optimization ๐ (Yes, that's how the spelling appears in the manpage, typo and all ๐)-mrelax,-mno-relaxโ-mrelaxtakes advantage of linker relaxations to cut down the number of instructions needed to materialize symbol addresses. The default is to take advantage of them ๐-mno-relaxturns that off.-memit-attribute,-mno-emit-attributeโ-memit-attributeemits a RISC-V attribute that records extra info into ELF objects, and-mno-emit-attributedoes not. This feature needs at least binutils 2.32 ๐ ๏ธ
๐ธ RL78 Options ๐ธ
-msimโ links in extra target libraries so your code can run inside a simulator ๐ฅ๏ธ-mmul=none,-mmul=g10,-mmul=g13,-mmul=g14,-mmul=rl78โ picks which type of hardware multiplication and division support to use. The simplest,"none", uses software for both multiplying and dividing, and it's the default ๐ง"g13"is for the hardware multiply/divide peripheral on the RL78/G13 (S2 core) targets."g14"uses the multiplication and division instructions from the RL78/G14 (S3 core) parts."rl78"is an alias for"g14", and"mg10"is an alias for"none"๐ฅ
Also, a C preprocessor macro gets defined based on this setting. The possible values are "__RL78_MUL_NONE__", "__RL78_MUL_G13__", or "__RL78_MUL_G14__" ๐ง
-mcpu=g10,-mcpu=g13,-mcpu=g14,-mcpu=rl78โ picks the RL78 core to target. The default is the G14 core, which is also called the S3 core or just RL78 ๐ The G13 (or S2) core has no multiply or divide instructions. It uses a hardware peripheral for those jobs instead. The G10 (or S1) core has no register banks, so it uses a different calling convention ๐
If you set this option, it also picks the type of hardware multiply support, unless an explicit -mmul=none on the command line overrides it. So -mcpu=g13 turns on the G13 hardware multiply peripheral, and -mcpu=g10 turns off hardware multiplication altogether ๐ซถ
๐ Note: the RL78/G14 core is the default target, but specifying-mcpu=g14or-mcpu=rl78on the command line does change how the toolchain behaves, because it also turns on G14 hardware multiply support. If you don't specify these on the command line, software multiplication routines get used even though the code targets the RL78 core. This is for backwards compatibility with older toolchains that didn't have hardware multiply and divide support ๐ฅน
Another C preprocessor macro gets defined based on this option. The possible values are "__RL78_G10__", "__RL78_G13__", or "__RL78_G14__" ๐
-mg10,-mg13,-mg14,-mrl78โ these are aliases for the matching-mcpu=option. They're only around for backwards compatibility ๐ฐ๏ธ-mallregsโ lets the compiler use all of the available registers ๐ฆ By default,r24..r31are reserved for interrupt handlers. With this option on, those registers 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โ-msave-mduc-in-interruptssays interrupt handler functions should preserve the MDUC registers. You only need this if normal code might touch the MDUC registers, for example because it does multiplication and division โจ By default the MDUC registers get ignored, which keeps the interrupt handlers faster โก To make this work, you need to pass the target option-mg13, 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 ๐ธ
-mpowerpc-gpopt,-mno-powerpc-gpoptโ tells GCC which instructions your processor has access to ๐ง-mpowerpc-gfxopt,-mno-powerpc-gfxoptโ same vibe, for the optional instructions ๐-mpowerpc64,-mno-powerpc64โ 64-bit goodies ๐-mmfcrf,-mno-mfcrfโ ๐-mpopcntb,-mno-popcntbโ โจ-mpopcntd,-mno-popcntdโ ๐-mfprnd,-mno-fprndโ ๐ง-mcmpb,-mno-cmpbโ ๐-mmfpgpr,-mno-mfpgprโ ๐ฆ-mhard-dfp,-mno-hard-dfpโ ๐
You use these options to specify which instructions are available on the processor you're using ๐ซถ The default value of these options gets determined when GCC is configured. Specifying -mcpu=cpu_type overrides these options. We recommend using -mcpu=cpu_type instead of the options listed above, bestie ๐
Specifying -mpowerpc-gpopt lets GCC use the optional PowerPC architecture instructions in the General Purpose group, including floating-point square root โจ Specifying -mpowerpc-gfxopt lets GCC use the optional instructions in the Graphics group, including floating-point select ๐จ
The -mmfcrf option lets GCC generate the move from condition register field instruction. It's implemented on the POWER4 processor and other processors that support the PowerPC V2.01 architecture ๐งญ The -mpopcntb option lets GCC generate the popcount and double-precision FP reciprocal estimate instruction, which is implemented on the POWER5 processor and other processors that support the PowerPC V2.02 architecture ๐ข The -mpopcntd option lets GCC generate the popcount instruction, implemented on the POWER7 processor and other processors that support the PowerPC V2.06 architecture ๐ช The -mfprnd option lets GCC generate the FP round to integer instructions, implemented on the POWER5+ processor and other processors that support the PowerPC V2.03 architecture ๐ The -mcmpb option lets GCC generate the compare bytes instruction, implemented on the POWER6 processor and other processors that support the PowerPC V2.05 architecture ๐ซง The -mmfpgpr option lets GCC generate the FP move to/from general-purpose register instructions, implemented on the POWER6X processor and other processors that support the extended PowerPC V2.05 architecture ๐ The -mhard-dfp option lets GCC generate the decimal floating-point instructions implemented on some POWER processors ๐
The -mpowerpc64 option lets GCC generate the additional 64-bit instructions found in the full PowerPC64 architecture, and treats GPRs as 64-bit, doubleword quantities ๐ GCC defaults to -mno-powerpc64 ๐
-mcpu=cpu_typeโ sets the architecture type, register usage, and instruction scheduling parameters for the machine typecpu_type๐ฅ๏ธ The supported values forcpu_typeare401,403,405,405fp,440,440fp,464,464fp,476,476fp,505,601,602,603,603e,604,604e,620,630,740,7400,7450,750,801,821,823,860,970,8540,a2,e300c2,e300c3,e500mc,e500mc64,e5500,e6500,ec603e,G3,G4,G5,titan,power3,power4,power5,power5+,power6,power6x,power7,power8,power9,powerpc,powerpc64,powerpc64le,rs64, andnative๐
-mcpu=powerpc, -mcpu=powerpc64, and -mcpu=powerpc64le are the generic ones. They give you pure 32-bit PowerPC (either endian), 64-bit big endian PowerPC, and 64-bit little endian PowerPC architecture machine types ๐ง An appropriate, generic processor model gets assumed for scheduling purposes.
Specifying native as the cpu type detects the host processor of the system doing the compiling, and selects the architecture option that matches it ๐ -mcpu=native has no effect if GCC doesn't recognize the processor, so no drama ๐ซถ
The other options name a specific processor. Code generated under those options runs best on that processor, and it may not run at all on others ๐ญ Choose wisely, bestie!
The -mcpu options automatically enable or disable the following options ๐:
Okay so the list of flags that -mcpu can switch on for a CPU keeps going, bestie ๐
-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
The exact combo of options a CPU gets can change between compiler versions ๐, because GCC picks whatever it thinks makes the best code for that chip. It is not a receipt of what the hardware can actually do ๐. Want to override one flag? Just put it after -mcpu, like -mcpu=970 -mno-altivec. Iconic move ๐.
On AIX, -maltivec and -mpowerpc64 don't get flipped by -mcpu right now, because AIX doesn't fully support them yet ๐ญ. You can still turn them on or off yourself if you're sure it'll work in your setup ๐ซถ.
-mtune=cpu_typeโ Sets up the instruction scheduling for the machine type cpu_type ๐, but leaves the architecture and register usage alone (that's-mcpu=cpu_type's job). Same values as-mcpuwork here. If you use both, the code uses the architecture and registers from-mcpu, but the scheduling comes from-mtuneโจ.-mcmodel=smallโ PowerPC64 code for the small model ๐ง. The TOC is capped at 64k.-mcmodel=mediumโ PowerPC64 code for the medium model ๐ธ. The TOC and other static data can total up to 4G. This is the default for 64-bit Linux ๐.-mcmodel=largeโ PowerPC64 code for the large model ๐. The TOC can be up to 4G. Other data and code are only limited by the 64-bit address space.-maltivec,-mno-altivecโ Turns AltiVec instructions on or off ๐ , and also unlocks built-in functions for more direct access to the AltiVec instruction set. You might need-mabi=altivectoo, to update the ABI with the AltiVec ABI enhancements ๐ฆ.
When you use -maltivec, the element order for AltiVec intrinsics like "vec_splat", "vec_extract", and "vec_insert" matches the array element order for the target's endianness ๐ง . On a big-endian target, element zero is the leftmost element in a vector register. On a little-endian target, element zero is the rightmost one.
-mvrsave,-mno-vrsaveโ Generates VRSAVE instructions when making AltiVec code ๐ท.-msecure-pltโ Makes code soldandld.socan build executables and shared libraries with non-executable".plt"and".got"sections ๐. This one's a PowerPC 32-bit SYSV ABI option.-mbss-pltโ Uses a BSS".plt"section thatld.sofills in ๐ช. It needs".plt"and".got"sections that are both writable and executable (a bit spicy ๐ถ๏ธ). This is also a PowerPC 32-bit SYSV ABI option.-misel,-mno-iselโ Turns ISEL instruction generation on or off ๐ฏ.-mvsx,-mno-vsxโ Makes code that does (or doesn't) use vector/scalar (VSX) instructions โก. Turning it on also unlocks built-in functions for more direct access to the VSX instruction set ๐.-mcrypto,-mno-cryptoโ Enables (or disables) built-in functions for direct access to the cryptographic instructions added in version 2.07 of the PowerPC ISA ๐.-mhtm,-mno-htmโ Enables (or disables) 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โ Makes code that keeps some integer operations next to each other, so the instructions can fuse together on POWER8 and later processors ๐. The-mno-version does not keep them together.-mpower8-vector,-mno-power8-vectorโ Makes code that does (or doesn't) use the vector and scalar instructions added in version 2.07 of the PowerPC ISA ๐ฆ. Turning it on also unlocks built-in functions for more direct access to the vector instructions ๐ .-mquad-memory,-mno-quad-memoryโ Makes code that does (or doesn't) use the non-atomic quad word memory instructions ๐ฆ.-mquad-memoryneeds 64-bit mode, so don't skip that part ๐.-mquad-memory-atomic,-mno-quad-memory-atomicโ Makes code that does (or doesn't) use the atomic quad word memory instructions โ๏ธ.-mquad-memory-atomicalso needs 64-bit mode ๐.-mfloat128,-mno-float128โ Turns the__float128keyword on or off for IEEE 128-bit floating point ๐, and picks either software emulation or hardware instructions for it ๐ ๏ธ.
You need the VSX instruction set (-mvsx, -mcpu=power7, or -mcpu=power8), or -mcpu=power9, enabled to use IEEE 128-bit floating point support ๐ซถ. This support only works on PowerPC Linux systems ๐ง.
-mfloat128 is on by default on PowerPC Linux systems using the VSX instruction set, and off everywhere else ๐.
If you use the ISA 3.0 instruction set (-mpower9-vector or -mcpu=power9) on a 64-bit system, IEEE 128-bit floating point support also turns on generation of ISA 3.0 IEEE 128-bit floating point instructions ๐. Otherwise, if you don't ask for ISA 3.0 instructions, or you're targeting a 32-bit big endian system, IEEE 128-bit floating point gets done with software emulation ๐ข.
-mfloat128-hardware,-mno-float128-hardwareโ Turns ISA 3.0 hardware instructions on or off for supporting the__float128data type ๐ง.
This one is on by default on PowerPC Linux systems using the ISA 3.0 instruction set, and off on other systems ๐.
-m32,-m64โ Generates code for 32-bit or 64-bit environments on Darwin and SVR4 targets (including GNU/Linux) ๐. The 32-bit environment setsint,long, and pointer to 32 bits, and runs on any PowerPC variant ๐ฆ. The 64-bit environment setsintto 32 bits, setslongand pointer to 64 bits, and generates code for PowerPC64, same as-mpowerpc64โจ.-mfull-toc,-mno-fp-in-toc,-mno-sum-in-toc,-mminimal-tocโ These change how the TOC (Table Of Contents) gets made, and every executable file has one ๐.-mfull-tocis the default. With it, GCC gives at least one TOC entry to each unique non-automatic variable reference in your program, and it also puts floating-point constants in the TOC ๐งพ. The catch is that only 16,384 entries fit in the TOC ๐ญ.
If the linker yells that you've overflowed the available TOC space, you can shrink the TOC use with -mno-fp-in-toc and -mno-sum-in-toc ๐ซถ. -mno-fp-in-toc stops GCC from putting floating-point constants in the TOC. -mno-sum-in-toc makes GCC generate code that works out the sum of an address and a constant at run time, instead of stashing that sum in the TOC ๐งฎ. You can use one or both. Each one makes the code very slightly slower and bigger, but saves TOC space ๐
.
If you still run out of TOC space with both of those, try -mminimal-toc ๐ฅบ. It makes just one TOC entry for every file. The code gets slower and bigger, but it uses extremely little TOC space. You might only want it for files with less frequently-executed code ๐.
-maix64,-maix32โ 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.-maix64implies-mpowerpc64.-maix32turns off the 64-bit ABI and implies-mno-powerpc64. GCC defaults to-maix32๐ซง.-mxl-compat,-mno-xl-compatโ Makes code that matches IBM XL compiler semantics more closely when you're using the AIX-compatible ABI ๐. It does a few things:- It passes floating-point arguments to prototyped functions beyond the register save area (RSA) on the stack, in addition to argument FPRs.
- It doesn't assume that the most significant double in a 128-bit
long doublevalue is properly rounded when comparing values and converting todouble. - It uses XL symbol names for
long doublesupport routines.
The AIX calling convention got extended without being documented at first ๐, to handle an obscure K&R C case: calling a function that takes the address of its arguments with fewer arguments than it declares ๐. IBM XL compilers read floating-point arguments that don't fit in the RSA from the stack when a subroutine gets compiled without optimization. Always storing floating-point arguments on the stack is inefficient and rarely needed, so this option is off by default. You only need it when calling subroutines compiled by IBM XL compilers without optimization ๐ซถ.
-mpeโ Supports the IBM RS/6000 SP Parallel Environment (PE) ๐ฅ๏ธ. It links an app that uses message passing with special startup code so the app can run ๐. The system needs PE installed in the standard location (/usr/lpp/ppe.poe/), or you have to override the specs file with-specs=to point at the right directory ๐. The Parallel Environment doesn't support threads, so-mpeand-pthreadare incompatible ๐ซ.-malign-natural,-malign-powerโ On AIX, 32-bit Darwin, and 64-bit PowerPC GNU/Linux,-malign-naturaloverrides the ABI-defined alignment of bigger types (like floating-point doubles) and puts them on their natural size-based boundary ๐.-malign-powertells GCC to follow the ABI's alignment rules instead. GCC defaults to the standard alignment from the ABI ๐ .
On 64-bit Darwin, natural alignment is the default, and -malign-power isn't supported there ๐
โโ๏ธ.
-msoft-float,-mhard-floatโ Makes code that doesn't use (or does use) the floating-point register set ๐งฎ. If you use-msoft-float, software floating-point emulation gets provided, as long as you also pass the option to GCC when linking โ ๏ธ.-mmultiple,-mno-multipleโ okay so these decide whether GCC generates code using theload multiple wordandstore multiple wordinstructions ๐ They're on by default for POWER systems and off for PowerPC systems. ๐ซถ Bestie, don't use-mmultipleon little-endian PowerPC systems ๐ญ those instructions don't work when the processor is in little-endian mode. The exceptions arePPC740andPPC750, which are totally fine with them in little-endian mode โจ-mupdate,-mno-updateโ this one is about the load or store instructions that update the base register to the address of the calculated memory location ๐ฆ They're on by default. Using-mno-updateleaves a small window between the moment the stack pointer gets updated and the moment the address of the previous frame gets stored.
โ ๏ธ Because of that window, code that walks the stack frame across interrupts or signals may end up with corrupted data. Not a vibe ๐
-mavoid-indexed-addresses,-mno-avoid-indexed-addressesโ this tells GCC to try to avoid (or, with the-mno-version, not avoid) indexed load or store instructions ๐ธ Those can cost you performance on Power6 processors in certain situations, like stepping through large arrays that cross a 16M boundary. It's enabled by default when targeting Power6 and disabled otherwise.-mfused-madd,-mno-fused-maddโ these control whether GCC uses the floating-point multiply and accumulate instructions ๐ฅ They're generated by default if hardware floating point is being used. Fun fact: the machine-dependent-mfused-maddis now mapped to the machine-independent-ffp-contract=fast, and-mno-fused-maddis mapped to-ffp-contract=offโจ-mmulhw,-mno-mulhwโ these control the half-word multiply and multiply-accumulate instructions on the IBM 405, 440, 464 and 476 processors ๐ They're generated by default when you're targeting those processors.-mdlmzb,-mno-dlmzbโ these control the string-searchdlmzbinstruction on the IBM 405, 440, 464 and 476 processors ๐ง Same deal, it's generated by default when targeting those processors.-mno-bit-align,-mbit-alignโ on System V.4 and embedded PowerPC systems, these decide whether structures and unions containing bit-fields get forced to align to the base type of the bit-field ๐ The-mno-bit-alignversion means "do not force it," and plain-mbit-alignmeans "do force it."
By default, a structure with nothing but 8 "unsigned" bit-fields of length 1 gets aligned to a 4-byte boundary and ends up being 4 bytes in size. Slide in with -mno-bit-align though, and that same structure is aligned to a 1-byte boundary and is just 1 byte in size ๐คฏ
-mno-strict-align,-mstrict-alignโ on System V.4 and embedded PowerPC systems, these say whether GCC should assume unaligned memory references are handled by the system ๐ซ-mno-strict-alignmeans "do not assume that," and-mstrict-alignmeans "do assume that."-mrelocatable,-mno-relocatableโ these allow (or, with-mno-, do not allow) a static executable to be relocated to a different address at run time ๐ A simple embedded PowerPC system loader should relocate the entire contents of".got2"and the 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-mrelocatableor-mrelocatable-lib. Also,-mrelocatablecode aligns the stack to an 8-byte boundary ๐-mrelocatable-lib,-mno-relocatable-libโ this one is basically the cousin of-mrelocatable๐ฆ It also generates a".fixup"section so static executables can be relocated at run time, but it does not use the smaller stack alignment that-mrelocatabledoes. Objects compiled with-mrelocatable-libcan be linked with objects compiled with any combination of the-mrelocatableoptions ๐-mno-toc,-mtocโ on System V.4 and embedded PowerPC systems, these decide whether GCC assumes register 2 contains a pointer to a global area pointing to the addresses used in the program ๐ง-mno-tocsays "nope, don't assume that," and-mtocsays "yes, assume it."-mlittle,-mlittle-endianโ on System V.4 and embedded PowerPC systems, this compiles your code for the processor in little-endian mode ๐ Also,-mlittle-endianis exactly the same as-mlittle, so pick whichever one your heart desires ๐-mbig,-mbig-endianโ same energy as above, but on System V.4 and embedded PowerPC systems this compiles code for the processor in big-endian mode ๐ And yep,-mbig-endianis the same as-mbig.-mdynamic-no-picโ on Darwin and Mac OS X systems, this compiles code so it is not relocatable, but its external references are relocatable ๐ The result is suitable for applications, but not for shared libraries.-msingle-pic-baseโ this treats the register used for PIC addressing as read-only, instead of loading it in the prologue for each function โจ The runtime system is responsible for initializing this register with an appropriate value before execution begins, so make sure it's on it ๐-mprioritize-restricted-insns=priorityโ this one controls the priority given to dispatch-slot restricted instructions during the second scheduling pass โญ Thepriorityargument takes the value0,1, or2, which assigns no, highest, or second-highest priority (respectively) to those instructions.-msched-costly-dep=dependence_typeโ this controls which dependences the target considers costly during instruction scheduling ๐ Thedependence_typeargument takes one of these values:noโ No dependence is costly.allโ All dependences are costly.true_store_to_loadโ A true dependence from store to load is costly.store_to_loadโ Any dependence from store to load is costly.numberโ Any dependence for which the latency is greater than or equal to number is costly.
-minsert-sched-nops=schemeโ this picks which NOP insertion scheme gets used during the second scheduling pass ๐ง Theschemeargument takes one of these values:noโ Don't insert NOPs.padโ Pad with NOPs any dispatch group that has vacant issue slots, according to the scheduler's grouping.regroup_exactโ Insert NOPs to force costly dependent insns into separate groups. Insert exactly as many NOPs as needed to force an insn to a new group, according to the estimated processor grouping.numberโ Insert NOPs to force costly dependent insns into separate groups. Insert number NOPs to force an insn to a new group.
-mcall-sysvโ on System V.4 and embedded PowerPC systems, this compiles code using calling conventions that adhere to the March 1995 draft of the System V Application Binary Interface, PowerPC processor supplement ๐ This is the default unless you configured GCC usingpowerpc-*-eabiaix.-mcall-sysv-eabi,-mcall-eabiโ these are shorthand for specifying both-mcall-sysvand-meabioptions ๐-mcall-sysv-noeabiโ this one is shorthand for specifying both-mcall-sysvand-mno-eabioptions ๐-mcall-aixdescโ on System V.4 and embedded PowerPC systems, this compiles code for the AIX operating system ๐ฆ-mcall-linuxโ on System V.4 and embedded PowerPC systems, this compiles code for the Linux-based GNU system ๐ง-mcall-freebsdโ on System V.4 and embedded PowerPC systems, this compiles code for the FreeBSD operating system ๐-mcall-netbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the NetBSD operating system ๐ฟ-mcall-openbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the OpenBSD operating system ๐ก-mtraceback=traceback_typeโ this selects the type of traceback table ๐ Valid values fortraceback_typearefull,part, andno.-maix-struct-returnโ this returns all structures in memory, as specified by the AIX ABI ๐งฑ-msvr4-struct-returnโ this returns structures smaller than 8 bytes in registers, as specified by the SVR4 ABI ๐โโ๏ธ-mabi=abi-typeโ this extends the current ABI with a particular extension, or removes that extension ๐ธ Valid values arealtivec,no-altivec,ibmlongdouble,ieeelongdouble,elfv1, andelfv2.-mabi=ibmlongdoubleโ this changes the current ABI to use 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 away from IEEE extended-precision, the compiler will issue a warning unless you use the-Wno-psabioption. It requires-mlong-double-128to be enabled.-mabi=ieeelongdoubleโ this changes the current ABI to use 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 away from IBM extended-precision, the compiler will issue a warning unless you use the-Wno-psabioption. It requires-mlong-double-128to be enabled.-mabi=elfv1โ this changes the current ABI to the ELFv1 ABI ๐งพ It's the default ABI for big-endian PowerPC 64-bit Linux.
๐ Overriding the default ABI requires special system support and is likely to fail in spectacular ways. Proceed with caution, bestie.
-mabi=elfv2โ this changes the current ABI to the ELFv2 ABI ๐งพ It's the default ABI for little-endian PowerPC 64-bit Linux.
๐ Same warning as above: overriding the default ABI requires special system support and is likely to fail in spectacular ways.
-mgnu-attribute,-mno-gnu-attributeโ these emit.gnu_attributeassembly directives to set tag/value pairs in a.gnu.attributessection, which specifies 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"), which indicates whether floating-point values are passed in the floating-point registers in case the function takes variable arguments. With-mprototype, only calls to prototyped variable argument functions set or clear that bit.-msimโ on embedded PowerPC systems, this assumes the startup module is calledsim-crt0.oand that the standard C libraries arelibsim.aandlibc.a๐ฎ This is the default forpowerpc-*-eabisimconfigurations.-mmvmeโ on embedded PowerPC systems, this assumes the startup module is calledcrt0.oand the standard C libraries arelibmvme.aandlibc.a๐น๏ธ-madsโ okay bestie, on embedded PowerPC ๐ง this one assumes your startup module iscrt0.oand your standard C libraries arelibads.aandlibc.a๐-myellowknifeโ same main character energy, but the library swap is different ๐ฆ on embedded PowerPC, the startup module is stillcrt0.o, but the C libraries are nowlibyk.aandlibc.a-mvxworksโ tell GCC you're building for a VxWorks system ๐ธ this one works on System V.4 and embedded PowerPC systems-membโ on embedded PowerPC systems, this sets thePPC_EMBbit in the ELF flags header ๐ which is how you signal that eabi extended relocations are being used-meabi,-mno-eabiโ on System V.4 and embedded PowerPC systems,-meabimeans you adhere to the Embedded Applications Binary Interface (EABI), a set of tweaks on top of the System V.4 specs ๐ซถ-mno-eabimeans you don't. Here's the lowkey important part:- With
-meabi, the stack is aligned to an 8-byte boundary, a function__eabigets called frommainto set up the EABI environment, and the-msdataoption can use bothr2andr13to point to two separate small data areas. - With
-mno-eabi, the stack is aligned to a 16-byte boundary, no EABI initialization function gets called frommain, and the-msdataoption only usesr13to point to a single small data area. -meabiis on by default if you configured GCC using one of thepowerpc*-*-eabi*options โจ
- With
-msdata=eabiโ on System V.4 and embedded PowerPC systems, this gets organized super neatly ๐- Small initialized
constglobal and static data goes in the.sdata2section, which is pointed to by registerr2. - Small initialized non-
constglobal and static data goes in the.sdatasection, which is pointed to by registerr13. - Small uninitialized global and static data goes in the
.sbsssection, which sits right next to.sdata. -msdata=eabiis incompatible with-mrelocatable, and it also turns on-memb.
- Small initialized
-msdata=sysvโ on System V.4 and embedded PowerPC systems, small global and static data goes in the.sdatasection, which is pointed to by registerr13๐ small uninitialized global and static data goes in.sbss, right beside.sdata. Heads up:-msdata=sysvis incompatible with-mrelocatable.-msdata=default,-msdataโ on System V.4 and embedded PowerPC systems, if-meabiis used, the code gets compiled the same as-msdata=eabi. Otherwise, it gets compiled the same as-msdata=sysv๐ฅ-msdata=dataโ on System V.4 and embedded PowerPC systems, small global data goes in the.sdatasection and small uninitialized global data goes in.sbss๐ the vibe here is that registerr13does not get used to address small data. 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โ read-only objects get put in the.sdatasection too ๐ this is the default.-mblock-move-inline-limit=numโ inlines all block moves (like calls tomemcpyor structure copies) that are less than or equal tonumbytes โญ the minimum value fornumis 32 bytes on 32-bit targets and 64 bytes on 64-bit targets. The default is target-specific.-mblock-compare-inline-limit=numโ generates non-looping inline code for all block compares (like calls tomemcmpor structure compares) that are less than or equal tonumbytes ๐ ifnumis0, all inline expansion of block compare is disabled, both the non-loop and loop kinds. The default is target-specific.-mblock-compare-inline-loop-limit=numโ generates an inline expansion using loop code for all block compares that are less than or equal tonumbytes, but greater than the limit for non-loop inline block compare expansion ๐ฆ if the block length isn't constant, at mostnumbytes get compared beforememcmpis called to handle the remainder of the block. The default is target-specific.-mstring-compare-inline-limit=numโ compares at mostnumstring bytes with inline code ๐ง if the difference or end of string isn't found at the end of the inline compare, a call tostrcmporstrncmptakes care of the rest. The default is 64 bytes.-G numโ on embedded PowerPC systems, global and static items that are less than or equal tonumbytes get put into the small data or BSS sections instead of the normal data or BSS section ๐ by default,numis 8. The-G numswitch also gets passed to the linker. Iykyk, but all modules should be compiled with the same-G numvalue ๐ญ-mregnames,-mno-regnamesโ on System V.4 and embedded PowerPC systems, this makes GCC emit register names in the assembly language output using symbolic forms (-mregnames), or not (-mno-regnames) ๐-mlongcall,-mno-longcallโ by default, GCC assumes all calls are far away, so it uses a longer and more expensive calling sequence. This is required for calls farther than 32 megabytes (33,554,432 bytes) from the current location ๐ a short call only gets generated if the compiler knows the call can't be that far away. You can override this with theshortcallfunction attribute, or with#pragma longcall(0).- Some linkers can detect out-of-range calls and generate glue code on the fly. On those systems, long calls are unnecessary and generate slower code. As of this writing, the AIX linker can do this, and so can the GNU linker for PowerPC/64. It's planned to add this feature to the GNU linker for 32-bit PowerPC systems as well.
- On PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers, GCC can generate long calls using an inline PLT call sequence (see
-mpltseq). PowerPC with-mbss-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 generatesbl calleeif the PPCblinstruction reaches the callee directly. Otherwise, it generatesbl L42to call the branch island. The branch island gets appended to the body of the calling function, and it computes the full 32-bit address of the callee and jumps to it. - On Mach-O (Darwin) systems, this option tells the compiler to emit the glue for every direct call, and then the Darwin linker decides whether to use it or discard it.
- In the future, GCC may ignore all
longcallspecifications when the linker is known to generate glue ๐ฎ
-mpltseq,-mno-pltseqโ implements (-mpltseq) or does not implement (-mno-pltseq)-fno-pltand long calls using an inline PLT call sequence. This supports lazy linking and long calls to functions indlopen'd shared libraries โจ inline PLT calls are only supported on PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers. They're enabled by default if the support is detected when configuring GCC, and, in the case of 32-bit PowerPC, only if GCC is configured with--enable-secureplt.
Watch out:-mpltseqcode and-mbss-plt32-bit PowerPC relocatable objects may not be linked together.
-mtls-markers,-mno-tls-markersโ marks (-mtls-markers) or does not mark (-mno-tls-markers) calls to__tls_get_addrwith a relocation that specifies the function argument ๐ this 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 enables the use of the reciprocal estimate and reciprocal square root estimate instructions, with additional Newton-Raphson steps to boost precision, instead of doing a divide, or a square root and a divide, for floating-point arguments ๐ง you should use-ffast-mathwhen using-mrecip, or at least-funsafe-math-optimizations,-ffinite-math-only,-freciprocal-mathand-fno-trapping-math.
Heads up: while the throughput of the sequence is generally higher than the throughput of the non-reciprocal instruction, the precision of the sequence can drop by up to 2 ulp (i.e. the inverse of 1.0 equals 0.99999994) for reciprocal square roots ๐
-mrecip=optโ 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 the option.allโ enables all estimate instructions.defaultโ enables the default instructions, which is the same as-mrecip.noneโ disables all estimate instructions, which is the same as-mno-recip.divโ enables the reciprocal approximation instructions for both single and double precision.divfโ enables the single-precision reciprocal approximation instructions.divdโ enables the double-precision reciprocal approximation instructions.rsqrtโ enables the reciprocal square root approximation instructions for both single and double precision.rsqrtfโ enables the single-precision reciprocal square root approximation instructions.rsqrtdโ enables the double-precision reciprocal square root approximation instructions.- So, for example,
-mrecip=all,!rsqrtdenables all of the reciprocal estimate instructions except for theFRSQRTE,XSRSQRTEDP, andXVRSQRTEDPinstructions, which handle the double-precision reciprocal square root calculations ๐ธ
-mrecip-precision,-mno-recip-precisionโ assumes (-mrecip-precision) or does not assume (-mno-recip-precision) that the reciprocal estimate instructions provide 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โ okay so this one picks the ABI for vectorizing intrinsics through an external library ๐ The only type that's supported right now ismass, which tells GCC to use IBM's Mathematical Acceleration Subsystem (MASS) libraries for vectorizing intrinsics with external libraries. GCC currently emits calls to the functions below when generating code forpower7โจ
acosd2, acosf4, acoshd2, acoshf4, asind2, asinf4, asinhd2, asinhf4,
atan2d2, atan2f4, atand2, atanf4, atanhd2, atanhf4, cbrtd2, cbrtf4,
cosd2, cosf4, coshd2, coshf4, erfcd2, erfcf4, erfd2, erff4,
exp2d2, exp2f4, expd2, expf4, expm1d2, expm1f4, hypotd2, hypotf4,
lgammad2, lgammaf4, log10d2, log10f4, log1pd2, log1pf4, log2d2, log2f4,
logd2, logf4, powd2, powf4, sind2, sinf4, sinhd2, sinhf4,
sqrtd2, sqrtf4, tand2, tanf4, tanhd2, tanhf4
Both -ftree-vectorize and -funsafe-math-optimizations must also be enabled, and the MASS libraries must be specified at link time. Don't forget that part, bestie ๐ญ
-mfriz,-mno-frizโ-mfrizmakes GCC generate (and-mno-frizmakes it not generate) thefrizinstruction ๐ฆ This only kicks in when-funsafe-math-optimizationsis on, and it's used to optimize rounding floating-point values to 64-bit integers and back again. Heads up:frizdoesn't return the same value if the float is too big to fit in an integer, so it's not totally innocent ๐-mpointers-to-nested-functions,-mno-pointers-to-nested-functionsโ on AIX and 64-bit Linux systems, a function pointer points to a 3-word descriptor that holds the function address, the TOC value to load into registerr2, and the static chain value to load into registerr11. With-mpointers-to-nested-functions(on by default), GCC generates code that loads up the static chain registerr11when calling through a pointer. With-mno-pointers-to-nested-functions, it doesn't ๐
If you use -mno-pointers-to-nested-functions, you cannot call through pointers to nested functions, or through pointers to functions compiled in other languages that use the static chain. Rough, I know ๐ญ
-msave-toc-indirect,-mno-save-toc-indirectโ on AIX and 64-bit Linux systems, if a function calls through a pointer,-msave-toc-indirectgenerates code that saves the TOC value in the reserved stack location in the function prologue. If the TOC value isn't saved in the prologue, it gets saved right before the call through the pointer.-mno-save-toc-indirectis the default ๐ธ-mcompat-align-parm,-mno-compat-align-parmโ-mcompat-align-parmgenerates code that passes structure parameters with a maximum alignment of 64 bits, so it stays compatible with older versions of GCC.-mno-compat-align-parm(the default) doesn't ๐
Older versions of GCC (prior to 4.9.0) incorrectly didn't align a structure parameter on a 128-bit boundary when that structure had a member that needed 128-bit alignment. Newer versions fixed this, and this option lets you generate code that works with functions compiled by those older versions โจ
-mstack-protector-guard=guardโ generates stack protection code using a canary atguard. The supported locations areglobal(a global canary) ortls(a per-thread canary in the TLS block, which is the default with GNU libc version 2.4 or later) ๐ฅ-mstack-protector-guard-reg=regand-mstack-protector-guard-offset=offsetโ these only come into play with thetlschoice. They specify which register to use as the base register for reading the canary, and what offset from that base register to read from. If you don't set them, the defaults come from the relevant ABI ๐ง-mstack-protector-guard-symbol=symbolโ this one overrides the offset with a symbol reference to a canary in the TLS block ๐
๐ฆ RX Options ๐ฆ
These command-line options are defined for RX targets ๐
-m64bit-doubles,-m32bit-doublesโ makes thedoubledata type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) in size. The default is-m32bit-doubles, and that's on purpose: RX floating-point hardware only works on 32-bit values โจ-fpu,-nofpuโ-fpuenables and-nofpudisables the use of RX floating-point hardware. It's enabled by default for the RX600 series and disabled by default for the RX200 series ๐
Floating-point instructions only get generated for 32-bit floating-point values, though. So if -m64bit-doubles is used, the FPU hardware isn't used for doubles.
Note: if-fpuis enabled, then-funsafe-math-optimizationsgets enabled automatically too. That's because the RX FPU instructions are themselves unsafe ๐
-mcpu=nameโ selects the type of RX CPU to target. Three types are supported right now: the generic RX600 and RX200 series hardware, and the specific RX610 CPU. The default is RX600 ๐
The only difference between RX600 and RX610 is that the RX610 doesn't support the MVTIPL instruction. And since the RX200 series doesn't have a hardware floating-point unit, -nofpu is turned on by default when that type is selected.
-mbig-endian-data,-mlittle-endian-dataโ stores data (but not code) in big-endian format with-mbig-endian-data. The default is-mlittle-endian-data, which stores data in little-endian format ๐-msmall-data-limit=Nโ sets the maximum size in bytes of global and static variables that can be placed into the small data area ๐ซถ Using the small data area can lead to smaller and faster code, but the area's size is limited, and it's up to you to make sure it doesn't overflow.
Also, when the small data area is used, one of the RX's registers (usually r13) gets reserved to point at this area, so the compiler can't use it anymore. That can make code slower and/or larger if variables get pushed onto the stack instead of being held in that register.
Note: common variables (uninitialized variables) and constants aren't placed in the small data area, because they get assigned to other sections in the output executable.
The default value is 0, which disables this feature. It isn't turned on by default at higher optimization levels (like -O2) because reserving a register can have potentially detrimental effects. You'll have to experiment and figure out if it helps your program ๐ฌ For how the register holding the small data area pointer gets chosen, check out the -mpid option below.
-msim,-mno-simโ-msimuses the simulator runtime. The default is to use the libgloss board-specific runtime ๐งช-mas100-syntax,-mno-as100-syntaxโ when generating assembler output,-mas100-syntaxuses 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 maximum size, in bytes, of a constant that can be used as an operand in an RX instruction. The RX instruction set does allow constants up to 4 bytes long, but a longer value means a longer instruction. So in some situations it can actually help to restrict the size of constants used in instructions โจ Constants that are too big get put into a constant pool instead and referenced through register indirection.
N can be between 0 and 4. A value of 0 (the default) or 4 means constants of any size are allowed ๐
-mrelaxโ enables linker relaxation. This is where the linker tries to shrink your program by finding shorter versions of various instructions. It's disabled by default ๐ฆ-mint-register=Nโ specifies how many registers to reserve for fast interrupt handler functions.Ncan be between0and4๐1reservesr13for the exclusive use of fast interrupt handlers.2reservesr13andr12.3reservesr13,r12andr11.4reservesr13throughr10.0(the default) doesn't reserve any registers.
-msave-acc-in-interruptsโ says that interrupt handler functions should preserve the accumulator register ๐ฅ This is only needed if normal code might use the accumulator, for example because it does 64-bit multiplications. By default GCC ignores the accumulator, because that makes the interrupt handlers faster ๐๏ธ-mpid,-mno-pidโ-mpidenables generating position-independent data. With it on, any access to constant data is done via an offset from a base address held in a register. That 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 make code slower and/or larger, especially in complicated functions ๐
Which register ends up holding the constant data base address depends on whether -msmall-data-limit and/or -mint-register are enabled. Starting with r13 and moving downwards, registers get allocated first to satisfy -mint-register, then -mpid, and finally -msmall-data-limit. So it's possible for the small data area register to end up being r8 if both -mint-register=4 and -mpid are specified on the command line ๐คฏ
By default this feature is not enabled. You can restore the default with -mno-pid ๐
-mno-warn-multiple-fast-interrupts,-mwarn-multiple-fast-interruptsโ-mno-warn-multiple-fast-interruptsstops GCC from issuing a warning if it finds more than one fast interrupt handler while compiling a file. By default GCC warns for each extra fast interrupt handler it finds, because the RX only supports one of them ๐
-mallow-string-insns -mno-allow-string-insns โจ Enables or disables the string manipulation instructions
Okay so bestie, this part picks up mid-OPTIONS, right where we left off with the RX port flags and keeps going through the S/390 and zSeries stuff. Let's gooo ๐ฆ
-mallow-string-insns
-mno-allow-string-insns
Okay so these two toggle the string manipulation instructions SMOVF, SCMPU, SMOVB, SMOVU, SUNTIL, SWHILE, and also the RMPA instruction ๐
. Lowkey important, because these instructions may prefetch data, and that is NOT safe if you're touching an I/O register ๐ญ. (Check section 12.2.7 of the RX62N Group User's Manual if you want the deets ๐.)
The default is to allow them ๐ธ. BUT GCC cannot reliably detect every time a string instruction might poke an I/O register, so it can't turn them off automatically ๐. It's literally on you, the programmer, to pass -mno-allow-string-insns if your program accesses I/O space ๐ซถ.
When they're enabled, GCC defines the C preprocessor symbol __RX_ALLOW_STRING_INSNS__. Otherwise it defines __RX_DISALLOW_STRING_INSNS__ โจ.
-mjsr
-mno-jsr
These tell the compiler to use only (or not only) JSR instructions to access functions ๐ง. This one is clutch when your code size goes past the range of BSR instructions ๐ฅ. Note that -mno-jsr does NOT mean "don't use JSR" ๐. It just means any type of branch may be used.
Note: The generic GCC command-line option-ffixed-reghas special significance to the RX port when used with theinterruptfunction attribute ๐. That attribute marks a function meant to handle fast interrupts. GCC makes sure it only uses the registersr10,r11,r12and/orr13, and only if the normal use of those registers has been restricted via-ffixed-regor-mint-register๐.
โจ OPTIONS โจ
S/390 and zSeries Options
These are the -m options defined for the S/390 and zSeries architecture ๐. Main character energy ๐.
-mhard-float,-msoft-floatโ Use (or don't use) the hardware floating-point instructions and registers for floating-point operations ๐ฅ. With-msoft-float, functions inlibgcc.ado the floating-point work ๐ซ . With-mhard-float, the compiler generates IEEE floating-point instructions. This is the default โจ.-mhard-dfp,-mno-hard-dfpโ Use (or don't use) the hardware decimal-floating-point instructions for decimal-floating-point operations ๐งฎ. With-mno-hard-dfp, functions inlibgcc.ahandle the decimal-floating-point operations. 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, and this is the default ๐.-mbackchain,-mno-backchainโ Store (or don't store) the address of the caller's frame as a backchain pointer in the callee's stack frame ๐ฆ. A backchain may be needed to allow debugging with tools that don't understand DWARF call frame information ๐. When-mno-packed-stackis in effect, the backchain pointer is stored at the bottom of the stack frame. When-mpacked-stackis in effect, the backchain goes into the topmost word of the 96/160 byte register save area ๐ง.
In general, code compiled with -mbackchain is call-compatible with code compiled with -mmo-backchain ๐ซถ. Heads up though: using the backchain for debugging usually means the whole binary has to be built with -mbackchain ๐ฌ. Also, the combination of -mbackchain, -mpacked-stack and -mhard-float is NOT supported โ ๏ธ. If you're building a Linux kernel, use -msoft-float ๐.
The default is to not maintain the backchain ๐ธ.
-mpacked-stack,-mno-packed-stackโ Use (or don't use) the packed stack layout ๐ฆ. With-mno-packed-stack, the compiler uses all the fields of the 96/160 byte register save area only for their default purpose, so unused fields still eat stack space ๐ญ. With-mpacked-stack, register save slots are densely packed at the top of the register save area, and unused space gets reused for other stuff, which is way more efficient ๐ฅ. However, when-mbackchainis also in effect, the topmost word of the save area is always used for the backchain, and the return address register is always saved two words below the backchain ๐.
As long as the stack frame backchain isn't used, code generated with -mpacked-stack is call-compatible with code generated with -mno-packed-stack โจ. Some non-FSF releases of GCC 2.95 for S/390 or zSeries generated code that uses the stack frame backchain at run time, not just for debugging. That code is NOT call-compatible with code compiled with -mpacked-stack ๐. Also, the combination of -mbackchain, -mpacked-stack and -mhard-float is not supported. For a Linux kernel, use -msoft-float ๐ซถ.
The default is to not use the packed stack layout ๐ธ.
-msmall-exec,-mno-small-execโ Generate (or don't generate) code using thebrasinstruction for subroutine calls ๐. This only works reliably if the total executable size doesn't exceed 64k ๐ฌ. The default is to use thebasrinstruction instead, which doesn't have this limitation ๐.-m64,-m31โ With-m31, generate code compliant to the GNU/Linux for S/390 ABI ๐งฉ. With-m64, generate code compliant to the GNU/Linux for zSeries ABI. This lets GCC generate 64-bit instructions, which is so iconic ๐. For the s390 targets the default is-m31, while the s390x targets default to-m64๐.-mzarch,-mesaโ With-mzarch, generate code using the instructions available on z/Architecture ๐ฆ. With-mesa, generate code using the instructions available on ESA/390 ๐ง. Note that-mesais NOT possible with-m64๐ . When generating code for the GNU/Linux for S/390 ABI, the default is-mesa. For the GNU/Linux for zSeries ABI, the default is-mzarch๐.-mhtm,-mno-htmโ The-mhtmoption enables a set of builtins that use instructions from the transactional execution facility, introduced with the IBM zEnterprise EC12 machine generation (S/390 System z Built-in Functions) ๐ง .-mhtmis enabled by default when using-march=zEC12โจ.-mvx,-mno-vxโ With-mvx, generate code using the instructions from the vector extension facility, introduced with the IBM z13 machine generation ๐. This option changes the ABI for some vector type values when it comes to alignment and calling conventions ๐ญ. If vector type values are used in an ABI-relevant context, a GAS.gnu_attributecommand gets added to mark the resulting binary with the ABI used ๐ท๏ธ.-mvxis enabled by default when using-march=z13๐ .-mzvector,-mno-zvectorโ This enables vector language extensions and builtins that use instructions from the vector extension facility (IBM z13) ๐. It adds support forvectoras a keyword to define vector type variables and arguments ๐ซถ. Important:vectoris only available when GNU extensions are enabled. It won't be expanded when you request strict standard compliance, e.g. with-std=c99๐ . On top of the GCC low-level builtins,-mzvectoralso enables a set of builtins added for compatibility with AltiVec-style implementations like Power and Cell ๐ง. To use these builtins you need to include the header filevecintrin.h๐.-mzvectoris disabled by default ๐ธ.-mmvcle,-mno-mvcleโ Generate (or don't generate) code using themvcleinstruction for block moves ๐. With-mno-mvcle, use anmvcloop instead. This is the default unless you're optimizing for size ๐.-mdebug,-mno-debugโ Print (or don't print) additional debug information when compiling ๐. The default is to not print debug information ๐ธ.-march=cpu-typeโ Generate code that runs oncpu-type, which is the name of a system representing a certain processor type ๐ฅ๏ธ. Possible values forcpu-typearez900/arch5,z990/arch6,z9-109,z9-ec/arch7,z10/arch8,z196/arch9,zEC12,z13/arch11,z14/arch12, andnativeโจ. The default is-march=z900๐ฆ.
Specifying native as the cpu type can be used to select the best architecture option for the host processor ๐ซถ. -march=native has no effect if GCC doesn't recognize the processor ๐คท.
-mtune=cpu-typeโ Tune everything applicable about the generated code tocpu-type, except for the ABI and the set of available instructions ๐๏ธ. The list ofcpu-typevalues is the same as for-march๐. The default is the value used for-march๐.-mtpf-trace,-mno-tpf-traceโ Generate code that adds (or doesn't add) TPF OS specific branches to trace routines in the operating system ๐ฐ๏ธ. This option is off by default, even when compiling for the TPF OS ๐.-mfused-madd,-mno-fused-maddโ Generate code that uses (or doesn't use) the floating-point multiply and accumulate instructions โ. These are generated by default if hardware floating point is used ๐ฅ.-mwarn-framesize=framesizeโ Emit a warning if the current function exceeds the given frame size ๐จ. Because this is a compile-time check, it doesn't need to be a real problem when the program runs ๐. It's meant to flag functions that most probably cause a stack overflow, so it's super useful in environments with a limited stack size, like the Linux kernel ๐ง.-mwarn-dynamicstackโ Emit a warning if the function callsallocaor uses dynamically-sized arrays ๐ข. This is generally a bad idea with a limited stack size ๐ฌ.
-mstack-guard=stack-guard โ wait, let's go! ๐ง These two are a matching set ๐ Turn on -mstack-guard=stack-guard and -mstack-size=stack-size together, and the S/390 back end slips extra instructions into the function prologue that trigger a trap if the stack gets stack-guard bytes past stack-size. (Reminder: on S/390 the stack grows downward, so the vibe is "how close am I to the edge" ๐ญ) If you leave out the stack-guard value, the compiler picks the smallest power of 2 larger than the frame size of the compiled function. These are built for debugging stack overflows ๐, and the extra code is so light that you could honestly keep it on in production-like systems without a big performance hit โจ
Rules, bestie ๐: both values have to be exact powers of 2, stack-size has to be greater than stack-guard, and it can't go past 64k ๐
โโ๏ธ The code also assumes the stack starts at an address aligned to the value given by stack-size, which is how it stays efficient ๐
And stack-guard only works in conjunction with stack-size, so never show up to the party without it ๐
-mhotpatch=pre-halfwords,post-halfwordsโ main character hotpatch energy ๐ฅ When this is enabled, every function in the compilation unit gets a "hot-patching" prologue. The function label gets a bunch of two-byte NOP instructions stuck in front of it (pre-halfwords, max1000000), and after the label,2 * post-halfwordsbytes get tacked on using the biggest NOP-like instructions the architecture allows (max1000000) ๐ฆ
If both arguments are zero, hotpatching is switched off ๐
Also, you can override this for individual functions with the "hotpatch" attribute, so you're still in control of the drama ๐
โจ Score Options โจ
These options are defined for Score implementations ๐ธ
-mebโ big-endian mode, and it's the default ๐-melโ compile for little-endian mode ๐ซถ-mnhwloopโ disables generation of "bcnz" instructions ๐ โโ๏ธ-mulsโ turns on generation of unaligned load and store instructions ๐ฅ-mmacโ enables the multiply-accumulate instructions ๐งฎ Heads up, it's disabled by default, so you gotta ask for it ๐-mscore5โ targets the SCORE5 architecture ๐-mscore5uโ targets the SCORE5U architecture ๐-mscore7โ targets the SCORE7 architecture, and yes, it's the default โญ-mscore7dโ targets the SCORE7D architecture โจ
โจ SH Options โจ
These -m options are defined for the SH implementations ๐ฆ Let's go through the whole SH lineup ๐
-m1โ generates code for the SH1 ๐ธ-m2โ generates code for the SH2 ๐ธ-m2eโ generates code for the SH2e ๐ธ-m2a-nofpuโ generates code for the SH2a without an FPU, or for an SH2a-FPU in a way where the floating-point unit isn't used ๐-m2a-single-onlyโ generates code for the SH2a-FPU so that no double-precision floating-point operations get used ๐ง-m2a-singleโ generates code for the SH2a-FPU, assuming the FPU is in single-precision mode by default ๐ฅ-m2aโ generates code for the SH2a-FPU, assuming the FPU is in double-precision mode by default ๐-m3โ generates code for the SH3 ๐ธ-m3eโ generates code for the SH3e ๐ธ-m4-nofpuโ generates code for the SH4 without a floating-point unit ๐-m4-single-onlyโ generates code for the SH4 with an FPU that only does single-precision arithmetic ๐-m4-singleโ generates code for the SH4, assuming the FPU is in single-precision mode by default ๐-m4โ generates code for the SH4 ๐ธ-m4-100โ generates code for SH4-100 ๐ธ-m4-100-nofpuโ generates code for SH4-100 in a way where the FPU isn't used ๐-m4-100-singleโ generates code for SH4-100, assuming the FPU is in single-precision mode by default ๐ฅ-m4-100-single-onlyโ generates code for SH4-100 so that no double-precision floating-point operations get used ๐ง-m4-200โ generates code for SH4-200 ๐ธ-m4-200-nofpuโ generates code for SH4-200 in a way where the FPU isn't used ๐-m4-200-singleโ generates code for SH4-200, assuming the FPU is in single-precision mode by default ๐ฅ-m4-200-single-onlyโ generates code for SH4-200 so that no double-precision floating-point operations get used ๐ง-m4-300โ generates code for SH4-300 ๐ธ-m4-300-nofpuโ generates code for SH4-300 in a way where the FPU isn't used ๐-m4-300-singleโ generates code for SH4-300 so that no double-precision floating-point operations get used ๐ง-m4-300-single-onlyโ generates code for SH4-300 so that no double-precision floating-point operations get used ๐ง-m4-340โ generates code for SH4-340, which has no MMU and no FPU ๐-m4-500โ generates code for SH4-500, which has no FPU ๐ It also passes-isa=sh4-nofputo the assembler ๐ง-m4a-nofpuโ generates code for the SH4al-dsp, or for an SH4a in a way where the FPU isn't used ๐-m4a-single-onlyโ generates code for the SH4a so that no double-precision floating-point operations get used ๐ง-m4a-singleโ generates code for the SH4a, assuming the FPU is in single-precision mode by default ๐ฅ-m4aโ generates code for the SH4a ๐ธ-m4alโ basically the same as-m4a-nofpu, except it implicitly passes-dspto the assembler โจ Lowkey, GCC doesn't generate any DSP instructions at the moment ๐-mbโ compiles for the processor in big-endian mode ๐-mlโ compiles for the processor in little-endian mode ๐ซถ-mdalignโ aligns doubles at 64-bit boundaries ๐
โ ๏ธ Bestie, be careful with-mdalign! It changes the calling conventions, so some functions from the standard C library won't work unless you recompile it first with-mdalign๐ญ
-mrelaxโ shortens some address references at link time when it's possible, using the linker option-relax๐-mbigtableโ uses 32-bit offsets in"switch"tables ๐ The default is 16-bit offsets, so this is the upgrade ๐-mbitopsโ enables bit manipulation instructions on SH2A ๐ง-mfmovdโ enables the use of thefmovdinstruction ๐ฆ Make sure to check-mdalignfor alignment constraints ๐-mrenesasโ follows the calling conventions defined by Renesas ๐-mno-renesasโ follows the calling conventions defined for GCC before the Renesas conventions were available ๐ฐ๏ธ This one is the default for all targets of the SH toolchain ๐-mnomacsaveโ marks the "MAC" register as call-clobbered, even if-mrenesasis given ๐-mieee,-mno-ieeeโ these control the IEEE compliance of floating-point comparisons, which decides how cases with an unordered comparison result get handled ๐ง By default,-mieeeis implicitly enabled. If-ffinite-math-onlyis enabled, then-mno-ieeeis implicitly set, which makes floating-point greater-equal and less-equal comparisons faster โก You can override either implicit setting by specifying-mieeeor-mno-ieeeyourself ๐-minline-ic_invalidateโ inlines code that invalidates instruction cache entries after setting up nested function trampolines ๐ง This does nothing if-musermodeis in effect and the code generation option you picked (like-m4) doesn't allow the"icbi"instruction ๐ If the option doesn't allow"icbi"and-musermodeisn't in effect, the inlined code pokes the instruction cache address array directly with an associative write ๐ฌ That needs privileged mode at run time, and it also fails if the cache line got mapped via the TLB and became unmapped ๐-misizeโ dumps instruction size and location in the assembly code ๐-mpadstructโ deprecated, so please don't reach for it ๐ โโ๏ธ It pads structures to multiples of 4 bytes, which is incompatible with the SH ABI ๐-matomic-model=modelโ sets the model of atomic operations plus any additional parameters, as a comma-separated list ๐งต For the deets on atomic built-in functions, check out __atomic Builtins ๐ These are the models and parameters that are supported:noneโ turns off compiler-generated atomic sequences and emits library calls for atomic operations instead ๐ This is the default if the target is not"sh*-*-linux*"๐soft-gusaโ generates GNU/Linux-compatible gUSA software atomic sequences for the atomic built-in functions ๐ง These need extra help from the interrupt/exception handling code of the system, and they're only suitable for SH3* and SH4* single-core systems ๐ฏ This option is enabled by default when the target is"sh*-*-linux*"and the chip is SH3* or SH4* โจ When the target is SH4A, it also partially uses the hardware atomic instructions"movli.l"and"movco.l"to 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 support from the interrupt/exception handling code, and they're only suitable for single-core systems ๐ฏ When you use this model, you also have to specify thegbr-offset=parameter ๐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 ๐ฏ You don't need extra support from the interrupt/exception handling code for this one ๐ It's enabled by default when the target is"sh*-*-linux*"and the chip is SH1* or SH2* ๐hard-llcsโ generates hardware atomic sequences using only the"movli.l"and"movco.l"instructions ๐ฉ This is only available on SH4A and is suitable for multi-core systems ๐ Since the hardware instructions only support 32-bit atomic variables, access to 8- or 16-bit variables gets emulated with 32-bit accesses ๐งฉ Code compiled with this option is also compatible with other software atomic model interrupt/exception handling systems if it runs on an SH4A system ๐ซถ You don't need extra support from the interrupt/exception handling code for this model either ๐
gbr-offset=โ Okay so this one picks the byte offset of the variable inside the thread control block structure that the generated atomic sequences use, but only when the soft-tcb model is selected ๐ง. Every other model just ignores it. The value has to be an integer multiple of four and sit somewhere in the 0-1020 range ๐ .strictโ This one bans mixing multiple atomic models, even when they'd be compatible ๐ โโ๏ธ. It also makes the compiler generate atomic sequences for the specified model only ๐.
-mtasโ This makes the compiler emit thetas.bopcode for__atomic_test_and_set๐ฆ. ngl, depending on your hardware and software setup, it can tank overall performance, becausetas.bforces operand cache line flushes ๐. On multi-core SH4A processors, you have to be extra careful withtas.b, since certain cache configurations can end in data corruption ๐ญ.-mprefergotโ When you're generating position-independent code, this emits function calls through the Global Offset Table instead of the Procedure Linkage Table ๐ธ.-musermode,-mno-usermodeโ The first one means don't allow the compiler to generate privileged mode code, and the second one means allow it ๐.-musermodealso implies-mno-inline-ic_invalidateif the inlined code wouldn't work in user mode โจ.-musermodeis the default when the target issh*-*-linux*๐ง. If the target is SH1* or SH2*,-musermodedoes nothing, because those chips have no user mode ๐.-multcost=numberโ Sets the cost the compiler assumes for a multiply insn ๐ข.-mdiv=strategyโ Picks the division strategy for integer division operations ๐.strategycan be one of these vibes:call-div1โ Calls a library function that uses the single-step division instructiondiv1to do the math ๐งฎ. Dividing by zero gives an unspecified result and doesn't trap. This is the default except for SH4, SH2A and SHcompact.call-fpโ Calls a library function that does the operation in double precision floating point ๐. Dividing by zero causes a floating-point exception. This is the default for SHcompact with FPU. If you ask for this on a target without a double precision FPU, it falls back tocall-div1.call-tableโ Calls a library function that uses a lookup table for small divisors, and thediv1instruction with case distinction for bigger divisors ๐. Dividing by zero gives an unspecified result and doesn't trap. This is the default for SH4. If you ask for this on a target without dynamic shift instructions, it falls back tocall-div1.
If you don't specify a strategy, the compiler picks the default based on the current target ๐ฏ. For SH2A, the default is to use the divs and divu instructions instead of library function calls โก.
-maccumulate-outgoing-argsโ Reserves space once for outgoing arguments in the function prologue, instead of around each call ๐ง. This is generally great for performance and size ๐. It's also needed for unwinding, so the stack frame doesn't 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, and the compiler still expects the same sets of input, output and clobbered registers as if this option weren't there ๐.-mfixed-range=register-rangeโ Makes the compiler treat the given register range as fixed registers ๐. A fixed register is one the register allocator isn't allowed to use, which is super useful when compiling kernel code ๐งโ๐ป. You write a register range as two registers separated by a dash, and if you want multiple ranges, separate them with a comma ๐งต.-mbranch-cost=numโ Tells the compiler to assumenumis the cost of a branch instruction ๐ฟ. Higher numbers make the compiler try to generate more branch-free code when that's possible ๐ฆ. If you don't specify it, the value is picked based on the processor type you're compiling for ๐.-mzdcbranch,-mno-zdcbranchโ These assume (or don't assume) that zero displacement conditional branch instructionsbtandbfare fast โก. With-mzdcbranch, the compiler prefers zero displacement branch code sequences ๐. It's enabled by default for SH4 and SH4A, and you can turn it off explicitly with-mno-zdcbranch๐ โโ๏ธ.-mcbranch-force-delay-slotโ Forces the use of delay slots for conditional branches, filling the delay slot with anopif a suitable instruction can't be found ๐ฅฑ. This is disabled by default. You can enable it to work around hardware bugs like the ones found in the original SH7055 ๐ ๏ธ.-mfused-madd,-mno-fused-maddโ These generate code that does (or doesn't) use the floating-point multiply and accumulate instructions ๐ฅ. They're generated by default when hardware floating point is in use ๐ . 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 to emit thefscainstruction for sine and cosine approximations ๐.-mfscahas to be used together with-funsafe-math-optimizations๐ง . It's enabled by default when generating code for SH4A. Using-mno-fscadisables sine and cosine approximations even if-funsafe-math-optimizationsis in effect ๐ซ.-mfsrra,-mno-fsrraโ These allow (or disallow) the compiler to emit thefsrrainstruction for reciprocal square root approximations โจ.-mfsrrahas to be used together with-funsafe-math-optimizationsand-ffinite-math-only๐. It's enabled by default when generating code for SH4A. Using-mno-fsrradisables reciprocal square root approximations even if-funsafe-math-optimizationsand-ffinite-math-onlyare in effect ๐ โโ๏ธ.-mpretend-cmoveโ Prefers zero-displacement conditional branches for conditional move instruction patterns ๐. This can 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โ Okay, so this tells the compiler to remove the hardware capabilities generated by the Solaris assembler ๐งน. It's only necessary when object files use ISA extensions the current machine doesn't support, but still check at runtime whether or not to use them ๐คทโโ๏ธ.-mimpure-textโ Used alongside-shared, this tells the compiler not to pass-z textto the linker when linking a shared object ๐. With it, you can link position-dependent code into a shared object ๐ฆ.
Warning:-mimpure-textquiets the "relocations remain against allocatable but non-writable sections" linker error ๐. But the necessary relocations trigger copy-on-write, so the shared object isn't actually shared across processes ๐. Instead of using-mimpure-text, compile all your source code with-fpicor-fPIC๐ซถ.
These switches are supported in addition to the above on Solaris 2 โจ:
-pthreadsโ This is just a synonym for-pthread๐งต.
๐ SPARC Options ๐
These -m options are supported on the SPARC ๐:
-mno-app-regs,-mapp-regsโ Specifying-mapp-regsgenerates output using global registers 2 through 4, which the SPARC SVR4 ABI reserves for applications ๐ง. Like global register 1, each of global registers 2 through 4 is then treated as an allocable register that gets clobbered by function calls. This is the default ๐ธ.
To be fully SVR4 ABI-compliant (at the cost of some performance loss), specify -mno-app-regs ๐. You should compile libraries and system software with this option ๐ซถ.
-mflat,-mno-flatโ With-mflat, the compiler doesn't generate save/restore instructions and uses a "flat" or single register window model ๐ช. This model is compatible with the regular register window model ๐. The local registers and the input registers (0--5) are still treated as "call-saved" registers and get saved on the stack as needed ๐ฆ.
With -mno-flat (the default), the compiler generates save/restore instructions, except for leaf functions ๐. This is the normal operating mode ๐.
-mfpu,-mhard-floatโ Generates output containing floating-point instructions. This is the default ๐ฅ.-mno-fpu,-msoft-floatโ Generates output containing library calls for floating point ๐.
Warning: the requisite libraries are NOT available for all SPARC targets ๐ญ. Normally the facilities of the machine's usual C compiler are used, but that can't be done directly in cross-compilation. You 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 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 the trap handler overhead, this is much slower than calling the ABI library routines, so the -msoft-quad-float option is the default ๐ข.
-mno-unaligned-doubles,-munaligned-doublesโ Assumes that doubles have 8-byte alignment. This is the default ๐.
With -munaligned-doubles, GCC only assumes doubles have 8-byte alignment if they're tucked inside another type or have an absolute address. Otherwise it assumes 4-byte alignment, bestie ๐ Turning this on avoids some rare compatibility problems with code from other compilers, but it's not the default because it costs performance, especially for floating-point code ๐
-muser-mode,-mno-user-modeโ Don't generate code that can only run in supervisor mode ๐ This only matters for thecasainstruction 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 unlocks pairs oflddandstdinstructions for copies in structure assignment, instead of twice as manyldandstpairs, so it's faster ๐๏ธ
โ ๏ธ Okay, this one is serious. Changing the alignment like this directly violates the SPARC ABI ๐ญ So it's only for targets where the developer acknowledges their resulting code isn't fully in line with the ABI rules. Don't just sprinkle it on everything, babe.
-mstd-struct-return,-mno-std-struct-returnโ With-mstd-struct-return, the compiler adds checking code to functions that return structures or unions ๐ It's there to catch size mismatches between the two sides of a function call, following the 32-bit ABI ๐ง
The default is -mno-std-struct-return ๐ธ This option has no effect in 64-bit mode ๐
โโ๏ธ
-mlra,-mno-lraโ Turns on Local Register Allocation ๐ง This has been the default for SPARC since GCC 7, so if you want the old Reload behaviour, you have to pass-mno-lra๐ฐ๏ธ-mcpu=cpu_typeโ Sets the instruction set, register set, and instruction scheduling parameters for the machine type cpu_type ๐ฅ๏ธ The supported values arev7,cypress,v8,supersparc,hypersparc,leon,leon3,leon3v7,sparclite,f930,f934,sparclite86x,sparclet,tsc701,v9,ultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7andm8๐
Native Solaris and GNU/Linux toolchains also accept native, which picks the best architecture option for the host processor โจ Heads up: -mcpu=native has no effect if GCC doesn't recognise the processor ๐
Default scheduling parameters are used for the values that select an architecture rather than an implementation ๐ Those are v7, v8, sparclite, sparclet and v9 ๐
Here's the lineup of each supported architecture and its implementations, no cap ๐
v7โcypress,leon3v7v8โsupersparc,hypersparc,leon,leon3sparcliteโf930,f934,sparclite86xsparcletโtsc701v9โultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7,m8
By default (unless configured otherwise), GCC generates code for the V7 variant of the SPARC architecture ๐ฆ With -mcpu=cypress, the compiler also optimises for the Cypress CY7C602 chip, as used in the SPARCStation/SPARCServer 3xx series ๐ฅ๏ธ This is also a good fit for the older SPARCStation 1, 2, IPX etc. ๐น๏ธ
With -mcpu=v8, GCC generates code for the V8 variant ๐ The only difference from V7 is that the compiler emits the integer multiply and integer divide instructions that exist in SPARC-V8 but not SPARC-V7 โ With -mcpu=supersparc, it's also optimised for the SuperSPARC chip, used in the SPARCStation 10, 1000 and 2000 series ๐
With -mcpu=sparclite, GCC generates code for the SPARClite variant ๐ฟ This adds the integer multiply, integer divide step and scan ("ffs") instructions that exist in SPARClite but not SPARC-V7 ๐ With -mcpu=f930, the compiler also optimises for the Fujitsu MB86930, which is the original SPARClite with no FPU ๐งฉ With -mcpu=f934, it optimises for the Fujitsu MB86934, the more recent SPARClite with an FPU ๐
With -mcpu=sparclet, GCC generates code for the SPARClet variant ๐ง This adds the integer multiply, multiply/accumulate, integer divide step and scan ("ffs") instructions that exist in SPARClet but not SPARC-V7 ๐ช With -mcpu=tsc701, the compiler also optimises for the TEMIC SPARClet chip ๐
With -mcpu=v9, GCC generates code for the V9 variant ๐ธ This adds 64-bit integer and floating-point move instructions, 3 additional floating-point condition code registers and conditional move instructions ๐ With -mcpu=ultrasparc, the compiler also optimises for the Sun UltraSPARC I/II/IIi chips โ๏ธ With -mcpu=ultrasparc3, it optimises for the Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips ๐ฅ With -mcpu=niagara, it optimises for Sun UltraSPARC T1 chips ๐ With -mcpu=niagara2, it optimises for Sun UltraSPARC T2 chips ๐ With -mcpu=niagara3, it optimises for Sun UltraSPARC T3 chips ๐ With -mcpu=niagara4, it optimises for Sun UltraSPARC T4 chips ๐ With -mcpu=niagara7, it optimises for Oracle SPARC M7 chips ๐ And With -mcpu=m8, it optimises for Oracle M8 chips ๐
-mtune=cpu_typeโ Sets the instruction scheduling parameters for the machine type cpu_type, but doesn't set the instruction set or register set the way-mcpu=cpu_typedoes ๐ฏ
The same values for -mcpu=cpu_type work for -mtune=cpu_type, but the only useful ones are those that select a particular CPU implementation ๐
Those are cypress, supersparc, hypersparc, leon, leon3, leon3v7, 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 uses version 2.0 of the UltraSPARC Visual Instruction Set extensions ๐ฆ The default is-mvis2when targeting a CPU that supports such instructions, like UltraSPARC-III and later ๐ Setting-mvis2also sets-mvis๐ซ-mvis3,-mno-vis3โ With-mvis3, GCC uses version 3.0 of the UltraSPARC Visual Instruction Set extensions ๐ The default is-mvis3when targeting a CPU that supports such instructions, like niagara-3 and later ๐ Setting-mvis3also sets-mvis2and-mvis๐-mvis4,-mno-vis4โ With-mvis4, GCC uses version 4.0 of the UltraSPARC Visual Instruction Set extensions ๐ธ The default is-mvis4when targeting a CPU that supports such instructions, like niagara-7 and later ๐ Setting-mvis4also sets-mvis3,-mvis2and-mvis๐ง-mvis4b,-mno-vis4bโ With-mvis4b, GCC uses 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, like m8 and later ๐ Setting-mvis4balso sets-mvis4,-mvis3,-mvis2and-mvis๐ซถ-mcbcond,-mno-cbcondโ With-mcbcond, GCC uses the UltraSPARC Compare-and-Branch-on-Condition instructions ๐ The default is-mcbcondwhen targeting a CPU that supports them, like Niagara-4 and later ๐ธ-mfmaf,-mno-fmafโ With-mfmaf, GCC uses the UltraSPARC Fused Multiply-Add Floating-point instructions ๐งฎ The default is-mfmafwhen targeting a CPU that supports them, like Niagara-3 and later ๐-mfsmuld,-mno-fsmuldโ With-mfsmuld, GCC uses the Floating-point Multiply Single to Double (FsMULd) instruction โ๏ธ The default is-mfsmuldwhen targeting a CPU that supports the architecture versions V8 or V9 with an FPU, except-mcpu=leon๐-mpopc,-mno-popcโ With-mpopc, GCC uses the UltraSPARC Population Count instruction ๐ข The default is-mpopcwhen targeting a CPU that supports it, like Niagara-2 and later ๐-msubxc,-mno-subxcโ With-msubxc, GCC uses the UltraSPARC Subtract-Extended-with-Carry instruction โ The default is-msubxcwhen targeting a CPU that supports it, like 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, and programs must be linked in the low 32 bits of memory ๐งธ Programs can be statically or dynamically linked ๐medmidโ The Medium/Middle code model: 64-bit addresses, and programs must be linked in the low 44 bits of memory ๐ The text and data segments must each be less than 2GB in size, and the data segment must be located within 2GB of the text segment ๐
medany: okay so this is the Medium/Anywhere code model ๐ You get 64-bit addresses โจ programs can be linked anywhere in memory ๐บ๏ธ but the text and data segments have to be less than 2GB in size, and the data segment has to sit within 2GB of the text segment ๐ซถembmedany: the Medium/Anywhere model but for embedded systems ๐ It's still 64-bit addresses, and the text and data segments must be less than 2GB, but both can start anywhere in memory (that gets decided at link time ๐ฆ). The global register%g4points to the base of the data segment ๐ Programs are statically linked, and PIC is not supported ๐
โจ -mmemory-model=mem-model โจ
Use this to set the memory model the processor runs with ๐ธ Pick one of these:
default: the default memory model for the processor and operating system ๐rmo: Relaxed Memory Order ๐pso: Partial Store Order ๐tso: Total Store Order ๐sc: Sequential Consistency ๐ง
These memory models are formally defined in Appendix D of the SPARC-V9 architecture manual ๐, and they get set in the processor's PSTATE.MM field ๐ฅ very technical, very iconic ๐ญ
-mstack-bias,-mno-stack-bias: with-mstack-bias, GCC assumes the stack pointer (and the frame pointer, if there is one) is offset by-2047, and that offset has to be added back whenever it makes a stack frame reference ๐ซถ This is the default in 64-bit mode ๐ Otherwise, GCC assumes no offset is there at all โจ
๐ฅ SPU Options ๐ฅ
These -m options are supported on the SPU ๐ฆ
-mwarn-reloc,-merror-reloc: the SPU loader doesn't handle dynamic relocations, so by default GCC throws an error when it generates code that needs one ๐-mno-error-relocturns that error off, and-mwarn-relocgives you a warning instead ๐-msafe-dma,-munsafe-dma: instructions that start a DMA or check whether one has finished must not get reordered around loads and stores of the memory being accessed ๐ญ With-munsafe-dma, you have to use thevolatilekeyword to protect those memory accesses, but that can make the code inefficient wherever the memory is known not to change ๐ฅบ Instead of marking everything volatile, you can use-msafe-dmato tell the compiler to treat DMA instructions as potentially affecting all memory ๐ง-mbranch-hints: by default, GCC generates a branch hint instruction to avoid pipeline stalls for always-taken or probably-taken branches โจ A hint is never generated closer than 8 instructions away from its branch ๐ There's little reason to turn these off, except for debugging or to make an object a little smaller ๐ค-msmall-mem,-mlarge-mem: by default, GCC generates code assuming addresses are never larger than 18 bits ๐ธ With-mlarge-mem, the code assumes a full 32-bit address ๐-mstdmain: by default, GCC links against startup code that assumes the SPU-stylemainfunction interface (which has an unconventional parameter list) ๐ค With-mstdmain, GCC links your program against startup code that assumes a C99-style interface tomain, including a local copy ofargvstrings ๐-mfixed-range=register-range: makes GCC generate code that treats the given register range as fixed registers ๐ A fixed register is one the register allocator can't use ๐ซ This is super useful when compiling kernel code ๐ซถ A register range is written as two registers separated by a dash, and you can list multiple ranges separated by a comma ๐-mea32,-mea64: compiles code assuming pointers to the PPU address space, accessed through the__eanamed address space qualifier, are either 32 or 64 bits wide โจ The default is 32 bits ๐ง This is an ABI-changing option, so all object code in an executable has to be compiled with the same setting ๐จ-maddress-space-conversion,-mno-address-space-conversion: allows or disallows treating the__eaaddress space as a superset of the generic address space ๐ Allowing it enables explicit type casts between__eaand generic pointers, as well as implicit conversions of generic pointers to__eapointers ๐ฆ The default is to allow address space pointer conversions ๐-mcache-size=cache-size: this option controls which version of libgcc the compiler links into an executable, and picks a software-managed cache for accessing variables in the__eaaddress space at a particular cache size ๐ Possible values forcache-sizeare 8, 16, 32, 64 and 128 ๐ The default cache size is 64KB ๐ธ-matomic-updates,-mno-atomic-updates: this option controls which version of libgcc gets linked, and whether atomic updates to the software-managed cache of PPU-side variables are used ๐ฅ With atomic updates, changes to a PPU variable from SPU code using the__eanamed address space qualifier don't interfere with changes to other PPU variables sharing the same cache line from PPU code ๐ Without them, that interference may happen, but writing back cache lines is more efficient ๐คทโโ๏ธ The default is to use atomic updates ๐-mdual-nops,-mdual-nops=n: by default, GCC inserts NOPs to increase dual issue when it expects that to boost performance ๐ncan be a value from 0 to 10, and a smallerninserts fewer NOPs ๐ค 10 is the default, and 0 is the same as-mno-dual-nops๐ซถ This is disabled with-Os๐ญ-mhint-max-nops=n: the maximum number of NOPs to insert for a branch hint ๐ง A branch hint has to be at least 8 instructions away from the branch it affects ๐ GCC inserts up tonNOPs to enforce that, and otherwise it doesn't generate the branch hint at all ๐-mhint-max-distance=n: the encoding of the branch hint instruction limits the hint to within 256 instructions of the branch it affects ๐ฆ By default, GCC makes sure it's within 125 ๐-msafe-hints: works around a hardware bug that makes the SPU stall indefinitely ๐ ๏ธ By default, GCC inserts thehbrpinstruction to make sure that stall won't happen ๐ซถ
๐ Options for System V ๐
These additional options are available on System V Release 4 for compatibility with other compilers on those systems ๐
-G: creates a shared object ๐ It's recommended to use-symbolicor-sharedinstead ๐-Qy: identifies the versions of each tool used by the compiler, in a.identassembler directive in the output ๐-Qn: refrains from adding.identdirectives to the output file (this is the default) ๐-YP,dirs: searches the directoriesdirs, and no others, for libraries specified with-l๐-Ym,dir: looks in the directorydirto find the M4 preprocessor ๐ง The assembler uses this option ๐ซถ
๐ฆ 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's no limitation on call distance, PC-relative addresses, or absolute addresses ๐-mcpu=name: selects the type of CPU to target ๐ Currently the only supported type istilegx๐ซถ-m32,-m64: generates code for a 32-bit or 64-bit environment ๐ The 32-bit environment setsint,long, and pointer to 32 bits ๐ง The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits ๐-mbig-endian,-mlittle-endian: 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 target ๐ 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: treat all calls as being far away (or near, for the-mno-version) ๐บ๏ธ If calls are assumed to be far away, the compiler always loads the function's address into a register and calls indirectly through the pointer ๐ซถ-mno-ep,-mep:-mno-epdoes not optimize basic blocks that use the same index pointer 4 or more times to copy the pointer into theepregister, and-mepdoes (and uses the shortersldandsstinstructions) ๐ธ The-mepoption is on by default if you optimize ๐ฅ-mno-prolog-function,-mprolog-function:-mno-prolog-functiondoes not use external functions to save and restore registers in a function's prologue and epilogue, and-mprolog-functiondoes ๐ The external functions are slower, but they use less code space if more than one function saves the same number of registers ๐ค The-mprolog-functionoption is on by default if you optimize โจ-mspace: tries to make the code as small as possible ๐ง At present, this just turns on the-mepand-mprolog-functionoptions ๐-mtda=n: puts static or global variables whose size isnbytes or less into the tiny data area that registereppoints to ๐ท The tiny data area can hold up to 256 bytes in total (128 bytes for byte references) ๐-msda=n: puts static or global variables whose size isnbytes or less into the small data area that registergppoints to ๐ The small data area can hold up to 64 kilobytes ๐ฆ-mzda=n: puts static or global variables whose size isnbytes or less into the first 32 kilobytes of memory ๐ง-mv850: specifies that the target processor is the V850 ๐-mv850e3v5: specifies that the target processor is the V850E3V5 ๐ฅ The preprocessor constant__v850e3v5__is defined if this option is used โจ-mv850e2v4: specifies that the target processor is the V850E3V5 ๐ This is an alias for the-mv850e3v5option ๐-mv850e2v3: specifies that the target processor is the V850E2V3 ๐ฆ The preprocessor constant__v850e2v3__is defined if this option is used ๐ซถ-mv850e2: specifies that the target processor is the V850E2 ๐ธ The preprocessor constant__v850e2__is defined if this option is used ๐-mv850e1: specifies that the target processor is the V850E1 ๐ The preprocessor constants__v850e1__and__v850e__are defined if this option is used ๐-mv850es: specifies that the target processor is the V850ES ๐ This is an alias for the-mv850e1option ๐ง-mv850eโ okay bestie, this tells GCC the target processor is the V850E ๐ Turn it on and the preprocessor constant__v850e__gets defined โจ If none of-mv850,-mv850e,-mv850e1,-mv850e2,-mv850e2v3, or-mv850e3v5are passed, GCC picks a default target processor for you and defines the matching__v850*__preprocessor constant ๐ง The constants__v850and__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. IfCALLTinstructions 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 back on) the generation of PC-relative jump instructions ๐-msoft-float,-mhard-floatโ turns off (or back on) hardware floating point instructions ๐ฅ This only matters when the target architecture is V850E2V3 or higher. If hardware floating point instructions are being generated, the preprocessor symbol__FPU_OK__is defined; otherwise__NO_FPU__is defined ๐-mloopโ enables the e3v5LOOPinstruction ๐ It's not turned on by default when the e3v5 architecture is selected, because its use is still experimental ๐-mrh850-abi,-mghsโ enables support for the RH850 version of the V850 ABI, which is the default ๐ With this version of the ABI, these rules apply:- Integer sized structures and unions are returned via a memory pointer rather than a register.
- Large structures and unions (more than 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 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 line up on 8-byte boundaries ๐ The default keeps 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 within a switch table ๐ญ-mapp-regsโ makes r2 and r5 get used in the code the compiler generates. This is the default โจ-mno-app-regsโ makes r2 and r5 get treated as fixed registers ๐ซถ
๐ฆ VAX Options
These -m options are defined for the VAX ๐
-munixโ doesn't output certain jump instructions (aobleqand so on) that the Unix assembler for the VAX can't handle across long ranges ๐-mgnuโ does output those jump instructions, on the assumption that the GNU assembler is being used ๐-mgโ outputs code for G-format floating-point numbers instead of D-format ๐ฅ
๐ธ Visium Options
-mdebugโ a program that does file I/O and is destined to run on an MCM target should be linked with this option ๐ It causes the librarieslibc.aandlibdebug.ato be linked. The program should be run on the target under the control of the GDB remote debugging stub ๐ง-msimโ a program that does file I/O and is destined to run on the simulator should be linked with option. This causes the librarieslibc.aandlibsim.ato be linked ๐-mfpu,-mhard-floatโ generates code containing floating-point instructions. This is the default ๐-mno-fpu,-msoft-floatโ generates code containing library calls for floating-point ๐ซถ
-msoft-floatchanges the calling convention in the output file, so it's only useful if you compile all of a program with this option ๐ญ You also need to compilelibgcc.a, the library that comes with GCC, with-msoft-floatin order for this to work ๐ฅ
-mcpu=cpu_typeโ sets the instruction set, register set, and instruction scheduling parameters for machine typecpu_typeโจ Supported values forcpu_typearemcm,gr5, andgr6.mcmis a synonym ofgr5, kept around for backward compatibility.- By default (unless configured otherwise), GCC generates code for the GR5 variant of the Visium architecture.
- With
-mcpu=gr6, GCC generates code for the GR6 variant of the Visium architecture. The only difference from GR5 code is that the compiler will generate block move instructions.
-mtune=cpu_typeโ sets the instruction scheduling parameters for machine typecpu_type, but doesn't 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, registers r24 to r31 can't be accessed in this mode. On the GR6, only registers r29 to r31 are affected.
๐ VMS Options
These -m options are defined for the VMS implementations ๐
-mvms-return-codesโ returns VMS condition codes frommain. The default is to return POSIX-style condition (e.g. error) codes ๐ง-mdebug-main=prefixโ flags the first routine whose name starts withprefixas the main routine for the debugger ๐-mmalloc64โ defaults to 64-bit memory allocation routines ๐ฅ-mpointer-size=sizeโ sets the default size of pointers ๐ Possible options forsizeare32orshortfor 32 bit pointers,64orlongfor 64 bit pointers, andnofor supporting only 32 bit pointers. The latter option disablespragma pointer_size๐
๐ VxWorks Options
The options in this section are defined for all VxWorks targets โจ Options specific to the target hardware are listed with the other options for that target ๐ซถ
-mrtpโ GCC can generate code for both VxWorks kernels and real time processes (RTPs) ๐ This option switches from the former to the latter. It also defines the preprocessor macro__RTP__๐ฆ-non-staticโ links an RTP executable against shared libraries rather than static libraries ๐ธ The options-staticand-sharedcan also be used for RTPs, and-staticis the default ๐ง-Bstatic,-Bdynamicโ these options are passed down to the linker ๐ They're defined for compatibility with Diab ๐-Xbind-lazyโ enables lazy binding of function calls โญ This option is equivalent to-Wl,-z,nowand is defined for compatibility with Diab ๐-Xbind-nowโ disables lazy binding of function calls ๐ This option is the default and is defined for compatibility with Diab ๐
๐ x86 Options
These -m options are defined for the x86 family of computers ๐
-march=cpu-typeโ generates instructions for the machine typecpu-type๐ฅ Unlike-mtune=cpu-type, which merely tunes the generated code for the specifiedcpu-type,-march=cpu-typeallows GCC to generate code that may not run at all on processors other than the one indicated ๐ญ Specifying-march=cpu-typeimplies-mtune=cpu-typeโจ
The choices for cpu-type are:
nativeโ selects the CPU to generate code for at compilation time by determining the processor type of the compiling machine ๐ง Using-march=nativeenables all instruction subsets supported by the local machine, so the result might not run on different machines ๐ Using-mtune=nativeproduces code optimized for the local machine under the constraints of the selected instruction set ๐x86-64โ a generic CPU with 64-bit extensions ๐i386โ the original Intel i386 CPU ๐ฆi486โ the Intel i486 CPU. (No scheduling is implemented for this chip.) ๐i586,pentiumโ the Intel Pentium CPU with no MMX support ๐ธlakemontโ the Intel Lakemont MCU, based on the Intel Pentium CPU ๐งpentium-mmxโ the Intel Pentium MMX CPU, based on the Pentium core with MMX instruction set support ๐pentiumproโ the Intel Pentium Pro CPU ๐i686โ when used with-march, the Pentium Pro instruction set is used, so the code runs on all i686 family chips. When used with-mtune, it has the same meaning asgeneric๐pentium2โ the Intel Pentium II CPU, based on the Pentium Pro core with MMX instruction set support โญpentium3,pentium3mโ the Intel Pentium III CPU, based on the Pentium Pro core with MMX and SSE instruction set support ๐ฅpentium-mโ the Intel Pentium M, a low-power version of the Intel Pentium III CPU with MMX, SSE and SSE2 instruction set support. Used by Centrino notebooks ๐ซถpentium4,pentium4mโ the Intel Pentium 4 CPU with MMX, SSE and SSE2 instruction set support ๐prescottโ an improved version of the Intel Pentium 4 CPU with MMX, SSE, SSE2 and SSE3 instruction set support ๐noconaโ an improved version of the Intel Pentium 4 CPU with 64-bit extensions, MMX, SSE, SSE2 and SSE3 instruction set support ๐
core2โ โจ Intel Core 2 CPU bestie! It comes with 64-bit extensions plus MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support ๐nehalemโ ๐ Intel Nehalem CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and POPCNT instruction set support ๐westmereโ ๐ฆ Intel Westmere CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES and PCLMUL instruction set support ๐sandybridgeโ ๐ธ Intel Sandy Bridge CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AES and PCLMUL instruction set support, and it's giving main character ๐ivybridgeโ ๐ง Intel Ivy Bridge CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AES, PCLMUL, FSGSBASE, RDRND and F16C instruction set support โจhaswellโ ๐ Intel Haswell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2 and F16C instruction set support ๐ฅbroadwellโ ๐ Intel Broadwell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED ADCX and PREFETCHW instruction set support ๐skylakeโ โญ Intel Skylake CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC and XSAVES instruction set support ๐ซถbonnellโ ๐ธ Intel Bonnell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support ๐ฆsilvermontโ ๐ Intel Silvermont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL and RDRND instruction set support โจgoldmontโ ๐ Intel Goldmont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT and FSGSBASE instruction set support ๐goldmont-plusโ ๐ฅ Intel Goldmont Plus CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX and UMIP instruction set support ๐งtremontโ ๐ฆ Intel Tremont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, UMIP, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, CLDEMOTE and WAITPKG instruction set support ๐knlโ ๐ Intel Knight's Landing CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, PREFETCHWT1, AVX512F, AVX512PF, AVX512ER and AVX512CD instruction set support ๐knmโ ๐ Intel Knights Mill CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, PREFETCHWT1, AVX512F, AVX512PF, AVX512ER, AVX512CD, AVX5124VNNIW, AVX5124FMAPS and AVX512VPOPCNTDQ instruction set support ๐ญskylake-avx512โ ๐ธ Intel Skylake Server CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ and AVX512CD instruction set support ๐ซถcannonlakeโ ๐ Intel Cannonlake Server CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA and UMIP instruction set support ๐ฅicelake-clientโ ๐ง Intel Icelake Client CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ and VAES instruction set support ๐icelake-serverโ ๐ Intel Icelake Server CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ, VAES, PCONFIG and WBNOINVD instruction set support ๐cascadelakeโ ๐ฆ Intel Cascadelake CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD and AVX512VNNI instruction set support โญ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 and CLWB instruction set support ๐ธ
k6โ ๐ AMD K6 CPU with MMX instruction set support ๐k6-2,k6-3โ ๐ Improved versions of AMD K6 CPU 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โ ๐ Improved AMD Athlon CPU with MMX, 3DNow!, enhanced 3DNow! and full SSE instruction set support ๐k8,opteron,athlon64,athlon-fxโ ๐ฆ Processors based on the AMD K8 core with x86-64 instruction set support, including the AMD Opteron, Athlon 64, and Athlon 64 FX processors. (This supersets MMX, SSE, SSE2, 3DNow!, enhanced 3DNow! and 64-bit instruction set extensions.) ๐ซถk8-sse3,opteron-sse3,athlon64-sse3โ ๐ง Improved versions of 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, PCL_MUL, 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, PCL_MUL, 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, PCL_MUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.) ๐bdver4โ ๐ง AMD Family 15h core based CPUs with x86-64 instruction set support. (This supersets BMI, BMI2, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, AVX2, XOP, LWP, AES, PCL_MUL, 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, PCL_MUL, 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, PCL_MUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, 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 includes MOVBE, F16C, BMI, AVX, PCL_MUL, 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, dealt in same way as i486 with additional MMX instruction set support ๐winchip2โ ๐ IDT WinChip 2 CPU, dealt in same way as i486 with additional MMX and 3DNow! instruction set support ๐ฅc3โ ๐ VIA C3 CPU with MMX and 3DNow! instruction set support. (No scheduling is implemented for this chip.) ๐ญc3-2โ ๐ VIA C3-2 (Nehemiah/C5XL) CPU with MMX and SSE instruction set support. (No scheduling is implemented for this chip.) ๐c7โ ๐ฆ VIA C7 (Esther) CPU with MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.) ๐ซถsamuel-2โ bestie, this is the VIA Eden Samuel 2 CPU ๐ธ It's got MMX and 3DNow! instruction set support. (No scheduling is implemented for this chip.)nehemiahโ the VIA Eden Nehemiah CPU โจ MMX and SSE instruction set support, all yours. (No scheduling is implemented for this chip.)estherโ the VIA Eden Esther CPU ๐ It brings MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.)eden-x2โ the VIA Eden X2 CPU ๐ฆ x86-64, MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.)eden-x4โ the VIA Eden X4 CPU ๐ It's giving 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โ the generic VIA Nano CPU ๐ง x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-1000โ the VIA Nano 1xxx CPU ๐ x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-2000โ the VIA Nano 2xxx CPU ๐ x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-3000โ the VIA Nano 3xxx CPU ๐ x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.)nano-x2โ the VIA Nano Dual Core CPU ๐ซถ x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.)nano-x4โ the VIA Nano Quad Core CPU ๐ฅ x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.)geodeโ the AMD Geode embedded processor ๐ MMX and 3DNow! instruction set support.
๐ -mtune=cpu-type ๐
Okay so -mtune=cpu-type tunes basically everything about the generated code for that chip โจ The one exception is the ABI and the set of available instructions. Picking a specific cpu-type schedules things nicely for that particular chip, but the compiler won't generate any code that can't run on the default machine type unless you also use a -march=cpu-type option. For example, if GCC is configured for i686-pc-linux-gnu, then -mtune=pentium4 makes code tuned for Pentium 4 that still runs on i686 machines ๐
The choices for cpu-type are the same as for -march. On top of that, -mtune supports 2 extra choices for cpu-type ๐ฆ
genericโ produce code optimized for the most common IA32/AMD64/EM64T processors ๐ธ If you know the CPU your code will run on, use the matching-mtuneor-marchoption instead of-mtune=generic. But if you don't know exactly what CPU your users will have, this is the one to pick.- 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 shift to reflect the processors that are most common when that version of GCC is released ๐ซถ
- There is no
-march=genericoption, because-marchis about the instruction set the compiler can use, and there's no generic instruction set that works for every processor.-mtune, on the other hand, is about the processor (or, in this case, the collection of processors) the code is optimized for ๐
intelโ produce code optimized for the most current Intel processors, which are Haswell and Silvermont for this version of GCC โจ If you know the CPU your code will run on, use the matching-mtuneor-marchoption instead of-mtune=intel. But if you want your app to perform well on both Haswell and Silvermont, this is your option ๐ฅ- As new Intel processors get deployed, the behavior of this option will change. So if you upgrade to a newer version of GCC, the code generation controlled by this option will reflect the most current Intel processors at the time that version is released ๐
- There is no
-march=inteloption, because-marchis about the instruction set the compiler can use, and there's no common instruction set that works for every processor.-mtuneis about the processor (or collection of processors) the code is optimized for ๐ง
๐ -mcpu=cpu-type ๐
This one is a deprecated synonym for -mtune ๐ Use -mtune instead, bestie.
๐ฆ -mfpmath=unit ๐ฆ
Generate floating-point arithmetic for the selected unit ๐ฅ The choices for unit are:
387โ use the standard 387 floating-point coprocessor, which is present on most chips and emulated otherwise ๐ Code compiled with this option runs almost everywhere. The temporary results are computed in 80-bit precision instead of the precision the type specifies, so the results can come out slightly different from most other chips. See-ffloat-storefor a more detailed description.- This is the default choice for non-Darwin x86-32 targets โจ
sseโ use scalar floating-point instructions from the SSE instruction set ๐ธ This instruction set is supported by Pentium III and newer chips, and in the AMD line by Athlon-4, Athlon XP and Athlon MP chips. The earlier version of the SSE instruction set only supports single-precision arithmetic, so double and extended-precision arithmetic still get done using 387. A later version, present only in Pentium 4 and AMD x86-64 chips, supports double-precision arithmetic too ๐ซถ- For the x86-32 compiler, you must use
-march=cpu-type,-msseor-msse2switches to enable SSE extensions and make this option work. For the x86-64 compiler, these extensions are enabled by default ๐ - The resulting code should be considerably faster in most cases and avoid the numerical instability problems of 387 code. But it may break some existing code that expects temporaries to be 80 bits ๐
- This is the default choice for the x86-64 compiler, Darwin x86-32 targets, and the default choice for x86-32 targets with the SSE2 instruction set when
-ffast-mathis enabled ๐
- For the x86-32 compiler, you must use
sse,387,sse+387,bothโ attempt to use both instruction sets at once ๐ This effectively doubles the number of available registers, and on chips with separate execution units for 387 and SSE, it can double the execution resources too. Use this option with care, though, because it is still experimental. The GCC register allocator doesn't model separate functional units well, which can lead to unstable performance ๐
๐ง -masm=dialect ๐ง
Output assembly instructions using the selected dialect โจ This also affects which dialect is used for basic "asm" and extended "asm". The supported choices (in dialect order) are att or intel. The default is att. Darwin does not support intel ๐
๐ -mieee-fp and -mno-ieee-fp ๐
Control whether or not the compiler uses IEEE floating-point comparisons ๐ These correctly handle the case where the result of a comparison is unordered.
๐ -m80387 and -mhard-float ๐
Generate output containing 80387 instructions for floating point ๐ฅ
๐ซถ -mno-80387 and -msoft-float ๐ซถ
Generate output containing library calls for floating point ๐ธ
Warning: the requisite libraries are not part of GCC ๐ญ Normally the facilities of the machine's usual C compiler are used, but this 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 ๐
Do not use the FPU registers for return values of functions ๐
The usual calling convention has functions return values of types "float" and "double" in an FPU register, even if there is no FPU. The idea is that the operating system should emulate an FPU โจ The option -mno-fp-ret-in-387 causes those values to be returned in ordinary CPU registers instead ๐ฆ
๐
-mno-fancy-math-387 ๐
Some 387 emulators don't support the "sin", "cos" and "sqrt" instructions for the 387 ๐ Specify this option to avoid generating those instructions. This option gets overridden when -march indicates that the target CPU always has an FPU, so the instruction doesn't need emulation. These instructions aren't generated unless you also use the -funsafe-math-optimizations switch ๐
๐ -malign-double and -mno-align-double ๐
Control whether GCC aligns "double", "long double", and "long long" variables on a two-word boundary or a one-word boundary ๐ Aligning "double" variables on a two-word boundary produces code that runs somewhat faster on a Pentium, at the expense of more memory โจ
On x86-64, -malign-double is enabled by default ๐ซถ
Warning: if you use the -malign-double switch, structures containing the above types are aligned differently than the published application binary interface specifications for the x86-32. They are not binary compatible with structures in code compiled without that switch ๐ญ
๐ง -m96bit-long-double and -m128bit-long-double ๐ง
These switches control the size of the "long double" type ๐ The x86-32 application binary interface specifies the size to be 96 bits, so -m96bit-long-double is the default in 32-bit mode.
Modern architectures (Pentium and newer) prefer "long double" to be aligned to an 8- or 16-byte boundary. In arrays or structures that conform to the ABI, that's not possible. So specifying -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 specifies that "long double" is aligned on a 16-byte boundary ๐
Notice that neither of these options enables any extra precision over the x87 standard of 80 bits for a "long double" ๐
๐ Warning: okay bestie, if you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables, as well as modifying the function calling convention for functions takinglong double. Hence they are not 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 โจ. At 64 bits,long doubleis equivalent todouble, which is the default for the 32-bit Bionic C library ๐ธ. At 128 bits,long doubleis equivalent to__float128, which is the default for the 64-bit Bionic C library ๐.
๐ Warning: same energy as before, bestie. If you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables, as well as modifying the function calling convention for functions takinglong double. Hence they are not binary-compatible with code compiled without that switch. ๐
-malign-data=typeโ this one controls how GCC aligns variables ๐ฆ. The supported values fortypeare:compatuses an increased alignment value ๐compatibleuses GCC 4.8 and earlier ๐abiuses the alignment value specified by the psABI ๐cachelineuses an increased alignment value to match the cache line size ๐ง
compat is the default, so you're good unless you're asking for something spicy ๐.
-mlarge-data-threshold=thresholdโ when-mcmodel=mediumis specified, data objects larger thanthresholdget placed in the large data section ๐. This value has to be the same across all objects linked into the binary, and it defaults to65535โญ.-mrtdโ this switches to a different function-calling convention ๐. Functions that take a fixed number of arguments return with theret numinstruction, which pops their arguments while returning ๐ฅ. That saves one instruction in the caller, since the caller doesn't have to pop the arguments itself โจ.
You can make one specific function use this calling sequence with the function attribute stdcall ๐ซถ. You can also override -mrtd for a function by using the function attribute cdecl ๐.
๐ Warning: this calling convention is incompatible with the one normally used on Unix, so you cannot use it if you need to call libraries compiled with the Unix compiler ๐ญ.
Also, you must provide function prototypes for all functions that take variable numbers of arguments (including printf), otherwise incorrect code gets generated for calls to those functions ๐. And seriously incorrect code results if you call a function with too many arguments ๐. Normally, extra arguments are harmlessly ignored, but not here, bestie ๐ซ .
-mregparm=numโ this 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โ this 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โ this returns 8-byte vectors in memory instead of MMX registers ๐งธ. It's the default on Solaris 8 and 9 and VxWorks, so it matches the ABI of the Sun Studio compilers up until version 12 ๐. Later compiler versions (starting with Studio 12 Update 1) follow the ABI used by other x86 targets, which is the default on Solaris 10 and later โจ.
Only use this option if you need to stay compatible with existing code produced by those previous compiler versions or older versions of GCC ๐.
-mpc32,-mpc64,-mpc80โ these set the 80387 floating-point precision to 32, 64, or 80 bits ๐ฅ.-mpc32rounds the significands of floating-point results to 24 bits (single precision) ๐ธ-mpc64rounds them to 53 bits (double precision) ๐ฆ-mpc80rounds them to 64 bits (extended double precision), which is the default ๐
When you use this option, higher-precision floating-point operations aren't available to the programmer unless you set the FPU control word explicitly ๐ .
Setting the rounding to less than the default 80 bits can speed some programs up by 2% or more โญ. But heads up: some mathematical libraries assume extended-precision (80-bit) floating-point operations are enabled by default ๐ญ. Routines in those libraries could suffer significant loss of accuracy, typically through so-called "catastrophic cancellation", when this option sets the precision below extended precision ๐.
-mstackrealignโ realigns the stack at entry ๐ง. On x86, this option generates an alternate prologue and epilogue that realigns the run-time stack if necessary ๐. It lets legacy code that keeps 4-byte stack alignment mix with modern code that keeps 16-byte stack alignment for SSE compatibility ๐. You can also check out the attributeforce_align_arg_pointer, which applies to individual functions ๐ซถ.-mpreferred-stack-boundary=numโ this 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) โจ.
๐ Warning: when generating code for the x86-64 architecture with SSE extensions disabled, -mpreferred-stack-boundary=3 can be used to keep the stack boundary aligned to an 8 byte boundary ๐. But the x86-64 ABI requires 16 byte stack alignment, so this is ABI incompatible ๐ญ. It's only meant for a controlled environment where stack space is an important limitation ๐งธ.
This option leads to wrong code when functions compiled with 16 byte stack alignment (like functions from a standard library) get called with a misaligned stack ๐. In that case, SSE instructions may lead to misaligned memory access traps ๐ซ . Variable arguments are also handled incorrectly for 16 byte aligned objects (including x87 long double and __int128), which leads to wrong results ๐ญ. You must build all modules with -mpreferred-stack-boundary=3, including any libraries. That includes the system libraries and startup modules ๐ซถ.
-mincoming-stack-boundary=numโ this assumes the incoming stack is aligned to a 2 raised tonumbyte boundary ๐ฆ. If you don't specify-mincoming-stack-boundary, the one specified by-mpreferred-stack-boundarygets used ๐ .
On Pentium and Pentium Pro, double and long double values should be aligned to an 8-byte boundary (see -malign-double), or they'll suffer significant run time performance penalties ๐ข. On Pentium III, the Streaming SIMD Extension (SSE) data type __m128 may not work properly if it isn't 16-byte aligned ๐.
To make sure these values are properly aligned on the stack, the stack boundary has to be as aligned as whatever value gets stored on the stack needs ๐ธ. Every function also has to be generated so it keeps the stack aligned ๐. So calling a function compiled with a higher preferred stack boundary from a function compiled with a lower one will most likely misalign the stack ๐ฌ. It's recommended that libraries which use callbacks always use the default setting ๐ซถ.
This extra alignment eats up extra stack space and generally increases code size ๐. Code that's sensitive to stack space usage, like embedded systems and operating system kernels, may want to lower the preferred alignment to -mpreferred-stack-boundary=2 ๐ง.
- The big instruction-set list โ these switches enable the use of instructions in the following extended instruction sets, and each one has a matching
-mno-option to turn it off ๐. Here's the full lineup, bestie, copied exactly:
-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
-mgfni
-mvaes
-mwaitpkg
-mvpclmulqdq
-mavx512bitalg
-mmovdiri
-mmovdir64b
-mavx512vpopcntdq
-mavx5124fmaps
-mavx512vnni
-mavx5124vnniw
-mcldemote
The instruction sets these flags cover are 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, AVX512VPOPCNTDQ, AVX5124FMAPS, AVX512VNNI, AVX5124VNNIW, and CLDEMOTE extended instruction sets โจ.
These extensions are also available as built-in functions, so check out x86 Built-in Functions for the details of which functions get enabled and disabled by these switches ๐งธ.
To generate SSE/SSE2 instructions automatically from floating-point code (as opposed to 387 instructions), see -mfpmath=sse ๐ฆ.
GCC basically benches the SSEx instructions when -mavx is used ๐ซ . Instead, it generates new AVX instructions, or AVX equivalents for all SSEx instructions, when needed ๐
.
okay so these options let GCC use the extended instructions in the code it generates ๐ซถ, even without -mfpmath=sse. โจ bestie, apps 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 needs to be compiled without these options ๐. no skipping this one ๐
-mdump-tune-featuresโ this tells GCC to dump the names of the x86 performance tuning features and their default settings ๐. You can use those names inside-mtune-ctrl=feature-list๐.-mtune-ctrl=feature-listโ the fine-grain control freak of x86 code generation features ๐๏ธ.feature-listis a comma separated list of feature names (see also-mdump-tune-features). If a name is not preceded by^, that feature gets turned on. If it is preceded by^, it gets turned off ๐.
Heads up, bestie ๐จ: this one is intended for GCC developers. Using it may lead to code paths that aren't covered by testing, and it can potentially result in 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 a"cld"instruction in the prologue of functions that use string instructions ๐งน. String instructions depend on the DF flag to pick between autoincrement or autodecrement mode. The ABI says DF should be cleared on function entry, but some operating systems don't clear it in their exception dispatchers ๐. So the exception handler can get invoked with DF set, which leads to 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. Generation of"cld"instructions can be suppressed with the-mno-cldcompiler option in this case.-mvzeroupperโ emits a"vzeroupper"instruction before control flow leaves the function, to minimize the AVX to SSE transition penalty ๐. It also removes unnecessary"zeroupper"intrinsics ๐งผ.-mprefer-avx128โ uses 128-bit AVX instructions instead of 256-bit AVX instructions in the auto-vectorizer ๐ฆ.-mprefer-vector-width=optโ usesopt-bit vector width in instructions instead of the default on the selected platform ๐. The options are:noneโ no extra limitations applied to GCC other than what the selected platform already defines ๐.128โ prefer 128-bit vector width for instructions ๐.256โ prefer 256-bit vector width for instructions ๐.512โ prefer 512-bit vector width for instructions ๐.
-mcx16โ lets GCC generate"CMPXCHG16B"instructions in 64-bit code to do compare-and-exchange operations on 16-byte aligned 128-bit objects ๐ฅ. It's super useful for atomic updates of data structures bigger than one machine word. The compiler uses this instruction to implement__syncBuiltins. However, for__atomicBuiltins operating on 128-bit integers, a library call is always used ๐.-msahfโ enables generation of"SAHF"instructions in 64-bit code ๐ง . Early Intel Pentium 4 CPUs with Intel 64 support, prior to the introduction of Pentium 4 G1 step in December 2005, lacked the"LAHF"and"SAHF"instructions that AMD64 supports ๐ญ. These are load and store instructions, respectively, for certain status flags. In 64-bit mode, the"SAHF"instruction is used to optimize"fmod","drem", and"remainder"built-in functions. See Other Builtins for details ๐.-mmovbeโ enables use of the"movbe"instruction to implement__builtin_bswap32and__builtin_bswap64๐.-mshstkโ enables shadow stack built-in functions from x86 Control-flow Enforcement Technology (CET) ๐ก๏ธ.-mcrc32โ the built-in functions"__builtin_ia32_crc32qi","__builtin_ia32_crc32hi","__builtin_ia32_crc32si"and"__builtin_ia32_crc32di"will generate the"crc32"machine instruction ๐ข.-mrecipโ enables use of"RCPSS"and"RSQRTSS"instructions (and their vectorized variants"RCPPS"and"RSQRTPS") with an extra Newton-Raphson step for precision ๐ฏ. This swaps out"DIVSS"and"SQRTSS"(and their vectorized variants) for single-precision floating-point arguments. These instructions are only generated when-funsafe-math-optimizationsis enabled together with-ffinite-math-onlyand-fno-trapping-math. Note that while the throughput of the sequence is higher than the throughput of the non-reciprocal instruction, the precision of the sequence can be decreased by up to 2 ulp (i.e. the inverse of 1.0 equals 0.99999994) ๐.
Note that GCC already implements "1.0f/sqrtf(x)" in terms of "RSQRTSS" (or "RSQRTPS") with -ffast-math (or the above option combination), so it doesn't need -mrecip ๐
.
Also note that GCC already emits the above sequence with the additional Newton-Raphson step for vectorized single-float division and vectorized "sqrtf(x)" with -ffast-math (or the above option combination), so it doesn't need -mrecip either โจ.
-mrecip=optโ 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. The choices are:allโ enable all estimate instructions.defaultโ enable the default instructions, equivalent to-mrecip.noneโ disable all estimate instructions, equivalent to-mno-recip.divโ enable the approximation for scalar division.vec-divโ enable the approximation for vectorized division.sqrtโ enable the approximation for scalar square root.vec-sqrtโ enable the approximation for vectorized square root.
So, for example, -mrecip=all,!sqrt enables all of the reciprocal approximations except for square root ๐ง.
-mveclibabi=typeโ picks the ABI type for vectorizing intrinsics using an external library ๐. Supported values fortypearesvmlfor the Intel short vector math library andacmlfor the AMD math core library. To use this option, both-ftree-vectorizeand-funsafe-math-optimizationshave to be enabled, and an SVML or ACML ABI-compatible library must be specified at link time.
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 matching function type when -mveclibabi=svml is used.
It also emits __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 when -mveclibabi=acml is used ๐ธ.
-mabi=nameโ generates code for the specified calling convention ๐ค. Permissible values aresysvfor the ABI used on GNU/Linux and other systems, andmsfor the Microsoft ABI. The default is the Microsoft ABI when targeting Microsoft Windows, and the SysV ABI on all other systems. You can control this behavior for specific functions with the function attributesms_abiandsysv_abi๐.-mforce-indirect-callโ forces all calls to functions to be indirect ๐. This is useful with Intel Processor Trace, where it gives more precise timing information for function calls โฑ๏ธ.-mmanual-endbrโ inserts an ENDBR instruction at function entry only via the"cf_check"function attribute ๐ฏ. This is useful when used with-fcf-protection=branch, to control ENDBR insertion at the function entry.-mcall-ms2sysv-xloguesโ because the 64-bit ABIs differ, any Microsoft ABI function that calls a System V ABI function has to treat RSI, RDI and XMM6-15 as clobbered ๐งจ. By default, the code for saving and restoring these registers is emitted inline, which makes the prologues and epilogues pretty lengthy ๐ฉ. Using-mcall-ms2sysv-xloguesemits prologues and epilogues that use stubs in the static portion of libgcc to do those saves and restores. That shrinks function size at the cost of a few extra instructions ๐ฆ.-mtls-dialect=typeโ generates code to access thread-local storage using thegnuorgnu2conventions ๐งต.gnuis the conservative default.gnu2is more efficient, but it may add compile- and run-time requirements that cannot be satisfied on all systems โ ๏ธ.-mpush-args,-mno-push-argsโ uses PUSH operations to store outgoing parameters ๐ฅ. This method is shorter and usually just as fast as the method using SUB/MOV operations, and it's enabled by default. In some cases, disabling it may improve performance because of improved scheduling and reduced dependencies ๐.-maccumulate-outgoing-argsโ if enabled, the maximum amount of space required for outgoing arguments is computed in the function prologue ๐งฎ. This is faster on most modern CPUs because of reduced dependencies, improved scheduling, and reduced stack usage when the preferred stack boundary is not equal to 2. The drawback is a notable increase in code size. This switch implies-mno-push-args.-mthreadsโ supports thread-safe exception handling on MinGW ๐งต. Programs that rely on thread-safe exception handling must compile and link all code with the-mthreadsoption. When compiling,-mthreadsdefines-D_MT. When linking, it links in a special thread helper library,-lmingwthrd, which cleans up per-thread exception-handling data ๐ซง.-mms-bitfields,-mno-ms-bitfieldsโ enable or disable bit-field layout compatible with the native Microsoft Windows compiler ๐ช.
okay so bestie, listen up ๐๐ if you slap "packed" on a structure, or throw bit-fields in there, the Microsoft ABI might lay that struct out totally differently from how GCC normally does it ๐ ngl this matters a LOT when you're passing packed data between GCC-compiled functions and the native Microsoft compiler, whether that's through a function call or data sitting in a file. you might literally need to be able to access either format ๐
This option is turned on by default for Microsoft Windows targets ๐ชโจ and you can also control it locally with variable or type attributes. For the full tea, check out x86 Variable Attributes and x86 Type Attributes ๐ฆ
The Microsoft struct layout algorithm is actually pretty simple... EXCEPT for bit-field packing ๐ญ Whether a bit-field can straddle a storage-unit boundary, plus the padding and alignment of structure members, are determined by these rules:
- Structure members are stored sequentially, in the order they're declared. The first member sits at the lowest memory address and the last member sits at the highest ๐ง
- Every data object has an alignment requirement ๐. For everything except structures, unions, and arrays, that requirement is either the size of the object or the current packing size (set with either the "aligned" attribute or the "pack" pragma), 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 their integral types are the same size, and the next bit-field fits in the current allocation unit without crossing the boundary imposed by the common alignment requirements of the bit-fields ๐
MSVC interprets zero-length bit-fields in the following ways ๐คจ
- If a zero-length bit-field is inserted between two bit-fields that would normally get coalesced, the bit-fields are not coalesced anymore ๐
For example:
struct
{
unsigned long bf_1 : 12;
unsigned long : 0;
unsigned long bf_2 : 12;
} t1;
The size of "t1" is 8 bytes with the zero-length bit-field. If the zero-length bit-field were removed, "t1"'s size would be 4 bytes.
- If a zero-length bit-field is inserted after a bit-field, "foo", and the alignment of the zero-length bit-field is greater than the member that follows it, "bar", then "bar" is aligned as the type of the zero-length bit-field ๐ฆ
For example:
struct
{
char foo : 4;
short : 0;
char bar;
} t2;
struct
{
char foo : 4;
short : 0;
double bar;
} t3;
For "t2", "bar" is placed at offset 2, rather than offset 1. Accordingly, the size of "t2" is 4. For "t3", the zero-length bit-field does not affect the alignment of "bar" or, as a result, the size of the structure ๐ธ
Taking this into account, it is important to note the following:
- If a zero-length bit-field follows a normal bit-field, the type of the zero-length bit-field may affect the alignment of the structure as a whole. For example, "t2" has a size of 4 bytes, since the zero-length bit-field follows a normal bit-field and is of type short ๐
- Even if a zero-length bit-field is not followed by a normal bit-field, it may still affect the alignment of the structure:
struct
{
char foo : 6;
long : 0;
} t4;
Here, "t4" takes up 4 bytes ๐
- Zero-length bit-fields following non-bit-field members are ignored:
struct
{
char foo;
long : 0;
char bar;
} t5;
Here, "t5" takes up 2 bytes โจ
-mno-align-stringopsโ Don't align the destination of inlined string operations. This switch shrinks code size and boosts performance when the destination is already aligned but GCC doesn't know it ๐ง-minline-all-stringopsโ By default GCC only inlines string operations when the destination is known to be aligned to at least a 4-byte boundary. This turns on more inlining, which increases code size, but it may improve performance of code that relies on fast "memcpy", "strlen", and "memset" for short lengths ๐-minline-stringops-dynamicallyโ For string operations of unknown size, use run-time checks with inline code for small blocks and a library call for large blocks ๐ฅ-mstringop-strategy=algโ Override GCC's internal decision heuristic for which algorithm to use when inlining string operations. The allowed values for alg are:rep_byte,rep_4byte,rep_8byteโ Expand using the i386repprefix of the specified size ๐byte_loop,loop,unrolled_loopโ Expand into an inline loop ๐libcallโ Always use a library call ๐
-mmemcpy-strategy=strategyโ Override the internal decision heuristic that decides whether "__builtin_memcpy" should be inlined, and which inline algorithm to use when the expected size of the copy operation is known. The strategy is a comma-separated list ofalg:max_size:dest_aligntriplets. The alg is one of the values from-mstringop-strategy, and max_size is the max byte size that inline algorithm alg is allowed for. For the last triplet, the max_size must be-1. The max_size values in the list must be specified in increasing order. The minimal byte size for alg is 0 for the first triplet, andmax_size + 1of the preceding range for the rest ๐-mmemset-strategy=strategyโ Similar to-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, which might make debugging harder ๐-mtls-direct-seg-refs,-mno-tls-direct-seg-refsโ Controls whether TLS variables may be accessed with offsets from the TLS segment register (%gsfor 32-bit,%fsfor 64-bit), or whether the thread base pointer must be added. Whether or not this is valid depends on the operating system, and on whether it maps the segment to cover the entire TLS area. For systems that use the GNU C Library, the default is on ๐ง-msse2avx,-mno-sse2avxโ Tell the assembler to encode SSE instructions with the VEX prefix. The option-mavxturns this on by default โจ-mfentry,-mno-fentryโ If profiling is active (-pg), put the profiling counter call before the prologue. Note: On x86 architectures, the attributems_hook_prologueisn't possible at the moment for-mfentryand-pgโ ๏ธ-mrecord-mcount,-mno-record-mcountโ If profiling is active (-pg), generate a__mcount_locsection that contains pointers to each profiling call. This is useful for automatically patching and out calls ๐ง-mnop-mcount,-mno-nop-mcountโ If profiling is active (-pg), generate the calls to the profiling functions as NOPs. This is useful when they should be patched in later dynamically. This is likely only useful together with-mrecord-mcount๐ฆ-minstrument-return=typeโ Instrument function exit in-pg -mfentryinstrumented functions with a call to the specified function. This only instruments true returns ending withret, but not sibling calls ending withjump. Valid types are:noneโ don't instrumentcallโ generate a call to__return__nop5โ generate a 5 byte nop
-mrecord-return,-mno-record-returnโ Generate a__return_locsection pointing to all return instrumentation code ๐-mfentry-name=nameโ Set the name of the__fentry__symbol that gets called at function entry for-pg -mfentryfunctions ๐-mfentry-section=nameโ Set the name of the section where-mrecord-mcountcalls get recorded (default__mcount_loc) ๐ธ-mskip-rax-setup,-mno-skip-rax-setupโ When generating code for the x86-64 architecture with SSE extensions disabled,-mskip-rax-setupcan be used to skip setting up the RAX register when no variable arguments are passed in vector registers.
โ ๏ธ Warning: Since the RAX register is used to avoid unnecessarily saving vector registers on the stack when passing variable arguments, the impacts of this option are: callees may waste some stack space, misbehave, or jump to a random location. GCC 4.4 or newer don't have those issues, regardless of the RAX register value ๐ญ
-m8bit-idiv,-mno-8bit-idivโ On some processors, like Intel Atom, 8-bit unsigned integer divide is much faster than 32-bit/64-bit integer divide. This option generates a run-time check. If both the dividend and divisor are within the range of 0 to 255, 8-bit unsigned integer divide is used instead of 32-bit/64-bit integer divide ๐ฅ-mavx256-split-unaligned-load,-mavx256-split-unaligned-storeโ Split 32-byte AVX unaligned load and store operations ๐-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ Generate stack protection code using a canary at guard. Supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block (the default). This option only has an effect when-fstack-protectoror-fstack-protector-allis specified ๐ก๏ธ
With the latter choice, the options -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset furthermore specify which segment register (%fs or %gs) to use as the base register for reading the canary, and from what offset from that base register. The default for those is as specified in the relevant ABI ๐
-mgeneral-regs-onlyโ okay bestie, this one is a whole vibe ๐ It tells the compiler to stick to only the general-purpose registers. No floating-point, vector, mask, or bound registers allowed, so it's basically a minimalist era ๐ธ-mindirect-branch=choiceโ this one changes how indirect calls and jumps get handled ๐ฆ You pick one of these choices:keepis the default, and it leaves indirect calls and jumps totally unmodified ๐ซถthunkconverts them to call and return thunks โจthunk-inlineconverts them to inlined call and return thunks ๐งthunk-externconverts them to external call and return thunks that live in a separate object file ๐
You can also control this for one specific function with the function attribute indirect_branch ๐
Note that -mcmodel=large is incompatible with -mindirect-branch=thunk and -mindirect-branch=thunk-extern, 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โ same energy, but for function returns ๐ Your options are:keepis the default, and it leaves function returns unmodified ๐thunkconverts function return to a call and return thunk ๐thunk-inlineconverts function return to an inlined call and return thunk โญthunk-externconverts function return 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 that -mcmodel=large is incompatible with -mfunction-return=thunk and -mfunction-return=thunk-extern, since the thunk function may not be reachable in the large code model ๐
-mindirect-branch-registerโ forces indirect calls and jumps to go through a register, no exceptions ๐
These -m switches are supported in addition to the above on x86-64 processors in 64-bit environments ๐
-m32,-m64,-mx32,-m16,-miamcuโ these set the code generation environment ๐ซถ-m32setsint,long, and pointer types to 32 bits, and generates code that runs on any i386 system ๐ธ-m64setsintto 32 bits andlongand pointer types to 64 bits, and generates code for the x86-64 architecture ๐ For Darwin only, 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, and it requires-m32to be turned on ๐
-mno-red-zoneโ okay so the x86-64 ABI mandates a "red zone," which is a 128-byte area beyond the stack pointer that signal or interrupt handlers don't touch ๐ซง That means you can stash temporary data there without adjusting the stack pointer. This flag disables the red zone, so no more freebies ๐-mcmodel=smallโ the small code model, where the program and its symbols must be linked in the lower 2 GB of the address space ๐ธ Pointers are 64 bits, and programs can be statically or dynamically linked. This is the default code model โจ-mcmodel=kernelโ the kernel code model, where the kernel runs in the negative 2 GB of the address space ๐ This model has to be used for Linux kernel code ๐-mcmodel=mediumโ the medium model, where the program is linked in the lower 2 GB of the address space ๐ฆ Small symbols get placed there too. Symbols with sizes larger than-mlarge-data-thresholdare put into large data or BSS sections, and those can be located above 2GB. Programs can be statically or dynamically linked ๐-mcmodel=largeโ the large model, which makes no assumptions about addresses and sizes of sections ๐-maddress-mode=longโ generates code for long address mode ๐ง This is only supported for 64-bit and x32 environments, and it's the default address mode for 64-bit environments ๐-maddress-mode=shortโ generates code for short address mode ๐ This is only supported for 32-bit and x32 environments, and it's the default address mode for 32-bit and x32 environments ๐ซถ
โจ x86 Windows Options โจ
These additional options are available for Microsoft Windows targets ๐ช
-mconsoleโ this 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 it's enabled by default on those targets ๐-mdllโ available for Cygwin and MinGW targets ๐ฆ It makes a DLL, which is a dynamic link library, and it lets you pick the required runtime startup object and entry point ๐ซถ-mnop-fun-dllimportโ available for Cygwin and MinGW targets ๐ It tells the compiler to ignore thedllimportattribute ๐-mthreadโ available for MinGW targets ๐งต It turns on MinGW-specific thread support โจ-municodeโ available for MinGW-w64 targets ๐ It predefines theUNICODEpreprocessor 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 ๐ It means 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 (which is used to set executable privileges) isn't available there ๐ญ-fwritable-relocated-rdataโ available for MinGW and Cygwin targets ๐ง It puts relocated data in a read-only section into the.datasection. This is necessary for older runtimes that don't support modifying.rdatasections for pseudo-relocation ๐ซง-mpe-aligned-commonsโ available for Cygwin and MinGW targets ๐ฆ It makes sure the GNU extension to the PE file format, which permits correct alignment of COMMON variables, gets used when generating code. It's enabled by default if GCC detects that the target assembler found during configuration supports the feature โจ
See also under x86 Options for standard options ๐
โจ Xstormy16 Options โจ
These options are defined for Xstormy16 ๐งธ
-msimโ chooses startup files and a linker script that work with the simulator ๐ฎ
โจ Xtensa Options โจ
These options are supported for Xtensa targets ๐
-mconst16,-mno-const16โ enable or disable the use ofCONST16instructions for loading constant values ๐ TheCONST16instruction isn't a standard option from Tensilica. When enabled,CONST16instructions are always used in place of the standardL32Rinstructions. The use ofCONST16is enabled by default only if theL32Rinstruction isn't available ๐ซถ-mfused-madd,-mno-fused-maddโ enable or disable fused multiply/add and multiply/subtract instructions in the floating-point option ๐ฅ This has no effect if the floating-point option isn't also enabled. Turning fused instructions off forces the compiler to use separate instructions for the multiply and the add/subtract operations. That can be handy 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 isn't sensitive to the compiler's ability to combine multiply and add/subtract operations ๐-mserialize-volatile,-mno-serialize-volatileโ when enabled, GCC insertsMEMWinstructions beforevolatilememory references to guarantee sequential consistency ๐ The default is-mserialize-volatile. Use-mno-serialize-volatileto omit theMEMWinstructions ๐-mforce-no-picโ for targets like GNU/Linux, where all user-mode Xtensa code has to be position-independent code (PIC), this option disables PIC for 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 places 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 remove redundant literals and shrink code size โจ With-mtext-section-literals, literals are interspersed in the text section so they stay as close as possible to their references. This may be necessary for large assembly files. Literals for each function are placed right before that function ๐ฆ
-mauto-litpools, -mno-auto-litpools โ okay so these two decide how literal pools get handled ๐ง The default is -mno-auto-litpools, which parks literals in their own separate section of the output file unless -mtext-section-literals is used. With -mauto-litpools, the assembler sprinkles the literals right into the text section instead ๐
The compiler doesn't emit explicit .literal directives. It loads literals into registers with MOVI instead of L32R, so the assembler can handle relaxation and place literals wherever they need to go. This lets the assembler make several literal pools per function, which means it can assemble really huge functions that might not be possible with -mtext-section-literals ๐
-mtarget-align, -mno-target-align โ when this is on, GCC tells the assembler to auto-align instructions so branch penalties go down, and the tradeoff is a little less code density ๐ฆ The assembler tries to widen density instructions so branch targets and the instructions after call instructions get lined up. If there aren't enough safe density instructions before a target to line it up, no widening happens. The default is -mtarget-align. These options don't change auto-aligned instructions like LOOP. The assembler always aligns those, either by widening density instructions or by inserting NOP instructions โจ
-mlongcalls, -mno-longcalls โ when enabled, GCC tells the assembler to turn direct calls into indirect calls, unless it can figure out that the target of a direct call is inside the range the call instruction allows ๐ธ This usually happens for calls to functions in other source files. Specifically, the assembler swaps a direct CALL for an L32R followed by a CALLX. The default is -mno-longcalls. Use this one in programs where the call target could possibly be out of range. It's implemented in the assembler, not the compiler, so the assembly GCC generates still shows direct call instructions. If you want to see what's actually happening, look at the disassembled object code ๐
Heads up: the assembler uses an indirect call for every cross-file call, not just the ones that really are out of range.
zSeries Options
These are listed under
โจ ENVIRONMENT โจ
This section covers several environment variables that change how GCC operates ๐ Some of them work by specifying directories or prefixes to search when GCC is hunting for different kinds of files. Others set up other parts of the compilation environment.
Note that you can also specify places to search using options such as -B, -I and -L. These beat environment variables, and environment variables beat whatever GCC's configuration says ๐
LANG,LC_CTYPE,LC_MESSAGES,LC_ALLโ these control the localization info GCC uses so it can work with different national conventions ๐ GCC looks at the LC_CTYPE and LC_MESSAGES locale categories if it's been configured to. They can be set to any value your installation supports. A typical value isen_GB.UTF-8, which means English in the United Kingdom encoded in UTF-8.LC_CTYPEsets character classification. GCC uses it to figure out where character boundaries are in a string. That matters for some multibyte encodings that have quote and escape characters, which would otherwise be read as the end of a string or as an escape.LC_MESSAGESsets the language used in diagnostic messages.- If
LC_ALLis set, it overridesLC_CTYPEandLC_MESSAGES. Otherwise,LC_CTYPEandLC_MESSAGESdefault to the value ofLANG. If none of these are set, GCC falls back to traditional C English behavior ๐ซถ
TMPDIRโ if set, it specifies the directory for temporary files ๐ฆ GCC uses temp files to hold the output of one stage of compilation that gets used as input to the next. For example, the preprocessor's output is the input to the compiler proper.GCC_COMPARE_DEBUGโ setting this is nearly the same as passing-fcompare-debugto the compiler driver. Check that option's documentation for more details ๐GCC_EXEC_PREFIXโ if set, it specifies a prefix to use in the names of the subprograms the compiler runs ๐ง No slash gets added when the prefix is combined with a subprogram's name, but you can end your prefix with a slash if you want one.- If
GCC_EXEC_PREFIXisn't set, GCC tries to work out a sensible prefix from the pathname it was invoked with. - If GCC can't find the subprogram using the specified prefix, it checks the usual places for it.
- The default value of
GCC_EXEC_PREFIXisprefix/lib/gcc/, where prefix is the prefix of the installed compiler. In many cases, prefix is the value of "prefix" you used when you ran the configure script. - Other prefixes specified with
-Btake precedence over this one. - This prefix is also used to find files like
crt0.othat get used for linking. - The prefix also gets used in an unusual way to find the directories that header files live in. For each standard directory whose name normally begins with
/usr/local/lib/gcc(more precisely, with the value ofGCC_INCLUDE_DIR), GCC tries swapping that beginning out for the specified prefix to make an alternate directory name. So with-Bfoo/, GCC searchesfoo/barjust before it searches the standard directory/usr/local/lib/bar. If a standard directory begins with the configured prefix, then the value of prefix gets replaced byGCC_EXEC_PREFIXwhen GCC looks for header files ๐
- If
COMPILER_PATHโ its value is a colon-separated list of directories, kinda likePATH๐ธ GCC tries these directories when searching for subprograms, but only if it can't find them usingGCC_EXEC_PREFIX.LIBRARY_PATHโ its value is a colon-separated list of directories, kinda likePATH๐ When GCC is configured as a native compiler, it tries these directories when searching for special linker files, but only if it can't find them usingGCC_EXEC_PREFIX. Linking with GCC also uses these directories when hunting for ordinary libraries for the-loption. Directories specified with-Lcome first, though.LANGโ this one passes locale info to the compiler โจ One thing it's used for is deciding which character set to use when parsing character literals, string literals and comments in C and C++. When the compiler is configured to allow multibyte characters, these values ofLANGare recognized:C-JISโ recognizes JIS characters.C-SJISโ recognizes SJIS characters.C-EUCJPโ recognizes EUCJP characters.
If LANG isn't defined, or it has some other value, the compiler uses mblen and mbtowc from the default locale to recognize and translate multibyte characters ๐
Some additional environment variables affect how the preprocessor behaves ๐
CPATH,C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATHโ each variable's value is a list of directories, separated by a special character, kinda likePATH, where GCC looks for header files ๐ That special character,PATH_SEPARATOR, depends on the target and gets decided at GCC build time. For Microsoft Windows-based targets it's a semicolon, and for almost every other target it's a colon.CPATHgets searched as if you'd specified the directories with-I, but after any paths given with-Ioptions on the command line. This variable is used no matter which language is being preprocessed.- The other three variables only apply when preprocessing their particular language. Each one gets searched as if its directories were specified with
-isystem, but after any paths given with-isystemoptions on the command line. - In all of these, an empty element tells the compiler to search its current working directory. Empty elements can show up at the beginning or end of a path. For instance, if the value of
CPATHis:/special/include, that has the same effect as-I. -I/special/include๐ฆ
DEPENDENCIES_OUTPUTโ if this is set, its value says how to output Make dependencies based on the non-system header files the compiler processes ๐ซถ System header files get ignored in the dependency output. The value can just be a file name, in which case the Make rules get written to that file, and the target name gets guessed from the source file name. Or the value can take the formfile target, in which case the rules get written to file using target as the target name.- In other words, this environment variable is equivalent to combining the options
-MMand-MF, with an optional-MTswitch too ๐
- In other words, this environment variable is equivalent to combining the options
SUNPRO_DEPENDENCIESโ this is the same asDEPENDENCIES_OUTPUT, except system header files aren't ignored. So it implies-Mrather than-MM. However, the dependence on the main input file is left out ๐SOURCE_DATE_EPOCHโ if this is set, its value specifies a UNIX timestamp to use in place of the current date and time in the__DATE__and__TIME__macros, so the embedded timestamps stay reproducible โฐ- The value must be a UNIX timestamp, which is the number of seconds (excluding leap seconds) since 01 Jan 1970 00:00:00, represented in ASCII. It's identical to the output of
date +%son GNU/Linux and other systems that support the%sextension in thedatecommand. - The value should be a known timestamp, like the last modification time of the source or package, and the build process should set it ๐ฅ
- The value must be a UNIX timestamp, which is the number of seconds (excluding leap seconds) since 01 Jan 1970 00:00:00, represented in ASCII. It's identical to the output of
๐ BUGS ๐
For instructions on reporting bugs, see <file:///usr/share/doc/gcc-9/README.Bugs> ๐
โจ FOOTNOTES โจ
- okay bestie, this one is the spicy footnote ๐ถ๏ธ On some systems,
gcc -sharedneeds to build supplementary stub code so constructors actually work ๐ง On multi-libbed systems,gcc -sharedhas to select the correct support libraries to link against ๐
๐ญ Failing to supply the correct flags may lead to subtle defects!! Supplying them when they aren't necessary is innocuous, so no harm done ๐
โจ SEE ALSO โจ
gpl(7),gfdl(7),fsf-funding(7),cpp(1),gcov(1),as(1),ld(1),gdb(1)anddbx(1)๐ฆ- the Info entries for
gcc,cpp,as,ld,binutilsandgdb๐
โจ AUTHOR โจ
the whole squad of contributors is listed in the Info entry for gcc, or at http://gcc.gnu.org/onlinedocs/gcc/Contributors.html ๐ซถ they're the real MVPs ๐
โจ COPYRIGHT โจ
Copyright (c) 1988-2019 Free Software Foundation, Inc. ๐งพ
okay the legal bit, but make it cute ๐ you're totally allowed to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation. The Invariant Sections are "GNU General Public License" and "Funding Free Software", the Front-Cover texts are (a) (see below), and the Back-Cover Texts are (b) (see below). A copy of the license is included in the gfdl(7) man page ๐ธ
(a) The FSF's Front-Cover Text is:
A GNU Manual
(b) The FSF's Back-Cover Text is:
You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development.
and that's the whole tea, bestie ๐โจ this page came from gcc-9, dated 2022-05-27, and I'm obsessed with how much GCC has going on ๐
๐ง
๐ฆ where this page comes from
- ubuntu jammy: g++-9-alpha-linux-gnu 9.5.0-1ubuntu1~22.04cross1
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms