GCC(1)
โจ GCC(1) from GNU โจ
Okay bestie, welcome to the GCC(1) manual page from GNU ๐ This is the official lore for the compiler, and I'm about to spill all of it ๐ง
โจ NAME โจ
gcc - GNU project C and C++ compiler ๐ธ That's the whole vibe: the GNU project's C and C++ compiler, no cap ๐
โจ SYNOPSIS โจ
Here's the core lineup of options. The rest come later ๐
gcc [-c|-S|-E] [-std=standard]
[-g] [-pg] [-Olevel]
[-Wwarn...] [-Wpedantic]
[-Idir...] [-Ldir...]
[-Dmacro[=defn]...] [-Umacro]
[-foption...] [-mmachine-option...]
[-o outfile] [@file] infile...
Only the most useful options are listed here, so see below for the remainder ๐ And g++ takes mostly the same options as gcc, so you're basically already fluent โจ
โจ DESCRIPTION โจ
So when you invoke GCC, it normally runs the whole pipeline: preprocessing, compilation, assembly, and linking ๐ฅ The "overall options" let you hit pause at an intermediate stage. For example, -c tells it not to run the linker, so what you get back are object files straight from the assembler ๐ฆ
Other options get passed along to one or more stages. Some control the preprocessor, some control the compiler itself, and some control the assembler and linker. Most of those last ones aren't documented here, because you're basically never going to need them ๐
Most of the command-line options you can use with GCC are built for C programs. When an option only makes sense for another language (usually C++), the explanation says so out loud. 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 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, invoke GCC as g++ instead ๐
The gcc program takes options and file names as operands. Lots of options have multi-letter names, so you can't stack single-letter options together. -dv is very different from -d -v, so don't get it twisted ๐
You can mix options and other arguments, and for the most part the order doesn't matter ๐ Order does matter when you use several options of the same kind. For example, if you specify -L more than once, the directories are searched in the order you specified them. Also, where you put the -l option is significant ๐
Lots of options have long names starting with -f or with -W---for, like -fmove-loop-invariants, -Wformat, and so on โจ Most of these have both positive and negative forms, and the negative form of -ffoo is -fno-foo. This manual only documents one of the two forms, whichever one isn't the default ๐ซถ
Some options take one or more arguments, usually separated from the option name either by a space or by the equals sign (=). Unless documented otherwise, an argument can be numeric or a string. Numeric arguments are typically small unsigned decimal or hexadecimal integers, and hexadecimal arguments must begin with the 0x prefix ๐
Arguments to options that set a size threshold can be arbitrarily large decimal or hexadecimal integers, followed by a byte size suffix for a multiple of bytes. That includes kB and KiB for kilobyte and kibibyte, MB and MiB for megabyte and mebibyte, and GB and GiB for gigabyte and gigibyte, and so on ๐ In the following text, these are called byte-size arguments. For the full listing and explanation of the binary and decimal byte size prefixes, check the NIST, IEC, and other relevant national and international standards โญ
โจ OPTIONS โจ
๐ธ Option Summary
Here's a summary of all the options, grouped by type. The explanations live in the following sections, so keep scrolling, bestie ๐
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-cache-depth=n -fconstexpr-loop-limit=n
-fconstexpr-ops-limit=n -fno-elide-constructors
-fno-enforce-eh-specs -fno-gnu-keywords -fno-implicit-templates
-fno-implicit-inline-templates -fno-implement-inlines
-fms-extensions -fnew-inheriting-ctors -fnew-ttp-matching
-fno-nonansi-builtins -fnothrow-opt -fno-operator-names
-fno-optional-diags -fpermissive -fno-pretty-templates -fno-rtti
-fsized-deallocation -ftemplate-backtrace-limit=n -ftemplate-depth=n
-fno-threadsafe-statics -fuse-cxa-atexit -fno-weak -nostdinc++
-fvisibility-inlines-hidden -fvisibility-ms-compat
-fext-numeric-literals -Wabi-tag -Wcatch-value -Wcatch-value=n
-Wno-class-conversion -Wclass-memaccess -Wcomma-subscript
-Wconditionally-supported -Wno-conversion-null -Wctor-dtor-privacy
-Wno-delete-incomplete -Wdelete-non-virtual-dtor -Wdeprecated-copy
-Wdeprecated-copy-dtor -Weffc++ -Wextra-semi
-Wno-inaccessible-base -Wno-inherited-variadic-ctor
-Wno-init-list-lifetime -Wno-invalid-offsetof -Wno-literal-suffix
-Wmismatched-tags -Wmultiple-inheritance -Wnamespaces -Wnarrowing
-Wnoexcept -Wnoexcept-type -Wnon-virtual-dtor -Wpessimizing-move
-Wno-placement-new -Wplacement-new=n -Wredundant-move
-Wredundant-tags -Wreorder -Wregister -Wstrict-null-sentinel
-Wno-subobject-linkage -Wtemplates -Wno-non-template-friend
-Wold-style-cast -Woverloaded-virtual -Wno-pmf-conversions
-Wsign-promo -Wsized-deallocation -Wsuggest-final-methods
-Wsuggest-final-types -Wsuggest-override -Wno-terminate
-Wuseless-cast -Wvirtual-inheritance -Wno-virtual-move-assign
-Wvolatile -Wzero-as-null-pointer-constant
Objective-C and Objective-C++ Language Options
-fconstant-string-class=class-name -fgnu-runtime -fnext-runtime
-fno-nil-receivers -fobjc-abi-version=n -fobjc-call-cxx-cdtors
-fobjc-direct-dispatch -fobjc-exceptions -fobjc-gc -fobjc-nilcheck
-fobjc-std=objc1 -fno-local-ivars
-fivar-visibility=[public|protected|private|package]
-freplace-objc-classes -fzero-link -gen-decls -Wassign-intercept
-Wno-property-assign-default -Wno-protocol -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-urls=[auto|never|always]
-fdiagnostics-format=[text|json] -fno-diagnostics-show-option
-fno-diagnostics-show-caret -fno-diagnostics-show-labels
-fno-diagnostics-show-line-numbers -fno-diagnostics-show-cwe
-fdiagnostics-minimum-margin-width=width
-fdiagnostics-parseable-fixits -fdiagnostics-generate-patch
-fdiagnostics-show-template-tree -fno-elide-type
-fdiagnostics-path-format=[none|separate-events|inline-events]
-fdiagnostics-show-path-depths -fno-show-column
โ ๏ธ Warning Options โ ๏ธ
okay bestie, this is the warning buffet ๐ every flag in here is a way of asking GCC to speak up about sus code, so grab a plate and get ready to be overwhelmed ๐
-fsyntax-only -fmax-errors=n -Wpedantic -pedantic-errors -w
-Wextra -Wall -Wabi=n -Waddress -Wno-address-of-packed-member
-Waggregate-return -Walloc-size-larger-than=byte-size -Walloc-zero
-Walloca -Walloca-larger-than=byte-size
-Wno-aggressive-loop-optimizations -Warith-conversion -Warray-bounds
-Warray-bounds=n -Wno-attributes -Wattribute-alias=n
-Wno-attribute-alias -Wno-attribute-warning -Wbool-compare
-Wbool-operation -Wno-builtin-declaration-mismatch
-Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat
-Wc11-c2x-compat -Wc++-compat -Wc++11-compat -Wc++14-compat
-Wc++17-compat -Wc++20-compat -Wcast-align -Wcast-align=strict
-Wcast-function-type -Wcast-qual -Wchar-subscripts -Wclobbered
-Wcomment -Wconversion -Wno-coverage-mismatch -Wno-cpp
-Wdangling-else -Wdate-time -Wno-deprecated
-Wno-deprecated-declarations -Wno-designated-init
-Wdisabled-optimization -Wno-discarded-array-qualifiers
-Wno-discarded-qualifiers -Wno-div-by-zero -Wdouble-promotion
-Wduplicated-branches -Wduplicated-cond -Wempty-body
-Wno-endif-labels -Wenum-compare -Wenum-conversion -Werror
-Werror=* -Wexpansion-to-defined -Wfatal-errors -Wfloat-conversion
-Wfloat-equal -Wformat -Wformat=2 -Wno-format-contains-nul
-Wno-format-extra-args -Wformat-nonliteral -Wformat-overflow=n
-Wformat-security -Wformat-signedness -Wformat-truncation=n
-Wformat-y2k -Wframe-address -Wframe-larger-than=byte-size
-Wno-free-nonheap-object -Wno-hsa -Wno-if-not-aligned
-Wno-ignored-attributes -Wignored-qualifiers
-Wno-incompatible-pointer-types -Wimplicit -Wimplicit-fallthrough
-Wimplicit-fallthrough=n -Wno-implicit-function-declaration
-Wno-implicit-int -Winit-self -Winline -Wno-int-conversion
-Wint-in-bool-context -Wno-int-to-pointer-cast
-Wno-invalid-memory-model -Winvalid-pch -Wjump-misses-init
-Wlarger-than=byte-size -Wlogical-not-parentheses -Wlogical-op
-Wlong-long -Wno-lto-type-mismatch -Wmain -Wmaybe-uninitialized
-Wmemset-elt-size -Wmemset-transposed-args -Wmisleading-indentation
-Wmissing-attributes -Wmissing-braces -Wmissing-field-initializers
-Wmissing-format-attribute -Wmissing-include-dirs
-Wmissing-noreturn -Wno-missing-profile -Wno-multichar
-Wmultistatement-macros -Wnonnull -Wnonnull-compare
-Wnormalized=[none|id|nfc|nfkc] -Wnull-dereference -Wno-odr
-Wopenmp-simd -Wno-overflow -Woverlength-strings
-Wno-override-init-side-effects -Wpacked
-Wno-packed-bitfield-compat -Wpacked-not-aligned -Wpadded
-Wparentheses -Wno-pedantic-ms-format -Wpointer-arith
-Wno-pointer-compare -Wno-pointer-to-int-cast -Wno-pragmas
-Wno-prio-ctor-dtor -Wredundant-decls -Wrestrict
-Wno-return-local-addr -Wreturn-type -Wno-scalar-storage-order
-Wsequence-point -Wshadow -Wshadow=global -Wshadow=local
-Wshadow=compatible-local -Wno-shadow-ivar -Wno-shift-count-negative
-Wno-shift-count-overflow -Wshift-negative-value
-Wno-shift-overflow -Wshift-overflow=n -Wsign-compare
-Wsign-conversion -Wno-sizeof-array-argument -Wsizeof-pointer-div
-Wsizeof-pointer-memaccess -Wstack-protector -Wstack-usage=byte-size
-Wstrict-aliasing -Wstrict-aliasing=n -Wstrict-overflow
-Wstrict-overflow=n -Wstring-compare -Wstringop-overflow=n
-Wno-stringop-truncation
-Wsuggest-attribute=[pure|const|noreturn|format|malloc] -Wswitch
-Wno-switch-bool -Wswitch-default -Wswitch-enum
-Wno-switch-outside-range -Wno-switch-unreachable -Wsync-nand
-Wsystem-headers -Wtautological-compare -Wtrampolines -Wtrigraphs
-Wtype-limits -Wundef -Wuninitialized -Wunknown-pragmas
-Wunsuffixed-float-constants -Wunused -Wunused-but-set-parameter
-Wunused-but-set-variable -Wunused-const-variable
-Wunused-const-variable=n -Wunused-function -Wunused-label
-Wunused-local-typedefs -Wunused-macros -Wunused-parameter
-Wno-unused-result -Wunused-value -Wunused-variable -Wno-varargs
-Wvariadic-macros -Wvector-operation-performance -Wvla
-Wvla-larger-than=byte-size -Wno-vla-larger-than
-Wvolatile-register-var -Wwrite-strings -Wzero-length-bounds
๐ Static Analyzer Options ๐
the analyzer flags are giving detective energy ๐ต๏ธโโ๏ธ these are the ones you pull out when you want GCC to go deep on your code flow โจ
-fanalyzer -fanalyzer-call-summaries -fanalyzer-checker=name
-fanalyzer-fine-grained -fanalyzer-state-merge
-fanalyzer-state-purge -fanalyzer-transitivity
-fanalyzer-verbose-edges -fanalyzer-verbose-state-changes
-fanalyzer-verbosity=level -fdump-analyzer -fdump-analyzer-stderr
-fdump-analyzer-callgraph -fdump-analyzer-exploded-graph
-fdump-analyzer-exploded-nodes -fdump-analyzer-exploded-nodes-2
-fdump-analyzer-exploded-nodes-3 -fdump-analyzer-state-purge
-fdump-analyzer-supergraph -Wno-analyzer-double-fclose
-Wno-analyzer-double-free -Wno-analyzer-exposure-through-output-file
-Wno-analyzer-file-leak -Wno-analyzer-free-of-non-heap
-Wno-analyzer-malloc-leak -Wno-analyzer-null-argument
-Wno-analyzer-null-dereference -Wno-analyzer-possible-null-argument
-Wno-analyzer-possible-null-dereference
-Wno-analyzer-stale-setjmp-buffer -Wno-analyzer-tainted-array-index
-Wanalyzer-too-complex
-Wno-analyzer-unsafe-call-within-signal-handler
-Wno-analyzer-use-after-free
-Wno-analyzer-use-of-pointer-in-stale-stack-frame
-Wno-analyzer-use-of-uninitialized-value
๐ง C and Objective-C-only Warning Options ๐ง
these ones are C and Objective-C only, so they won't show up for every language, babe ๐ซถ
-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 ๐
okay the debugging flags are where the magic happens ๐ช this is the list you reach for when you want GCC to leave you breadcrumbs for your debugger ๐โจ
-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]
-fno-eliminate-unused-debug-symbols -femit-class-debug-always
-fno-merge-debug-strings -fno-dwarf2-cfi-asm -fvar-tracking
-fvar-tracking-assignments
โจ Optimization Options โจ
okay bestie, this is the big optimization drawer ๐ so many flags, so many vibes. here's the whole lineup, no cap ๐ฅ
-faggressive-loop-optimizations-falign-functions[=n[:m:[n2[:m2]]]]-falign-jumps[=n[:m:[n2[:m2]]]]-falign-labels[=n[:m:[n2[:m2]]]]-falign-loops[=n[:m:[n2[:m2]]]]-fno-allocation-dce-fallow-store-data-races-fassociative-math-fauto-profile-fauto-profile[=path]-fauto-inc-dec-fbranch-probabilities-fcaller-saves-fcombine-stack-adjustments-fconserve-stack-fcompare-elim-fcprop-registers-fcrossjumping-fcse-follow-jumps-fcse-skip-blocks-fcx-fortran-rules-fcx-limited-range-fdata-sections-fdce-fdelayed-branch-fdelete-null-pointer-checks-fdevirtualize-fdevirtualize-speculatively-fdevirtualize-at-ltrans-fdse-fearly-inlining-fipa-sra-fexpensive-optimizations-ffat-lto-objects-ffast-math-ffinite-math-only-ffloat-store-fexcess-precision=style-ffinite-loops-fforward-propagate-ffp-contract=style-ffunction-sections-fgcse-fgcse-after-reload-fgcse-las-fgcse-lm-fgraphite-identity-fgcse-sm-fhoist-adjacent-loads-fif-conversion-fif-conversion2-findirect-inlining-finline-functions-finline-functions-called-once-finline-limit=n-finline-small-functions-fipa-cp-fipa-cp-clone-fipa-bit-cp-fipa-vrp-fipa-pta-fipa-profile-fipa-pure-const-fipa-reference-fipa-reference-addressable-fipa-stack-alignment-fipa-icf-fira-algorithm=algorithm-flive-patching=level-fira-region=region-fira-hoist-pressure-fira-loop-pressure-fno-ira-share-save-slots-fno-ira-share-spill-slots-fisolate-erroneous-paths-dereference-fisolate-erroneous-paths-attribute-fivopts-fkeep-inline-functions-fkeep-static-functions-fkeep-static-consts-flimit-function-alignment-flive-range-shrinkage-floop-block-floop-interchange-floop-strip-mine-floop-unroll-and-jam-floop-nest-optimize-floop-parallelize-all-flra-remat-flto-flto-compression-level-flto-partition=alg-fmerge-all-constants-fmerge-constants-fmodulo-sched-fmodulo-sched-allow-regmoves-fmove-loop-invariants-fno-branch-count-reg-fno-defer-pop-fno-fp-int-builtin-inexact-fno-function-cse-fno-guess-branch-probability-fno-inline-fno-math-errno-fno-peephole-fno-peephole2-fno-printf-return-value-fno-sched-interblock-fno-sched-spec-fno-signed-zeros-fno-toplevel-reorder-fno-trapping-math-fno-zero-initialized-in-bss-fomit-frame-pointer-foptimize-sibling-calls-fpartial-inlining-fpeel-loops-fpredictive-commoning-fprefetch-loop-arrays-fprofile-correction-fprofile-use-fprofile-use=path-fprofile-partial-training-fprofile-values-fprofile-reorder-functions-freciprocal-math-free-frename-registers-freorder-blocks-freorder-blocks-algorithm=algorithm-freorder-blocks-and-partition-freorder-functions-frerun-cse-after-loop-freschedule-modulo-scheduled-loops-frounding-math-fsave-optimization-record-fsched2-use-superblocks-fsched-pressure-fsched-spec-load-fsched-spec-load-dangerous-fsched-stalled-insns-dep[=n]-fsched-stalled-insns[=n]-fsched-group-heuristic-fsched-critical-path-heuristic-fsched-spec-insn-heuristic-fsched-rank-heuristic-fsched-last-insn-heuristic-fsched-dep-count-heuristic-fschedule-fusion-fschedule-insns-fschedule-insns2-fsection-anchors-fselective-scheduling-fselective-scheduling2-fsel-sched-pipelining-fsel-sched-pipelining-outer-loops-fsemantic-interposition-fshrink-wrap-fshrink-wrap-separate-fsignaling-nans-fsingle-precision-constant-fsplit-ivs-in-unroller-fsplit-loops-fsplit-paths-fsplit-wide-types-fsplit-wide-types-early-fssa-backprop-fssa-phiopt-fstdarg-opt-fstore-merging-fstrict-aliasing-fthread-jumps-ftracer-ftree-bit-ccp-ftree-builtin-call-dce-ftree-ccp-ftree-ch-ftree-coalesce-vars-ftree-copy-prop-ftree-dce-ftree-dominator-opts-ftree-dse-ftree-forwprop-ftree-fre-fcode-hoisting-ftree-loop-if-convert-ftree-loop-im-ftree-phiprop-ftree-loop-distribution-ftree-loop-distribute-patterns-ftree-loop-ivcanon-ftree-loop-linear-ftree-loop-optimize-ftree-loop-vectorize-ftree-parallelize-loops=n-ftree-pre-ftree-partial-pre-ftree-pta-ftree-reassoc-ftree-scev-cprop-ftree-sink-ftree-slsr-ftree-sra-ftree-switch-conversion-ftree-tail-merge-ftree-ter-ftree-vectorize-ftree-vrp-funconstrained-commons-funit-at-a-time-funroll-all-loops-funroll-loops-funsafe-math-optimizations-funswitch-loops-fipa-ra-fvariable-expansion-in-unroller-fvect-cost-model-fvpt-fweb-fwhole-program-fwpa-fuse-linker-plugin--param name=value-O-O0-O1-O2-O3-Os-Ofast-Og
๐ Program Instrumentation Options ๐
this is the tracking-and-protection squad ๐ซถ these are the flags for profiling, coverage, sanitizers, and stack protection. main character energy โจ
-p-pg-fprofile-arcs--coverage-ftest-coverage-fprofile-abs-path-fprofile-dir=path-fprofile-generate-fprofile-generate=path-fprofile-note=path-fprofile-prefix-path=path-fprofile-update=method-fprofile-filter-files=regex-fprofile-exclude-files=regex-fprofile-reproducible=[multithreaded|parallel-runs|serial]-fsanitize=style-fsanitize-recover-fsanitize-recover=style-fasan-shadow-offset=number-fsanitize-sections=s1,s2,...-fsanitize-undefined-trap-on-error-fbounds-check-fcf-protection=[full|branch|return|none|check]-fstack-protector-fstack-protector-all-fstack-protector-strong-fstack-protector-explicit-fstack-check-fstack-limit-register=reg-fstack-limit-symbol=sym-fno-stack-limit-fsplit-stack-fvtable-verify=[std|preinit|none]-fvtv-counts-fvtv-debug-finstrument-functions-finstrument-functions-exclude-function-list=sym,sym,...-finstrument-functions-exclude-file-list=file,file,...
๐ Preprocessor Options ๐
okay the preprocessor is where the macros and includes get handled ๐ so many little knobs, let's go
-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-fmax-include-depth=depth-fno-canonical-system-headers-fpch-deps-fpch-preprocess-fpreprocessed-ftabstop=width-ftrack-macro-expansion-fwide-exec-charset=charset-fworking-directory-H-imacros file-include file-M-MD-MF-MG-MM-MMD-MP-MQ-MT-no-integrated-cpp-P-pthread-remap-traditional-traditional-cpp-trigraphs-Umacro-undef-Wp,option-Xpreprocessor option
๐ฆ Assembler Options ๐ฆ
-Wa,option-Xassembler option
๐ Linker Options ๐
linking time, bestie ๐ objects, libraries, and all the static-vs-shared drama
object-file-name-fuse-ld=linker-llibrary-nostartfiles-nodefaultlibs-nolibc-nostdlib-e entry--entry=entry-pie-pthread-r-rdynamic-s-static-static-pie-static-libgcc-static-libstdc++-static-libasan-static-libtsan-static-liblsan-static-libubsan-shared-shared-libgcc-symbolic-T script-Wl,option-Xlinker option-u symbol-z keyword
๐ธ Directory Options ๐ธ
where gcc goes looking for stuff ๐ง search paths, prefixes, sysroots, the whole map
-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 the section for how the actual machine code gets generated ๐ exceptions, unwinding, PIC/PIE, visibility, and more
-fcall-saved-reg-fcall-used-reg-ffixed-reg-fexceptions-fnon-call-exceptions-fdelete-dead-exceptions-funwind-tables-fasynchronous-unwind-tables-fno-gnu-unique-finhibit-size-directive-fcommon-fno-ident-fpcc-struct-return-fpic-fPIC-fpie-fPIE-fno-plt-fno-jump-tables-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 deep-dive, debugging, and dump-everything section ๐ ngl this one is a lot, but we got this ๐
-dletters-dumpspecs-dumpmachine-dumpversion-dumpfullversion-fcallgraph-info[=su,da]-fchecking-fchecking=n-fdbg-cnt-list-fdbg-cnt=counter-value-list-fdisable-ipa-pass_name-fdisable-rtl-pass_name-fdisable-rtl-pass-name=range-list-fdisable-tree-pass_name-fdisable-tree-pass-name=range-list-fdump-debug-fdump-earlydebug-fdump-noaddr-fdump-unnumbered-fdump-unnumbered-links-fdump-final-insns[=file]-fdump-ipa-all-fdump-ipa-cgraph-fdump-ipa-inline-fdump-lang-all-fdump-lang-switch-fdump-lang-switch-options-fdump-lang-switch-options=filename-fdump-passes-fdump-rtl-pass-fdump-rtl-pass=filename-fdump-statistics-fdump-tree-all-fdump-tree-switch-fdump-tree-switch-options-fdump-tree-switch-options=filename-fcompare-debug[=opts]-fcompare-debug-second-fenable-kind-pass-fenable-kind-pass=range-list-fira-verbose=n-flto-report-flto-report-wpa-fmem-report-wpa-fmem-report-fpre-ipa-mem-report-fpost-ipa-mem-report-fopt-info-fopt-info-options[=file]-fprofile-report-frandom-seed=string-fsched-verbose=n-fsel-sched-verbose-fsel-sched-dump-cfg-fsel-sched-pipelining-verbose-fstats-fstack-usage-ftime-report-ftime-report-details-fvar-tracking-assignments-toggle-gtoggle-print-file-name=library-print-libgcc-file-name-print-multi-directory-print-multi-lib-print-multi-os-directory-print-prog-name=program-print-search-dirs-Q-print-sysroot-print-sysroot-headers-suffix-save-temps-save-temps=cwd-save-temps=obj-time[=file]
๐ Machine-Dependent Options ๐
last stop, the target-specific flags ๐ these depend on which machine you're building for
๐ฆ AArch64 Options ๐ฆ
-mabi=name-mbig-endian-mlittle-endian-mgeneral-regs-only-mcmodel=tiny-mcmodel=small-mcmodel=large-mstrict-align-mno-strict-align-momit-leaf-frame-pointer-mtls-dialect=desc-mtls-dialect=traditional-mtls-size=size-mfix-cortex-a53-835769-mfix-cortex-a53-843419-mlow-precision-recip-sqrt-mlow-precision-sqrt-mlow-precision-div-mpc-relative-literal-loads-msign-return-address=scope-mbranch-protection=none|standard|pac-ret[+leaf +b-key]|bti-mharden-sls=opts-march=name-mcpu=name-mtune=name-moverride=string-mverbose-cost-dump-mstack-protector-guard=guard-mstack-protector-guard-reg=sysreg-mstack-protector-guard-offset=offset-mtrack-speculation-moutline-atomics
โจ Adapteva Epiphany Options โจ
Okay bestie, first up is the Adapteva Epiphany crew ๐ฆ Here's the whole squad:
-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 โจ
Next, the AMD GCN options ๐ Only three, but they're iconic:
-march=gpu -mtune=gpu -mstack-size=bytes
โจ ARC Options โจ
Now we're going into the ARC options, and this list is LONG ๐ญ Lowkey the most options in the whole group chat ๐ฅ
-mbarrel-shifter -mjli-always -mcpu=cpu -mA6 -mARC600
-mA7 -mARC700 -mdpfp -mdpfp-compact -mdpfp-fast -mno-dpfp-lrsr
-mea -mno-mpy -mmul32x16 -mmul64 -matomic -mnorm -mspfp
-mspfp-compact -mspfp-fast -msimd -msoft-float -mswap -mcrc
-mdsp-packa -mdvbf -mlock -mmac-d16 -mmac-24 -mrtsc -mswape
-mtelephony -mxy -misize -mannotate-align -marclinux
-marclinux_prof -mlong-calls -mmedium-calls -msdata
-mirq-ctrl-saved -mrgf-banked-regs -mlpc-width=width -G num
-mvolatile-cache -mtp-regno=regno -malign-call -mauto-modify-reg
-mbbit-peephole -mno-brcc -mcase-vector-pcrel -mcompact-casesi
-mno-cond-exec -mearly-cbranchsi -mexpand-adddi -mindexed-loads
-mlra -mlra-priority-none -mlra-priority-compact mlra-priority-
noncompact -mmillicode -mmixed-code -mq-class -mRcq -mRcw
-msize-level=level -mtune=cpu -mmultcost=num -mcode-density-frame
-munalign-prob-threshold=probability -mmpy-option=multo -mdiv-rem
-mcode-density -mll64 -mfpu=fpu -mrf16 -mbranch-index
โจ ARM Options โจ
ARM time ๐ธ This group is a whole vibe, so buckle up:
-mapcs-frame -mno-apcs-frame -mabi=name
-mapcs-stack-check -mno-apcs-stack-check -mapcs-reentrant
-mno-apcs-reentrant -mgeneral-regs-only -msched-prolog
-mno-sched-prolog -mlittle-endian -mbig-endian -mbe8 -mbe32
-mfloat-abi=name -mfp16-format=name -mthumb-interwork
-mno-thumb-interwork -mcpu=name -march=name -mfpu=name -mtune=name
-mprint-tune-info -mstructure-size-boundary=n -mabort-on-noreturn
-mlong-calls -mno-long-calls -msingle-pic-base
-mno-single-pic-base -mpic-register=reg -mnop-fun-dllimport
-mpoke-function-name -mthumb -marm -mflip-thumb -mtpcs-frame
-mtpcs-leaf-frame -mcaller-super-interworking
-mcallee-super-interworking -mtp=name -mtls-dialect=dialect
-mword-relocations -mfix-cortex-m3-ldrd -munaligned-access
-mneon-for-64bits -mslow-flash-data -masm-syntax-unified
-mrestrict-it -mverbose-cost-dump -mpure-code -mcmse
-mfix-cmse-cve-2021-35465 -mfdpic
โจ AVR Options โจ
AVR options are up next ๐ง
-mmcu=mcu -mabsdata -maccumulate-args
-mbranch-cost=cost -mcall-prologues -mgas-isr-prologues -mint8
-mdouble=bits -mlong-double=bits -mn_flash=size -mno-interrupts
-mmain-is-OS_task -mrelax -mrmw -mstrict-X -mtiny-stack
-mfract-convert-truncate -mshort-calls -nodevicelib -nodevicespecs
-Waddr-space-convert -Wmisspelled-isr
โจ Blackfin Options โจ
Blackfin next ๐ฅ Pay attention to the -mcpu=cpu[-sirevision] one, it has a little bracket situation going on:
-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 โจ
Quick one: the C6X options ๐
-mbig-endian -mlittle-endian -march=cpu -msim
-msdata=sdata-type
โจ CRIS Options โจ
CRIS is giving main character energy ๐
-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 โจ
CR16 options, bestie ๐
-mmac -mcr16cplus -mcr16c -msim -mint32 -mbit-ops
-mdata-model=model
โจ C-SKY Options โจ
C-SKY next ๐ฆ This list is giving "I have a lot of opinions about endianness" energy:
-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
โจ Darwin Options โจ
Darwin options are a whole mood ๐ Lots of them, so grab a snack:
-all_load -allowable_client -arch
-arch_errors_fatal -arch_only -bind_at_load -bundle
-bundle_loader -client_name -compatibility_version
-current_version -dead_strip -dependency-file -dylib_file
-dylinker_install_name -dynamic -dynamiclib -exported_symbols_list
-filelist -flat_namespace -force_cpusubtype_ALL
-force_flat_namespace -headerpad_max_install_names -iframework
-image_base -init -install_name -keep_private_externs
-multi_module -multiply_defined -multiply_defined_unused
-noall_load -no_dead_strip_inits_and_terms -nofixprebinding
-nomultidefs -noprebind -noseglinkedit -pagezero_size -prebind
-prebind_all_twolevel_modules -private_bundle -read_only_relocs
-sectalign -sectobjectsymbols -whyload -seg1addr -sectcreate
-sectobjectsymbols -sectorder -segaddr -segs_read_only_addr
-segs_read_write_addr -seg_addr_table -seg_addr_table_filename
-seglinkedit -segprot -segs_read_only_addr -segs_read_write_addr
-single_module -static -sub_library -sub_umbrella
-twolevel_namespace -umbrella -undefined -unexported_symbols_list
-weak_reference_mismatches -whatsloaded -F -gused -gfull
-mmacosx-version-min=version -mkernel -mone-byte-bool
โจ DEC Alpha Options โจ
DEC Alpha ๐ Some of these are a little old school, but they're still iconic:
-mno-fp-regs -msoft-float -mieee
-mieee-with-inexact -mieee-conformant -mfp-trap-mode=mode
-mfp-rounding-mode=mode -mtrap-precision=mode -mbuild-constants
-mcpu=cpu-type -mtune=cpu-type -mbwx -mmax -mfix -mcix
-mfloat-vax -mfloat-ieee -mexplicit-relocs -msmall-data
-mlarge-data -msmall-text -mlarge-text -mmemory-latency=time
โจ eBPF Options โจ
eBPF is so cute rn ๐ง
-mbig-endian -mlittle-endian -mkernel=version
-mframe-limit=bytes -mxbpf
โจ FR30 Options โจ
FR30 options, short and sweet ๐
-msmall-model -mno-lsim
โจ FT32 Options โจ
FT32 next ๐ธ
-msim -mlra -mnodiv -mft32b -mcompress -mnopm
โจ FRV Options โจ
FRV options! Literally a wall of flags, not gonna lie ๐
-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 โจ
GNU/Linux options ๐ซถ
-mglibc -muclibc -mmusl -mbionic -mandroid
-tno-android-cc -tno-android-ld
โจ H8/300 Options โจ
H8/300 next ๐
-mrelax -mh -ms -mn -mexr -mno-exr -mint32
-malign-300
โจ HPPA Options โจ
HPPA options, and yes, they're all lowercase vibes ๐
-march=architecture-type -mcaller-copies
-mdisable-fpregs -mdisable-indexing -mfast-indirect-calls -mgas
-mgnu-ld -mhp-ld -mfixed-range=register-range -mjump-in-delay
-mlinker-opt -mlong-calls -mlong-load-store -mno-disable-fpregs
-mno-disable-indexing -mno-fast-indirect-calls -mno-gas
-mno-jump-in-delay -mno-long-load-store -mno-portable-runtime
-mno-soft-float -mno-space-regs -msoft-float -mpa-risc-1-0
-mpa-risc-1-1 -mpa-risc-2-0 -mportable-runtime -mschedule=cpu-type
-mspace-regs -msio -mwsio -munix=unix-std -nolibdld -static
-threads
โจ IA-64 Options โจ
IA-64, the big one ๐ Scroll slowly, there are a LOT of scheduling flags in here:
-mbig-endian -mlittle-endian -mgnu-as -mgnu-ld
-mno-pic -mvolatile-asm-stop -mregister-names -msdata -mno-sdata
-mconstant-gp -mauto-pic -mfused-madd
-minline-float-divide-min-latency
-minline-float-divide-max-throughput -mno-inline-float-divide
-minline-int-divide-min-latency -minline-int-divide-max-throughput
-mno-inline-int-divide -minline-sqrt-min-latency
-minline-sqrt-max-throughput -mno-inline-sqrt -mdwarf2-asm
-mearly-stop-bits -mfixed-range=register-range -mtls-size=tls-size
-mtune=cpu-type -milp32 -mlp64 -msched-br-data-spec
-msched-ar-data-spec -msched-control-spec -msched-br-in-data-spec
-msched-ar-in-data-spec -msched-in-control-spec -msched-spec-ldc
-msched-spec-control-ldc -msched-prefer-non-data-spec-insns
-msched-prefer-non-control-spec-insns
-msched-stop-bits-after-every-cycle
-msched-count-spec-in-critical-path
-msel-sched-dont-check-control-spec -msched-fp-mem-deps-zero-cost
-msched-max-memory-insns-hard-limit -msched-max-memory-insns=max-insns
โจ LM32 Options โจ
LM32 options ๐ง
-mbarrel-shift-enabled -mdivide-enabled
-mmultiply-enabled -msign-extend-enabled -muser-enabled
โจ M32R/D Options โจ
M32R/D next ๐
-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 โจ
M32C, quick and easy ๐
-mcpu=cpu -msim -memregs=number
โจ M680x0 Options โจ
M680x0 is a whole era ๐ Lots of CPU and CPU-variant flags, so take your time:
-march=arch -mcpu=cpu -mtune=tune -m68000 -m68020
-m68020-40 -m68020-60 -m68030 -m68040 -m68060 -mcpu32 -m5200
-m5206e -m528x -m5307 -m5407 -mcfv4e -mbitfield -mno-bitfield
-mc68000 -mc68020 -mnobitfield -mrtd -mno-rtd -mdiv -mno-div
-mshort -mno-short -mhard-float -m68881 -msoft-float -mpcrel
-malign-int -mstrict-align -msep-data -mno-sep-data
-mshared-library-id=n -mid-shared-library -mno-id-shared-library
-mxgot -mno-xgot -mlong-jump-table-offsets
โจ MCore Options โจ
MCore options ๐ธ
-mhardlit -mno-hardlit -mdiv -mno-div
-mrelax-immediates -mno-relax-immediates -mwide-bitfields
-mno-wide-bitfields -m4byte-functions -mno-4byte-functions
-mcallgraph-data -mno-callgraph-data -mslow-bytes -mno-slow-bytes
-mno-lsim -mlittle-endian -mbig-endian -m210 -m340
-mstack-increment
โจ MeP Options โจ
MeP options, the final stretch ๐ฆ
-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 โจ
And last but not least, MicroBlaze ๐ซถ We made it, bestie ๐ญ
-msoft-float -mhard-float -msmall-divides
-mcpu=cpu -mmemcpy -mxl-soft-mul -mxl-soft-div -mxl-barrel-shift
-mxl-pattern-compare -mxl-stack-check -mxl-gp-opt -mno-clearbss
-mxl-multiply-high -mxl-float-convert -mxl-float-sqrt -mbig-endian
-mlittle-endian -mxl-reorder -mxl-mode-app-model
-mpic-data-is-text-relative
โจ MIPS Options โจ
Okay bestie, MIPS has a whole buffet of flags ๐ฆ Here's the full spread ๐
-EL-EB-march=arch-mtune=arch-mips1-mips2-mips3-mips4-mips32-mips32r2-mips32r3-mips32r5-mips32r6-mips64-mips64r2-mips64r3-mips64r5-mips64r6-mips16-mno-mips16-mflip-mips16-minterlink-compressed-mno-interlink-compressed-minterlink-mips16-mno-interlink-mips16-mabi=abi-mabicalls-mno-abicalls-mshared-mno-shared-mplt-mno-plt-mxgot-mno-xgot-mgp32-mgp64-mfp32-mfpxx-mfp64-mhard-float-msoft-float-mno-float-msingle-float-mdouble-float-modd-spreg-mno-odd-spreg-mabs=mode-mnan=encoding-mdsp-mno-dsp-mdspr2-mno-dspr2-mmcu-mmno-mcu-meva-mno-eva-mvirt-mno-virt-mxpa-mno-xpa-mcrc-mno-crc-mginv-mno-ginv-mmicromips-mno-micromips-mmsa-mno-msa-mloongson-mmi-mno-loongson-mmi-mloongson-ext-mno-loongson-ext-mloongson-ext2-mno-loongson-ext2-mfpu=fpu-type-msmartmips-mno-smartmips-mpaired-single-mno-paired-single-mdmx-mno-mdmx-mips3d-mno-mips3d-mmt-mno-mt-mllsc-mno-llsc-mlong64-mlong32-msym32-mno-sym32-Gnum-mlocal-sdata-mno-local-sdata-mextern-sdata-mno-extern-sdata-mgpopt-mno-gopt-membedded-data-mno-embedded-data-muninit-const-in-rodata-mno-uninit-const-in-rodata-mcode-readable=setting-msplit-addresses-mno-split-addresses-mexplicit-relocs-mno-explicit-relocs-mcheck-zero-division-mno-check-zero-division-mdivide-traps-mdivide-breaks-mload-store-pairs-mno-load-store-pairs-mmemcpy-mno-memcpy-mlong-calls-mno-long-calls-mmad-mno-mad-mimadd-mno-imadd-mfused-madd-mno-fused-madd-nocpp-mfix-24k-mno-fix-24k-mfix-r4000-mno-fix-r4000-mfix-r4400-mno-fix-r4400-mfix-r5900-mno-fix-r5900-mfix-r10000-mno-fix-r10000-mfix-rm7000-mno-fix-rm7000-mfix-vr4120-mno-fix-vr4120-mfix-vr4130-mno-fix-vr4130-mfix-sb1-mno-fix-sb1-mflush-func=func-mno-flush-func-mbranch-cost=num-mbranch-likely-mno-branch-likely-mcompact-branches=policy-mfp-exceptions-mno-fp-exceptions-mvr4130-align-mno-vr4130-align-msynci-mno-synci-mlxc1-sxc1-mno-lxc1-sxc1-mmadd4-mno-madd4-mrelax-pic-calls-mno-relax-pic-calls-mmcount-ra-address-mframe-header-opt-mno-frame-header-opt
โจ MMIX Options โจ
Next up, MMIX ๐
-mlibfuncs-mno-libfuncs-mepsilon-mno-epsilon-mabi=gnu-mabi=mmixware-mzero-extend-mknuthdiv-mtoplevel-symbols-melf-mbranch-predict-mno-branch-predict-mbase-addresses-mno-base-addresses-msingle-exit-mno-single-exit
โจ MN10300 Options โจ
-mmult-bug-mno-mult-bug-mno-am33-mam33-mam33-2-mam34-mtune=cpu-type-mreturn-pointer-on-d0-mno-crt0-mrelax-mliw-msetlb
โจ Moxie Options โจ
-meb-mel-mmul.x-mno-crt0
โจ MSP430 Options โจ
-msim-masm-hex-mmcu=-mcpu=-mlarge-msmall-mrelax-mwarn-mcu-mcode-region=-mdata-region=-msilicon-errata=-msilicon-errata-warn=-mhwmult=-minrt-mtiny-printf
โจ NDS32 Options โจ
-mbig-endian-mlittle-endian-mreduced-regs-mfull-regs-mcmov-mno-cmov-mext-perf-mno-ext-perf-mext-perf2-mno-ext-perf2-mext-string-mno-ext-string-mv3push-mno-v3push-m16bit-mno-16bit-misr-vector-size=num-mcache-block-size=num-march=arch-mcmodel=code-model-mctor-dtor-mrelax
โจ Nios II Options โจ
-G num-mgpopt=option-mgpopt-mno-gpopt-mgprel-sec=regexp-mr0rel-sec=regexp-mel-meb-mno-bypass-cache-mbypass-cache-mno-cache-volatile-mcache-volatile-mno-fast-sw-div-mfast-sw-div-mhw-mul-mno-hw-mul-mhw-mulx-mno-hw-mulx-mno-hw-div-mhw-div-mcustom-insn=N-mno-custom-insn-mcustom-fpu-cfg=name-mhal-msmallc-msys-crt0=name-msys-lib=name-march=arch-mbmx-mno-bmx-mcdx-mno-cdx
โจ Nvidia PTX Options โจ
-m32-m64-mmainkernel-moptimize
โจ OpenRISC Options โจ
-mboard=name-mnewlib-mhard-mul-mhard-div-msoft-mul-msoft-div-msoft-float-mhard-float-mdouble-float-munordered-float-mcmov-mror-mrori-msext-msfimm-mshftimm
โจ PDP-11 Options โจ
-mfpu-msoft-float-mac0-mno-ac0-m40-m45-m10-mint32-mno-int16-mint16-mno-int32-msplit-munix-asm-mdec-asm-mgnu-asm-mlra
โจ picoChip Options โจ
-mae=ae_type-mvliw-lookahead=N-msymbol-as-address-mno-inefficient-warnings
โจ PowerPC Options โจ
Just go check the RS/6000 and PowerPC section, it's got everything ๐ See RS/6000 and PowerPC Options.
โจ PRU Options โจ
-mmcu=mcu-minrt-mno-relax-mloop-mabi=variant
โจ RISC-V Options โจ
-mbranch-cost=N-instruction-mplt-mno-plt-mabi=ABI-string-mfdiv-mno-fdiv-mdiv-mno-div-march=ISA-string-mtune=processor-string-mpreferred-stack-boundary=num-msmall-data-limit=N-bytes-msave-restore-mno-save-restore-mstrict-align-mno-strict-align-mcmodel=medlow-mcmodel=medany-mexplicit-relocs-mno-explicit-relocs-mrelax-mno-relax-mriscv-attribute-mmo-riscv-attribute-malign-data=type
โจ RL78 Options โจ
-msim-mmul=none-mmul=g13-mmul=g14-mallregs-mcpu=g10-mcpu=g13-mcpu=g14-mg10-mg13-mg14-m64bit-doubles-m32bit-doubles-msave-mduc-in-interrupts
โจ RS/6000 and PowerPC Options โจ
This one's a monster, bestie ๐ญ Grab a snack, here we go ๐
-mcpu=cpu-type-mtune=cpu-type-mcmodel=code-model-mpowerpc64-maltivec-mno-altivec-mpowerpc-gpopt-mno-powerpc-gpopt-mpowerpc-gfxopt-mno-powerpc-gfxopt-mmfcrf-mno-mfcrf-mpopcntb-mno-popcntb-mpopcntd-mno-popcntd-mfprnd-mno-fprnd-mcmpb-mno-cmpb-mhard-dfp-mno-hard-dfp-mfull-toc-mminimal-toc-mno-fp-in-toc-mno-sum-in-toc-m64-m32-mxl-compat-mno-xl-compat-mpe-malign-power-malign-natural-msoft-float-mhard-float-mmultiple-mno-multiple-mupdate-mno-update-mavoid-indexed-addresses-mno-avoid-indexed-addresses-mfused-madd-mno-fused-madd-mbit-align-mno-bit-align-mstrict-align-mno-strict-align-mrelocatable-mno-relocatable-mrelocatable-lib-mno-relocatable-lib-mtoc-mno-toc-mlittle-mlittle-endian-mbig-mbig-endian-mdynamic-no-pic-mswdiv-msingle-pic-base-mprioritize-restricted-insns=priority-msched-costly-dep=dependence_type-minsert-sched-nops=scheme-mcall-aixdesc-mcall-eabi-mcall-freebsd-mcall-linux-mcall-netbsd-mcall-openbsd-mcall-sysv-mcall-sysv-eabi-mcall-sysv-noeabi-mtraceback=traceback_type-maix-struct-return-msvr4-struct-return-mabi=abi-type-msecure-plt-mbss-plt-mlongcall-mno-longcall-mpltseq-mno-pltseq-mblock-move-inline-limit=num-mblock-compare-inline-limit=num-mblock-compare-inline-loop-limit=num-mstring-compare-inline-limit=num-misel-mno-isel-mvrsave-mno-vrsave-mmulhw-mno-mulhw-mdlmzb-mno-dlmzb-mprototype-mno-prototype-msim-mmvme-mads-myellowknife-memb-msdata-msdata=opt-mreadonly-in-sdata-mvxworks-G num-mrecip-mrecip=opt-mno-recip-mrecip-precision-mno-recip-precision-mveclibabi=type-mfriz-mno-friz-mpointers-to-nested-functions-mno-pointers-to-nested-functions-msave-toc-indirect-mno-save-toc-indirect-mpower8-fusion-mno-mpower8-fusion-mpower8-vector-mno-power8-vector-mcrypto-mno-crypto-mhtm-mno-htm-mquad-memory-mno-quad-memory-mquad-memory-atomic-mno-quad-memory-atomic-mcompat-align-parm-mno-compat-align-parm-mfloat128-mno-float128-mfloat128-hardware-mno-float128-hardware-mgnu-attribute-mno-gnu-attribute-mstack-protector-guard=guard-mstack-protector-guard-reg=reg-mstack-protector-guard-offset=offset-mprefixed-mno-prefixed-mpcrel-mno-pcrel-mmma-mno-mmma
โจ RX Options โจ
-m64bit-doubles-m32bit-doubles-fpu-nofpu-mcpu=-mbig-endian-data-mlittle-endian-data-msmall-data-msim-mno-sim-mas100-syntax-mno-as100-syntax-mrelax-mmax-constant-size=-mint-register=-mpid-mallow-string-insns-mno-allow-string-insns-mjsr-mno-warn-multiple-fast-interrupts-msave-acc-in-interrupts
โจ S/390 and zSeries Options โจ
-mtune=cpu-type-march=cpu-type-mhard-float-msoft-float-mhard-dfp-mno-hard-dfp-mlong-double-64-mlong-double-128-mbackchain-mno-backchain-mpacked-stack-mno-packed-stack-msmall-exec-mno-small-exec-mmvcle-mno-mvcle-m64-m31-mdebug-mno-debug-mesa-mzarch-mhtm-mvx-mzvector-mtpf-trace-mno-tpf-trace-mtpf-trace-skip-mno-tpf-trace-skip-mfused-madd-mno-fused-madd-mwarn-framesize-mwarn-dynamicstack-mstack-size-mstack-guard-mhotpatch=halfwords,halfwords
โจ Score Options โจ
-meb-mel-mnhwloop-muls-mmac-mscore5-mscore5u-mscore7-mscore7d
โจ SH Options โจ
-m1-m2-m2e-m2a-nofpu-m2a-single-only-m2a-single-m2a-m3-m3e-m4-nofpu-m4-single-only-m4-single-m4-m4a-nofpu-m4a-single-only-m4a-single-m4a-m4al-mb-ml-mdalign-mrelax-mbigtable-mfmovd-mrenesas-mno-renesas-mnomacsave-mieee-mno-ieee-mbitops-misize-minline-ic_invalidate-mpadstruct-mprefergot-musermode-multcost=number-mdiv=strategy-mdivsi3_libfunc=name-mfixed-range=register-range-maccumulate-outgoing-args-matomic-model=atomic-model-mbranch-cost=num-mzdcbranch-mno-zdcbranch-mcbranch-force-delay-slot-mfused-madd-mno-fused-madd-mfsca-mno-fsca-mfsrra-mno-fsrra-mpretend-cmove-mtas
โจ Solaris 2 Options โจ
-mclear-hwcap-mno-clear-hwcap-mimpure-text-mno-impure-text-pthreads
โจ SPARC Options โจ
-mcpu=cpu-type-mtune=cpu-type-mcmodel=code-model-mmemory-model=mem-model-m32-m64-mapp-regs-mno-app-regs-mfaster-structs-mno-faster-structs-mflat-mno-flat-mfpu-mno-fpu-mhard-float-msoft-float-mhard-quad-float-msoft-quad-float-mstack-bias-mno-stack-bias-mstd-struct-return-mno-std-struct-return-munaligned-doubles-mno-unaligned-doubles-muser-mode-mno-user-mode-mv8plus-mno-v8plus-mvis-mno-vis-mvis2-mno-vis2-mvis3-mno-vis3-mvis4-mno-vis4-mvis4b-mno-vis4b-mcbcond-mno-cbcond-mfmaf-mno-fmaf-mfsmuld-mno-fsmuld-mpopc-mno-popc-msubxc-mno-subxc-mfix-at697f-mfix-ut699-mfix-ut700-mfix-gr712rc-mlra-mno-lra
โจ System V Options โจ
-Qy-Qn-YP,paths-Ym,dir
โจ TILE-Gx Options โจ
-mcpu=CPU-m32-m64-mbig-endian-mlittle-endian-mcmodel=code-model
โจ TILEPro Options โจ
-mcpu=cpu-m32
โจ V850 Options โจ
-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 ๐
okay bestie, these are the Visium flags, and they're giving main character energy ๐ฆ
-mdebug -msim -mfpu -mno-fpu -mhard-float
-msoft-float -mcpu=cpu-type -mtune=cpu-type -msv-mode -muser-mode
๐ธ VMS Options ๐ธ
the VMS crew gets its own set โจ
-mvms-return-codes -mdebug-main=prefix -mmalloc64 -mpointer-size=size
๐ง VxWorks Options ๐ง
and now the VxWorks ones, which are lowkey iconic ๐
-mrtp -non-static -Bstatic -Bdynamic -Xbind-lazy -Xbind-now
๐ x86 Options ๐
the x86 list is LONG and it is not playing ๐ญ but every single one is here, no cap ๐ฅ
-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 -mavx512bf16 -menqcmd
-mvpclmulqdq -mavx512bitalg -mmovdiri -mmovdir64b -mavx512vpopcntdq
-mavx5124fmaps -mavx512vnni -mavx5124vnniw -mprfchw -mrdpid -mrdseed -msgx
-mavx512vp2intersect -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 -mharden-sls=choice -mindirect-branch-cs-prefix
๐ช x86 Windows Options ๐ช
the Windows flags, bestie, and yes the last one is a whole mouthful ๐
-mconsole -mcygwin -mno-cygwin -mdll -mnop-fun-dllimport -mthread -municode
-mwin32 -mwindows -fno-set-stack-executable
๐ Xstormy16 Options ๐
just one for the Xstormy16 crew ๐
-msim
๐ Xtensa Options ๐
the Xtensa list is a whole vibe, ngl ๐
-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 ๐
the zSeries stuff lives somewhere else, so go check there ๐ซถ
See S/390 and zSeries Options.
โจ Options Controlling the Kind of Output โจ
okay so compilation can have up to four stages: preprocessing, compilation proper, assembly and linking, always in that order ๐ฅ GCC can preprocess and compile several files into several assembler input files, or into one assembler input file. Then each assembler input file produces an object file, and linking combines all the object files (the newly compiled ones and the ones you specified as input) into an executable file ๐
For any given input file, the file name suffix decides what kind of compilation happens. Here's the whole lineup ๐ฆ
file.cโ C source code that must be preprocessed.file.iโ C source code that should not be preprocessed.file.iiโ C++ source code that should not be preprocessed.file.mโ Objective-C source code. Note that you must link with thelibobjclibrary to make an Objective-C program work.file.miโ Objective-C source code that should not be preprocessed.file.mm,file.Mโ Objective-C++ source code. Note that you must link with thelibobjclibrary to make an Objective-C++ program work. Note that.Mrefers to a literal capital M.file.miiโ Objective-C++ source code that should not be preprocessed.file.hโ C, C++, Objective-C or Objective-C++ header file to be turned into a precompiled header (default), or C, C++ header file to be turned into an Ada spec (via the-fdump-ada-specswitch).file.cc,file.cp,file.cxx,file.cpp,file.CPP,file.c++,file.Cโ C++ source code that must be preprocessed. Note that in.cxx, the last two letters must both be literallyx. Likewise,.Crefers to a literal capital C.file.mm,file.Mโ Objective-C++ source code that must be preprocessed.file.miiโ Objective-C++ source code that should not be preprocessed.file.hh,file.H,file.hp,file.hxx,file.hpp,file.HPP,file.h++,file.tccโ C++ header file to be turned into a precompiled header or Ada spec.file.f,file.for,file.ftnโ Fixed form Fortran source code that should not be preprocessed.file.F,file.FOR,file.fpp,file.FPP,file.FTNโ Fixed form Fortran source code that must be preprocessed (with the traditional preprocessor).file.f90,file.f95,file.f03,file.f08โ Free form Fortran source code that should not be preprocessed.file.F90,file.F95,file.F03,file.F08โ Free form Fortran source code that must be preprocessed (with the traditional preprocessor).file.goโ Go source code.file.brigโ BRIG files (binary representation of HSAIL).file.dโ D source code.file.diโ D interface file.file.ddโ D documentation code (Ddoc).file.adsโ Ada source code file that contains a library unit declaration (a declaration of a package, subprogram, or generic, or a generic instantiation), or a library unit renaming declaration (a package, generic, or subprogram renaming declaration). Such files are also called specs.file.adbโ Ada source code file containing a library unit body (a subprogram or package body). Such files are also called bodies.file.sโ Assembler code.file.S,file.sxโ Assembler code that must be preprocessed.otherโ An object file to be fed straight into linking. Any file name with no recognized suffix is treated this way.
You can also spell out the input language yourself with the -x option ๐
-x languageโ Explicitly sets the language for the following input files, instead of letting the compiler guess from the file name suffix. This option applies to all following input files until the next-xoption. 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 later files get handled by their file name suffixes (same as if-xwas never used at all) ๐ซถ
If you only want some of the stages, use -x (or filename suffixes) to tell gcc where to start, and one of -c, -S, or -E to say where gcc should stop. Heads up though, some combos (like -x cpp-output -E) make gcc do absolutely nothing at all ๐
Heads up:-x cpp-output -Einstructsgccto do nothing at all, so don't be confused if nothing happens!
-cโ Compiles or assembles the source files, but does not link. The linking stage simply is not done, so the ultimate output is an object file for each source file. By default, the object file name for a source file is made by replacing the suffix.c,.i,.s, etc., with.o. Unrecognized input files, which don't need compilation or assembly, are ignored.-Sโ Stops after the compilation proper stage and doesn't assemble. The output is an assembler code file for each non-assembler input file you specify. By default, the assembler file name for a source file is made by replacing the suffix.c,.i, etc., with.s. Input files that don't require compilation are ignored.-Eโ Stops after the preprocessing stage and doesn't run the compiler proper. The output is preprocessed source code, which gets sent to the standard output. Input files that don't require preprocessing are ignored.-o fileโ Places the output infile. This applies to whatever sort of output is being produced, whether that's an executable, an object file, an assembler file, or preprocessed C code. If-oisn't specified, the default is an executable file ina.out, the object file forsource.suffixinsource.o, its assembler file insource.s, a precompiled header file insource.suffix.gch, and all preprocessed C source on standard output โจ-vโ Prints (on standard error output) the commands executed to run the stages of compilation. It also prints the version number of the compiler driver program and of the preprocessor and the compiler proper ๐ฅ-###โ Like-v, except the commands are not executed, and arguments get quoted unless they contain only alphanumeric characters or"./-_". This is super useful for shell scripts that want to capture the driver-generated command lines ๐ง--helpโ Prints (on the standard output) a description of the command-line optionsgccunderstands. If-vis also specified, then--helpis passed on to the various processesgccinvokes, so they can show the command-line options they accept. If-Wextrawas also specified (before the--helpoption), then command-line options that have no documentation are displayed too ๐--target-helpโ Prints (on the standard output) a description of the target-specific command-line options for each tool. For some targets, extra target-specific information may also be printed ๐--help={class|[^]qualifier}[,...]โ okay bestie, this one is a whole vibe ๐ It prints (to standard output) a rundown of every command-line option the compiler understands that fits into all the classes and qualifiers you list. These are the supported classes:optimizersโ every optimization option the compiler supports โจwarningsโ every option that controls the warning messages the compiler produces ๐ฅtargetโ target-specific options. Unlike--target-help, this one skips the target-specific options of the linker and assembler, because those tools don't support the extended--help=syntax yet ๐งparamsโ the values that--paramrecognizes ๐languageโ the options supported for language, where language is one of the languages in this version of GCC. If an option works for every language, you need to pick thecommonclass ๐ธcommonโ the options shared by all languages ๐ซถ
These are the supported qualifiers:
undocumentedโ only the options that have no documentation ๐joinedโ options that take an argument hanging off an equal sign in the same continuous chunk of text, like--help=target๐ฆseparateโ options that take an argument as their own separate word right after the option, like-o output-file๐
Thus, for example, to display all the undocumented target-specific switches the compiler supports, use:
--help=target,undocumented
The sense of a qualifier can be flipped by putting the ^ character in front of it. So if you want all the binary warning options (the ones that are either on or off and don't take an argument) that have a description, use:
--help=warnings,^joined,^undocumented
The argument to --help= should not consist solely of inverted qualifiers. Don't be that person ๐
Combining several classes is possible, although it usually filters things down so much that 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 time you use it, it displays its requested class of options, skipping anything that's already been shown. If --help is also specified anywhere on the command line, then it takes precedence over any --help= option ๐
If the -Q option shows up on the command line before the --help= option, the descriptive text displayed by --help= changes. Instead of describing the options, it tells you whether each one is enabled, disabled or set to a specific value (assuming the compiler knows that at the point where --help= is used) โจ
Here is 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, for example, you can find out which optimizations are enabled at -O2 by using:
-Q -O2 --help=optimizers
Alternatively, you can discover which binary optimizations are enabled by -O3 by using:
gcc -c -Q -O3 --help=optimizers > /tmp/O3-opts
gcc -c -Q -O2 --help=optimizers > /tmp/O2-opts
diff /tmp/O2-opts /tmp/O3-opts | grep enabled
--versionโ shows the version number and copyrights of the GCC you invoked ๐-pass-exit-codesโ okay so, normally thegccprogram exits with the code of 1 if any phase of the compiler returns a non-success return code. With-pass-exit-codes, it instead returns the numerically highest error produced by any phase that reported an error ๐ The C, C++, and Fortran front ends return 4 if they hit an internal compiler error.-pipeโ uses pipes instead of temporary files to pass data between the various stages of compilation ๐ฆ Heads up: this fails on some systems where the assembler can't read from a pipe. The GNU assembler has no trouble with it though ๐-specs=fileโ processes file after the compiler reads in the standard specs file. This lets you 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โ runs all subcommands under a wrapper program. You pass the wrapper's name and its parameters as a comma separated list. Like this:
gcc -c t.c -wrapper gdb,--args
That invokes all the subprograms of gcc under gdb --args, so the call to cc1 becomes gdb --args cc1 .... ๐ง
-ffile-prefix-map=old=newโ when compiling files living in directory old, any references to them in the compilation result get recorded as if the files lived in directory new instead ๐บ๏ธ Setting this is the same as setting all the individual-f*-prefix-mapoptions. It's a great way to make reproducible builds that don't depend on location. See also-fmacro-prefix-mapand-fdebug-prefix-map.-fplugin=name.soโ loads the plugin code from name.so, which should be a shared object the compiler willdlopen. The base name of the shared object file is what identifies the plugin when arguments get parsed (see-fplugin-arg-name-key=valuebelow). Each plugin should define the callback functions listed in the Plugins API ๐-fplugin-arg-name-key=valueโ defines an argument called key with a value of value for the plugin called name ๐-fdump-ada-spec[-slim]โ for C and C++ source and include files, generates matching Ada specs ๐-fada-spec-parent=unitโ used together with-fdump-ada-spec[-slim]above, this generates the Ada specs as child units of the parent unit ๐-fdump-go-spec=fileโ for input files in any language, generates matching Go declarations in file. You get Goconst,type,var, andfuncdeclarations, which can be a handy head start if you're writing a Go interface to code written in some other language ๐น@fileโ reads command-line options from file. The options read get inserted in place of the original@fileoption. If file doesn't exist or can't be read, the option is treated literally and doesn't get removed ๐ซ Options inside file are separated by whitespace. You can include a whitespace character in an option by wrapping the whole option in single or double quotes. Any character (backslash included) can be included by putting a backslash in front of it. The file can even contain more@fileoptions of its own, and those get processed recursively ๐
โจ Compiling C++ Programs โจ
C++ source files conventionally use one of the suffixes .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx. C++ header files often use .hh, .hpp, .H, or (for shared template code) .tcc, and preprocessed C++ files use the suffix .ii. GCC recognizes files with these names and compiles them as C++ programs, even if you call the compiler the same way you would for C programs (usually with the name gcc) ๐
However, using gcc doesn't add the C++ library. g++ is 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 under the name c++.
When you compile C++ programs, you can use lots of the same command-line options you'd use for programs in any language, options meaningful for C and related languages, or options that only matter 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 GCC features that clash with ISO C90 (when compiling C code) or standard C++ (when compiling C++ code). Think the asm and typeof keywords, and predefined macros like 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 also disables recognition of C++ style // comments, plus the inline keyword ๐
The alternate keywords __asm__, __extension__, __inline__ and __typeof__ keep working even with -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 like __unix__ and __vax__ are also available, with or without -ansi ๐
The -ansi option doesn't reject non-ISO programs left and right. For that, you need -Wpedantic in addition to -ansi ๐ง
The macro __STRICT_ANSI__ is predefined when -ansi is used. Some header files might notice this macro and hold back from declaring certain functions or defining certain macros that the ISO standard doesn't call for. This avoids messing with programs that use those names for other things ๐ซถ
Functions that are normally built in but don't have semantics defined by ISO C (like alloca and ffs) are not built-in functions when -ansi is used ๐ซ
-std=โ determines the language standard. This option is currently only supported when compiling C or C++ ๐ธ
okay so bestie, -std is where things get spicy ๐ถ๏ธโจ you can pick a base standard like c90 or c++98, or a GNU dialect of one like gnu90 or gnu++98 ๐
with a base standard, GCC takes every program that follows that standard, plus any GNU extensions that don't clash with it ๐ for example, -std=c90 switches off GCC features that aren't ISO C90 compatible, like the asm and typeof keywords ๐ but it keeps other GNU extensions that don't mean anything in ISO C90, like leaving out the middle term of a ?: expression ๐
then there's the GNU dialect side, and it's lowkey a different vibe ๐ญ when you pick one, every feature the compiler supports gets turned on, even the ones that change what the base standard means ๐ฅ so, ngl, some strict-conforming programs might get rejected ๐ -Wpedantic uses whichever standard you picked to decide which features count as GNU extensions ๐ฆ so -std=gnu90 -Wpedantic will warn you about C++ style // comments, but -std=gnu99 -Wpedantic won't ๐
you must give this option a value, and these are your choices ๐ซถ
c90,c89,iso9899:1990โ full ISO C90 support, with the GNU extensions that clash with ISO C90 switched off ๐ this is the same as-ansifor C code โจiso9899:199409โ ISO C90 with amendment 1 baked in ๐ธc99,c9x,iso9899:1999,iso9899:199xโ ISO C99 ๐ฆ it's substantially completely supported, modulo bugs and floating-point issues (mostly, but not entirely, around optional C99 features from Annexes F and G) ๐ check<http://gcc.gnu.org/c99status.html>for the tea โ the namesc9xandiso9899:199xare deprecated, so retire them, bestie ๐c11,c1x,iso9899:2011โ ISO C11, the 2011 revision ๐ also substantially completely supported, modulo bugs and floating-point issues (mostly around optional C11 features from Annexes F and G) plus the optional Annexes K (Bounds-checking interfaces) and L (Analyzability) ๐c1xis deprecated ๐c17,c18,iso9899:2017,iso9899:2018โ ISO C17, the 2017 revision (published in 2018) ๐ it's the same as C11 except for defect corrections (all of which are also applied with-std=c11) and a new value of__STDC_VERSION__โจ so it gets the same level of support as C11 ๐ซถc2xโ the next version of ISO C, still cooking ๐ง support is experimental and incomplete, so be careful ๐gnu90,gnu89โ the GNU dialect of ISO C90, which also picks up some C99 features ๐gnu99,gnu9xโ the GNU dialect of ISO C99 ๐gnu9xis deprecated ๐gnu11,gnu1xโ the GNU dialect of ISO C11 ๐ฅgnu1xis deprecated ๐gnu17,gnu18โ the GNU dialect of ISO C17 ๐ this is the default for C code ๐gnu2xโ the next ISO C version plus GNU extensions ๐ธ support is experimental and incomplete โจc++98,c++03โ the 1998 ISO C++ standard plus the 2003 technical corrigendum and some extra defect reports ๐ฆ this is the same as-ansifor C++ code ๐gnu++98,gnu++03โ the GNU dialect of-std=c++98๐c++11,c++0xโ the 2011 ISO C++ standard plus amendments ๐c++0xis deprecated, so switch over ๐gnu++11,gnu++0xโ the GNU dialect of-std=c++11๐ซถgnu++0xis deprecated โจc++14,c++1yโ the 2014 ISO C++ standard plus amendments ๐c++1yis deprecated ๐gnu++14,gnu++1yโ the GNU dialect of-std=c++14๐ this is the default for C++ code ๐ฅgnu++1yis deprecated ๐c++17,c++1zโ the 2017 ISO C++ standard plus amendments ๐c++1zis deprecated ๐gnu++17,gnu++1zโ the GNU dialect of-std=c++17โจgnu++1zis deprecated ๐c++20,c++2aโ the next revision of ISO C++, planned for 2020 ๐ง support is highly experimental, and it will almost certainly change in incompatible ways in future releases ๐gnu++20,gnu++2aโ the GNU dialect of-std=c++20๐ฆ support is highly experimental too, and it'll almost certainly change in incompatible ways in future releases ๐
-fgnu89-inline
okay, so this one tells GCC to use the traditional GNU semantics for inline functions when you're in C99 mode ๐ธ using it is roughly the same as slapping the gnu_inline function attribute on every inline function ๐ซถ
-fno-gnu89-inline does the opposite and tells GCC to use the C99 semantics for inline when you're in C99 or gnu99 mode ๐
(it's the default behavior, so it's basically just being explicit ๐) and it's not supported in -std=c90 or -std=gnu90 mode ๐
the preprocessor macros __GNUC_GNU_INLINE__ and __GNUC_STDC_INLINE__ can be used to check which inline semantics are in effect ๐ฅ
-fpermitted-flt-eval-methods=style
ISO/IEC TS 18661-3 adds new allowed values for FLT_EVAL_METHOD ๐ฆ these say that operations and constants with a semantic type that's an interchange or extended format should be evaluated to the precision and range of that type โจ the new values are a superset of what C99/C11 allows, and C99/C11 doesn't say what any other positive values of FLT_EVAL_METHOD mean ๐ so code that follows C11 might never have expected the new values, bestie ๐ญ
-fpermitted-flt-eval-methods lets you decide whether the compiler only allows the FLT_EVAL_METHOD values from C99/C11, or the extended set from ISO/IEC TS 18661-3 ๐
style is either c11 or ts-18661-3, whichever fits ๐
the default in a standards compliant mode (like -std=c11 or similar) is -fpermitted-flt-eval-methods=c11 ๐ the default in a GNU dialect (like -std=gnu11 or similar) is -fpermitted-flt-eval-methods=ts-18661-3 ๐
-aux-info filename
this one writes prototyped declarations for every function declared and/or defined in a translation unit into the given filename ๐ง that includes functions in header files too ๐ it's silently ignored in any language that isn't C ๐ซถ
the file also has comments telling you where each declaration came from (source file and line) ๐ the character right after the line number and colon tells you whether the declaration was implicit, prototyped, or unprototyped: I, N for new, or O for old, respectively ๐ the character after that tells you whether it came from a declaration or a definition: C or F, respectively ๐ธ for function definitions, you also get a K&R-style list of arguments followed by their declarations, tucked inside comments after the declaration ๐ฆ
-fallow-parameterless-variadic-functions
this one accepts variadic functions without named parameters โจ you can define one, but it's not very useful because you can't read the arguments ๐ it's only supported for C, since C++ already allows this construct ๐
-fno-asm
this stops GCC from treating asm, inline, or typeof as keywords, so your code can use those words as identifiers ๐
you can use __asm__, __inline__, and __typeof__ instead ๐ -ansi implies -fno-asm ๐
in C++, this switch only affects the typeof keyword, since asm and inline are standard keywords there ๐ฅ you might want to use -fno-gnu-keywords instead, which has the same effect ๐ in C99 mode (-std=c99 or -std=gnu99), it only affects the asm and typeof keywords, since inline is a standard keyword in ISO C99 ๐ฆ
-fno-builtin, -fno-builtin-function
this tells GCC not to recognize built-in functions that don't start with the prefix __builtin_ ๐ซถ
GCC usually generates special code for certain built-in functions so they run faster ๐ for example, calls to alloca can turn into single instructions that adjust the stack directly, and calls to memcpy can become inline copy loops ๐ธ the code is often smaller and faster, but since those calls don't show up as calls anymore, you can't set a breakpoint on them, and you can't change what they do by linking with a different library ๐ญ also, once a function counts as built-in, GCC can use that info to warn you about problems with calls to it, or to generate better code, even if the result still contains calls to that function ๐ for example, you get -Wformat warnings for bad calls to printf when printf is built in, and strlen is known not to modify global memory ๐
with -fno-builtin-function, only that one built-in function gets disabled ๐ function must not begin with __builtin_ ๐
if the function you name isn't built-in in this version of GCC, the option is just ignored โจ there's no matching -fbuiltin-function option, so if you want to pick built-in functions one at a time with -fno-builtin or -ffreestanding, you can define macros like these ๐ง
#define abs(n) __builtin_abs ((n))
#define strcpy(d, s) __builtin_strcpy ((d), (s))
-fgimple
this enables parsing of function definitions marked with __GIMPLE ๐งช it's an experimental feature that lets you unit test GIMPLE passes ๐ฅ
-fhosted
this asserts that compilation targets a hosted environment, and it implies -fbuiltin ๐ a hosted environment is one where the entire standard library is available, and main has a return type of int ๐ซถ think basically everything except a kernel ๐
this is equivalent to -fno-freestanding ๐
-ffreestanding
this asserts that compilation targets a freestanding environment, and it implies -fno-builtin ๐ฆ a freestanding environment is one where the standard library might not exist, and program startup might not necessarily begin at main ๐ญ the most obvious example is an OS kernel ๐ this is equivalent to -fno-hosted ๐
-fopenaccโ okay so this one turns on handling for OpenACC directives, which means#pragma accin C/C++ and!$accin Fortran ๐ . With it on, the compiler generates accelerated code following the OpenACC Application Programming Interface v2.6<https://www.openacc.org>. It also implies-pthread, so it only works on targets that support-pthread๐ง-fopenacc-dim=geomโ bestie, this sets the default compute dimensions for parallel offload regions that don't specify their own ๐geomis a triple of sizes separated by:, in the ordergang,workerandvector. You can leave any size out to get a target-specific default โจ-fopenmpโ this one enables handling of OpenMP directives,#pragma ompin C/C++ and!$ompin Fortran ๐ฅ With it on, the compiler generates parallel code following the OpenMP Application Program Interface v4.5<https://www.openmp.org>. It implies-pthread, so again, only on targets that support-pthread. It also implies-fopenmp-simd๐-fopenmp-simdโ the lowkey version of the above ๐ฆ It turns on handling of OpenMP's SIMD directives written as#pragma ompin C/C++ and!$ompin Fortran. Every other OpenMP directive just gets ignored ๐-fgnu-tmโ this is the transactional memory one ๐ With-fgnu-tm, the compiler generates code for the Linux variant of Intel's current Transactional Memory ABI specification document (Revision 1.1, May 6 2009). Heads up, it's experimental, so the interface might change in future GCC versions as the official spec changes. Also not every architecture supports it, so check before you get attached ๐
For more information on GCC's support for transactional memory,
Note that the transactional memory feature is not supported with non-call exceptions (-fnon-call-exceptions).
-fms-extensionsโ accept some non-standard constructs that show up in Microsoft header files ๐ In C++ code, this lets member names in structures match earlier type declarations, which is giving chaotic but valid. Like this:
typedef int UOW;
struct ABC {
UOW UOW;
};
Some cases of unnamed fields in structures and unions only get accepted with this option ๐ซถ Also, this option is off for all targets except x86 targets using ms-abi.
-fplan9-extensionsโ accept some non-standard constructs from Plan 9 code ๐ธ This turns on-fms-extensions, lets you pass pointers to structures with anonymous fields into functions that expect pointers to elements of the field's type, and lets you refer to anonymous fields declared with a typedef. It's only supported for C, not C++, so don't try it in your C++ era ๐ โโ๏ธ-fcond-mismatchโ allow conditional expressions with mismatched types in the second and third arguments ๐ The value of that kind of expression isvoid. Not supported for C++ ๐-flax-vector-conversionsโ allow implicit conversions between vectors with different numbers of elements and/or incompatible element types ๐ญ This option should not be used for new code, so save it for the old stuff.-funsigned-charโ let the typecharbe unsigned, likeunsigned char๐ Every machine has a default for whatcharshould be. It's either likeunsigned charby default or likesigned charby default. Ideally, a portable program always usessigned charorunsigned charwhenever it cares about signedness. But plenty of programs were written with plaincharand expect it to be signed or unsigned depending on the machine they were built for. This option and its inverse let you make those programs work with the opposite default ๐ง The typecharis always its own distinct type from bothsigned charandunsigned char, even though it behaves exactly like one of them.-fsigned-charโ let the typecharbe signed, likesigned charโจ This is equivalent to-fno-unsigned-char, which is the negative form of-funsigned-char. And the other way around:-fno-signed-charis equivalent to-funsigned-char๐ฆ-fsigned-bitfields,-funsigned-bitfields,-fno-signed-bitfields,-fno-unsigned-bitfieldsโ these control whether a bit-field is signed or unsigned when the declaration doesn't use eithersignedorunsigned๐ By default, a bit-field is signed, and that's honestly the consistent choice, since basic integer types likeintare signed too ๐-fsso-struct=endiannessโ set the default scalar storage order of structures and unions to the endianness you pick ๐ฅ The accepted values arebig-endian,little-endian, andnative, which is the native endianness of the target and also the default. This option is not supported for C++ ๐
Warning: the -fsso-struct switch causes GCC to generate code that is not binary compatible with code generated without it if the specified endianness is not the native endianness of the target. Read that twice, bestie ๐
๐ Options Controlling C++ Dialect ๐
This section covers the command-line options that only matter for C++ programs ๐ You can still use most GNU compiler options no matter what language your program is in. For example, you might compile a file firstClass.C like this:
g++ -g -fstrict-enums -O -c firstClass.C
In that example, only -fstrict-enums is meant only for C++ programs. You can use the other options with any language GCC supports โจ
Some options for compiling C programs, such as -std, are also relevant for C++ programs ๐ซถ
Here is a list of options that are only for compiling C++ programs:
-fabi-version=nโ use versionnof the C++ ABI ๐ The default is version 0.- Version 0 refers to the version that conforms most closely to the C++ ABI specification. Because of that, the ABI you get with version 0 will change across G++ versions as ABI bugs get fixed ๐
- Version 1 is the version of the C++ ABI that first appeared in G++ 3.2 ๐ธ
- Version 2 is the version of the C++ ABI that first appeared in G++ 3.4, and it was the default through G++ 4.9 ๐
- Version 3 corrects an error in mangling a constant address as a template argument ๐
- Version 4, which first appeared in G++ 4.5, implements a standard mangling for vector types ๐ฆ
- Version 5, which first appeared in G++ 4.6, corrects the mangling of attribute const/volatile on function pointer types, decltype of a plain decl, and use of a function parameter in the declaration of another parameter ๐ง
- Version 6, which first appeared in G++ 4.7, corrects the promotion behavior of C++11 scoped enums and the mangling of template argument packs, const/static_cast, prefix ++ and --, and a class scope function used as a template argument โญ
- Version 7, which first appeared in G++ 4.8, treats
nullptr_tas a builtin type and corrects the mangling of lambdas in default argument scope ๐ - Version 8, which first appeared in G++ 4.9, corrects the substitution behavior of function types with function-cv-qualifiers ๐
- Version 9, which first appeared in G++ 5.2, corrects the alignment of
nullptr_t๐ - Version 10, which first appeared in G++ 6.1, adds mangling of attributes that affect type identity, such as ia32 calling convention attributes (e.g. stdcall) ๐ฅ
- Version 11, which first appeared in G++ 7, 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, which first appeared in G++ 8, corrects the calling conventions for empty classes on the x86_64 target 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, which first appeared in G++ 8.2, fixes the accidental change in version 12 ๐
- Version 14, which first appeared in G++ 10, corrects the mangling of the nullptr expression ๐
See also -Wabi.
-fabi-compat-version=nโ on targets that support strong aliases, G++ works around mangling changes by creating an alias with the correct mangled name whenever it defines a symbol with an incorrect mangled name ๐ง This switch picks which ABI version to use for that alias.
With -fabi-version=0 (the default), this defaults to 11 (GCC 7 compatibility). If you explicitly select another ABI version, it defaults to 0. For 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 (without a version), the version from this option is used for the warning ๐
-fno-access-controlโ turns off all access checking ๐ This switch is mainly useful for working around bugs in the access control code, so it's more of a last-resort move ๐-faligned-newโ enables support for C++17newof types that need more alignment thanvoid* ::operator new(std::size_t)provides โจ You can pass a numeric argument like-faligned-new=32to say how much alignment (in bytes) that function provides, but very few users will need to override the default ofalignof(std::max_align_t)๐ฆ
This flag is enabled by default for -std=c++17 ๐
-fchar8_t,-fno-char8_tโ enable support forchar8_tas adopted for C++2a ๐ This adds a brand-newchar8_tfundamental type, changes the types of UTF-8 string and character literals, adds new signatures for user-defined literals, comes with standard library updates, and adds the new__cpp_char8_tand__cpp_lib_char8_tfeature test macros ๐
This option lets you overload functions for ordinary strings and UTF-8 strings:
int f(const char *); // #1
int f(const char8_t *); // #2
int v1 = f("text"); // Calls #1
int v2 = f(u8"text"); // Calls #2
and it introduces new signatures for user-defined literals:
int operator""_udl1(char8_t);
int v3 = u8'x'_udl1;
int operator""_udl2(const char8_t*, std::size_t);
int v4 = u8"text"_udl2;
template<typename T, T...> int operator""_udl3();
int v5 = u8"text"_udl3;
The UTF-8 literal change is a real heads-up, bestie ๐ซถ It breaks code that compiles fine under ISO C++11 and later, and that includes these lines 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
โจ OPTIONS (continued) โจ
-fcheck-newโ ๐ This makes G++ check that the pointeroperator newhands back isn't null before it starts writing into that storage. Honestly you usually don't need it, because the standard saysoperator newonly returns 0 when it's declaredthrow(), and in that case the compiler checks the return value anyway, even without this flag. For every other case, whenoperator newhas a non-empty exception specification, running out of memory gets signalled by throwingstd::bad_allocinstead. See alsonew (nothrow)๐ง-fconcepts,-fconcepts-tsโ ๐ฆ Below-std=c++2a,-fconceptsturns on support for the C++ Extensions for Concepts Technical Specification, ISO 19217 (2015). With-std=c++2aand above, Concepts are officially part of the language, so-fconceptsis on by default. The standard version of Concepts is quite different from the TS though, so a few things the TS allowed but the standard dropped can still be turned on with-fconcepts-ts๐-fconstexpr-depth=nโ ๐ Sets the maximum nested evaluation depth for C++11constexprfunctions ton. The limit is what catches endless recursion while constant expressions are being evaluated. The standard's minimum is 512 โจ-fconstexpr-cache-depth=nโ ๐ Sets the deepest nesting level of C++11constexprfunction evaluation that gets cached, ton. It's a heuristic balancing compile speed (the cache skips repeated work) against memory (the cache can balloon with really recursive evaluations). The default is 8. Very few people need to touch it, but if your code does heavyconstexprmath, feel free to experiment and see which value slaps the hardest for you ๐ฅ-fconstexpr-loop-limit=nโ ๐ Sets the maximum number of iterations for a loop in C++14constexprfunctions ton. This is the safety net that catches infinite loops during constant expression evaluation. The default is 262144 (1<<18) ๐ธ-fconstexpr-ops-limit=nโ ๐ซง Sets the maximum number of operations allowed during a singleconstexprevaluation. The loop limit above still applies per loop, but you can end up with several nested loops that each stay under that limit and still take forever together. Or a loop body, or even code outside any loop, can have so many expressions to evaluate that the wholeconstexprevaluation drags on too long. This flag is there to cap that. The default is 33554432 (1<<25) ๐ญ-fcoroutinesโ ๐งช Turns on support for the C++ coroutines extension. It's experimental, so be a little careful with it ๐-fno-elide-constructorsโ ๐ The C++ standard lets an implementation skip making a temporary that only exists to initialize another object of the same type. This flag turns that optimization off and makes G++ call the copy constructor every single time. It also makes G++ call trivial member functions that would otherwise get expanded inline. In C++17, the compiler is required to skip these temporaries, but this flag still affects trivial member functions ๐-fno-enforce-eh-specsโ ๐ง Skips generating the code that checks for exception specification violations at run time. This goes against the C++ standard, but it can be useful for shrinking code size in production builds, kind of like definingNDEBUG. It doesn't give your code permission to throw exceptions that break the exception specifications, though. The compiler still optimizes based on those specs, so if you throw an unexpected exception, you get undefined behavior at run time. Yikes ๐ฌ-fextern-tls-init,-fno-extern-tls-initโ ๐งต The C++11 and OpenMP standards letthread_localandthreadprivatevariables have dynamic (run-time) initialization. To make that work, any use of such a variable goes through a wrapper function that does whatever initialization is needed. When the use and the definition are in the same translation unit, the compiler can optimize that overhead away. But when the use is in a different translation unit, there's a big overhead even if the variable never actually needs dynamic initialization. If you can be sure that no use in a non-defining TU needs to trigger the dynamic initialization (because the variable is statically initialized, or because a use in the defining TU always runs before any use in another TU), 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 don't support symbol aliases, the default is-fno-extern-tls-initโจ-fno-gnu-keywordsโ ๐ Stopstypeoffrom being treated as a keyword, so your code can use that word as an identifier. You can use the keyword__typeof__instead. This option is implied by the strict ISO C++ dialects, like-ansi,-std=c++98,-std=c++11, and so on ๐-fno-implicit-templatesโ ๐ฏ Never emits code for non-inline templates that get instantiated implicitly (that is, by use). Only explicit instantiations get code emitted. If you use this, you have to be careful to structure your code so it includes all the explicit instantiations you need, or you'll get undefined symbols at link time ๐ต-fno-implicit-inline-templatesโ ๐ Doesn't emit code for implicit instantiations of inline templates either. By default, inlines are handled differently so that compiles with and without optimization need the same set of explicit instantiations ๐ฆข-fno-implement-inlinesโ ๐ชถ To save space, this skips emitting out-of-line copies of inline functions controlled by#pragma implementation. Heads-up: if those functions don't get inlined everywhere they're called, you'll get linker errors ๐-fms-extensionsโ ๐ช Disables-Wpedanticwarnings about constructs used in MFC, like implicitintand getting a pointer to a member function through non-standard syntax ๐ผ-fnew-inheriting-ctorsโ ๐งฌ Enables the P0136 change to how C++11 constructor inheritance works. It's part of C++17, but it's also considered a Defect Report against C++11 and C++14. This flag is on by default unless-fabi-version=10or lower is specified ๐-fnew-ttp-matchingโ ๐ญ Enables the P0522 resolution to Core issue 150, which covers template template parameters and default arguments. It lets a template with default template arguments be passed as an argument for a template template parameter that has fewer template parameters. This flag is on by default for-std=c++17๐งฉ-fno-nonansi-builtinsโ ๐ซ Disables the built-in declarations of functions that aren't mandated by ANSI/ISO C. These includeffs,alloca,_exit,index,bzero,conjf, and other related functions ๐-fnothrow-optโ ๐ช Treats athrow()exception specification as if it were anoexceptspecification. That can reduce or wipe out the text size overhead compared to a function with no exception specification. If the function has local variables with types that have non-trivial destructors, the exception specification actually makes the function smaller, since the EH cleanups for those variables can be optimized away. The semantic effect is that an exception thrown out of a function with this kind of exception specification callsterminateinstead ofunexpected๐จ-fno-operator-namesโ ๐ค Stops the operator name keywordsand,bitand,bitor,compl,not,or, andxorfrom being treated as synonyms for the operators they stand for ๐ โโ๏ธ-fno-optional-diagsโ ๐ Disables diagnostics that the standard says a compiler doesn't need to issue. Right now, the only one G++ issues in that category is the one for a name that has multiple meanings within a class ๐ซฅ-fpermissiveโ ๐ง Downgrades some diagnostics about nonconformant code from errors to warnings. So-fpermissivelets some nonconforming code compile, which is a little bit of a bend-the-rules move ๐-fno-pretty-templatesโ ๐๏ธ When an error message points at a specialization of a function template, the compiler normally prints the template's signature, followed by the template arguments and any typedefs or typenames in that signature. For example, you'd seevoid f(T) [with T = int]instead ofvoid f(int), so it's clear which template is involved. When an error message points at a specialization of a class template, the compiler leaves out any template arguments that match that template's default arguments. If either of those behaviors makes errors harder to read instead of easier, use-fno-pretty-templatesto turn them off ๐-fno-rttiโ ๐ง Disables generating the run-time type information for every class with virtual functions, which the C++ run-time type identification features (dynamic_castandtypeid) use. If you don't use those parts of the language, this flag can save some space. Exception handling uses the same information, but G++ generates it only when it's needed. Thedynamic_castoperator still works for casts that don't need run-time type information, meaning casts tovoid *or to unambiguous base classes ๐ธ
โ ๏ธ Mixing code compiled with-frttiwith code compiled with-fno-rttimay not work. For example, programs may fail to link if a class compiled with-fno-rttiis used as a base for a class compiled with-frtti.
-fsized-deallocationโ okay bestie, this one is giving global deallocation ๐งนโจ It turns on the built-in global declarations introduced in C++14, which are:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
These are so useful for your own replacement deallocation functions, like ones that use the object's size to make deallocation faster ๐๏ธ๐จ. It's enabled by default under -std=c++14 and above. And -Wsized-deallocation is the warning that calls out places that might want to add a definition ๐.
-fstrict-enumsโ the compiler gets to optimize while assuming a value of an enumerated type can only be one of the enumeration's values ๐ . This follows the C++ standard, so basically it's a value that fits in the minimum number of bits needed to represent all the enumerators. Heads up though: this assumption may not hold if the program uses a cast to turn some arbitrary integer into the enumerated type ๐.-fstrong-eval-orderโ this slays ๐ฅ It evaluates member access, array subscripting, and shift expressions left-to-right, and assignment right-to-left, as adopted for C++17. It's on by default with-std=c++17.-fstrong-eval-order=someonly enables the ordering of member access and shift expressions, and it's the default without-std=c++17.-ftemplate-backtrace-limit=nโ sets the max number of template instantiation notes for a single warning or error to n ๐. The default is10.-ftemplate-depth=nโ sets the max instantiation depth for template classes to n ๐. You need a limit here so the compiler can catch endless recursions during template class instantiation. ANSI/ISO C++ conforming programs must not rely on a maximum depth greater than17(changed to1024in C++11) ๐ โโ๏ธ. The default is900, because the compiler can run out of stack space before hitting1024in some situations ๐ฅ.-fno-threadsafe-staticsโ no extra code for thread-safe initialization of local statics via the routines from the C++ ABI ๐งต๐ซ. Use this to shave a little code size off code that doesn't need to be thread-safe ๐ธ.-fuse-cxa-atexitโ registers destructors for objects with static storage duration using__cxa_atexitinstead 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 the runtime routine isn't available.-fvisibility-inlines-hiddenโ this switch is a promise ๐ค that you won't compare pointers to inline functions or methods where the addresses of the two functions 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 within the DSO ๐ง. Enabling this option can have a dramatic effect on load and link times of a DSO, because it massively reduces the size of the dynamic export table when the library makes heavy use of templates ๐.
This isn't quite the same as marking the methods as hidden directly, because it doesn't affect static variables local to the function, and it doesn't cause the compiler to deduce that the function is defined in only one shared object ๐ค.
You can mark a method with an explicit visibility to negate the effect of the switch for that method. For example, if you do want to compare pointers to a particular inline method, you might mark it as having default visibility. Marking the enclosing class with explicit visibility has no effect ๐.
Explicitly instantiated inline methods are unaffected by this option, since their linkage might otherwise cross a shared library boundary ๐ง.
-fvisibility-ms-compatโ this flag tries to use visibility settings to make GCC's C++ linkage model compatible with Microsoft Visual Studio ๐ช๐. It makes these changes to GCC's linkage model:- It sets the default visibility to
hidden, like-fvisibility=hidden. - Types, but not their members, are not hidden by default.
- The One Definition Rule is relaxed for types without explicit visibility specifications that are defined in more than one shared object: those declarations are permitted if they're permitted when this option isn't used.
- It sets the default visibility to
In new code it's better to use -fvisibility=hidden and export the classes that are meant to be externally visible ๐
. Unfortunately, it's possible for code to rely on the Visual Studio behavior, perhaps accidentally ๐ฌ.
Among the consequences of these changes: static data members of the same type, with the same name, but defined in different shared objects are different, so changing one doesn't change the other ๐ซ . Pointers to function members defined in different shared objects may also not compare equal. When this flag is given, it's a violation of the ODR to define types with the same name differently ๐ซ.
-fno-weakโ don't use weak symbol support, even if the linker provides it ๐ . By default, G++ uses weak symbols if they're available. This option exists only for testing and should not be used by end-users, since it results in inferior code and has no benefits ๐ฅ. It may be removed in a future release of G++.-fext-numeric-literals(C++ and Objective-C++ only) โ accepts imaginary, fixed-point, or machine-defined literal number suffixes as GNU extensions โจ. When this option is turned off, these suffixes are treated as C++11 user-defined literal numeric suffixes. This is on by default for all pre-C++11 dialects and all GNU dialects:-std=c++98,-std=gnu++98,-std=gnu++11,-std=gnu++14. It's off by default for ISO C++11 onwards (-std=c++11, ...).-nostdinc++โ don't search for header files in the standard directories specific to C++, but do still search the other standard directories ๐. (This option is used when building the C++ library ๐๏ธ.)
In addition, these warning options have meanings only for C++ programs: ๐
-Wabi-tag(C++ and Objective-C++ only) โ warns when a type with an ABI tag is used in a context that doesn't have that ABI tag ๐ท๏ธ. See C++ Attributes for more information about ABI tags.-Wcomma-subscript(C++ and Objective-C++ only) โ warns about uses of a comma expression within a subscripting expression ๐. This usage was deprecated in C++2a. However, a comma expression wrapped in( )is not deprecated. Example:
void f(int *a, int b, int c) {
a[b,c]; // deprecated
a[(b,c)]; // OK
}
Enabled by default with -std=c++2a.
-Wctor-dtor-privacy(C++ and Objective-C++ only) โ warns when a class seems unusable because all of its constructors or destructors are private, and it has neither friends nor public static member functions ๐. It also warns if there are no non-private methods, and there's at least one private member function that isn't a constructor or destructor.-Wdelete-non-virtual-dtor(C++ and Objective-C++ only) โ warns whendeleteis used to destroy an instance of a class that has virtual functions and a non-virtual destructor ๐. It's unsafe to delete an instance of a derived class through a pointer to a base class if the base class doesn't have a virtual destructor. This warning is enabled by-Wall.-Wdeprecated-copy(C++ and Objective-C++ only) โ warns that the implicit declaration of a copy constructor or copy assignment operator is deprecated if the class has a user-provided copy constructor or copy assignment operator, in C++11 and up ๐. This warning is enabled by-Wextra. With-Wdeprecated-copy-dtor, it also deprecates the implicit declaration if the class has a user-provided destructor.-Wno-init-list-lifetime(C++ and Objective-C++ only) โ don't warn about uses ofstd::initializer_listthat are likely to leave you with dangling pointers ๐ซฃ. The underlying array for aninitializer_listis handled like a normal C++ temporary object, so it's easy to accidentally keep a pointer to the array past the end of the array's lifetime. For example:- If a function returns a temporary
initializer_list, or a localinitializer_listvariable, the array's lifetime ends at the end of the return statement, so the value returned has a dangling pointer. - If a new-expression creates an
initializer_list, the array only lives until the end of the enclosing full-expression, so theinitializer_listin the heap has a dangling pointer. - When an
initializer_listvariable is assigned from a brace-enclosed initializer list, the temporary array created for the right side of the assignment only lives until the end of the full-expression, so at the next statement theinitializer_listvariable has a dangling pointer.
- 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, this doesn't extend the lifetime of the array, so if a class variable is constructed from a temporaryinitializer_list, the pointer is left dangling by the end of the variable declaration statement.
-Wno-literal-suffix(C++ and Objective-C++ only) โ don't warn when a string or character literal is followed by a ud-suffix that doesn't begin with an underscore ๐. As a conforming extension, GCC treats such suffixes as separate preprocessing tokens, in order to maintain backwards compatibility with code that uses formatting macros from<inttypes.h>. For example:
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <stdio.h>
int main() {
int64_t i64 = 123;
printf("My int64: %" PRId64"\n", i64);
}
Look at that, bestie ๐ In this case, PRId64 gets treated as its own separate preprocessing token ๐ง
This option also keeps an eye on user-defined literal operators that get declared with a literal suffix identifier which doesn't start with an underscore ๐ Those names are reserved for future standardization, so GCC is basically like "hey, hands off" ๐
These warnings are enabled by default โจ
-Wno-narrowing(C++ and Objective-C++ only) โ okay so, for C++11 and later, GCC catches narrowing conversions by default, because the standard says so ๐ค A narrowing conversion from a constant is an error, and a narrowing conversion from a non-constant is a warning.-Wno-narrowingshuts that diagnostic up ๐ Just know that this doesn't change what well-formed code means. Narrowing conversions are still ill-formed in SFINAE contexts, so no sneaky loopholes, periodt ๐-Wnarrowing(C++ and Objective-C++ only) โ in C++98, this one 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 anoexcept-expression evaluates tofalsebecause of a call to a function that doesn't have a non-throwing exception specification (that'sthrow()or"noexcept"), even though the compiler knows it never actually throws ๐ธ Main character drama, but make it compiler-approved.-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 they gave:
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>. Iconic glow-up, no cap โจ
-Wclass-memaccess(C++ and Objective-C++ only) โ warns when the destination of a raw memory function likememsetormemcpyis an object of class type, and when writing into that object might bypass a non-trivial or deleted constructor or copy assignment, break const-correctness or encapsulation, or corrupt virtual table pointers. Messing with the representation of these objects can violate invariants that the class member functions depend on ๐ญ Here, thememsetcall is undefined because it modifies a non-trivial class object, so GCC diagnoses it:
std::string str = "abc";
memset (&str, 0, sizeof str);
The safe move is to initialize or clear these objects with the appropriate constructor or assignment operator, if one exists ๐ซถ -Wclass-memaccess is enabled by -Wall. If you explicitly cast the pointer to the class object to void *, or to a type that the raw memory function can safely access, the warning goes away ๐
-Wnon-virtual-dtor(C++ and Objective-C++ only) โ warns when a class has virtual functions and an accessible non-virtual destructor, either on itself or on an accessible polymorphic base class. That makes it possible (but unsafe) to delete a derived-class instance through a pointer to the class or base class ๐ โโ๏ธ This warning is automatically enabled if-Weffc++is specified.-Wregister(C++ and Objective-C++ only) โ warns on uses of theregisterstorage class specifier, unless it's part of the GNU Explicit Register Variables extension. Theregisterkeyword was deprecated in C++11 and removed in C++17, so it's enabled by default with-std=c++17๐-Wreorder(C++ and Objective-C++ only) โ warns when the order of member initializers in the code doesn't match the order they actually have to run in. For example:
struct A {
int i;
int j;
A(): j (0), i (1) { }
};
GCC rearranges the initializers for i and j to match the declaration order of the members, and emits a warning about it. This warning is enabled by -Wall ๐
-Wno-pessimizing-move(C++ and Objective-C++ only) โ this warning goes off when a call tostd::moveprevents copy elision. Copy elision typically happens when you return from a function with a class return type, the expression being returned is the name of a non-volatile automatic object (and not a function parameter), and it has the same type as the function's return type. Here's the example:
struct T {
...
};
T fn()
{
T t;
...
return std::move (t);
}
In this example, the std::move call prevents copy elision, so it's pessimizing your code ๐ค This warning is enabled by -Wall.
-Wno-redundant-move(C++ and Objective-C++ only) โ this warning calls out redundantstd::movecalls, meaning a move would have happened even without thestd::move. It happens because the compiler gets forced to treat an 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 ๐
Because G++ implements Core Issue 1579, there's another example:
struct T { // convertible to U
...
};
struct U {
...
};
U fn()
{
T t;
...
return std::move (t);
}
In this one, copy elision isn't applicable, because the type of the returned expression and the function return type differ. Even so, G++ treats the return value as if it were designated by an rvalue ๐ฆ This warning is enabled by -Wextra.
-Wredundant-tags(C++ and Objective-C++ only) โ warns about redundant class-key and enum-key in references to class and enumerated types, in spots where the key could be dropped without creating an ambiguity. For example:
struct foo;
struct foo *p; // warn that keyword struct can be eliminated
But in this example, there's no warning, because the keyword is needed to avoid confusion with the function:
struct foo;
void foo (); // "hides" struct foo
void bar (struct foo&); // no warning, keyword struct is necessary
-Wno-subobject-linkage(C++ and Objective-C++ only) โ don't warn if a class type has a base or a field whose type uses the anonymous namespace or depends on a type with no linkage ๐ Here's the tea: if a type A depends on a type B with no or internal linkage, defining it in multiple translation units would be an ODR violation, because B means something different in each translation unit. If A only shows up in a single translation unit, the best way to silence the warning is to give it internal linkage by putting it in an anonymous namespace too. GCC doesn't warn for types defined in the main.Cfile, since those are unlikely to have multiple definitions.-Wsubobject-linkageis enabled by default.-Weffc++(C++ and Objective-C++ only) โ warns about violations of the following style guidelines from Scott Meyers' Effective C++ series of books ๐ bestie, these are the iconic rules:- Define a copy constructor and an assignment operator for classes with dynamically-allocated memory.
- Prefer initialization to assignment in constructors.
- Have
operator=return a reference to*this. - Don't try to return a reference when you must return an object.
- Distinguish between prefix and postfix forms of increment and decrement operators.
- Never overload
&&,||, or,.
This option also enables -Wnon-virtual-dtor, which is also one of the effective C++ recommendations. However, the check is extended to warn about the lack of a virtual destructor in accessible non-polymorphic base classes too ๐ซถ Heads up, though: the standard library headers don't obey all of these guidelines, so when you select this option, use grep -v to filter out those warnings ๐
-Wstrict-null-sentinel(C++ and Objective-C++ only) โ warns about using an uncastedNULLas a sentinel. When compiling only with GCC, this is a valid sentinel, becauseNULLis defined to__null. Even though it's a null pointer constant rather than a null pointer, it's guaranteed to be the same size as a pointer. But this use isn't portable across different compilers, so GCC wants you to know ๐-Wno-non-template-friend(C++ and Objective-C++ only) โ disables warnings when non-template friend functions get declared within a template. In very old versions of GCC that predate the ISO standard implementation, declarations likefriend int foo(int), where the friend's name is an unqualified-id, could be interpreted as a particular specialization of a template function. The warning exists to diagnose compatibility problems, and it's enabled by default ๐ธ-Wold-style-cast(C++ and Objective-C++ only) โ warns if an old-style (C-style) cast to a non-void type is used in a C++ program. The new-style casts (dynamic_cast,static_cast,reinterpret_cast, andconst_cast) are less vulnerable to unintended effects and way easier to search for ๐ Glow up your casts, bestie ๐-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);
};
Here, the A class version of f is hidden in B, and code like this:
B* b;
b->f();
fails to compile ๐
-Wno-pmf-conversions(C++ and Objective-C++ only) โ disables the diagnostic for converting a bound pointer to member function into a plain pointer ๐ฆ-Wsign-promo(C++ and Objective-C++ only) โ okay so this one watches overload resolution ๐ It warns when the compiler picks a promotion from an unsigned or enumerated type to a signed type, instead of a conversion to an unsigned type of the same size. Older G++ versions tried to keep the unsignedness, but the standard literally mandates the current behavior, so that's the vibe now ๐-Wtemplates(C++ and Objective-C++ only) โ warns whenever a primary template declaration shows up ๐ซ If your coding rules ban templates, this is how you enforce it. It stays quiet inside system headers like the STL, so you can still use the STL ๐ You're also free to instantiate or specialize templates โจ-Wmismatched-tags(C++ and Objective-C++ only) โ warns for declarations of structs, classes, and class templates (plus their specializations) whose class-key doesn't match the definition, or the first declaration if no definition is provided ๐ง
For example, the declaration of struct Object in the argument list of draw triggers the warning. To avoid it, either remove the redundant struct or swap it for class to match the definition:
class Object {
public:
virtual ~Object () = 0;
};
void draw (struct Object*);
Using struct to declare a class isn't wrong, as the example above shows ๐คทโโ๏ธ This option just helps you keep a consistent style for class declarations. In code meant to be portable to Windows-based compilers, it also helps prevent unresolved references caused by the different symbol mangling of different class-keys ๐ฆ You can use -Wmismatched-tags on its own or together with -Wredundant-tags.
-Wmultiple-inheritance(C++ and Objective-C++ only) โ warns when a class is defined with multiple direct base classes ๐ โโ๏ธ Some coding rules disallow multiple inheritance, so this is your enforcer. It's inactive inside system headers like the STL, so the STL is still fair game ๐ธ You can also define classes that indirectly use multiple inheritance.-Wvirtual-inheritanceโ warns when a class is defined with a virtual direct base class ๐ง Some coding rules disallow multiple inheritance, so use this to enforce that rule. It's inactive inside system headers like the STL, so you can still use the STL ๐ You can also define classes that indirectly use virtual inheritance.-Wno-virtual-move-assignโ suppresses warnings about inheriting from a virtual base that has a non-trivial C++11 move assignment operator ๐
๐ This one is dangerous, 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, this warning can be disabled ๐ซถ
-Wnamespacesโ warns when a namespace definition is opened ๐๏ธ Some coding rules disallow namespaces, and this is how you enforce that. It's inactive inside system headers like the STL, so the STL keeps working for you ๐ You can still use using directives and qualified names ๐-Wno-terminate(C++ and Objective-C++ only) โ disables the warning about a throw-expression that will immediately result in a call to "terminate" ๐-Wno-class-conversion(C++ and Objective-C++ only) โ don't warn when a conversion function converts an object to the same type, to a base class of that type, or tovoid. Those conversion functions will never be called, so the warning is just noise ๐-Wvolatile(C++ and Objective-C++ only) โ warns about deprecated uses of thevolatilequalifier ๐ That covers:- postfix and prefix
++and--expressions onvolatile-qualified types - simple assignments where the left operand is a
volatile-qualified non-class type, where the value gets used - compound assignments where the left operand is a
volatile-qualified non-class type volatile-qualified function return typesvolatile-qualified parameter types- structured bindings of a
volatile-qualified type
- postfix and prefix
โ ๏ธ This usage was deprecated in C++20, so it's time to let those old habits go ๐ญ
Enabled by default with -std=c++2a.
-Wzero-as-null-pointer-constant(C++ and Objective-C++ only) โ warns when a literal0is used as a null pointer constant ๐ Super handy if you're moving over tonullptrin C++11.-Waligned-newโ warns about a new-expression of a type that needs greater alignment thanalignof(std::max_align_t)but uses an allocation function without an explicit alignment parameter ๐ This option is enabled by-Wall.
Normally this only warns about global allocation functions, but -Waligned-new=all also warns about class member allocation functions ๐ฅ
-Wno-placement-new,-Wplacement-new=nโ warns about placement new expressions with undefined behavior, like constructing an object in a buffer that's too small for the object's type ๐งฑ For example, this placement new gets flagged because it tries to construct an array of 64 integers in a buffer only 64 bytes large:
char buf [64];
new (buf) int[64];
This warning is enabled by default.
-Wplacement-new=1โ this is the default warning level ๐ At this level, the warning skips some strictly undefined constructs that GCC allows as extensions for compatibility with legacy code. For example, the followingnewexpression isn't diagnosed here, even though it's undefined behavior according to the C++ standard, because it writes past the end of the one-element array:
struct S { int n, a[1]; };
S *s = (S *)malloc (sizeof *s + 31 * sizeof s->a[0]);
new (s->a)int [32]();
-Wplacement-new=2โ at this level, you get everything from level 1, plus a diagnostic for placement new expressions that construct an object in the last member of a struct, where that member is an array of a single element and its size is less than the size of the object being constructed ๐งจ The previous example gets diagnosed here, but the following construct uses the flexible member array extension to dodge the warning at level 2:
struct S { int n, a[]; };
S *s = (S *)malloc (sizeof *s + 32 * sizeof s->a[0]);
new (s->a)int [32]();
-Wcatch-value,-Wcatch-value=n(C++ and Objective-C++ only) โ warns about catch handlers that don't catch via reference ๐ฃ-Wcatch-value=1(or just-Wcatch-valuefor short) warns about polymorphic class types that are caught by value-Wcatch-value=2warns about all class types that are caught by value-Wcatch-value=3warns about all types that aren't caught by reference
-Wcatch-value is enabled by -Wall.
-Wconditionally-supported(C++ and Objective-C++ only) โ warns for conditionally-supported (C++11 [intro.defs]) constructs ๐-Wno-delete-incomplete(C++ and Objective-C++ only) โ don't warn when deleting a pointer to an incomplete type ๐
๐ Deleting a pointer to an incomplete type may cause undefined behavior at runtime.
This warning is enabled by default.
-Wextra-semi(C++, Objective-C++ only) โ warns about redundant semicolons after in-class function definitions โ๏ธ-Wno-inaccessible-base(C++, Objective-C++ only) โ controls warnings when a base class is inaccessible in a class derived from it due to ambiguity ๐ต๏ธ This warning is enabled by default. Note that the warning for ambiguous virtual bases is enabled by the-Wextraoption.
struct A { int a; };
struct B : A { };
struct C : B, A { };
-Wno-inherited-variadic-ctorโ suppresses warnings about using C++11 inheriting constructors when the base class being inherited from has a C variadic constructor ๐ซถ The warning is on by default because the ellipsis is not inherited.-Wno-invalid-offsetof(C++ and Objective-C++ only) โ suppresses warnings from applying theoffsetofmacro to a non-POD type ๐โโ๏ธ According to the 2014 ISO C++ standard, applyingoffsetofto a non-standard-layout type is undefined. In existing C++ implementations, though,offsetoftypically gives meaningful results. This flag is for users who know they're writing nonportable code and have deliberately chosen to ignore the warning about it.
The restrictions on offsetof may be relaxed in a future version of the C++ standard ๐ฎ
-Wsized-deallocation(C++ and Objective-C++ only) โ warns about a definition of an unsized deallocation function ๐๏ธ
void operator delete (void *) noexcept;
void operator delete[] (void *) noexcept;
without a definition of the corresponding sized deallocation function:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
or vice versa. This is enabled by -Wextra along with -fsized-deallocation.
-Wsuggest-final-typesโ warns about types with virtual methods where code quality would be improved if the type were declared with the C++11finalspecifier, or, if possible, declared in an anonymous namespace ๐ง This lets GCC devirtualize 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โ warns about virtual methods where code quality would be improved if the method were declared with the C++11finalspecifier, or, if possible, if its type were declared in an anonymous namespace or with thefinalspecifier ๐ This is also more effective with link-time optimization, where the class hierarchy graph info is more complete. It's recommended to first consider the suggestions of-Wsuggest-final-types, then rebuild with new annotations ๐-Wsuggest-overrideโ warns about overriding virtual functions that aren't marked with theoverridekeyword ๐ท๏ธ-Wuseless-cast(C++ and Objective-C++ only) โ warns when an expression is cast to its own type ๐งน-Wno-conversion-null(C++ and Objective-C++ only) โ bestie, this one tells GCC to stop warning about conversions betweenNULLand non-pointer types ๐ Heads up:-Wconversion-nullis already on by default, so this is the flag that quiets it ๐
๐ฆ Options Controlling Objective-C and Objective-C++ Dialects ๐ฆ
NOTE: okay so this manual does NOT teach you the Objective-C and Objective-C++ languages themselves ๐ It's only about the flags!
This section is all about the command-line options that only matter for Objective-C and Objective-C++ programs ๐ You can still use most of the language-independent GNU compiler options too, no cap. For example, you might compile a file called some_class.m like this:
gcc -g -fgnu-runtime -O -c some_class.m
In that example, -fgnu-runtime is an option meant only for Objective-C and Objective-C++ programs, but the other options work with any language GCC supports โจ
Since Objective-C is an extension of the C language, Objective-C compiles may also use options specific to the C front-end (e.g., -Wtraditional) ๐ธ Similarly, Objective-C++ compiles 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, iykyk ๐ซถ
-fconstant-string-class=class-nameโ okay so this tells GCC which class to instantiate for each literal string written as"@"...""๐ The default is"NXConstantString"if the GNU runtime is being used, and"NSConstantString"if the NeXT runtime is being used (see below). If you also pass-fconstant-cfstrings, it wins over-fconstant-string-classand makes"@"...""literals get laid out as constant CoreFoundation strings ๐-fgnu-runtimeโ generates object code that's compatible with the standard GNU Objective-C runtime. This is the default 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 notnilโญ This lets the runtime use more efficient entry points. It's only available together with the NeXT runtime and ABI version 0 or 1 ๐-fobjc-abi-version=nโ uses version n of the Objective-C ABI for the selected runtime ๐ Right now this is only supported for the NeXT runtime. Version 0 is the traditional (32-bit) ABI without support for properties and other Objective-C 2.0 additions. Version 1 is the traditional (32-bit) ABI with support for properties and other Objective-C 2.0 additions. Version 2 is the modern (64-bit) ABI. If you don't specify anything, the default is Version 0 on 32-bit target machines, and Version 2 on 64-bit target machines ๐ฆ-fobjc-call-cxx-cdtorsโ for each Objective-C class, GCC checks if 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, which runs those non-trivial default constructors on the instance variables, in order, and then returnsself. Similarly, if any instance variable is a C++ object with a non-trivial destructor, GCC synthesizes a special- (void) .cxx_destructmethod that runs all such 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 responsibility of the Objective-C runtime to invoke all such methods in an object's inheritance hierarchy ๐ซถ The - (id) .cxx_construct methods are invoked by the runtime immediately after a new object instance is allocated, and the - (void) .cxx_destruct methods are invoked immediately before the runtime deallocates an object instance ๐ญ
As of this writing, only the NeXT runtime on Mac OS X 10.4 and later has support for invoking the - (id) .cxx_construct and - (void) .cxx_destruct methods ๐
-fobjc-direct-dispatchโ allows fast jumps to the message dispatcher โก On Darwin, this is accomplished via the comm page ๐ธ-fobjc-exceptionsโ enables syntactic support for structured exception handling in Objective-C, kind of like what C++ offers ๐ You need this option to use the Objective-C keywords@try,@throw,@catch,@finallyand@synchronized๐ It's available with both the GNU runtime and the NeXT runtime, but NOT with the NeXT runtime on Mac OS X 10.2 and earlier ๐-fobjc-gcโ enables garbage collection (GC) in Objective-C and Objective-C++ programs ๐๏ธ This is only available with the NeXT runtime. The GNU runtime has a different 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 language recognized by GCC 4.0 ๐ This only affects the Objective-C additions to the C/C++ language. It does NOT affect conformance to C/C++ standards, which is controlled by the separate C/C++ dialect option flags ๐ โโ๏ธ When this option is used with the Objective-C or Objective-C++ compiler, any Objective-C syntax that GCC 4.0 doesn't recognize gets rejected. This is useful if you need to make sure your Objective-C code can be compiled with older versions of GCC ๐ซถ-freplace-objc-classesโ emits a special marker that tellsld(1)not to statically link in the resulting object file, and letsdyld(1)load it at run time instead โจ This gets used with the Fix-and-Continue debugging mode, where the object file might be recompiled and dynamically reloaded while the program is running, without restarting the whole program ๐ 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-linksuppresses that behavior and keeps the calls toobjc_getClass("...")๐ง This is useful in Zero-Link debugging mode, since it lets you modify individual class implementations during program execution ๐ช 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 ๐ This 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, so you avoid those variable shadowing issues ๐-fivar-visibility=[public|protected|private|package]โ sets the default instance variable visibility to the option you pick ๐ Instance variables declared outside the scope of any access modifier directives will default to that visibility ๐ฆ-gen-declsโ dumps the interface declarations for all classes seen in the source file to a file namedsourcename.decl๐-Wassign-intercept(Objective-C and Objective-C++ only) โ warns whenever an Objective-C assignment is being intercepted by the garbage collector ๐๏ธ-Wno-property-assign-default(Objective-C and Objective-C++ only) โ doesn't warn if a property for an Objective-C object has no assign semantics specified ๐-Wno-protocol(Objective-C and Objective-C++ only) โ if a class is declared to implement a protocol, GCC warns for every method in that 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 ๐ค With-Wno-protocol, methods inherited from the superclass count as implemented, so no warning is issued for them ๐ซถ-Wselector(Objective-C and Objective-C++ only) โ warns if multiple methods of different types for the same selector are found during compilation ๐ The check runs on the list of methods in the final stage of compilation. There's also a check for each selector appearing in a@selector(...)expression, if a corresponding method for that selector was found during compilation ๐ Because these checks only scan the method table at the very end, these warnings aren't produced if the final stage of compilation isn't reached. That can happen because an error was found during compilation, or because-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 using that selector to a receiver of typeidorClass๐ฃ When this flag is off (which is the default behavior), the compiler skips such 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 whole vibe check on your@selector(...)expressions ๐ It warns when a@selector(...)points at a selector nobody declared. A selector counts as undeclared if no method with that name was declared before the@selector(...)expression, either explicitly in an@interfaceor@protocoldeclaration, or implicitly in an@implementationsection. This option checks the second it spots a@selector(...), while-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. Literally main character energy ๐-print-objc-runtime-infoโ this one 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 what the output device looked like (its width, ...) ๐ These options let you control the formatting algorithm, like how many characters go on a line and how often source location info gets reported. Some language front ends might not honor these options, so just a heads up ๐ซถ
-fmessage-length=nโ this tries to format error messages so they fit on lines of about n characters. If n is zero, no line-wrapping happens and each error message sits on a single line. This is the default for all front ends ๐
Note: this option also affects how#errorand#warningpre-processor directives get displayed, plus the deprecated function/type/variable attribute. It does not affectpragma GCC warningandpragma GCC errorpragmas, so don't get confused ๐
-fdiagnostics-show-location=onceโ only meaningful in line-wrapping mode โจ This tells the diagnostic reporter to emit source location info once. So if a message is too long and gets wrapped, the location isn't slapped on as a prefix over and over on each continuation line. This is the default behavior ๐-fdiagnostics-show-location=every-lineโ also only meaningful in line-wrapping mode ๐ This makes the reporter emit the same source location info (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โ this turns color on in diagnostics ๐ WHEN can benever,always, orauto. The default depends on how the compiler was configured. It can be any of those WHEN options, orneverif theGCC_COLORSenvironment variable isn't present, andautootherwise.autoonly uses color when standard error is a terminal and you're not running in an emacs shell ๐ง The forms-fdiagnostics-colorand-fno-diagnostics-colorare just 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 are interpreted by your terminal or terminal emulator, so check your text terminal's docs for the permitted values and what they mean as character attributes. These substring values are integers in decimal form, and they can be stuck together with semicolons. Common ones include 1 for bold, 4 for underline, 5 for blink, 7 for inverse, 39 for default foreground color, 30 to 37 for foreground colors, 90 to 97 for 16-color mode foreground colors, 38;5;0 to 38;5;255 for 88-color and 256-color mode foreground colors, 49 for default background color, 40 to 47 for background colors, 100 to 107 for 16-color mode background colors, and 48;5;0 to 48;5;255 for 88-color and 256-color mode background colors ๐
The default GCC_COLORS is:
error=01;31:warning=01;35:note=01;36:range1=32:range2=34:locus=01:\
quote=01:path=01;36:fixit-insert=32:fixit-delete=31:\
diff-filename=01:diff-hunk=32:diff-delete=31:diff-insert=32:\
type-diff=01;32
Where 01;31 is bold red, 01;35 is bold magenta, 01;36 is bold cyan, 32 is green, 34 is blue, 01 is bold, and 31 is red ๐ Setting GCC_COLORS to the empty string disables colors. Here are the supported capabilities:
"error="โ the SGR substring forerror:markers ๐จ"warning="โ the SGR substring forwarning:markers โ ๏ธ"note="โ the SGR substring fornote:markers ๐"path="โ the SGR substring for colorizing paths of control-flow events printed via-fdiagnostics-path-format=, like the identifiers of individual events and the lines showing interprocedural calls and returns ๐ฆ"range1="โ the SGR substring for the first additional range ๐"range2="โ the SGR substring for the second additional range ๐"locus="โ the SGR substring for location info, likefile:lineorfile:line:columnetc. ๐"quote="โ the SGR substring for info printed within quotes ๐ฌ"fixit-insert="โ the SGR substring for fix-it hints suggesting text to be inserted or replaced โ"fixit-delete="โ the SGR substring for fix-it hints suggesting text to be deleted โ"diff-filename="โ the SGR substring for filename headers within generated patches ๐งพ"diff-hunk="โ the SGR substring for the starts of hunks within generated patches ๐งฉ"diff-delete="โ the SGR substring for deleted lines within generated patches โ"diff-insert="โ the SGR substring for inserted lines within generated patches โ"type-diff="โ the SGR substring for highlighting mismatching types within template arguments in the C++ frontend ๐-fdiagnostics-urls[=WHEN]โ this uses escape sequences to embed URLs in diagnostics ๐ For example, when-fdiagnostics-show-optionshows the command-line option controlling a diagnostic, it can embed a URL pointing to that option's docs ๐ WHEN can benever,always, orauto.automakes GCC use URL escape sequences only when standard error is a terminal, and when you're not running in an emacs shell or any graphical terminal that's known to be incompatible with this feature (see below) ๐
The default depends on how the compiler was configured, and it can be any of the above WHEN options. GCC can also be configured (via the --with-diagnostics-urls=auto-if-env configure-time option) so the default is affected by environment variables. Under that configuration, GCC defaults to auto if either the GCC_URLS or TERM_URLS environment variables are present and non-empty in the compiler's environment, or never if neither one is ๐ธ
Even with -fdiagnostics-urls=always, the behavior still depends on those environment variables:
- If
GCC_URLSis set to empty orno, URLs are not embedded in diagnostics ๐ - If set to
st, URLs use ST escape sequences ๐ - If set to
bel, which is the default, URLs use BEL escape sequences ๐ - Any other non-empty value enables the feature โจ
If GCC_URLS isn't set, TERM_URLS is used as a fallback. Quick side note: ST is an ANSI escape sequence, the string terminator ESC \. BEL is an ASCII character, CTRL-G, which usually sounds like a beep ๐
At this time GCC also tries to detect a few terminals that don't implement the URL feature, and that have bugs (or at least had bugs in some versions still in use) where URL escapes are likely to misbehave and print garbage on the screen ๐ญ That list is currently xfce4-terminal, certain known-buggy gnome-terminal versions, the linux console, and mingw. This check can be skipped with -fdiagnostics-urls=always.
-fno-diagnostics-show-optionโ by default, each diagnostic emitted includes text showing the command-line option that directly controls it (if the diagnostic machinery knows that option). This flag suppresses that behavior ๐-fno-diagnostics-show-caretโ by default, each diagnostic includes the original source line and a caret^pointing at the column. This option hides that info ๐ซฃ The source line gets truncated to n characters if-fmessage-length=nis given. When output goes to the terminal, the width is limited to the width given by theCOLUMNSenvironment variable or, if that's not set, the terminal width ๐-fno-diagnostics-show-labelsโ by default, when printing source code (via-fdiagnostics-show-caret), diagnostics can label ranges of source code with pertinent info, like the types of expressions ๐ท๏ธ Here's what that looks like:
printf ("foo %s bar", long_i + long_j);
~^ ~~~~~~~~~~~~~~~
| |
char * long int
This option suppresses those labels (so in the example above, the vertical bars and the char * and long int text go away) ๐งน
-fno-diagnostics-show-cweโ diagnostic messages can optionally have an associated CWE identifier (https://cwe.mitre.org/index.html) ๐ก๏ธ GCC itself only provides this metadata for some of the-fanalyzerdiagnostics, and GCC plugins may also provide diagnostics with it. By default, if this info is present, it gets printed with the diagnostic. This option suppresses printing that metadata ๐ โโ๏ธ-fno-diagnostics-show-line-numbersโ by default, when printing source code (via-fdiagnostics-show-caret), a left margin showing line numbers is printed ๐ข This option suppresses that left margin.-fdiagnostics-minimum-margin-width=widthโ this controls the minimum width of the left margin printed by-fdiagnostics-show-line-numbers. It defaults to6๐-fdiagnostics-parseable-fixitsโ this emits fix-it hints in a machine-parseable format, perfect for IDEs ๐ค For each fix-it, a line gets printed after the relevant diagnostic, starting with the stringfix-it:. For example:
fix-it:"test.c":{45:3-45:21}:"gtk_widget_show_all"
okay so the location is a half-open range ๐ measured as a count of bytes, and it starts at byte 1 for the initial column (not 0, so pay attention ๐). In the example below, bytes 3 through 20 of line 45 of "test.c" are getting swapped out for the replacement string โจ
00000000011111111112222222222
12345678901234567890123456789
gtk_widget_showall (dlg);
^^^^^^^^^^^^^^^^^^
gtk_widget_show_all
The filename and replacement string escape a backslash as "\\", a tab as "\t", a newline as "\n", and a double quote as "\"". Non-printable characters get written in octal, so a vertical tab becomes "\013" ๐ฆ
An empty replacement string means the range gets deleted ๐๏ธ and an empty range like "45:3-45:3" means the string gets inserted right at that spot ๐
โจ -fdiagnostics-generate-patch โจ
This one prints fix-it hints to stderr as a unified diff ๐งพ and it shows up after any diagnostics have been printed. Here's what it looks like:
--- 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 ๐ and it follows the same rules as regular diagnostics (see -fdiagnostics-color).
โจ -fdiagnostics-show-template-tree โจ
In the C++ frontend, when diagnostics show mismatching template types, you get something like this ๐ญ
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
Using -fdiagnostics-show-template-tree turns on a tree-like view that shows the common and differing parts of the types, like this ๐ณ
map<
[...],
vector<
[double != float]>>
The parts that differ are highlighted with color, so "double" and "float" pop in this case ๐ฅ
โจ -fno-elide-type โจ
By default, when the C++ frontend shows mismatching template types, the common parts get squished down into "[...]" so the error message isn't a total wall of text ๐ Here's the same example from before:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
If you pass -fno-elide-type, that squishing behavior gets turned off ๐
โโ๏ธ This flag also changes the output of -fdiagnostics-show-template-tree, so keep that in mind ๐ซถ
โจ -fdiagnostics-path-format=KIND โจ
This one decides how paths of control-flow events get printed for diagnostics that have a path attached ๐ค๏ธ
KIND can be none, separate-events, or inline-events, and the default is inline-events ๐
noneโ means no diagnostic paths get printed at all ๐separate-eventsโ prints a separate "note" diagnostic for each event inside the diagnostic. It looks like this:
test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which requires a non-NULL parameter
test.c:25:10: note: (1) when 'PyList_New' fails, returning NULL
test.c:27:3: note: (2) when 'i < count'
test.c:29:5: note: (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
inline-eventsโ prints the events "inline" right inside the source code ๐ง It tries to group events that are close together into runs and labels them as ranges in the source. The same events from above might show up like this:
'test': events 1-3
|
| 25 | list = PyList_New(0);
| | ^~~~~~~~~~~~~
| | |
| | (1) when 'PyList_New' fails, returning NULL
| 26 |
| 27 | for (i = 0; i < count; i++) {
| | ~~~
| | |
| | (2) when 'i < count'
| 28 | item = PyLong_FromLong(random());
| 29 | PyList_Append(list, item);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
|
Interprocedural control flow (where the path jumps between functions) gets shown by grouping the events by stack frame ๐งฉ Indentation shows how the stack frames are nested, pushed, and popped. For example:
'test': events 1-2
|
| 133 | {
| | ^
| | |
| | (1) entering 'test'
| 134 | boxed_int *obj = make_boxed_int (i);
| | ~~~~~~~~~~~~~~~~~~
| | |
| | (2) calling 'make_boxed_int'
|
+--> 'make_boxed_int': events 3-4
|
| 120 | {
| | ^
| | |
| | (3) entering 'make_boxed_int'
| 121 | boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (4) calling 'wrapped_malloc'
|
+--> 'wrapped_malloc': events 5-6
|
| 7 | {
| | ^
| | |
| | (5) entering 'wrapped_malloc'
| 8 | return malloc (size);
| | ~~~~~~~~~~~~~
| | |
| | (6) calling 'malloc'
|
<-------------+
|
'test': event 7
|
| 138 | free_boxed_int (obj);
| | ^~~~~~~~~~~~~~~~~~~~
| | |
| | (7) calling 'free_boxed_int'
|
(etc)
โจ -fdiagnostics-show-path-depths โจ
This option adds extra info when printing control-flow paths tied to a diagnostic ๐ If you give this option, the stack depth gets printed for each run of events within -fdiagnostics-path-format=separate-events.
It's mainly meant for GCC developers and plugin developers who are debugging diagnostics that report interprocedural control flow ๐ ๏ธ
โจ -fno-show-column โจ
This one stops column numbers from showing up in diagnostics ๐
โโ๏ธ You might need it if a program that scans the diagnostics doesn't understand column numbers, such as dejagnu ๐ค
โจ -fdiagnostics-format=FORMAT โจ
FORMAT can be text or json, and the default is text ๐
The json format is a top-level JSON array full of JSON objects, and each object represents one diagnostic ๐ The JSON gets emitted as one single line with no formatting. The examples below have been formatted only so they're easier to read โจ
Diagnostics can have child diagnostics too. Take this error and its note:
misleading-indentation.c:15:3: warning: this 'if' clause does not
guard... [-Wmisleading-indentation]
15 | if (flag)
| ^~
misleading-indentation.c:17:5: note: ...this statement, but the latter
is misleadingly indented as if it were guarded by the 'if'
17 | y = 2;
| ^
After formatting, it might be printed in JSON form 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",
"option_url": "https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wmisleading-indentation",
"children": [
{
"kind": "note",
"locations": [
{
"caret": {
"column": 5,
"file": "misleading-indentation.c",
"line": 17
}
}
],
"message": "...this statement, but the latter is ..."
}
]
},
...
]
Here the "note" is a child of the "warning" ๐ซง
A diagnostic has a "kind". If that kind is "warning", there's also an "option" key that describes the command-line option controlling the warning โ ๏ธ
A diagnostic can have zero or more locations. Each location can have up to three positions: a "caret" position, plus 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, bestie ๐ Its primary one is the + token sitting at column 23. It also has two secondary locations for the left and right-hand sides of the expression, and both of those come with labels ๐ It might be printed in JSON form like this:
{
"children": [],
"kind": "error",
"locations": [
{
"caret": {
"column": 23, "file": "bad-binary-ops.c", "line": 64
}
},
{
"caret": {
"column": 10, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 21, "file": "bad-binary-ops.c", "line": 64
},
"label": "S {aka struct s}"
},
{
"caret": {
"column": 25, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 36, "file": "bad-binary-ops.c", "line": 64
},
"label": "T {aka struct t}"
}
],
"message": "invalid operands to binary + ..."
}
If a diagnostic has fix-it hints, it gets a "fixits" array made of half-open intervals, kinda like what -fdiagnostics-parseable-fixits spits out ๐ฆ For example, here's a diagnostic with a replacement fix-it hint:
demo.c:8:15: error: 'struct s' has no member named 'colour'; did you
mean 'color'?
8 | return ptr->colour;
| ^~~~~~
| color
And that one 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 ..."
}
Here the fix-it hint basically says to replace the text from "start" up to but not including "next" with the value of "string" โจ Deletions are expressed with an empty value for "string", and insertions are done by having "start" equal "next" ๐ง
If the diagnostic has a path of control-flow events attached to it, it gets a "path" array of objects that represent those events ๐ธ Each event object has a "description" string, a "location" object, a "function" string, and a "depth" number, which is how interprocedural paths get represented. The "function" tells you which function is current at that event, and the "depth" is the stack depth relative to some baseline: the higher the number, the more frames are on the stack ๐
For example, the intraprocedural example shown for -fdiagnostics-path-format= might have this JSON for its path:
"path": [
{
"depth": 0,
"description": "when 'PyList_New' fails, returning NULL",
"function": "test",
"location": {
"column": 10,
"file": "test.c",
"line": 25
}
},
{
"depth": 0,
"description": "when 'i < count'",
"function": "test",
"location": {
"column": 3,
"file": "test.c",
"line": 27
}
},
{
"depth": 0,
"description": "when calling 'PyList_Append', passing NULL from (1) as argument 1",
"function": "test",
"location": {
"column": 5,
"file": "test.c",
"line": 29
}
}
]
โจ Options to Request or Suppress Warnings โจ
Okay so, warnings are the "hmm, that's sus" messages ๐ They flag constructions that aren't straight-up wrong, but that are risky or that suggest there might have been a mistake somewhere ๐
These language-independent options don't turn on any specific warnings. Instead, they control what kinds of diagnostics GCC produces ๐
-fsyntax-onlyโ Checks your code for syntax errors, and that's it. It doesn't go any further than that ๐-fmax-errors=nโ Caps the number of error messages atn, and then GCC bails instead of trying to keep going ๐ Ifnis0(the default), there's no limit on how many error messages get produced. If-Wfatal-errorsis also specified, then-Wfatal-errorstakes precedence over this option.-wโ Inhibits all warning messages. Silence is golden ๐คซ-Werrorโ Turns every warning into an error. No more "eh, it's just a warning" ๐ค-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 switch also has a negative form, which you use to undo
-Werrorfor specific warnings. For example,-Wno-error=switchmakes-Wswitchwarnings not be errors, even when-Werroris in effect ๐ โโ๏ธ - Every controllable warning's message includes the option that controls it, and you can use that option with
-Werror=and-Wno-error=the same way. (Printing of the option in the warning message can be disabled with the-fno-diagnostics-show-optionflag, if you hate that vibe ๐) - Heads up: specifying
-Werror=fooautomatically implies-Wfoo. However,-Wno-error=foodoes not imply anything ๐ง
- This switch also has a negative form, which you use to undo
-Wfatal-errorsโ Aborts compilation on the first error that occurs, 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 that begins with -Wno- to turn 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. Additional warnings can be produced by enabling the static analyzer;
Some options, like -Wall and -Wextra, turn on other options, like -Wunused, which may turn on even more options, like -Wunused-value. The combined effect of positive and negative forms is that more specific options win over less specific ones, no matter where they sit on the command-line. For options of the same specificity, the last one takes effect. Options enabled or disabled via pragmas take effect as if they appeared at the end of the command-line ๐
When you request an unrecognized warning option (e.g., -Wunknown-warning), GCC emits a diagnostic saying the option isn't recognized. The -Wno- form acts a little differently though: no diagnostic is produced for -Wno-unknown-warning unless other diagnostics are being produced. This lets you use new -Wno- options with old compilers, but if something goes wrong, the compiler warns that an unrecognized option is present ๐ซถ
The effectiveness of some warnings depends on optimizations also being enabled. For example, -Wsuggest-final-types is more effective with link-time optimization, and -Wmaybe-uninitialized doesn'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 rejects some other programs that don't follow ISO C and ISO C++. For ISO C, it follows the version of the ISO C standard specified by any-stdoption used ๐
Valid ISO C and ISO C++ programs should compile properly with or without this option, though a rare few require -ansi or a -std option that specifies the required version of ISO C. Without this option, though, certain GNU extensions and traditional C and C++ features are supported too. With this option, they get rejected ๐
โโ๏ธ
-Wpedantic doesn't cause warning messages for use of the alternate keywords whose names begin and end with __. This alternate format can also be used to disable warnings for non-ISO __intN types, i.e. __intN__. Pedantic warnings are also disabled in the expression that follows __extension__. However, only system header files should use these escape routes, so application programs should avoid them ๐ซ
Some users try to use -Wpedantic to check programs for strict ISO C conformance, and then they soon find it doesn't do quite what they want ๐ญ It finds some non-ISO practices, but not all---only the ones where ISO C requires a diagnostic, plus some others that have had diagnostics added.
A feature to report any failure to conform to ISO C might be useful in some instances, but okay, bestie, that would take a LOT of extra work and would be a totally different vibe from -Wpedantic ๐ญ. We don't have plans to support something like that anytime soon ๐
Where the standard you pick with -std is a GNU extended dialect, like gnu90 or gnu99, there's a matching base standard: the version of ISO C that 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 GNU dialect you picked, since by definition the GNU dialects include every feature the compiler supports with that option, so there would be nothing to warn about ๐
-pedantic-errors
Give an error whenever the base standard (see -Wpedantic) requires a diagnostic. This also covers some cases with undefined behavior at compile-time, and some other cases that don't stop programs that are valid according to the standard from compiling โจ Heads up: this is not the same as -Werror=pedantic, since there are errors this option turns on that the other one doesn't, and vice versa ๐จ
-Wall
This turns on a big bundle of warnings about constructions that some users find questionable, and that are easy to avoid (or tweak to dodge the warning), 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 the following warning flags:
-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++) -Wenum-conversion in
C/ObjC; -Wformat -Wformat-overflow -Wformat-truncation
-Wint-in-bool-context -Wimplicit (C and Objective-C only)
-Wimplicit-int (C and Objective-C only)
-Wimplicit-function-declaration (C and Objective-C only) -Winit-self
(only for C++) -Wlogical-not-parentheses -Wmain (only for C/ObjC and
unless -ffreestanding) -Wmaybe-uninitialized -Wmemset-elt-size
-Wmemset-transposed-args -Wmisleading-indentation (only for C/C++)
-Wmissing-attributes -Wmissing-braces (only for C/ObjC)
-Wmultistatement-macros -Wnarrowing (only for C++) -Wnonnull
-Wnonnull-compare -Wopenmp-simd -Wparentheses -Wpessimizing-move
(only for C++) -Wpointer-sign -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 -Wzero-length-bounds
Note that some warning flags are not implied by -Wall ๐ Some of them warn about constructions users generally don't consider questionable, but that you might occasionally want to check for. Others warn about constructions that are necessary or hard to avoid in some cases, and there's no simple way to change the code to suppress the warning. Some of them are enabled by -Wextra, but many of them must be enabled individually.
-Wextra
This enables some extra warning flags that are not enabled by -Wall ๐ (This option used to be called -W. The older name is still supported, but the newer name is more descriptive.)
-Wclobbered -Wcast-function-type -Wdeprecated-copy (C++ only)
-Wempty-body -Wignored-qualifiers -Wimplicit-fallthrough=3
-Wmissing-field-initializers -Wmissing-parameter-type (C only)
-Wold-style-declaration (C only) -Woverride-init -Wsign-compare (C
only) -Wstring-compare -Wredundant-move (only for C++) -Wtype-limits
-Wuninitialized -Wshift-negative-value (in C++11 to C++17 and in C99
and newer) -Wunused-parameter (only with -Wunused or -Wall)
-Wunused-but-set-parameter (only with -Wunused or -Wall)
The option -Wextra also prints warning messages for the following cases:
- A pointer is compared against integer zero with
<,<=,>, or>=. - (C++ only) An enumerator and a non-enumerator both appear in a conditional expression.
- (C++ only) Ambiguous virtual bases.
- (C++ only) Subscripting an array that has been declared
register. - (C++ only) Taking the address of a variable that has been declared
register. - (C++ only) A base class is not initialized in the copy constructor of a derived class.
-Wabi (C, Objective-C, C++ and Objective-C++ only)
Warn about code affected by ABI changes ๐ฆ This includes code that may not be compatible with the vendor-neutral C++ ABI, as well as the psABI for the particular target.
Since G++ now defaults to updating the ABI with each major release, -Wabi normally only warns about C++ ABI compatibility problems if a check was added later in a release series for an ABI issue discovered since the initial release. -Wabi warns about more things if an older ABI version is selected (with -fabi-version=n).
-Wabi can also take an explicit version number to warn about C++ ABI compatibility with a particular -fabi-version level, e.g. -Wabi=2 to warn about changes relative to -fabi-version=2.
If an explicit version number is provided and -fabi-compat-version is not specified, the version number from this option is used for compatibility aliases. If no explicit version number is provided with this option, but -fabi-compat-version is specified, that version number is used for C++ ABI warnings.
Although an effort has been made to warn about all such cases, there are probably some cases that aren't warned about, even though G++ is generating incompatible code. There may also be cases where warnings are emitted even though the generated code is compatible.
You should rewrite your code to avoid these warnings if you're concerned that code generated by G++ may not be binary compatible with code generated by other compilers ๐ซถ
Known incompatibilities in -fabi-version=2 (which was the default from GCC 3.4 to 4.9) include:
- A template with a non-type template parameter of reference type was mangled incorrectly:
extern int N;
template <int &> struct S {};
void n (S<N>) {2}
This was fixed in -fabi-version=3.
- SIMD vector types declared using
__attribute ((vector_size))were mangled in a non-standard way that does not allow for overloading of functions taking vectors of different sizes. The mangling was changed in-fabi-version=4. __attribute ((const))andnoreturnwere mangled as type qualifiers, anddecltypeof a plain declaration was folded away. These mangling issues were fixed in-fabi-version=5.- Scoped enumerators passed as arguments to a variadic function are promoted like unscoped enumerators, causing
va_argto complain. On most targets this doesn't actually affect the parameter passing ABI, since there's no way to pass an argument smaller thanint. Also, the ABI changed the mangling of template argument packs,const_cast,static_cast, prefix increment/decrement, and a class scope function used as a template argument. These issues were corrected in-fabi-version=6. - Lambdas in default argument scope were mangled incorrectly, and the ABI changed the mangling of
nullptr_t. These issues were corrected in-fabi-version=7. - When mangling a function type with function-cv-qualifiers, the un-qualified function type was incorrectly treated as a substitution candidate. This was fixed in
-fabi-version=8, the default for GCC 5.1. decltype(nullptr)incorrectly had an alignment of 1, leading to unaligned accesses. Note that this did not affect the ABI of a function with anullptr_tparameter, as parameters have a minimum alignment. This was fixed in-fabi-version=9, the default for GCC 5.2.- Target-specific attributes that affect the identity of a type, such as ia32 calling conventions on a function type (stdcall, regparm, etc.), did not affect the mangled name, leading to name collisions when function pointers were used as template arguments. This was fixed in
-fabi-version=10, the default for GCC 6.1.
This option also enables warnings about psABI-related changes ๐ The known psABI changes at this point include:
- For SysV/x86-64, unions with
long doublemembers are passed in memory as specified in psABI. Prior to GCC 4.4, this was not the case. For example:
union U {
long double ld;
int i;
};
union U is now always passed in memory.
-Wchar-subscripts
Warn if an array subscript has type char ๐ This is a super common mistake, since programmers often forget that this type is signed on some machines. This warning is enabled by -Wall.
-Wno-coverage-mismatch
Warn if feedback profiles don't match when using the -fprofile-use option ๐ฅ If a source file is changed between compiling with -fprofile-generate and with -fprofile-use, the files with the profile feedback can fail to match the source file, and GCC can't use the profile feedback information. By default, this warning is enabled and is treated as an error. -Wno-coverage-mismatch can be used to disable the warning, or -Wno-error=coverage-mismatch can be used to disable the error.
Disabling the error for this warning can result in poorly optimized code, and it's only useful for very minor changes such as bug fixes to an existing code-base. Completely disabling the warning is not recommended.
-Wno-cpp
(C, Objective-C, C++, Objective-C++ and Fortran only) Suppress warning messages emitted by #warning directives ๐
๐ -Wdouble-promotion (C, C++, Objective-C and Objective-C++ only)
okay bestie, this one is a vibe check for your float math ๐
It gives you a warning when a float gets implicitly promoted to a double. Why do we care? Some CPUs have a 32-bit single-precision floating-point unit, which handles float in hardware, but double gets emulated in software ๐ญ So on those machines, doing math with double values is way more expensive because of all that software emulation overhead.
It is so easy to do this by accident because floating-point literals are implicitly double, no cap ๐ Check this out:
float area(float radius)
{
return 3.14159 * radius * radius;
}
The compiler does the entire computation in double because that floating-point literal is a double. Main character energy, but make it expensive ๐
๐ธ -Wduplicate-decl-specifier (C and Objective-C only)
Lowkey simple: this warns if a declaration has a duplicate const, volatile, restrict or _Atomic specifier. Messy, bestie ๐ This warning is enabled by -Wall, so you get it for free โจ
๐ฆ -Wformat
okay this one is the queen of the format checks ๐ It checks calls to printf and scanf, etc., to make sure the arguments you pass have types that match the format string, and that the conversions in the format string actually make sense. It covers the standard functions plus anything else marked with format attributes, in the printf, scanf, strftime and strfmon families (strfmon is an X/Open extension, so it's not in the C standard, fr fr) or other target-specific families. Which functions get checked without any format attributes depends on the standard version you pick, and those extra checks get turned off by -ffreestanding or -fno-builtin.
The formats get checked against the format features supported by GNU libc version 2.2. That includes all ISO C90 and C99 features, plus stuff from the Single Unix Specification and some BSD and GNU extensions. Other libraries might not support all of these, and GCC doesn't warn about features that go beyond a particular library's limits. BUT if you use -Wpedantic together with -Wformat, you'll get warnings about format features that aren't in your selected standard version (not for strfmon formats though, since those aren't in any version of the C standard).
-Wformat=1,-Wformatโ-Wformatis the same thing as-Wformat=1, and-Wno-formatis the same as-Wformat=0. Since-Wformatalso checks for null format arguments in several functions, it also implies-Wnonnull. Some parts of this level can be turned off with-Wno-format-contains-nul,-Wno-format-extra-args, and-Wno-format-zero-length.-Wformatis enabled by-Wall๐-Wformat=2โ turns on-Wformatplus extra format checks. Right now that's the same as-Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k๐ฅ
๐ง -Wno-format-contains-nul
If you've got -Wformat on, this tells GCC to chill and not warn about format strings that contain NUL bytes ๐ซถ
๐ -Wno-format-extra-args
With -Wformat on, this stops GCC from complaining about extra arguments passed to a printf or scanf format function. The C standard says those extra args just get ignored, so it's not really a problem ๐
There's a catch though ๐ If the unused arguments sit between used arguments that have $ operand number specifications, GCC still warns, because the implementation couldn't know what type to pass to va_arg to skip the unused ones. BUT for scanf formats, this option suppresses that warning when the unused arguments are all pointers, since the Single Unix Specification says those unused arguments are allowed.
โญ -Wformat-overflow / -Wformat-overflow=level
This one warns about calls to formatted output functions like sprintf and vsprintf that might overflow the destination buffer ๐ญ When GCC can't figure out at compile time exactly how many bytes a format directive writes, it estimates using heuristics based on the level and on optimization. Turning on optimization usually makes the warning more accurate, but it can also cause false positives, so keep that in mind bestie โจ
-Wformat-overflow,-Wformat-overflow=1โ Level 1 is enabled by-Wformatand is super conservative. It only warns about calls that most likely overflow the buffer. At this level, numeric arguments with unknown values are assumed to be one, and strings of unknown length are assumed to be empty. Numeric arguments known to be bounded to a subrange of their type, or string arguments whose output is bounded by their directive's precision or by a finite set of string literals, are assumed to take whichever value in range results in the most bytes of output. For example, thissprintfcall gets diagnosed, because even with bothaandbequal to zero, the terminating NUL character ('\0') that the function appends gets written past the end of the buffer ๐ Making the buffer one byte bigger is enough to dodge the warning, though it might not be enough to avoid the actual overflow.
void f (int a, int b)
{
char buf [13];
sprintf (buf, "a = %i, b = %i\n", a, b);
}
-Wformat-overflow=2โ Level 2 is even more dramatic ๐ฅ It also warns about calls that might overflow the destination buffer given an argument of sufficient length or magnitude. At level 2, unknown numeric arguments are assumed to have the minimum representable value for signed types with a precision greater than 1, and the maximum representable value otherwise. Unknown string arguments that can't be assumed bounded (by the directive's precision, by a finite set of string literals they might evaluate to, or by the character array they might point to) are assumed to be 1 character long.
At level 2, the call in the example above gets diagnosed again, but this time because if a is a 32-bit INT_MIN, the first %i directive writes some of its digits past the end of the buffer. To make the call safe no matter what the two variables are, the destination buffer has to be at least 34 bytes. GCC even includes the minimum buffer size in an informational note after the warning, which is so helpful ๐ฅน
Another option instead of growing the buffer is to constrain the range of the formatted values. You can bound the max length of string arguments by specifying the precision in the format directive. And 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 reduces the required buffer size. For example, if a and b in the example above can be assumed to fit in the short int type, then using either the %hi format directive or casting the argument to short reduces the max required buffer size to 24 bytes.
void f (int a, int b)
{
char buf [23];
sprintf (buf, "a = %hi, b = %i\n", a, (short)b);
}
๐ซง -Wno-format-zero-length
With -Wformat on, this tells GCC not to warn about zero-length formats. The C standard says zero-length formats are allowed, so you're all good bestie ๐ธ
๐ -Wformat-nonliteral
If -Wformat is on, this also warns if the format string isn't a string literal, which means GCC can't check it. The exception is when the format function takes its format arguments as a va_list, since then it's not something GCC can warn about in this way ๐
๐จ -Wformat-security
Ngl, this one matters ๐ค If -Wformat is on, this also warns about uses of format functions that could be security problems. Right now, it warns about calls to printf and scanf functions where the format string isn't a string literal and there are no format arguments, like printf (foo);. This can be a security hole if that format string came from untrusted input and contains %n. (This is currently a subset of what -Wformat-nonliteral warns about, but future warnings might get added to -Wformat-security that aren't in -Wformat-nonliteral, so stay tuned ๐)
๐ท -Wformat-signedness
With -Wformat on, this also warns if the format string needs an unsigned argument and you pass a signed one, and vice versa ๐
๐ช -Wformat-truncation / -Wformat-truncation=level
This is the cousin of -Wformat-overflow, but for functions like snprintf and vsnprintf that might truncate the output โ๏ธ Same deal as before: when the exact number of bytes can't be determined at compile time, GCC estimates it using heuristics that depend on the level and on optimization. Optimization usually helps accuracy but can also bring false positives. Unless noted otherwise, this option uses the same logic as -Wformat-overflow.
-Wformat-truncation,-Wformat-truncation=1โ Level 1 is enabled by-Wformatand is conservative. It only warns about calls to bounded functions whose return value is unused and that will most likely result in truncation ๐ฆ-Wformat-truncation=2โ also warns about calls to bounded functions whose return value is used, and that might truncate given an argument of sufficient length or magnitude โจ
๐ -Wformat-y2k
If -Wformat is on, this also warns about strftime formats that might only give you a two-digit year ๐
Very much a "we don't do that anymore" energy ๐
๐ฅ -Wnonnull
This one warns about passing a null pointer for arguments that the nonnull function attribute says must be non-null ๐ซ
-Wnonnull is included in both -Wall and -Wformat. You can turn it off with the -Wno-nonnull option.
๐ -Wnonnull-compare
This warns when you compare an argument marked with the nonnull function attribute against null inside the function. Like, why are you checking for something that's already promised not to be null? ๐
-Wnonnull-compare is included in -Wall. You can disable it with the -Wno-nonnull-compare option.
-Wnull-dereferenceโ okay bestie, this one is the null pointer watchdog ๐ซฃ GCC warns if it spots a path that triggers erroneous or undefined behavior by dereferencing a null pointer. It's only active when-fdelete-null-pointer-checksis active, which optimizations turn on in most targets ๐. How precise the warnings are depends on the optimization options you use.-Winit-self(C, C++, Objective-C and Objective-C++ only) โ this warns about uninitialized variables that get initialized with themselves ๐ It can only be used alongside-Wuninitialized, so keep that in mind. Look at this:
int f()
{
int i = i;
return i;
}
GCC only warns about i being uninitialized in that snippet when -Winit-self has been specified. This warning is enabled by -Wall in C++.
-Wno-implicit-int(C and Objective-C only) โ this controls warnings when a declaration doesn't specify a type โจ It's enabled by default in C99 and later dialects of C, and also by-Wall.-Wno-implicit-function-declaration(C and Objective-C only) โ this controls warnings when a function gets used before it's declared ๐ It's enabled by default in C99 and later dialects of C, and also by-Wall. Also,-pedantic-errorsturns this warning into an error, so be careful ๐ญ-Wimplicit(C and Objective-C only) โ same as-Wimplicit-intand-Wimplicit-function-declaration๐ธ It's enabled by-Wall.-Wimplicit-fallthroughโ-Wimplicit-fallthroughis the same as-Wimplicit-fallthrough=3, and-Wno-implicit-fallthroughis the same as-Wimplicit-fallthrough=0.-Wimplicit-fallthrough=nโ okay, the big fallthrough one ๐ฆ It warns when a switch case falls through. Like this:
switch (cond)
{
case 1:
a = 1;
break;
case 2:
a = 2;
case 3:
a = 3;
break;
}
It doesn't warn when the last statement of a case can't fall through, e.g. when there's a return statement or a call to a function declared with the noreturn attribute. -Wimplicit-fallthrough= also takes control flow statements like ifs into account, so it only warns when it's actually appropriate. E.g.:
switch (cond)
{
case 1:
if (i > 3) {
bar (5);
break;
} else if (i < 1) {
bar (0);
} else
return;
default:
...
}
Sometimes a fallthrough is totally intentional, so GCC gives you an attribute, __attribute__ ((fallthrough)), to use along with a null statement to suppress the warning that would normally show up ๐ซถ
switch (cond)
{
case 1:
bar (0);
__attribute__ ((fallthrough));
default:
...
}
C++17 gives you a standard way to suppress the -Wimplicit-fallthrough warning with [[fallthrough]]; instead of the GNU attribute. In C++11 or C++14, you can use [[gnu::fallthrough]];, which is a GNU extension. Instead of these attributes, you can also add a fallthrough comment to silence the warning ๐ The whole body of the C or C++ style comment has to match the given regular expressions. The option argument n decides which kinds of comments are accepted:
-Wimplicit-fallthrough=0disables the warning altogether.-Wimplicit-fallthrough=1matches the.*regular expression, so any comment counts as a fallthrough comment.-Wimplicit-fallthrough=2case insensitively matches the.*falls?[ \t-]*thr(ough|u).*regular expression.-Wimplicit-fallthrough=3case sensitively matches one of the following regular expressions:
"-fallthrough"
"@fallthrough@"
"lint -fallthrough[ \t]*"
"[ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?FALL(S | |-)?THR(OUGH|U)[
\t.!]*(-[^\n\r]*)?"
"[ \t.!]*(Else,? |Intentional(ly)? )?Fall((s |
|-)[Tt]|t)hr(ough|u)[ \t.!]*(-[^\n\r]*)?"
"[ \t.!]*([Ee]lse,? |[Ii]ntentional(ly)? )?fall(s |
|-)?thr(ough|u)[ \t.!]*(-[^\n\r]*)?"
-Wimplicit-fallthrough=4case sensitively matches one of the following regular expressions:
"-fallthrough"
"@fallthrough@"
"lint -fallthrough[ \t]*"
"[ \t]*FALLTHR(OUGH|U)[ \t]*"
-Wimplicit-fallthrough=5doesn't recognize any comments as fallthrough comments, so only attributes disable the warning ๐ โโ๏ธ
The comment needs to come right after optional whitespace and other comments, followed by a case or default keyword, or by a user label that precedes some case or default label. Like so:
switch (cond)
{
case 1:
bar (0);
/* FALLTHRU */
default:
...
}
The -Wimplicit-fallthrough=3 warning is enabled by -Wextra โจ
-Wno-if-not-aligned(C, C++, Objective-C and Objective-C++ only) โ controls whether warnings triggered by thewarn_if_not_alignedattribute should get issued. These are enabled by default ๐-Wignored-qualifiers(C and C++ only) โ warns if a function's return type has a type qualifier likeconst. In ISO C, that qualifier has no effect, since a function's returned value isn't an lvalue ๐ For C++, the warning only fires for scalar types orvoid. ISO C prohibits qualifiedvoidreturn types on function definitions, so those always get a warning, even without this option. This warning is also enabled by-Wextra.-Wno-ignored-attributes(C and C++ only) โ controls warnings when an attribute gets ignored. This is different from-Wattributes, because it warns whenever the compiler decides to drop an attribute, not whether the attribute is unknown or used in the wrong place ๐ It's enabled by default.-Wmainโ warns if the type ofmainis suspicious ๐mainshould be a function with external linkage, returningint, and taking either zero arguments, two, or three arguments of appropriate types. This warning is enabled by default in C++, and it's enabled by either-Wallor-Wpedantic.-Wmisleading-indentation(C and C++ only) โ warns when the indentation of the code doesn't reflect the block structure ๐ Specifically, a warning is issued forif,else,while, andforclauses with a guarded statement that doesn't use braces, followed by an unguarded statement with the same indentation. In this example, the call tobaris misleadingly indented as if it were guarded by theifconditional:
if (some_condition ())
foo ();
bar (); /* Gotcha: this is not guarded by the "if". */
In the case of mixed tabs and spaces, the warning uses the -ftabstop= option to determine if the statements line up (defaulting to 8). The warning is not issued for code involving multiline preprocessor logic, like this:
if (flagA)
foo (0);
#if SOME_CONDITION_THAT_DOES_NOT_HOLD
if (flagB)
#endif
foo (1);
The warning is also not issued after a #line directive, since this typically indicates autogenerated code, and no assumptions can be made about the layout of the file that the directive references. This warning is enabled by -Wall in C and C++ ๐ฆ
-Wmissing-attributesโ warns when a function declaration is missing one or more attributes that a related function is declared with, and whose absence might mess with the correctness or efficiency of the generated code ๐ง For example, the warning gets issued for declarations of aliases that use attributes to specify less restrictive requirements than those of their targets. This usually represents a potential optimization opportunity. By contrast,-Wattribute-alias=2controls warnings issued when the alias is more restrictive than the target, which could lead to incorrect code generation. The attributes considered includealloc_align,alloc_size,cold,const,hot,leaf,malloc,nonnull,noreturn,nothrow,pure,returns_nonnull, andreturns_twice.
In C++, the warning is issued when an explicit specialization of a primary template declared with the attribute alloc_align, alloc_size, assume_aligned, format, format_arg, malloc, or nonnull is declared without it. The attributes deprecated, error, and warning suppress the warning.
You can use the copy attribute to apply the same set of attributes to a declaration as the one on another declaration, without explicitly enumerating the attributes. This attribute can be applied to declarations of functions, variables, or types. -Wmissing-attributes is enabled by -Wall.
For example, since the declaration of the primary function template below makes use of both the malloc and alloc_size attributes, the declaration of the explicit specialization of the template is diagnosed because it's missing one of them ๐
template <class T>
T* __attribute__ ((malloc, alloc_size (1)))
allocate (size_t);
template <>
void* __attribute__ ((malloc)) // missing alloc_size
allocate<void> (size_t);
-Wmissing-bracesโ warns if an aggregate or union initializer isn't fully bracketed ๐ In the following example, the initializer foraisn't fully bracketed, but the one forbis:
int a[2][2] = { 0, 1, 2, 3 };
int b[2][2] = { { 0, 1 }, { 2, 3 } };
This warning is enabled by -Wall.
-Wmissing-include-dirs(C, C++, Objective-C and Objective-C++ only) โ warns if a user-supplied include directory doesn't exist ๐ธ-Wno-missing-profileโ okay so this one is the profile watchdog ๐. It warns you when profile feedback is missing while you're using-fprofile-use. It catches the sneaky stuff, like when you add a new function or a new file between compiling with-fprofile-generateand-fprofile-useand never regenerate the profiles. Then the profile feedback data files have no info about that new function or file. The same goes if the profile count data (.gcda) files get deleted, because then GCC can't use any profile feedback. Every one of those cases gets a warning that's basically saying "bestie, it's time for a profile generation step" ๐ซถ. Ignore it and your code can come out poorly optimized ๐.-Wno-missing-profileturns the warning off, but it's not recommended, and you should only do it when having non-existent profile data is actually justified ๐.-Wmultistatement-macrosโ this one is about macros that lie to you ๐. It warns about unsafe macros with multiple statements that look guarded by anif,else,for,switch, orwhile, when only the first statement is actually guarded after the macro expands. Check out the drama:
#define DOIT x++; y++
if (c)
DOIT;
That will increment y unconditionally, not just when c holds ๐ญ. This usually gets fixed by wrapping the macro in a do-while loop:
#define DOIT do { x++; y++; } while (0)
if (c)
DOIT;
This warning is enabled by -Wall in C and C++ โจ.
-Wparenthesesโ parentheses are not optional, bestie ๐ . It warns when parentheses get left out in certain contexts, like an assignment where a truth value is expected, or when operators are nested in ways people often mix up ๐. It also warns if you write a comparison likex<=y<=z. That's equivalent to(x<=y ? 1 : 0) <= z, which is NOT what ordinary math notation means, so it's giving major confusion ๐. It also flags dangerous uses of the GNU extension to?:with the middle operand omitted. When the condition is a boolean expression, the omitted value is always1, but programmers usually expect it to be a value computed inside the conditional expression instead ๐.
For C++, this also warns about some unnecessary parentheses in declarations, which can mean you tried 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โ this is the chaos one, so buckle up ๐ช๏ธ. It warns about code that may have undefined semantics because of violations of the sequence point rules in the C and C++ standards. Sequence points are the partial ordering of when parts of your program run: the stuff before a sequence point and the stuff after it. They show up after a full expression finishes (one that isn't part of a bigger expression), after the first operand of&&,||,? :, or the,(comma) operator, before a function is called (but after its arguments and the expression naming the called function are evaluated), and in a few other places. Outside of those rules, the order that subexpressions get evaluated in is not specified. Since it's only a partial order, if two functions are called inside one expression with no sequence point between them, the order they run in is unspecified. The standards committee did rule that function calls don't overlap, though ๐ซถ.
It's not specified when modifications to object values actually take effect between sequence points. Programs whose behavior depends 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 your program breaks these rules, the results on any particular implementation are entirely unpredictable ๐ญ.
Examples of undefined behavior are a = a++;, a[n] = b[n++], and a[i++] = i;. Some more complicated cases don't get diagnosed by this option, and it may give the occasional false positive. Overall though, it's been found pretty effective at catching this kind of problem in programs โจ.
C++17 is going to define the order of evaluation for operands in more cases. In particular, it requires the right-hand side of an assignment to be evaluated before the left-hand side, so the examples above are no longer undefined. This option will still warn about them anyway, to help people avoid writing code that's undefined in C and earlier revisions of C++ ๐ง.
The standard is worded confusingly, so there's some debate over the precise meaning of the sequence point rules in subtle cases. Links to discussions of the problem, including proposed formal definitions, can be found on the GCC readings page, at <http://gcc.gnu.org/readings.html> ๐.
This warning is enabled by -Wall for C and C++ ๐.
-Wno-return-local-addrโ no yelling about returning stuff that dies ๐ฆ. It stops the warning about returning a pointer (or, in C++, a reference) to a variable that goes out of scope once the function returns.-Wreturn-typeโ returns are a whole vibe โจ. It warns whenever a function is defined with a return type that defaults toint. It also warns about anyreturnstatement with no return value in a function whose return type isn'tvoid(falling off the end of the function body counts as returning without a value). For C only, it warns about areturnstatement with an expression in a function whose return type isvoid, unless the expression's type is alsovoid. As a GNU extension, that latter case is accepted without a warning unless-Wpedanticis used. Trying to use the return value of a non-voidfunction other thanmainthat flows off the end by reaching the closing curly brace is undefined ๐.
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. Unlike C, C++ is not chill about it ๐ค.
This warning is enabled by default in C++ and by -Wall otherwise ๐ธ.
-Wno-shift-count-negativeโ negative shift counts, not it โญ. It controls warnings if a shift count is negative. This warning is enabled by default.-Wno-shift-count-overflowโ shifts that go too far ๐. It controls warnings if a shift count is greater than or equal to the bit width of the type. This warning is enabled by default.-Wshift-negative-valueโ left shifting a negative is cursed ๐. It warns if you left shift a negative value. This warning is enabled by-Wextrain C99 (and newer) and in C++11 to C++17 modes.-Wno-shift-overflow,-Wshift-overflow=nโ left shift overflow, the full saga ๐. These options control warnings about left shift overflows. There are two levels you can pick from:-Wshift-overflow=1โ this is the default level ๐. It's the warning level for-Wshift-overflowand is 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โ the stricter, extra-dramatic level ๐ค. This level also warns about left-shifting1into the sign bit, unless C++14 mode (or newer) is active.
-Wswitchโ every case deserves a seat at the table ๐ . It warns whenever aswitchstatement has an index of enumerated type and lacks acasefor one or more of the named codes of that enumeration. (Having adefaultlabel prevents this warning.)caselabels outside the enumeration range also trigger warnings with this option, even if there's adefaultlabel. This warning is enabled by-Wall๐ซถ.-Wswitch-defaultโ no default? no vibes ๐ง. It warns whenever aswitchstatement doesn't have adefaultcase.-Wswitch-enumโ the strictest switch check, iykyk ๐. It warns whenever aswitchstatement has an index of enumerated type and lacks acasefor one or more of the named codes of that enumeration.caselabels outside the enumeration range also trigger warnings. The only difference between-Wswitchand this option is that this one warns about an omitted enumeration code even when there's adefaultlabel ๐ฅ.-Wno-switch-boolโ booleans don't need to be dramatic ๐ธ. It stops the warning when aswitchstatement has an index of boolean type and the case values are outside the range of a boolean type. You can suppress this warning by casting the controlling expression to a type other thanbool. For example:
switch ((int) (a == 4))
{
...
}
This warning is enabled by default for C and C++ programs ๐.
-Wno-switch-outside-rangeโ case values that are way out of bounds ๐ฆ. This option controls warnings when aswitchcasehas a value outside of its respective type range. This warning is enabled by default for C and C++ programs.-Wno-switch-unreachableโ code that never runs is literally wasted ๐. It stops the warning when aswitchstatement contains statements between the controlling expression and the firstcaselabel that will never be executed. For example:
switch (cond)
{
i = 15;
...
case 5:
...
}
-Wswitch-unreachable does not warn if the statement between the controlling expression and the first case label is just a declaration:
switch (cond)
{
int i;
...
case 5:
i = 5;
...
}
This warning is enabled by default for C and C++ programs โจ.
-Wsync-nand(C and C++ only) โ this one is outdated, be warned โ ๏ธ. It 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โ assigned but never used, bestie ๐ซถ. It warns whenever a function parameter is assigned to but otherwise unused (aside from its declaration) ๐.
To suppress this warning, use the "unused" attribute ๐ซถ
This warning also turns on with -Wunused together with -Wextra. Iykyk ๐
-Wunused-but-set-variable: wait, I already covered this one, so skip ahead. (Ignore this line, it's a stray note and not part of the page.)
Let me restart that bullet cleanly. Here is the continuation from the top of this part:
-Wunused-functionโ okay so this one yells whenever astaticfunction is declared but never defined, or when a non-inlinestaticfunction just sits there unused ๐ This warning is enabled by-Wall.-Wunused-labelโ warns when a label is declared but never used ๐ท๏ธ This is enabled by-Wall. To suppress it, use the"unused"attribute.-Wunused-local-typedefs(C, Objective-C, C++ and Objective-C++ only) โ warns when a typedef defined locally inside a function never gets used. This is enabled by-Wall.-Wunused-parameterโ warns whenever a function parameter goes unused past its declaration. To suppress it, use the"unused"attribute.-Wno-unused-resultโ no warning if a caller of a function marked with the attribute"warn_unused_result"doesn't use its return value. The default is-Wunused-result.-Wunused-variableโ warns whenever a local or static variable is unused past its declaration. This option implies-Wunused-const-variable=1for C, but not for C++. It's enabled by-Wall. To suppress it, use the"unused"attribute.-Wunused-const-variable/-Wunused-const-variable=nโ warns whenever a constant static variable is unused past its declaration.-Wunused-const-variable=1is enabled by-Wunused-variablefor C, but not for C++. In C this declares variable storage, but in C++ it's not an error, since const variables take the place of"#define"s. To suppress it, use the"unused"attribute.-Wunused-const-variable=1โ the level that-Wunused-variableturns on for C. It only warns about unused static const variables defined in the main compilation unit, not about static const variables declared in any header included.-Wunused-const-variable=2โ also warns about unused constant static variables in headers (excluding system headers). This is the warning level of-Wunused-const-variable, and it must be explicitly requested, since in C++ this isn't an error and in C it might be harder to clean up all the headers included.
-Wunused-valueโ warns whenever a statement computes a result that is explicitly not used. To suppress 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, an expression such asx[i,j]causes a warning, whilex[(void)i,j]does not. This is enabled by-Wall.-Wunusedโ all the above-Wunusedoptions combined. To get a warning about an unused function parameter, you must either specify-Wextra -Wunused(note that-Wallimplies-Wunused), or separately specify-Wunused-parameter.-Wuninitializedโ warns if an automatic variable is used without first being initialized. In C++, it also warns if a non-static reference or non-static"const"member appears in a class without constructors.- If you want to warn about code that uses the uninitialized value of the variable in its own initializer, use the
-Winit-selfoption. - These warnings occur for individual uninitialized elements of structure, union or array variables, as well as for variables that are uninitialized as a whole. They do not occur for variables or elements declared
"volatile". Because these warnings depend on optimization, the exact variables or elements that get warnings depend on the precise optimization options and version of GCC used. - There may be no warning about a variable that is used only to compute a value that itself is never used, because such computations may be deleted by data flow analysis before the warnings are printed.
- If you want to warn about code that uses the uninitialized value of the variable in its own initializer, use the
-Wno-invalid-memory-modelโ controls warnings for invocations of__atomicBuiltins,__syncBuiltins, and the C11 atomic generic functions with a memory consistency argument that is either invalid for the operation or outside the range of values of the"memory_order"enumeration. For example, since the"__atomic_store"and"__atomic_store_n"built-ins are only defined for the relaxed, release, and sequentially consistent memory orders, the following code is diagnosed:
void store (int *i)
{
__atomic_store_n (i, 0, memory_order_consume);
}
-Winvalid-memory-model is enabled by default ๐
-Wmaybe-uninitializedโ for an automatic (i.e. local) variable, if there exists a path from the function entry to a use of the variable that is initialized, but there exist some other paths for which the variable is not initialized, the compiler emits a warning if it cannot prove the uninitialized paths are not executed at run time.
These warnings are only possible in optimizing compilation, because otherwise GCC does not keep track of the state of variables.
These warnings are made optional because GCC may not be able to determine when the code is correct in spite of appearing to have an error. Here is one example of how this can happen:
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
foo (x);
}
If the value of y is always 1, 2 or 3, then x is always initialized, but GCC doesn't know this. 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 sees only the calls to setjmp. It cannot know where longjmp will be called; in fact, a signal handler could call it at any point in the code. As a result, you may get a warning even when there is in fact no problem, because longjmp cannot in fact be called at the place that would cause a problem.
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 is encountered that is not understood by GCC. If this command-line option is used, warnings are even issued for unknown pragmas in system header files. This is not the case if the warnings are only enabled by the-Wallcommand-line option.-Wno-pragmasโ doesn't warn about misuses of pragmas, such as incorrect parameters, invalid syntax, or conflicts between pragmas. See also-Wunknown-pragmas.-Wno-prio-ctor-dtorโ doesn't warn if a priority from 0 to 100 is used for a constructor or destructor. The use of constructor and destructor attributes lets you assign a priority to the constructor/destructor to control its order of execution beforemainis called or after it returns. The priority values must be greater than 100, as the compiler reserves priority values between 0--100 for the implementation.-Wstrict-aliasingโ only active when-fstrict-aliasingis active. It warns about code that might break the strict aliasing rules that the compiler is using for optimization. The warning does not catch all cases, but it does attempt to catch the more common pitfalls. It is included in-Wall. It is equivalent to-Wstrict-aliasing=3.-Wstrict-aliasing=nโ only active when-fstrict-aliasingis active. It warns about code that might break the strict aliasing rules that the compiler is using for optimization. Higher levels correspond to higher accuracy (fewer false positives). Higher levels also correspond to more effort, similar to the way-Oworks.-Wstrict-aliasingis equivalent to-Wstrict-aliasing=3.- Level 1: Most aggressive, quick, least accurate. Possibly useful when higher levels do not warn but
-fstrict-aliasingstill breaks the code, as it has very few false negatives. However, it has many false positives. Warns for all pointer conversions between possibly incompatible types, even if never dereferenced. Runs in the front end only. - Level 2: Aggressive, quick, not too precise. May still have many false positives (not as many as level 1 though), and few false negatives (but possibly more than level 1). Unlike level 1, it only warns when an address is taken. Warns about incomplete types. Runs in the front end only.
- Level 3 (default for
-Wstrict-aliasing): Should have very few false positives and few false negatives. Slightly slower than levels 1 or 2 when optimization is enabled. Takes care of the common pun+dereference pattern in the front end:*(int*)&some_float. If optimization is enabled, it also runs in the back end, where it deals with multiple statement cases using flow-sensitive points-to information. Only warns when the converted pointer is dereferenced. Does not warn about incomplete types.
- Level 1: Most aggressive, quick, least accurate. Possibly useful when higher levels do not 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 does not occur. Note that it does not warn about all cases where the code might overflow: it only warns about cases where the compiler implements some optimization. Thus this warning depends on the optimization level.
An optimization that assumes signed overflow never happens is perfectly safe, as long as the variables involved never actually overflow ๐ So this warning can totally give a false positive, which is a warning about code that isn't actually a problem ๐ To help us focus on what matters, GCC has several warning levels โจ No warnings are issued for undefined signed overflow while the compiler is estimating how many iterations a loop needs, especially when it's figuring out whether a loop runs at all ๐
-Wstrict-overflow=1
Warn about cases that are both questionable and easy to avoid ๐ For example, the compiler simplifies x + 1 > x to 1. This level of -Wstrict-overflow is turned on by -Wall. Higher levels aren't, so you have to ask for them yourself ๐โโ๏ธ
-Wstrict-overflow=2
Also warn about other cases where a comparison gets simplified to a constant ๐ฆ For example, abs (x) >= 0. This can only be simplified when signed integer overflow is undefined, because abs (INT_MIN) overflows to INT_MIN, which is less than zero. -Wstrict-overflow with no level is the same as -Wstrict-overflow=2.
-Wstrict-overflow=3
Also warn about other cases where a comparison is simplified ๐ธ For example, x + 1 > 1 is simplified to x > 0.
-Wstrict-overflow=4
Also warn about other simplifications that aren't covered by the cases above โจ For example, (x * 10) / 5 is simplified to x * 2.
-Wstrict-overflow=5
Also warn about cases where the compiler shrinks the magnitude of a constant in a comparison ๐ญ For example, x + 2 > y is simplified to x + 1 >= y. This one is only reported at the highest warning level, because this simplification applies to so many comparisons that this level gives a very large number of false positives ๐
-Wstring-compare
GCC will side-eye any strcmp and strncmp call whose result is locked in as zero or non-zero during an equality test ๐ That happens when one argument is longer than the array the other argument is stored in (or the bound, in the case of strncmp). Those calls could be mistakes ๐ In the example below, the strcmp call gets flagged because its result has to be non-zero no matter what's stored in the array a.
extern char a[4];
void f (char *d)
{
strcpy (d, "string");
...
if (0 == strcmp (a, d)) // cannot be true
puts ("a and d are the same");
}
-Wstring-compare is enabled by -Wextra ๐ฅ
-Wstringop-overflow, -Wstringop-overflow=type
GCC warns about calls to string manipulation functions like memcpy and strcpy that are going to overflow the destination buffer ๐ง The optional argument is one greater than the type of Object Size Checking to use when figuring out the size of the destination. That argument only matters for functions that work on character arrays. Raw memory functions like memcpy always use Object Size type-0. The option also warns about calls that specify a size bigger than the largest possible object, or at most SIZE_MAX / 2 bytes. It works best with optimization turned on. It can still catch a small subset of simple buffer overflows without optimization, in calls to GCC built-in functions like __builtin_memcpy that match the standard functions. Either way, it only warns about a subset of the overflows that the matching overflow-checking built-ins can detect ๐ For example, the option warns about the strcpy call below, because it copies at least 5 characters (the string "blue" including the terminating NUL) into a buffer of size 4.
enum Color { blue, purple, yellow };
const char* f (enum Color clr)
{
static char buf [4];
const char *str;
switch (clr)
{
case blue: str = "blue"; break;
case purple: str = "purple"; break;
case yellow: str = "yellow"; break;
}
return strcpy (buf, str); // warning here
}
Heads up: -Wstringop-overflow=2 is enabled by default ๐
-Wstringop-overflow, -Wstringop-overflow=1
The -Wstringop-overflow=1 option uses type-zero Object Size Checking to figure out the sizes of destination objects ๐ This is the default setting of the option. At this setting, it doesn't warn about writes past the end of subobjects of larger objects accessed through pointers, unless the size of the largest surrounding object is known. When the destination might be one of several objects, it's assumed to be the largest one of them. On Linux systems, when optimization is enabled at this setting, the option warns about the same code as when the _FORTIFY_SOURCE macro is defined to a non-zero value ๐ซถ
-Wstringop-overflow=2
The -Wstringop-overflow=2 option uses type-one Object Size Checking to figure out the sizes of destination objects. At this setting, it warns about overflows when writing to members of the largest complete objects whose exact size is known ๐ It does not warn about excessive writes to the same members of unknown objects referenced by pointers, since those pointers may point to arrays with an unknown number of elements.
-Wstringop-overflow=3
The -Wstringop-overflow=3 option uses type-two Object Size Checking to figure out the sizes of destination objects. At this setting, it warns about overflowing the smallest object or data member. This is the most restrictive setting of the option that may result in warnings for safe code ๐ฌ
-Wstringop-overflow=4
The -Wstringop-overflow=4 option uses type-three Object Size Checking to figure out the sizes of destination objects. At this setting, it warns about overflowing any data members. When the destination is one of several objects, it uses the size of the largest of them to decide whether to warn. Just like -Wstringop-overflow=3, this setting may result in warnings for benign code ๐
-Wno-stringop-truncation
Don't warn about calls to bounded string manipulation functions like strncat, strncpy, and stpncpy that might either truncate the copied string or leave the destination unchanged ๐
In the following example, the call to strncat specifies a bound that's less than the length of the source string. That means the copy gets truncated, so the call is diagnosed. To avoid the warning, use bufsize - strlen (buf) - 1) as the bound โจ
void append (char *buf, size_t bufsize)
{
strncat (buf, ".txt", 3);
}
Another example: the following call to strncpy copies just the characters before the terminating NUL into d, without appending the NUL to the end. Assuming the result of strncpy is always a NUL-terminated string is a super common mistake, so the call is diagnosed ๐ญ To avoid the warning when the result isn't supposed to be NUL-terminated, call memcpy instead.
void copy (char *d, const char *s)
{
strncpy (d, s, strlen (s));
}
In the following example, the call to strncpy uses the size of the destination buffer as the bound. If the length of the source string is equal to or greater than that size, the copy won't be NUL-terminated. So, the call is also 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 ๐ฆ Those arrays aren't suitable arguments for functions that expect NUL-terminated strings, though. To help catch accidental misuse of them, GCC issues warnings unless it can prove the use is safe ๐ซถ
-Wsuggest-attribute=[pure|const|noreturn|format|cold|malloc]
Warn about cases where adding an attribute might be beneficial โจ The attributes currently supported are listed below.
-Wsuggest-attribute=pure, -Wsuggest-attribute=const, -Wsuggest-attribute=noreturn, -Wmissing-noreturn, -Wsuggest-attribute=malloc
Warn about functions that might be good candidates for the attributes pure, const, noreturn, or malloc ๐ The compiler only warns about functions that are visible in other compilation units, or (for pure and const) if it can't prove that the function returns normally. A function returns normally if it doesn't contain an infinite loop, and doesn't return abnormally by throwing, calling abort, or trapping. This analysis requires the option -fipa-pure-const, which is enabled by default at -O and higher. Higher optimization levels make the analysis more accurate ๐ธ
-Wsuggest-attribute=format, -Wmissing-format-attribute
Warn about function pointers that might be candidates for format attributes ๐ง These are only possible candidates, not absolute ones. GCC guesses that function pointers with format attributes that are used in assignments, initializations, parameter passing, or return statements should have a matching format attribute in the resulting type. In other words, the left-hand side of the assignment or initialization, the type of the parameter variable, or the return type of the containing function should also have a format attribute to avoid the warning, respectively ๐
okay so GCC also warns about function definitions that might be candidates for format attributes ๐ and bestie, these are ONLY possible candidates, not confirmed ones ๐ซถ GCC guesses that a format attribute might fit any function that calls something like vprintf or vscanf, but that's not always the case ๐. Some functions where a format attribute is actually right might not get flagged at all ๐
-Wsuggest-attribute=coldโ โ๏ธ GCC warns about 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 around C++throwor fatal error reporting functions that lead toabort.-Walloc-zeroโ ๐ซง GCC warns about calls to allocation functions decorated with thealloc_sizeattribute that ask for zero bytes. This includes the built-in forms ofaligned_alloc,alloca,calloc,malloc, andrealloc. What these functions do with a zero size differs between implementations (andreallochas been deprecated for it), so relying on that behaviour can cause subtle portability bugs. Avoid it, periodt ๐-Walloc-size-larger-than=byte-sizeโ ๐ GCC warns about calls to functions decorated with thealloc_sizeattribute that try to allocate objects bigger than the number of bytes you specify. It also warns if the result of the size computation, done in an integer type with infinite precision, would go overPTRDIFF_MAXon the target.-Walloc-size-larger-than=PTRDIFF_MAXis on by default. You can turn these warnings off by giving a byte-size ofSIZE_MAXor more, or by using-Wno-alloc-size-larger-than.-Wno-alloc-size-larger-thanโ ๐ซ Disables-Walloc-size-larger-than=warnings. It's the same as-Walloc-size-larger-than=SIZE_MAXor larger.-Wallocaโ ๐ Warns on every use ofallocain your source. No exceptions, bestie.-Walloca-larger-than=byte-sizeโ ๐ง Warns on calls toallocawhose integer argument is either zero, or isn't bounded by a controlling predicate that limits it to at most byte-size. It also warns when the bound is unknown. Arguments of non-integer types count as unbounded, even if they look like they're in the expected range.
For example, a bounded case of alloca could be:
void func (size_t n)
{
void *p;
if (n <= 1000)
p = alloca (n);
else
p = malloc (n);
f (p);
}
In the above example, passing -Walloca-larger-than=1000 would not issue a warning, because the call to alloca is known to be at most 1000 bytes. However, if -Walloca-larger-than=500 were passed, the compiler would emit a warning. ๐ซฃ
Unbounded uses, on the other hand, are uses of alloca with no controlling predicate constraining its integer argument. For example:
void func ()
{
void *p = alloca (n);
f (p);
}
If -Walloca-larger-than=500 were passed, the above would trigger a warning, but this time because of the lack of bounds checking. ๐ค
Note that even seemingly correct code involving signed integers could cause a warning:
void func (signed int n)
{
if (n < 500)
{
p = alloca (n);
f (p);
}
}
In the above example, n could be negative, causing a larger than expected argument to be implicitly cast into the alloca call. Wild, right? ๐
This option also warns when alloca is used in a loop. ๐
-Walloca-larger-than=PTRDIFF_MAX is enabled by default, but it's usually only effective when -ftree-vrp is active (default for -O2 and above). โจ
See also -Wvla-larger-than=byte-size. ๐ฆ
-Wno-alloca-larger-thanโ ๐ซ Disables-Walloca-larger-than=warnings. It's equivalent to-Walloca-larger-than=SIZE_MAXor larger.-Warith-conversionโ ๐ข Warns about implicit conversions from arithmetic operations, even when converting the operands to the same type can't change their values. This affects warnings from-Wconversion,-Wfloat-conversion, and-Wsign-conversion.
void f (char c, int i)
{
c = c + i; // warns with -Wconversion
c = c + 1; // only warns with -Warith-conversion
}
-Warray-bounds,-Warray-bounds=nโ ๐งบ This option is only active when-ftree-vrpis active (default for-O2and above). It warns about subscripts to arrays that are always out of bounds. It's enabled by-Wall.-Warray-bounds=1โ ๐ท This is the warning level of-Warray-boundsand is enabled by-Wall. Higher levels aren't, so you have to ask for them explicitly.-Warray-bounds=2โ ๐ต๏ธ This level also warns about out of bounds access for arrays at the end of a struct, and for arrays accessed through pointers. It may give a bigger pile of false positives, so it's deactivated by default. ๐ญ
-Wattribute-alias=n,-Wno-attribute-aliasโ ๐ช Warns about declarations using thealiasand similar attributes whose target is incompatible with the type of the alias.-Wattribute-alias=1โ ๐ฅฐ The default level. It diagnoses incompatibilities between the type of the alias declaration and that of its target. These are usually a sign of bugs.-Wattribute-alias=2โ ๐ง At this level,-Wattribute-aliasalso diagnoses cases where the attributes of the alias declaration are more restrictive than the attributes applied to its target. These mismatches can lead to incorrect code generation. Other times they're harmless, and you can fix them just by adding the missing attribute to the target. For comparison, see the-Wmissing-attributesoption, which controls diagnostics when the alias declaration is less restrictive than the target, rather than more.
Attributes considered include alloc_align, alloc_size, cold, const, hot, leaf, malloc, nonnull, noreturn, nothrow, pure, returns_nonnull, and returns_twice. ๐
-Wattribute-alias is equivalent to -Wattribute-alias=1, and that's the default. You can disable these warnings with either -Wno-attribute-alias or -Wattribute-alias=0. ๐
โโ๏ธ
-Wbool-compareโ โ๏ธ Warns about a boolean expression being compared with an integer value other thantrueorfalse. For instance, the following comparison is always false:
int n = 5;
...
if ((n > 1) == 2) { ... }
This warning is enabled by -Wall. ๐
-Wbool-operationโ ๐งฉ Warns about suspicious operations on expressions of a boolean type. For instance, bitwise negation of a boolean is very likely a bug in the program. For C, this warning also warns about incrementing or decrementing a boolean, which rarely makes sense. (In C++, decrementing a boolean is always invalid. Incrementing a boolean is invalid in C++17, and deprecated otherwise.) ๐
This warning is enabled by -Wall.
-Wduplicated-branchesโ ๐ฏ Warns when an if-else has identical branches. This warning catches cases like:
if (p != NULL)
return 0;
else
return 0;
It doesn't warn when both branches contain just a null statement. This warning also warns for conditional operators:
int i = x ? *p : *p;
-Wduplicated-condโ ๐ Warns about duplicated conditions in an if-else-if chain. For instance, it warns for the following code:
if (p->q != NULL) { ... }
else if (p->q != NULL) { ... }
-Wframe-addressโ ๐ช Warns when__builtin_frame_addressor__builtin_return_addressis called with an argument greater than 0. Those calls may return indeterminate values or crash the program. This warning is included in-Wall. ๐-Wno-discarded-qualifiers(C and Objective-C only) โ ๐ Stops GCC from warning when type qualifiers on pointers are being discarded. Normally the compiler warns if aconst char *variable gets passed to a function that takes achar *parameter. This option suppresses that warning.-Wno-discarded-array-qualifiers(C and Objective-C only) โ ๐ Stops GCC from warning when type qualifiers on arrays that are pointer targets are being discarded. Normally the compiler warns if aconst int (*)[]variable gets passed to a function that takes anint (*)[]parameter. This option suppresses that warning.-Wno-incompatible-pointer-types(C and Objective-C only) โ ๐ซ Stops GCC from warning when there's a conversion between pointers with incompatible types. This covers cases not handled by-Wno-pointer-sign, which warns about pointer argument passing or assignment with different signedness.-Wno-int-conversion(C and Objective-C only) โ ๐ Stops GCC from warning about incompatible integer-to-pointer and pointer-to-integer conversions. This warning is about implicit conversions. For explicit conversions, you can use-Wno-int-to-pointer-castand-Wno-pointer-to-int-castinstead.-Wzero-length-boundsโ ๐ Warns about accesses to elements of zero-length array members that might overlap other members of the same object. Declaring interior zero-length arrays is discouraged, because accesses to them are undefined. See
For example, the first two stores in function bad are diagnosed, because the array elements overlap the subsequent members b and c. The third store is diagnosed by -Warray-bounds because it's beyond the bounds of the enclosing object. ๐งธ
struct X { int a[0]; int b, c; };
struct X x;
void bad (void)
{
x.a[0] = 0; // -Wzero-length-bounds
x.a[1] = 1; // -Wzero-length-bounds
x.a[2] = 2; // -Warray-bounds
}
Option -Wzero-length-bounds is enabled by -Warray-bounds. and that's the vibe, bestie ๐ธ
-Wdiv-by-zero... wait, let's get into the flags ๐
-Wno-div-by-zeroโ okay so this one tells GCC to stop yelling about integer division by zero that it can spot at compile time ๐ Floating-point division by zero doesn't get flagged either, bc dividing by zero with floats can be a totally legit way to get infinities and NaNs โจ-Wsystem-headersโ normally GCC zips its lips about warnings from system header files, bc those usually aren't real problems and would just make the output messier ๐ธ With this flag it treats system header warnings like they came from your own code ๐ ngl but heads up: using-Wallwith this still won't warn about unknown pragmas in system headers. For that you also need-Wunknown-pragmas๐ซถ-Wtautological-compareโ warns when you compare something to itself and it's always true or always false ๐ likeint i = 1;thenif (i > i) { ... }is giving nothing but mistakes ๐ญ It also catches bitwise comparisons that are always true or false, likeif ((a & 16) == 10) { ... }which will always be false ๐ โโ๏ธ This one is enabled by-Wall๐-Wtrampolinesโ warns about trampolines made for pointers to nested functions ๐ง A trampoline is a little bit of data or code created at run time on the stack when you take the address of a nested function, and it's used to call that nested function indirectly ๐ฆ For some targets it's just data and needs no special treatment, but for most targets it's code, which means the stack has to be made executable for the program to work properly ๐ฅ-Wfloat-equalโ warns when floating-point values get used in equality comparisons ๐ The vibe is that sometimes you treat floats like approximations of real numbers, and then you need to figure out the max (or likely max) error your computation introduces and allow for it ๐ Instead of testing for equality, check whether the two values' ranges overlap, which is done with the relational operators, so equality comparisons are probably mistaken ๐-Wtraditional(C and Objective-C only) โ warns about constructs that act differently in traditional C vs ISO C, plus ISO C stuff that has no traditional equivalent and problematic stuff you should avoid ๐ Here's the full list of what it looks out for:- Macro parameters inside string literals in the macro body ๐ Traditional C does replacement inside string literals, but ISO C doesn't.
- Some preprocessor directives didn't exist in traditional C. Traditional preprocessors only treated a line as a directive if the
#was in column 1, so-Wtraditionalwarns about directives traditional C understands but ignores because the#isn't the first character on the line ๐ซ It also suggests indenting directives like#pragmathat traditional C doesn't understand ๐ Some traditional implementations don't recognize#elif, so this option suggests avoiding it altogether ๐ โโ๏ธ - A function-like macro that shows up without arguments ๐งฉ
- The unary plus operator โ
- The
Uinteger constant suffix, or theForLfloating-point constant suffixes. (Traditional C does support theLsuffix on integer constants.) Heads up, these suffixes show up in macros defined in system headers on most modern systems, like the_MIN/_MAXmacros in<limits.h>๐ Using those macros in your own code could 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 that block ends ๐
- A
switchstatement whose operand is of typelong๐ - A non-
staticfunction declaration that follows astaticone. Some traditional C compilers don't accept this ๐ - The ISO type of an integer constant has a different width or signedness from its traditional type. This only gets issued if the constant's base is ten, so hexadecimal or octal values (which usually represent bit patterns) aren't warned about ๐ข
- ISO string concatenation ๐งต
- Initialization of automatic aggregates ๐ฆ
- Identifier conflicts with labels. Traditional C doesn't have a separate namespace for labels ๐ท๏ธ
- Initialization of unions. If the initializer is zero, the warning gets skipped, bc the assumption is that a zero initializer appears conditioned on something like
__STDC__to avoid missing-initializer warnings and relies on default zeroing in traditional C ๐ซถ - Conversions by prototypes between fixed-point and floating-point values, and vice versa. Missing these prototypes when compiling with traditional C causes serious problems ๐ This is a subset of the possible conversion warnings; for the full set use
-Wtraditional-conversion๐ - ISO C style function definitions. This one is intentionally not issued for prototype declarations or variadic functions, bc those ISO C features show up in your code when you use libiberty's traditional C compatibility macros,
PARAMSandVPARAMS๐ It's also skipped for nested functions, bc that's already a GCC extension and isn't relevant to traditional C compatibility ๐
-Wtraditional-conversion(C and Objective-C only) โ warns if a prototype causes a type conversion that's different from what would happen to the same argument without a prototype ๐ That includes fixed-to-floating and floating-to-fixed conversions, plus conversions that change the width or signedness of a fixed-point argument, except when it matches the default promotion ๐ง-Wdeclaration-after-statement(C and Objective-C only) โ warns when a declaration shows up after a statement in a block ๐โโ๏ธ This came from C++ and was introduced with ISO C99, and GCC allows it by default. 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 ๐ช In C++, the compiler warns if a local variable shadows an explicit typedef, but not if it shadows a struct, class, or enum ๐ง When this warning is on, it also includes all instances of local shadowing, which means-Wno-shadow=localand-Wno-shadow=compatible-localget ignored when-Wshadowis used ๐ Same as-Wshadow=global๐-Wno-shadow-ivar(Objective-C only) โ don't warn when a local variable shadows an instance variable in an Objective-C method ๐ฆ-Wshadow=globalโ warns for any shadowing. Same as-Wshadowโจ-Wshadow=localโ warns when a local variable shadows another local variable or parameter ๐ธ-Wshadow=compatible-localโ warns when a local variable shadows another local variable or parameter whose type is compatible with the shadowing variable's type. In C++, "compatible" means the shadowing variable's type can be converted to the shadowed variable's type ๐ซง The idea behind this flag (on top of-Wshadow=local) is that when a local variable shadows one of an incompatible type, it's most likely intentional and not a bug or typo. Like in this example:
for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i)
{
for (int i = 0; i < N; ++i)
{
...
}
...
}
Since the two i variables in that example have incompatible types, enabling only -Wshadow=compatible-local doesn't emit a warning ๐ Bc their types are incompatible, if a programmer accidentally uses one in place of the other, type checking is expected to catch it and emit an error or warning ๐ก๏ธ Using this flag instead of -Wshadow=local can reduce the number of warnings triggered by intentional shadowing ๐ Also, shadowing const char *i with char *i does not emit a warning ๐ค
This warning is also enabled by -Wshadow=local ๐
-Wlarger-than=byte-sizeโ warns whenever an object is defined whose size is bigger than byte-size ๐-Wlarger-than=PTRDIFF_MAXis enabled by default. You can disable these warnings by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-larger-than๐ โโ๏ธ-Wno-larger-thanโ disables-Wlarger-than=warnings. It's the same as-Wlarger-than=SIZE_MAXor larger ๐-Wframe-larger-than=byte-sizeโ warns if the size of a function frame exceeds byte-size ๐ผ๏ธ The stack frame size calculation is approximate and not conservative, so the actual requirements might be somewhat bigger than byte-size even if you don't get a warning ๐ฌ Also, space allocated withalloca, variable-length arrays, or related constructs isn't counted when GCC decides whether to warn ๐ซ-Wframe-larger-than=PTRDIFF_MAXis enabled by default. Disable these warnings by specifying a byte-size ofSIZE_MAXor more, or with-Wno-frame-larger-than๐ฆ-Wno-frame-larger-thanโ disables-Wframe-larger-than=warnings. Same as-Wframe-larger-than=SIZE_MAXor larger ๐-Wno-free-nonheap-objectโ don't warn when someone tries to free an object that wasn't allocated on the heap ๐งน-Wstack-usage=byte-sizeโ okay so this one warns bestie if a function's stack usage might go overbyte-size๐โจ. The math is super cautious on purpose ๐ซถ. The compiler counts space fromalloca, variable-length arrays, and related constructs too when deciding whether to warn ๐ .
The message matches what -fstack-usage prints ๐, and there are three flavours:
- If the stack usage is fully static but goes over the limit, you get
warning: stack usage is 1120 bytes๐ญ - If it's partly dynamic but bounded, you get
warning: stack usage might be 1648 bytes๐ธ - If it's partly dynamic and unbounded, you get
warning: stack usage might be unbounded๐
-Wstack-usage=PTRDIFF_MAX is on by default ๐ฅ. To silence these warnings, give a byte-size of SIZE_MAX or more, or just use -Wno-stack-usage ๐.
-Wno-stack-usageโ the "I'm not doing this rn" option ๐ง. It turns off-Wstack-usage=warnings and is the same as-Wstack-usage=SIZE_MAXor larger ๐.-Wunsafe-loop-optimizationsโ warns when a loop can't be optimised because the compiler can't assume anything about its index bounds ๐. With-funsafe-loop-optimizations, it instead warns when the compiler does make those assumptions ๐.-Wno-pedantic-ms-format(MinGW targets only) โ ngl, this one's very specific ๐ช. Used together with-Wformatand-pedanticwithout GNU extensions, it stops the warnings about the non-ISOprintfandscanfwidth specifiersI32,I64, andIon Windows targets, since those depend on the MS runtime ๐ฆ.-Wpointer-arithโ warns about anything that depends on the "size of" a function type or ofvoid๐ท. GNU C gives those types a size of 1 sovoid *pointers and function pointers are easier to do maths with ๐. In C++, it also warns when an arithmetic operation involvesNULLโญ. This one gets switched on by-Wpedantictoo ๐ซง.-Wno-pointer-compareโ stops the warning for comparing a pointer with a zero character constant ๐. That usually means the pointer was supposed to get dereferenced, so the warning is actually helpful, but you can turn it off here ๐. Check out this example:
const char *p = foo ();
if (p == '\0')
return 42;
Heads up: the code above is invalid in C++11 ๐.
This warning is enabled by default ๐ .
-Wtype-limitsโ warns if a comparison is always true or always false because of the limited range of the data type ๐. Constant expressions don't get this warning ๐. For example, it warns if an unsigned variable is compared against zero with<or>=๐. This one is also turned on by-Wextraโจ.-Wabsolute-value(C and Objective-C only) โ calls to standard absolute-value functions get flagged when there's a better function for the job ๐ฆ. For example,abs(3.14)triggers it becausefabsis the right call for adouble๐ . It also triggers when the argument has an unsigned type ๐ซถ. You can suppress it with an explicit type cast, and-Wextraturns it on too ๐ธ.-Wcomment,-Wcommentsโ warns whenever a/*comment-start sequence shows up inside a/* comment, or whenever a backslash-newline appears in a//comment ๐. It's enabled by-Wall๐ฅ.-Wtrigraphsโ warns if any trigraphs pop up that might change what the program means ๐ง. Trigraphs inside comments don't get warned about, except the ones that would form escaped newlines ๐.
-Wall implies this option ๐. If -Wall isn't given, it's still enabled unless trigraphs are enabled ๐. If you want trigraph conversion without the warnings but still want the other -Wall warnings, use -trigraphs -Wall -Wno-trigraphs ๐.
-Wundefโ warns if an undefined identifier gets evaluated in an#ifdirective โจ. Those identifiers get replaced with zero ๐ซง.-Wexpansion-to-definedโ warns wheneverdefinedshows up in a macro's expansion, including when the macro is expanded by an#ifdirective ๐ธ. That kind of usage isn't portable, so it's a red flag ๐ฉ. This warning is also enabled by-Wpedanticand-Wextra๐ .-Wunused-macrosโ warns about macros defined in the main file that never get used ๐ฆ. A macro counts as used if it gets expanded or tested for existence at least once ๐. The preprocessor also warns if the macro hasn't been used by the time it gets redefined or undefined ๐ญ.
Built-in macros, macros defined on the command line, and macros defined in include files are not warned about ๐ซถ.
Note: if a macro is actually used but only inside skipped conditional blocks, the preprocessor still reports it as unused ๐. To dodge the warning, you can improve the scope of the macro's definition, like moving it into the first skipped block ๐ท. Or you could provide a dummy use, something like this:
#if defined the_macro_causing_the_warning
#endif
-Wno-endif-labelsโ stops the warning for when an#elseor#endifis followed by text ๐. This 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 ๐. This warning is on by default ๐
.
-Wbad-function-cast(C and Objective-C only) โ warns when a function call gets cast to a non-matching type ๐. For example, it warns if a call to a function returning an integer type is cast to a pointer type ๐.-Wc90-c99-compat(C and Objective-C only) โ warns about features that are in ISO C99 but not in ISO C90 ๐. Think variable length arrays, thelong longtype, thebooltype, compound literals, designated initializers, and so on โจ. This option doesn't depend on the standards mode ๐ง. 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 ๐. Think anonymous structures and unions, the_Atomictype qualifier, the_Thread_localstorage-class specifier, the_Alignasspecifier, theAlignofoperator, the_Generickeyword, and so on ๐. It's independent of the standards mode too ๐ฆ, and warnings are disabled in the expression that follows__extension__๐ .-Wc11-c2x-compat(C and Objective-C only) โ features in ISO C11 that aren't in ISO C2X get flagged here ๐ธ. For instance, omitting the string in_Static_assert, using[[]]attribute syntax, and using decimal floating-point types ๐ฅ. Again, it doesn't care about the standards mode ๐ซถ, and warnings are disabled in the expression that follows__extension__โจ.-Wc++-compat(C and Objective-C only) โ warns about ISO C constructs that live outside the common subset of ISO C and ISO C++ ๐. For example, implicitly converting fromvoid *to a pointer to a non-voidtype ๐.-Wc++11-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning changes between ISO C++ 1998 and ISO C++ 2011 ๐. For example, identifiers that were fine in ISO C++ 1998 but are keywords in ISO C++ 2011 ๐ . This one turns on-Wnarrowingand is enabled by-Wall๐ง.-Wc++14-compat(C++ and Objective-C++ only) โ same vibe, but for constructs that differ between ISO C++ 2011 and ISO C++ 2014 ๐. Enabled by-Wall๐ซง.-Wc++17-compat(C++ and Objective-C++ only) โ constructs that differ between ISO C++ 2014 and ISO C++ 2017 ๐ฆ. Enabled by-Wall๐.-Wc++20-compat(C++ and Objective-C++ only) โ constructs that differ between ISO C++ 2017 and ISO C++ 2020 โญ. Enabled by-Wall๐ธ.-Wcast-qualโ warns whenever a pointer gets cast in a way that removes a type qualifier from the target type ๐. For example, it warns if aconst char *is cast to a plainchar *๐ .
It also warns when a cast introduces a type qualifier in an unsafe way ๐ญ. Casting char ** to const char ** is unsafe, as in this example ๐:
/* p is char ** value. */
const char **q = (const char **) p;
/* Assignment of readonly string to const char * is OK. */
*q = "string";
/* Now char** pointer points to read-only memory. */
**p = 'b';
-Wcast-alignโ warns whenever a pointer is cast so that the required alignment of the target goes up ๐ท. For example, it warns if achar *is cast to anint *on machines where integers can only be accessed at two- or four-byte boundaries ๐.-Wcast-align=strictโ same idea, but stricter ๐ฅ. It warns whenever the required alignment goes up regardless of the target machine ๐. For example, it warns if achar *is cast to anint *no matter what ๐ .-Wcast-function-typeโ warns when a function pointer is cast to an incompatible function pointer ๐ง. 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 are ignored, likeintvs.longon ILP32 targets ๐ฆ. Type qualifiers are ignored too ๐ซถ.
The function type void (*) (void) is special and matches everything, so you can use it to suppress this warning โจ. For casts involving pointer to member types, this warning goes off whenever the cast changes the pointer to member type ๐. It's enabled by -Wextra ๐.
-Wwrite-stringsโ when 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 help you catch, at compile time, code that might try to write into a string constant ๐ซถ. But they only really work if you've been super careful withconstin declarations and prototypes ๐ญ. Otherwise, honestly, they're just a nuisance ๐. That's why-Walldoesn't request these warnings ๐ธ.
When compiling C++, it warns about the deprecated conversion from string literals to char * ๐
. This warning is enabled by default for C++ programs ๐ฅ.
-Wclobberedโ warns for variables that might be changed bylongjmporvfork๐ง. This one is also enabled by-Wextraโญ.-Wconversionโ okay bestie, this one is all about sneaky implicit conversions that might quietly change a value ๐ It catches real-to-integer swaps likeabs (x)whenxisdouble, signed-to-unsigned drama likeunsigned ui = -1, and squishing things into smaller types likesqrtf (M_PI)๐ซฃ
NGL the good news is it won't flag explicit casts like abs ((int) x) or ui = (unsigned) -1 ๐
and it skips anything where the value doesn't actually change, like abs (2.0) ๐ Warnings about signed/unsigned integer conversions can be switched off with -Wno-sign-conversion ๐ซถ
For C++ it's a whole different vibe ๐ฅ It also warns about confusing overload resolution for user-defined conversions, plus conversions that never use a type conversion operator: conversions to void, the same type, a base class, or a reference to them. Signed/unsigned conversion warnings are disabled by default in C++ unless you explicitly turn on -Wsign-conversion ๐
Warnings about conversion from arithmetic on a small type back to that type only show up with -Warith-conversion ๐ฆ
-Wdangling-elseโ heads up, this one catches constructions where it's unclear whichifstatement anelsebranch belongs to ๐ Check out this sus example:
{
if (a)
if (b)
foo ();
else
bar ();
}
Here's the tea โ In C/C++, every else branch belongs to the innermost possible if statement, which in this example is if (b). That's often NOT what the programmer expected, as the indentation in the example above shows ๐ When there's potential for this confusion, GCC issues a warning when this flag is specified. To eliminate the warning, add explicit braces around the innermost if statement so there's no way the else can belong to the enclosing if. The fixed code looks like this:
{
if (a)
{
if (b)
foo ();
else
bar ();
}
}
This warning is enabled by -Wparentheses โจ
-Wdate-timeโ this one warns when the macros__TIME__,__DATE__or__TIMESTAMP__show up, because they might stop your compilations from being bit-wise-identical and reproducible ๐ฐ๏ธ-Wempty-bodyโ warns if an empty body shows up in anif,elseordo whilestatement ๐ซฅ This warning is also enabled by-Wextra๐-Wno-endif-labelsโ the vibe here is "chill": it stops GCC from warning about stray tokens after#elseand#endif๐ฆ-Wenum-compareโ warns about a comparison between values of different enumerated types ๐ In C++, enumerated type mismatches in conditional expressions get diagnosed too, and this warning is enabled by default there. In C, it's enabled by-Wall๐-Wenum-conversion(C, Objective-C only) โ warns when a value of enumerated type gets implicitly converted to a different enumerated type ๐ This warning is enabled by-Wextraโจ-Wjump-misses-init(C, Objective-C only) โ this one is for when agotoorswitchstatement jumps forward across the initialization of a variable, or jumps backward to a label after that variable has already been initialized ๐ It only warns about variables that are initialized when they're declared. It's only supported for C and Objective-C, because in C++ this sort of branch is an error anyway ๐ โโ๏ธ
-Wjump-misses-init is included in -Wc++-compat ๐ and it can be disabled with the -Wno-jump-misses-init option ๐ซถ
-Wsign-compareโ warns when a comparison between signed and unsigned values could give you an incorrect result, because the signed value gets converted to unsigned ๐ญ In C++, this warning is also enabled by-Wall. In C, it's enabled by-Wextra๐ธ-Wsign-conversionโ warns about implicit conversions that might change the sign of an integer value, like assigning a signed integer expression to an unsigned integer variable ๐ An explicit cast silences the warning. In C, this option is also enabled by-Wconversion๐-Wfloat-conversionโ warns about implicit conversions that reduce the precision of a real value ๐ That includes conversions from real to integer, and from higher precision real to lower precision real values. This option is also enabled by-Wconversion๐-Wno-scalar-storage-orderโ stops GCC from warning on suspicious constructs involving reverse scalar storage order ๐ง-Wsizeof-pointer-divโ warns about suspicious divisions of twosizeofexpressions that divide the pointer size by the element size. That's the usual way to compute an array size, but it won't work out correctly with pointers ๐ This warning warns e.g. aboutsizeof (ptr) / sizeof (ptr[0])ifptris not an array, but a pointer. This warning is enabled by-Wall๐-Wsizeof-pointer-memaccessโ warns about suspicious length parameters passed to certain string and memory built-in functions when the argument usessizeof๐ง It triggers for example formemset (ptr, 0, sizeof (ptr));ifptris not an array but a pointer, and it suggests a possible fix. It also flags stuff likememcpy (&foo, ptr, sizeof (&foo));.
-Wsizeof-pointer-memaccess also warns about calls to bounded string copy functions like strncat or strncpy that specify the bound as a sizeof expression of the source array. For example, in the following function the call to strncat specifies the size of the source string as the bound. That's almost certainly a mistake, so the call is diagnosed ๐
void make_file (const char *name)
{
char path[PATH_MAX];
strncpy (path, name, sizeof path - 1);
strncat (path, ".text", sizeof ".text");
...
}
The -Wsizeof-pointer-memaccess option is enabled by -Wall โจ
-Wno-sizeof-array-argumentโ do not warn when thesizeofoperator is applied to a parameter that's declared as an array in a function definition ๐ซถ This warning is enabled by default for C and C++ programs ๐-Wmemset-elt-sizeโ warns about suspicious calls to thememsetbuilt-in function if the first argument references an array, and the third argument is a number equal to the number of elements, but not equal to the size of the array in memory ๐งฎ This usually means you forgot to multiply by the element size ๐ญ This warning is enabled by-Wall๐-Wmemset-transposed-argsโ warns about suspicious calls to thememsetbuilt-in function where the second argument is not zero and the third argument is zero ๐ For example, the callmemset (buf, sizeof buf, 0)gets diagnosed becausememset (buf, 0, sizeof buf)was what you meant. The diagnostic is only emitted if the third argument is a literal zero. If it's an expression that folds to zero, or a cast of zero to some type, it's far less likely the arguments got mistakenly transposed, so no warning is emitted ๐ค This warning is enabled by-Wallโจ-Waddressโ warns about suspicious uses of memory addresses ๐ These include using the address of a function in a conditional expression, such asvoid func(void); if (func), and comparisons against the memory address of a string literal, such asif (x == "abc").
These uses typically point to a programmer error. The address of a function always evaluates to true, so using it in a conditional usually means you forgot the parentheses in a function call ๐คฆโโ๏ธ Comparisons against string literals result in unspecified behavior and aren't portable in C, so they usually mean you meant to use strcmp ๐ This warning is enabled by -Wall ๐
-Wno-address-of-packed-memberโ do not warn when the address of a packed member of a struct or union is taken, which usually results in an unaligned pointer value ๐ง This is enabled by default ๐-Wlogical-opโ warns about suspicious uses of logical operators in expressions ๐ง This includes using logical operators in contexts where a bit-wise operator is likely to be expected. It also warns when the operands of a logical operator are the same:
extern int a;
if (a < 0 && a < 0) { ... }
-Wlogical-not-parenthesesโ warns about logical not used on the left hand side operand of a comparison ๐ This option does not warn if the right operand is considered to be a boolean expression. Its purpose is to detect suspicious code like the following:
int a;
...
if (!a > 1) { ... }
You can suppress the warning by wrapping the LHS 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 elicits a warning.)-Wno-aggressive-loop-optimizationsโ warns if, in a loop with a constant number of iterations, the compiler detects undefined behavior in some statement during one or more of the iterations ๐ Undefined behavior is no joke, bestie ๐ซฃ-Wno-attributesโ do not warn if an unexpected__attribute__is used, such as unrecognized attributes, function attributes applied to variables, etc. ๐ท๏ธ This does not stop errors for incorrect use of supported attributes โ-Wno-builtin-declaration-mismatchโ warns if a built-in function is declared with an incompatible signature or as a non-function, or when a built-in function declared with a type that doesn't include a prototype is called with arguments whose promoted types don't match those expected by the function ๐งฉ When-Wextrais specified, it also warns when a built-in function that takes arguments is declared without a prototype. The-Wbuiltin-declaration-mismatchwarning is enabled by default. To avoid the warning, include the appropriate header to bring the prototypes of built-in functions into scope ๐
Check out this example: the call to memset 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 as well ๐
extern void* memset ();
void f (void *d)
{
memset (d, '\0', 32);
}
-Wno-builtin-macro-redefinedโ okay so this one stops GCC from yelling when certain built-in macros get redefined. That covers__TIMESTAMP__,__TIME__,__DATE__,__FILE__, and__BASE_FILE__. ๐-Wstrict-prototypes(C and Objective-C only) โ this warns if a function is declared or defined without spelling out its argument types. An old-style definition gets a pass with no warning if an earlier declaration already listed the argument types. ๐-Wold-style-declaration(C and Objective-C only) โ this flags obsolescent declarations, going by the C Standard. For example, it warns if storage-class specifiers likestaticaren't the very first thing in a declaration. It's also turned on by-Wextra. โจ-Wold-style-definition(C and Objective-C only) โ this warns whenever an old-style function definition shows up, even if there's already a prototype. A definition using()doesn't count as old-style in C2X mode, since it means the same thing as(void)there. For older standards, though, it does count as old-style. ๐ฆ-Wmissing-parameter-type(C and Objective-C only) โ this catches a parameter declared without a type specifier in K&R-style functions, like this:
void foo(bar) { }
It's also enabled by -Wextra. ๐ธ
-Wmissing-prototypes(C and Objective-C only) โ this warns if a global function gets defined without a previous prototype declaration. It fires even when the definition itself provides a prototype. Use it to sniff out 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 provides a prototype, and a non-matching declaration just declares an overload instead of conflicting with an earlier one. For C++, use-Wmissing-declarationsto find missing declarations instead.-Wmissing-declarationsโ this warns if a global function is defined without a previous declaration, even if the definition provides a prototype. Use it to find global functions that aren't declared in header files. In C, there are no warnings for functions with previous non-prototype declarations, so use-Wmissing-prototypesfor those. In C++, there are no warnings for function templates, inline functions, or functions in anonymous namespaces. ๐-Wmissing-field-initializersโ this warns if a structure's initializer is missing some fields. In the example below,x.his implicitly zero, so it triggers the warning:
struct s { int f, g, h; };
struct s x = { 3, 4 };
It does not warn about designated initializers, so this version is fine:
struct s { int f, g, h; };
struct s x = { .f = 3, .g = 4 };
In C, it also doesn't warn about the universal zero initializer { 0 }:
struct s { int f, g, h; };
struct s x = { 0 };
And in C++, the empty { } initializer gets a pass too:
struct s { int f, g, h; };
s x = { };
This warning is included in -Wextra. If you want the other -Wextra warnings without this one, use -Wextra -Wno-missing-field-initializers. ๐
-Wno-multicharโ don't warn when a multicharacter constant like'FOOF'shows up. These usually mean there's a typo in your code, since their values are implementation-defined, so you shouldn't use them in portable code anyway. ๐-Wnormalized=[none|id|nfc|nfkc]โ okay, this one is a whole vibe. In ISO C and ISO C++, two identifiers are different if they're different sequences of characters. But when you use characters outside basic ASCII, you can end up with two different sequences that 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 if your identifiers haven't been normalized. This option controls that warning. ๐ง
There are four levels. The default is -Wnormalized=nfc, which warns about any identifier that isn't in the ISO 10646 "C" normalized form, NFC. NFC is the recommended form for most uses, and it's equivalent to -Wnormalized.
Here's the tea: some characters that ISO C and ISO C++ allow in identifiers aren't allowed in identifiers once they've been turned into NFC. That means there's no way to use these 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 will fix this, which is why it isn't the default. ๐ซถ
You can switch the warning off for all characters with -Wnormalized=none or -Wno-normalized. Only do this if you're using some other normalization scheme (like "D"), because otherwise you can easily create bugs that are literally impossible to see. ๐ญ
Some ISO 10646 characters have distinct meanings but look identical in some fonts or display methods, especially once formatting has been applied. For instance, \u207F, SUPERSCRIPT LATIN SMALL LETTER N, displays just like a regular n that's been placed in a superscript. ISO 10646 defines the NFKC normalization scheme to convert all of these into a standard form too, and GCC warns if your code isn't NFKC when you use -Wnormalized=nfkc. This is kind of like warning about every identifier that contains the letter O, because it might get confused with the digit 0. It's not the default, but it can be a useful local coding convention if your programming environment can't be fixed to display these characters distinctly. ๐
-Wno-attribute-warningโ don't warn about usage of functions declared with thewarningattribute. This warning is on by default. 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 usage of deprecated features. ๐ฆ-Wno-deprecated-declarationsโ don't warn about uses of functions, variables, and types marked as deprecated with thedeprecatedattribute. โจ-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's enabled by default. ๐-Wopenmp-simdโ this warns if the vectorizer cost model overrides the OpenMP simd directive that you set. If you want to loosen the cost model, you can use-fsimd-cost-model=unlimited. ๐ฅ-Woverride-init(C and Objective-C only) โ this warns if an initialized field without side effects gets overridden when you're using designated initializers. It's included in-Wextra. To get the other-Wextrawarnings without this one, use-Wextra -Wno-override-init. ๐-Wno-override-init-side-effects(C and Objective-C only) โ don't warn if an initialized field with side effects gets overridden when you're using designated initializers. This is enabled by default. ๐ธ-Wpackedโ this warns if a structure is given thepackedattribute but that attribute has no effect on the layout or size of the structure. Structures like that can end up misaligned for little benefit. In the example below, the variablef.xinstruct baris misaligned, even thoughstruct bardoesn't have the packed attribute itself:
struct foo {
int x;
char a, b, c, d;
} __attribute__((packed));
struct bar {
char z;
struct foo f;
};
-Wnopacked-bitfield-compatโ the 4.1, 4.2, and 4.3 series of GCC ignored thepackedattribute on bit-fields of typechar. That got fixed in GCC 4.4, but the change can lead to differences in structure layout. GCC tells you when the offset of such a field has changed in GCC 4.4. For example, there's no longer a 4-bit padding between fieldaand fieldbin 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) โ this warns if a structure field with explicitly specified alignment, inside a packed struct or union, is misaligned. In the code below, a warning gets issued onstruct Sthat says something likewarning: 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โ this warns if padding is included in a structure, either to align one of its elements or to align the whole structure. Sometimes you can rearrange the fields to cut down the padding and make the structure smaller. ๐-Wredundant-declsโ this warns if anything is declared more than once in the same scope, even in cases where multiple declarations are valid and change nothing. ๐-Wrestrictโ this warns when an object referenced by arestrict-qualified parameter (or a__restrict-qualified parameter, in C++) is aliased by another argument, or when copies between those objects overlap. In the example below, thestrcpycall tries to truncate the string by replacing its first characters with the last four. But because the call writes the terminating NUL intoa[4], the copies overlap, and the call gets diagnosed:
void foo (void)
{
char a[] = "abcd1234";
strcpy (a, a + 4);
...
}
The -Wrestrict option detects some instances of simple overlap even without optimization, but it works best at -O2 and above. It's included in -Wall. ๐
-Wnested-externs(C and Objective-C only) โ this warns if anexterndeclaration is encountered inside a function. ๐-Winlineโ okay so this one yells at you if a function you markedinlinedoesn't actually get inlined ๐ญ. Heads up though, even with this on, the compiler won't warn about failed inlining in functions declared in system headers ๐. GCC uses a bunch of heuristics to decide, like how big the function is and how much inlining has already happened in the current function. So ngl, tiny edits to your source can make these warnings pop up or disappear out of nowhere ๐ซ โจ-Wint-in-bool-contextโ this is the vibe check for integers that are pretending to be booleans ๐ . It flags sketchy stuff like conditional expressions (?:) using non-boolean integer constants in a boolean context, such asif (a <= b ? 2 : 3). It also catches left shifting signed integers in a boolean context, likefor (a = 0; 1 << a; a++);, and likewise for all kinds of multiplications no matter the data type ๐ง. This one is switched on by-Wall๐ธ-Wno-int-to-pointer-castโ the "nah, don't tell me about it" option ๐. It hushes the warnings for casts to a pointer type from an integer of a different size. Just so you know, in C++ casting to a pointer type of smaller size is an error, not a warning ๐.Wint-to-pointer-castis turned on by default ๐-Wno-pointer-to-int-cast(C and Objective-C only) โ same energy, different direction ๐. This one silences warnings for casts from a pointer to an integer type of a different size ๐ฆ-Winvalid-pchโ warns you when a precompiled header is sitting in the search path but can't actually be used ๐ญ๐ซถ-Wlong-longโ flags any use of the"long long"type ๐. It gets turned on by either-Wpedanticor-Wtraditionalin ISO C90 and C++98 modes. If you want those messages gone, reach for-Wno-long-long๐-Wvariadic-macrosโ this one calls out variadic macros when you're in ISO C90 mode, or when the GNU alternate syntax shows up in ISO C99 mode ๐. It's enabled by either-Wpedanticor-Wtraditional, and you can shush it with-Wno-variadic-macros๐คซ-Wno-varargsโ tells GCC to stop side-eyeing questionable usage of the macros that handle variable arguments, likeva_start๐. These warnings are already on by default, so this is the off switch ๐-Wvector-operation-performanceโ warns when a vector operation isn't being handled by the SIMD capabilities of your architecture โญ. It's mostly useful when you're doing performance tuning ๐ฅ. There are three ways a vector operation can get implemented, and the compiler is judging them all:- "piecewise" means the scalar operation runs on every single vector element ๐งฉ
- "in parallel" means the vector operation is done using scalars of a wider type, which is usually more performance efficient ๐
- "as a single scalar" means the vector fits into a scalar type ๐ซง
-Wvlaโ warns if a variable-length array shows up anywhere in the code ๐ท.-Wno-vlastops the-Wpedanticwarning about variable-length arrays, so you can keep your peace โ๏ธ-Wvla-larger-than=byte-sizeโ okay this one is a whole mood ๐. If you use it, the compiler warns about declarations of variable-length arrays whose size is either unbounded, or bounded by an argument that lets the array size go past byte-size bytes ๐. It's similar to how-Walloca-larger-than=byte-sizeworks, just for variable-length arrays instead ๐ฆ
Also, GCC might optimize small variable-length arrays with a known value into plain arrays, so this warning might not fire for those ๐
-Wvla-larger-than=PTRDIFF_MAX is enabled by default, but it's typically only effective when -ftree-vrp is active, which happens by default for -O2 and above ๐
See also -Walloca-larger-than=byte-size ๐ซถ
-Wno-vla-larger-thanโ turns off the-Wvla-larger-than=warnings ๐. It's the same as-Wvla-larger-than=SIZE_MAXor larger ๐-Wvolatile-register-varโ warns if a register variable gets declaredvolatile๐คจ. Here's the tea: thevolatilemodifier doesn't stop every optimization that might remove reads and/or writes to register variables ๐ต. This warning is enabled by-Wallโจ-Wdisabled-optimizationโ warns when a requested optimization pass gets turned off ๐ ๏ธ. Real talk, this doesn't usually mean your code is wrong ๐ซถ. It just means GCC's optimizers can't handle the code well ๐ฅบ. Often your code is just too big or too complex, and GCC refuses to optimize programs when the optimization would take inordinate amounts of time โณ-Wpointer-sign(C and Objective-C only) โ flags pointer argument passing or assignment where the signedness is different ๐ง. This option is only supported for C and Objective-C ๐. It's implied by-Walland by-Wpedantic, and you can disable it with-Wno-pointer-sign๐ โโ๏ธ-Wstack-protectorโ this one is only active when-fstack-protectoris active ๐ก๏ธ. It warns about functions that aren't protected against stack smashing ๐-Woverlength-stringsโ warns about string constants that are longer than the "minimum maximum" length the C standard specifies ๐. Modern compilers are chill about much longer strings, but if you want your code to be super portable, you should avoid them ๐
The limit applies after string constant concatenation, and it doesn't count the trailing NUL ๐ข. In C90 the limit was 509 characters, and in C99 it got raised to 4095 ๐. C++98 doesn't specify a normative minimum maximum, so GCC doesn't diagnose overlength strings in C++ ๐
This option is implied by -Wpedantic, and you can turn it off with -Wno-overlength-strings ๐
-Wunsuffixed-float-constants(C and Objective-C only) โ warns about any floating constant that doesn't have a suffix ๐ข. When you pair it with-Wsystem-headers, it also warns about those constants in system header files ๐งพ. This can be super handy when you're getting code ready to use with the"FLOAT_CONST_DECIMAL64"pragma from the decimal floating-point extension to C99 ๐ธ-Wno-lto-type-mismatchโ during link-time optimization, this tells GCC not to warn about type mismatches in global declarations from different compilation units ๐ค. It requires-fltoto be enabled, and it's enabled by default ๐-Wno-designated-init(C and Objective-C only) โ silences the warnings when a positional initializer is used to initialize a structure that's been marked with the"designated_init"attribute ๐๐-Wno-hsaโ stops the warnings for when HSAIL can't be emitted for the compiled function or OpenMP construct ๐ซง. These warnings are enabled by default, so this is how you mute them ๐
โจ Options That Control Static Analysis โจ
-fanalyzerโ this turns on a static analysis of program flow ๐. It hunts for "interesting" interprocedural paths through your code and issues warnings for any problems it finds on them ๐ต๏ธโโ๏ธ. Warning: this analysis is much more expensive than other GCC warnings, so it's not gonna be instant ๐ข๐
Enabling this option effectively turns on all of these warnings too:
-Wanalyzer-double-fclose -Wanalyzer-double-free
-Wanalyzer-exposure-through-output-file -Wanalyzer-file-leak
-Wanalyzer-free-of-non-heap -Wanalyzer-malloc-leak
-Wanalyzer-possible-null-argument
-Wanalyzer-possible-null-dereference -Wanalyzer-null-argument
-Wanalyzer-null-dereference -Wanalyzer-stale-setjmp-buffer
-Wanalyzer-tainted-array-index
-Wanalyzer-unsafe-call-within-signal-handler
-Wanalyzer-use-after-free
-Wanalyzer-use-of-pointer-in-stale-stack-frame
This option is only available if GCC was configured with analyzer support enabled ๐ ๏ธ
-Wanalyzer-too-complexโ if-fanalyzeris enabled, the analyzer uses a bunch of heuristics to explore the control flow and data flow in your program ๐ง . But sufficiently complicated code can totally defeat them ๐ตโ๐ซ. By default, if the code is too complicated and the analyzer hits an internal limit, it just quietly stops ๐คซ. This option warns you when that happens ๐ฃ-Wno-analyzer-double-fcloseโ this warning requires-fanalyzer, which enables it, and you can use-Wno-analyzer-double-fcloseto disable it ๐ โโ๏ธ. It warns for paths through the code where a"FILE *"can havefclosecalled on it more than once ๐-Wno-analyzer-double-freeโ this warning requires-fanalyzer, which enables it, and you can use-Wno-analyzer-double-freeto disable it ๐ซ. It warns for paths through the code where a pointer can havefreecalled on it more than once ๐ฅ-Wno-analyzer-exposure-through-output-fileโ this warning requires-fanalyzer, which enables it, and you can use-Wno-analyzer-exposure-through-output-fileto disable it ๐. It warns for paths through the code where a security-sensitive value gets written to an output file, like writing a password to a log file ๐๐-Wno-analyzer-file-leakโ this warning requires-fanalyzer, which enables it, and you can use-Wno-analyzer-file-leakto disable it ๐ง. It warns for paths through the code where a"<stdio.h>" "FILE *"stream object is leaked ๐ซ-Wno-analyzer-free-of-non-heapโ this warning requires-fanalyzer, which enables it, and you can use-Wno-analyzer-free-of-non-heapto disable it ๐งน. It warns for paths through the code wherefreeis called on a non-heap pointer, like an on-stack buffer or a global ๐ฅด-Wno-analyzer-malloc-leakโ this warning requires-fanalyzer, which enables it, and you can use-Wno-analyzer-malloc-leakto disable it ๐ซ . It warns for paths through the code where a pointer allocated viamallocis leaked ๐ฉธ-Wno-analyzer-possible-null-argumentโ this warning requires-fanalyzer, which enables it, and you can use-Wno-analyzer-possible-null-argumentto disable it ๐ค. It warns for paths through the code where a possibly-NULL value gets passed to a function argument marked with__attribute__((nonnull))as needing a non-NULL value ๐ซฃ-Wno-analyzer-possible-null-dereferenceโ this warning requires-fanalyzer, which enables it, and you can use-Wno-analyzer-possible-null-dereferenceto disable it ๐. It warns for paths through the code where a possibly-NULL value gets dereferenced ๐-Wno-analyzer-null-argumentโ this warning requires-fanalyzer, which enables it, and you can use-Wno-analyzer-null-argumentto disable it ๐ท. It warns for paths through the code where a value known to be NULL gets passed to a function argument marked with__attribute__((nonnull))as needing a non-NULL value โ-Wno-analyzer-null-dereferenceโ this warning requires-fanalyzer, which enables it, and you can use-Wno-analyzer-null-dereferenceto disable it ๐ซถ
Okay so the analyzer has a whole squad of warnings, and this next bit is where we get into the spicy ones ๐ฅ
This one yells when there's a path through your code where a value that's known to be NULL gets dereferenced ๐
-Wno-analyzer-stale-setjmp-bufferโ ๐ฆ This warning needs-fanalyzerto be on, which turns it on for you. If you want it gone, use-Wno-analyzer-stale-setjmp-buffer. It's bestie-level important: it flags paths wherelongjmpis used to rewind to ajmp_buftied to asetjmpcall, but the function that made thatsetjmpcall has already returned. Whensetjmprecords a rewind location on ajmp_buf, it saves the stack frame, and that frame goes invalid once the function containing thesetjmpcall returns. Trying to rewind there withlongjmpwould reference a stack frame that no longer exists, and that's likely to lead to a crash (or worse ๐ญ).-Wno-analyzer-tainted-array-indexโ ๐ This one needs both-fanalyzerand-fanalyzer-checker=taintto be enabled. To turn it off, use-Wno-analyzer-tainted-array-index. It warns about paths where a value that could be under an attacker's control gets used as the index of an array access without being sanitized.-Wno-analyzer-unsafe-call-within-signal-handlerโ โ ๏ธ This warning requires-fanalyzer, which enables it. Disable it with-Wno-analyzer-unsafe-call-within-signal-handler. It catches paths where a function that's known to be async-signal-unsafe (likefprintf) gets called from inside a signal handler.-Wno-analyzer-use-after-freeโ ๐๏ธ This one needs-fanalyzer, which enables it. Use-Wno-analyzer-use-after-freeto disable it. It flags paths where a pointer gets used afterfreehas already been called on it. Iykyk ๐-Wno-analyzer-use-of-pointer-in-stale-stack-frameโ ๐ป This warning requires-fanalyzer, which enables it. Use-Wno-analyzer-use-of-pointer-in-stale-stack-frameto disable it. It warns about paths where a pointer gets dereferenced while it points at a variable in a stale stack frame.
Okay, so if you want to tweak how the analyzer explores your code, these are the pertinent parameters ๐ง --param analyzer-bb-explosion-factor=value, --param analyzer-max-enodes-per-program-point=value, --param analyzer-max-recursion-depth=value, and --param analyzer-min-snodes-for-call-summary=value.
The following options control the analyzer ๐
-fanalyzer-call-summariesโ ๐ธ This one simplifies interprocedural analysis by computing the effect of certain calls, instead of exploring every path through the function from the callsite to each possible return. If it's enabled, call summaries only get used for functions with more than one call site, and that are sufficiently complicated (as per--param analyzer-min-snodes-for-call-summary=value).-fanalyzer-checker=nameโ ๐ฏ Restricts the analyzer to run just the checker you name, and enables it. Some checkers are disabled by default (even with-fanalyzer), like the "taint" checker that implements-Wanalyzer-tainted-array-index. You need this option to turn them on.-fanalyzer-fine-grainedโ ๐ฌ This one is for analyzer developers. Internally, the analyzer builds an "exploded graph" that combines control flow graphs with data flow information. By default, an edge in this graph can contain the effects of a run of multiple statements within a basic block. With-fanalyzer-fine-grained, each statement gets its own edge.-fanalyzer-show-duplicate-countโ ๐งฎ Also for analyzer developers. If multiple diagnostics have been detected as duplicates of each other, this emits a note when reporting the best diagnostic, giving the number of additional diagnostics that were suppressed by the deduplication logic.-fno-analyzer-state-mergeโ ๐ซ For analyzer developers, again. By default the analyzer tries to simplify things by merging sufficiently similar states at each program point as it builds its "exploded graph". With-fno-analyzer-state-merge, that merging gets suppressed, which is handy for debugging state-handling issues.-fno-analyzer-state-purgeโ ๐งน Developer territory. By default, the analyzer simplifies analysis by purging aspects of state at a program point that seem no longer relevant, e.g. the values of locals that aren't accessed later in the function and that aren't relevant to leak analysis. With-fno-analyzer-state-purge, that purging gets suppressed, for debugging state-handling issues.-fanalyzer-transitivityโ ๐ Turns on transitivity of constraints within the analyzer.-fanalyzer-verbose-edgesโ ๐ For analyzer developers. It enables more verbose, lower-level detail in the descriptions of control flow within diagnostic paths.-fanalyzer-verbose-state-changesโ ๐ Also for analyzer developers. It enables more verbose, lower-level detail in the descriptions of events relating to state machines within diagnostic paths.-fanalyzer-verbosity=levelโ ๐๏ธ This controls how complex the control flow paths are that get emitted for analyzer diagnostics. The level can be one of:0โ At this level, interprocedural call and return events get displayed, along with the most pertinent state-change events relating to a diagnostic. For example, for a double-"free" diagnostic, both calls to "free" will be shown.1โ Same as the previous level, but also shows events for the entry to each function.2โ Same as the previous level, but also shows events relating to control flow that are significant to triggering the issue (e.g. "true path taken" at a conditional). This level is the default ๐3โ Same as the previous level, but shows all control flow events, not just the significant ones.4โ For analyzer developers. It adds various other events intended for debugging the analyzer ๐งช
-fdump-analyzerโ ๐๏ธ Dumps internal details about what the analyzer is doing tofile.analyzer.txt. This option is overridden by-fdump-analyzer-stderr.-fdump-analyzer-stderrโ ๐ฅ๏ธ Dumps internal details about what the analyzer is doing to stderr. This option overrides-fdump-analyzer.-fdump-analyzer-callgraphโ ๐ธ๏ธ Dumps a representation of the call graph, suitable for viewing with GraphViz, tofile.callgraph.dot.-fdump-analyzer-exploded-graphโ ๐จ Dumps a representation of the "exploded graph", suitable for viewing with GraphViz, tofile.eg.dot. Nodes are color-coded based on state-machine states to emphasize state changes.-fdump-analyzer-exploded-nodesโ ๐ Emits diagnostics showing where nodes in the "exploded graph" sit in relation to the program source.-fdump-analyzer-exploded-nodes-2โ ๐ Dumps a textual representation of the "exploded graph" tofile.eg.txt.-fdump-analyzer-exploded-nodes-3โ ๐ Dumps a textual representation of the "exploded graph" to one dump file per node, namedfile.eg-id.txt. Heads up, this is typically a large number of dump files ๐-fdump-analyzer-state-purgeโ ๐งพ As per-fdump-analyzer-supergraph, this dumps a representation of the "supergraph" suitable for viewing with GraphViz, but annotates the graph with information on what state will be purged at each node. The graph is written tofile.state-purge.dot.-fdump-analyzer-supergraphโ ๐ Dumps representations of the "supergraph" suitable for viewing with GraphViz tofile.supergraph.dotandfile.supergraph-eg.dot. These show all of the control flow graphs in the program, with interprocedural edges for calls and returns. The second dump contains annotations showing nodes in the "exploded graph" and the diagnostics associated with them.
๐ Options for Debugging Your Program ๐
To tell GCC to emit extra information for a debugger, in almost all cases you only need to add -g to your other options ๐
GCC lets you use -g with -O. Fair warning, though: the shortcuts taken by optimized code can be a little 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 be 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. Still, it's possible to debug optimized output, which makes it reasonable to use the optimizer for programs that might have bugs โจ
If you're not using some other optimization option, consider using -Og with -g. With no -O option at all, some compiler passes that collect information useful for debugging don't run at all, so -Og may give you a better debugging experience ๐ง
-gโ ๐ Produces debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF). GDB can work with this debugging information. On most systems that use stabs format,-genables extra debugging information that only GDB can use. That extra information makes debugging work better in GDB, but it probably makes other debuggers crash or refuse to read the program. If you want to control for certain whether the extra information gets generated, use-gstabs+,-gstabs,-gxcoff+,-gxcoff, or-gvms(see below).-ggdbโ ๐ Produces debugging information for GDB. This means using the most expressive format available (DWARF, stabs, or the native format if neither of those is supported), including GDB extensions if at all possible.-gdwarf,-gdwarf-versionโ ๐ Produces debugging information in DWARF format (if that's supported). The value of version may be 2, 3, 4 or 5, and the default version for most targets is 4. DWARF Version 5 is only experimental, so proceed with a little caution ๐งช
Note that with DWARF Version 2, some ports require and always use some non-conflicting DWARF 3 extensions in the unwind tables.
Version 4 may require GDB 7.0 and -fvar-tracking-assignments for maximum benefit.
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) retain a reference to DWARF Version 2 in their names, but they apply to all currently-supported versions of DWARF.
-gstabsโ okay so this one makes debug info in stabs format (if your setup even supports it) but with no GDB extras ๐ง. It's the format DBX uses on most BSD systems. Heads up bestie: on MIPS, Alpha, and System V Release 4 systems, this makes stabs output that DBX can't read ๐. On System V Release 4 you also need the GNU assembler.-gstabs+โ same stabs format (if supported), but now with GNU extensions that only the GNU debugger (GDB) understands ๐ฆ. Heads up: other debuggers might crash or refuse to read your program ๐ญ.-gxcoffโ XCOFF format (if supported) ๐ธ, the one DBX uses on IBM RS/6000 systems.-gxcoff+โ XCOFF format (if supported) with GNU extensions that only GDB gets ๐ฅ. Other debuggers may crash or refuse to read it, and assemblers that aren't the GNU assembler (GAS) might throw an error ๐.-gvmsโ Alpha/VMS debug format (if supported) ๐. This is the one DEBUG uses on Alpha/VMS systems.-glevel,-ggdblevel,-gstabslevel,-gxcofflevel,-gvmslevelโ ask for debug info and choose how much with level โจ. The default level is 2.- Level 0 gives zero debug info, so
-g0negates-g๐ . - Level 1 is minimal, just enough for backtraces in parts of your program you don't plan to debug ๐ชต. It includes function and external variable descriptions plus line number tables, but no info about local variables.
- Level 3 adds extra goodies, like all the macro definitions in your program ๐. Some debuggers can expand macros when you use
-g3. - If you stack up multiple
-goptions, with or without level numbers, the last one wins ๐. -gdwarfdoesn't accept a stuck-on level, so it doesn't get mixed up with-gdwarf-level. Use an extra-gleveloption to change the debug level for DWARF instead ๐งฉ.
- Level 0 gives zero debug info, so
-fno-eliminate-unused-debug-symbolsโ by default, no debug info gets made for symbols that never actually get used ๐. Use this if you want debug info for all symbols ๐.-femit-class-debug-alwaysโ instead of emitting debug info for a C++ class in only one object file, emit it in every object file that uses the class ๐ง. Only reach for this with debuggers that can't handle the normal way GCC emits class debug info, because it can make the debug info up to as much as a factor of two bigger ๐ฆ.-fno-merge-debug-stringsโ tells the linker to not merge together identical strings in debug info across different object files ๐งต. Not every assembler or linker supports merging. Merging shrinks the debug info in the output file but makes link processing take longer โณ. Merging is enabled by default โ .-fdebug-prefix-map=old=newโ when compiling files living in directory old, debug info describes them as if they lived in directory new instead ๐บ๏ธ. This is handy for swapping a build-time path for an install-time path. You can also turn an absolute path into a relative one by using.for new. This can give more reproducible builds, which are location independent ๐, but you might need an extra command to tell GDB where to find the source files. See also-ffile-prefix-map.-fvar-trackingโ runs the variable tracking pass, which figures out where variables are stored at each position in the code ๐. Better debug info gets generated from that (if your debug info format supports it). It's enabled by default when compiling with optimization (-Os,-O,-O2, ...), with debug info (-g), and when the debug info format supports it ๐ .-fvar-tracking-assignmentsโ annotates assignments to user variables early in compilation and tries to carry those annotations all the way to the end ๐ช, to improve debug info while optimizing. Using-gdwarf-4alongside it is recommended โจ. It can be enabled even if var-tracking is disabled, in which case the annotations get created and maintained, but thrown away at the end. By default this flag is enabled together 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 extension.dwo๐. This lets the build system avoid linking files that have debug info. To be useful, you'll need a debugger that can read.dwofiles ๐ซถ.-gdescribe-diesโ adds description attributes to some DWARF DIEs that have no name attribute ๐ท๏ธ, like artificial variables, external references, and call site parameter DIEs.-gpubnamesโ generates the DWARF".debug_pubnames"and".debug_pubtypes"sections ๐ฆ.-ggnu-pubnamesโ generates".debug_pubnames"and".debug_pubtypes"sections in a format that's suitable for converting into a GDB index ๐. It's only useful with a linker that can produce GDB index version 7.-fdebug-types-sectionโ when using DWARF Version 4 or higher, type DIEs can go into their own".debug_types"section instead of being part of".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".debug_types"makes the debug info larger instead of smaller ๐ญ.-grecord-gcc-switches,-gno-record-gcc-switchesโ this one tacks the command-line options used to invoke the compiler (the ones that may affect code generation) onto theDW_AT_producerattribute in DWARF debug info ๐. The options get concatenated with spaces separating them from each other and from the compiler version. It's enabled by default. See also-frecord-gcc-switchesfor another way to store compiler options in the object file.-gstrict-dwarfโ disallows using extensions from a later DWARF standard version than the one selected with-gdwarf-version๐ซ. On most targets, using non-conflicting DWARF extensions from later standard versions is allowed anyway.-gno-strict-dwarfโ allows using extensions from a later DWARF standard version than the one selected with-gdwarf-version๐.-gas-loc-supportโ tells the compiler that the assembler supports".loc"directives ๐ ๏ธ. The compiler may then use them so the assembler generates DWARF2+ line number tables. This is usually desirable, because assembler-generated line number tables are a lot more compact than the ones the compiler can make itself ๐ค. This option is enabled 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 DWARF2+ line number tables are going to be generated ๐ง .-gas-locview-supportโ tells the compiler that the assembler supports"view"assignment and reset assertion checking in".loc"directives ๐. It's enabled by default if GCC's configure step found the assembler supports them.-gno-as-locview-supportโ forces GCC to assign view numbers internally, if-gvariable-location-viewsis explicitly requested ๐ง.-gcolumn-info,-gno-column-infoโ emits location column information into DWARF debug info, not just file and line ๐. This option is enabled by default.-gstatement-frontiers,-gno-statement-frontiersโ makes GCC create markers in the internal representation at the beginning of statements ๐ฉ, and keep them roughly in place throughout compilation. Those markers guide the output of"is_stmt"markers in the line number table. This is enabled by default when compiling with optimization (-Os,-O,-O2, ...) and outputting DWARF 2 debug info at the normal level ๐.-gvariable-location-views,-gvariable-location-views=incompat5,-gno-variable-location-viewsโ augments variable location lists with progressive view numbers implied from the line number table ๐ญ. This lets debug info consumers inspect state at certain points of the program, even if no instructions tied to those source locations exist there ๐ต๏ธ. If the assembler lacks support for view numbers in line number tables, the compiler will emit the line number table, which makes them somewhat less compact ๐. The augmented line number tables and location lists are fully backward-compatible, so older consumers can read them, but they won't get any benefit from them either ๐คท. This is enabled by default when outputting DWARF 2 debug info at the normal level, as long as there's assembler support,-fvar-tracking-assignmentsis enabled, and-gstrict-dwarfis not ๐. When assembler support isn't available, it may still be enabled, but it forces GCC to output internal line number tables.
Careful, bestie ๐จ: if assembler support isn't available and -ginternal-reset-location-views isn't enabled, that will most certainly lead to silently mismatching location views ๐ฑ.
There's a proposed representation for view numbers that is not backward compatible with the location list format introduced in DWARF 5. You can enable it with -gvariable-location-views=incompat5 ๐งช. This option may be removed in the future, and it's only provided as a reference implementation of the proposed representation.
Also a big warning ๐ : debug info consumers aren't expected to support this extended format, and they would be unable to decode location lists that use it.
Okay so the debug flags are next, bestie, and they get a little spicy ๐ธ
-ginternal-reset-location-views,-gno-internal-reset-location-viewsโ this one tries to figure out which location views can be left out of location view lists ๐ฆ. It needs the compiler to have super accurate insn length estimates, and ngl that isn't always the case ๐ญ. If the estimates are off and you're using an assembler that doesn't support location view lists, it can silently generate incorrect view lists ๐. The GNU assembler will flag any of these with a "view number mismatch" error. It only gets turned on for ports that define a reliable estimation function ๐ .-ginline-points,-gno-inline-pointsโ generates extended debug info for inlined functions โจ. Location view tracking markers get inserted at inlined entry points, so address and view numbers can be computed and output in the debug info. You can enable this on its own without location views, and then the view numbers just won't be output ๐ง. It can only be enabled along with statement frontiers, though, and it's only on by default if location views are on.-gz[=type]โ produces 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โ struct-like types only get debug info when the base name of the compilation source file matches the base name of the file where the struct is defined ๐. This one seriously shrinks your debug info, but it can cost you a lot of type information for the debugger ๐ฌ. If you want something less aggressive, check out-femit-struct-debug-reduced, and for more detailed control, look at-femit-struct-debug-detailed. Heads up: this only works with DWARF debug output.-femit-struct-debug-reducedโ struct-like types only get debug info 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 still shrinks debug info a lot, with some possible loss of type info for the debugger. For a more aggressive version, see-femit-struct-debug-baseonly, and for finer control, see-femit-struct-debug-detailed. This also works only with DWARF debug output.-femit-struct-debug-detailed[=spec-list]โ lets you pick exactly which struct-like types get debug info ๐งโโ๏ธ. The whole point is to cut down on duplicate struct debug info across different object files in the same program. It's a detailed version of-femit-struct-debug-reducedand-femit-struct-debug-baseonly, and honestly that covers most needs. A specification follows this syntax:[dir:|ind:]โ the optional first word limits things to structs used directly (dir:) or used indirectly (ind:). A struct is used directly when it's the type of a variable or member. Indirect uses come through pointers to structs, meaning when using an incomplete struct is valid, the use is indirect. For example:struct one direct; struct two * indirect;[ord:|gen:]โ the optional second word limits things to ordinary structs (ord:) or generic structs (gen:). Generic structs are a bit of a mouthful ๐. In C++, these are non-explicit specializations of template classes, or non-template classes within the above. Other languages have generics, but-femit-struct-debug-detaileddoesn't implement them yet.(any|sys|base|none)โ the third word picks which source files the structs should come from.noneandanymean what you'd expect.basemeans the base of the name of the file where the type declaration appears has to match the base of the name of the main compilation file. So when compilingfoo.c, debug info gets generated for types declared in that file andfoo.h, but not other header files ๐.sysmeans those types satisfyingbaseor declared in system or compiler headers.
You might 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 symbols for types that are nowhere used in the source file being compiled. Sometimes you actually want debug info for every type declared in a compilation unit, even unused ones. For example, if you want to cast a value to a type in the debugger that's declared but never used in your program. More often, though, this just wastes a ton of space ๐ฅฒ.
โก Options That Control Optimization
Okay, this section is all about the optimization flags, and these are the ones that make your code go brrr ๐ฅ. These options control various sorts of optimizations.
Without any optimization option, the compiler's goal is to reduce the cost of compilation and to make debugging produce the expected results. Statements are independent: if you stop the program with a breakpoint between statements, you can then assign a new value to any variable or change the program counter to any other statement in the function and get exactly the results you expect from the source code ๐.
Turning on optimization flags makes the compiler try to improve performance and/or code size, but at the expense of compilation time and possibly your ability to debug the program ๐ญ. The compiler optimizes based on what it knows about the program. Compiling multiple files at once to a single output file lets the compiler use info gathered from all of the files when compiling each of them ๐ง .
Not every optimization is controlled by a flag, so only the optimizations that have a flag are listed in this section ๐ฆ.
Most optimizations are completely disabled at -O0, or if an -O level isn't set on the command line, even if you specify individual optimization flags. Similarly, -Og suppresses many optimization passes ๐
โโ๏ธ.
A slightly different set of optimizations may be enabled at each -O level depending on the target and how GCC was configured, so it might not match what's listed here ๐ธ. If you want the exact set for each level, invoke GCC with -Q --help=optimizers.
๐ธ -O and -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 doing 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 does 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
-ffinite-loops -fgcse -fgcse-lm -fhoist-adjacent-loads
-finline-functions -finline-small-functions -findirect-inlining
-fipa-bit-cp -fipa-cp -fipa-icf -fipa-ra -fipa-sra -fipa-vrp
-fisolate-erroneous-paths-dereference -flra-remat
-foptimize-sibling-calls -foptimize-strlen -fpartial-inlining
-fpeephole2 -freorder-blocks-algorithm=stc
-freorder-blocks-and-partition -freorder-functions
-frerun-cse-after-loop -fschedule-insns -fschedule-insns2
-fsched-interblock -fsched-spec -fstore-merging -fstrict-aliasing
-fthread-jumps -ftree-builtin-call-dce -ftree-pre
-ftree-switch-conversion -ftree-tail-merge -ftree-vrp
Bestie, please note the warning under-fgcseabout invoking-O2on programs that use computed gotos. It's giving danger ๐.
NOTE: In Ubuntu 8.10 and later versions,-D_FORTIFY_SOURCE=2is set by default, and it's activated when-Ois set to 2 or higher. This enables extra 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 -fipa-cp-clone -floop-interchange
-floop-unroll-and-jam -fpeel-loops -fpredictive-commoning
-fsplit-loops -fsplit-paths -ftree-loop-distribution
-ftree-loop-vectorize -ftree-partial-pre -ftree-slp-vectorize
-funswitch-loops -fvect-cost-model -fvect-cost-model=dynamic
-fversion-loops-for-strides
๐ธ -O0
Reduce compilation time and make debugging produce the expected results ๐. This is the default ๐.
๐ธ -Os
Optimize for size! ๐งธ -Os enables all -O2 optimizations except those that often increase code size:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fprefetch-loop-arrays -freorder-blocks-algorithm=stc
Okay so this bit is giving code-size glow-up ๐ง It also turns on -finline-functions, tells the compiler to tune for code size instead of execution speed, and runs extra optimizations that shrink your binary โจ
-Ofastโ Okay the spicy one ๐ถ๏ธ-Ofastthrows strict standards compliance out the window ๐ It enables all-O3optimizations, plus optimizations that aren't valid for every standard-compliant program, so proceed with caution bestie ๐ญ It turns on-ffast-math,-fallow-store-data-racesand the Fortran-specific-fstack-arrays, unless-fmax-stack-var-sizeis specified, and-fno-protect-parens๐ฅ-Ogโ Optimize debugging experience ๐ฆ-Ogis the level of choice for the standard edit-compile-debug cycle. It gives you a reasonable amount of optimization while keeping compilation fast and debugging smooth ๐ It's a better pick than-O0for debuggable code, because some compiler passes that collect debug information are disabled at-O0๐ซถ
Like -O0, -Og completely disables a bunch of optimization passes, so the individual options that control them do nothing. Otherwise -Og enables all -O1 optimization flags except the ones that might mess with debugging:
-fbranch-count-reg -fdelayed-branch -fdse -fif-conversion
-fif-conversion2 -finline-functions-called-once
-fmove-loop-invariants -fssa-phiopt -ftree-bit-ccp -ftree-dse
-ftree-pta -ftree-sra
If you use multiple -O options, with or without level numbers, the last one is the one that counts ๐
Okay, so -fflag options are the machine-independent flags ๐ธ Most of them come in positive and negative forms, and the negative form of -ffoo is -fno-foo. The list below only shows one form, the one you'll usually reach for. To get the other, just remove no- or add it ๐
The following options control specific optimizations. They're either switched on by -O options or closely related to ones that are. Use these flags in the rare moments when you want to fine-tune which optimizations happen ๐
-fno-defer-popโ For machines that have to pop arguments after a function call, pop them as soon as each function returns ๐งน At-O1and higher,-fdefer-popis the default. That lets the compiler stack up arguments across several function calls and pop them all in one go ๐ฅ-fforward-propagateโ Runs a forward propagation pass on RTL โจ It tries to combine two instructions and checks whether the result can be simplified. If loop unrolling is active, two passes run, and the second one is scheduled after loop unrolling ๐ฆ Enabled by default at optimization levels-O,-O2,-O3,-Os.-ffp-contract=styleโ Controls floating-point expression contraction ๐งฎ-ffp-contract=offdisables it completely ๐-ffp-contract=fastenables it, like forming fused multiply-add operations, if the target has native support for them ๐-ffp-contract=onenables it if the language standard allows. This is currently not implemented and is treated the same as-ffp-contract=off. ๐- The default is
-ffp-contract=fast. ๐
-fomit-frame-pointerโ Omits the frame pointer in functions that don't need one ๐ง This skips the instructions that save, set up and restore the frame pointer, and on many targets it 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 left out ๐ญ
Heads up: -fno-omit-frame-pointer doesn't guarantee the frame pointer is used in every function. Several targets always omit it in leaf functions ๐ Enabled by default at -O and 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", "strchr" or "strcpy") and their "_FORTIFY_SOURCE" counterparts 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 not optimizing. Single functions can be exempted from inlining by marking them with thenoinlineattribute ๐-finline-small-functionsโ Integrates functions into their callers when their body is smaller than the code for the function call itself, so the overall program gets smaller ๐ The compiler heuristically decides which functions are simple enough for this. It applies to all functions, even ones not declared inline ๐ Enabled at levels-O2,-O3,-Os.-findirect-inliningโ Inlines indirect calls that are known at compile time thanks to earlier inlining ๐ง This only does anything when inlining is already on, via-finline-functionsor-finline-small-functions๐ซถ Enabled at levels-O2,-O3,-Os.-finline-functionsโ Considers all functions for inlining, even ones not declared inline ๐ฅ The compiler heuristically decides which ones are worth integrating. If every call to a given function is integrated and the function is declaredstatic, it normally isn't output as assembler code on its own ๐ฆ Enabled at levels-O2,-O3,-Os. Also enabled by-fprofile-useand-fauto-profileโจ-finline-functions-called-onceโ Considers allstaticfunctions that are called once for inlining into their caller, even if they aren't markedinline๐ฏ If a call to a given function is 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 markedalways_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 way cheaper and usually makes inlining faster on programs with huge 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.-finline-limit=nsets some of them like this:max-inline-insns-singleโ is set ton/2.max-inline-insns-autoโ is set ton/2.
See below for documentation of the individual inlining parameters and their defaults ๐
Note: there may be no value to -finline-limit that results in default behavior. ๐
Note: a pseudo instruction, in this context, is an abstract measurement of a function's size. It in no way represents 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, which only applies to functions declared with thedllexportattribute or declspec ๐ฆ-fkeep-inline-functionsโ In C, emitsstaticfunctions declaredinlineinto the object file, even if they've been inlined into all of their callers ๐ซง This doesn't 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 whether optimization is on, use-fno-keep-static-consts๐-fmerge-constantsโ Tries to merge identical constants (string constants and floating-point constants) across compilation units ๐งฉ This is the default for optimized compilation if the assembler and linker support it. Use-fno-merge-constantsto stop this behavior ๐ Enabled at levels-O,-O2,-O3,-Os.-fmerge-all-constantsโ Tries 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 ๐
โ ๏ธ Danger zone: 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 conformant, bestie ๐
-fmodulo-schedโ Performs swing modulo scheduling right before the first scheduling pass ๐ It looks at the innermost loops and reorders their instructions by overlapping different iterations ๐-fmodulo-sched-allow-regmovesโ 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 only works when-fmodulo-schedis enabled. ๐-fno-branch-count-regโ Disables the pass that hunts for chances to use "decrement and branch" instructions on a count register, instead of sequences that decrement a register, compare it to zero, and then branch based on the result ๐ข This is only meaningful on architectures that support such instructions, which include x86, PowerPC, IA-64 and S/390 ๐ฅ๏ธ Heads up:-fno-branch-count-regdoesn't remove the decrement and branch instructions that other optimization passes introduced into the generated instruction stream ๐ซถ
The default is -fbranch-count-reg at -O1 and higher, except for -Og ๐
โจ
-fno-function-cseโ okay so this one turns OFF putting function addresses in registers ๐ฆ Instead, every instruction that calls a constant function spells out the function's address right there.
This makes the code less efficient ๐ญ but some strange hacks that tweak the assembler output can get confused by the optimizations you get when this option isn't used, so it's there if you need it.
The default is -ffunction-cse ๐ธ
-fno-zero-initialized-in-bssโ if the target has a BSS section, GCC normally tosses variables that start out as zero into BSS, which can save space ๐ง
This option turns that behavior off, because some programs actually rely on variables living in the data section. Like, so the executable can find the beginning of that section, and/or make assumptions based on it ๐
The default is -fzero-initialized-in-bss.
-fthread-jumpsโ this one checks whether a jump lands somewhere another comparison (one that the first comparison subsumes) is found ๐ If so, the first branch gets redirected to either the destination of the second branch or the spot right after it, depending on whether the condition is known to be true or false.
Enabled at levels -O2, -O3, -Os.
-fsplit-wide-typesโ when a type takes up multiple registers, like"long long"on a 32-bit system, this splits the registers apart and allocates them independently. It normally generates better code for those types, but it may make debugging more difficult ๐
Enabled at levels -O, -O2, -O3, -Os.
-fsplit-wide-types-earlyโ fully splits wide types early instead of very late. This option does nothing unless-fsplit-wide-typesis turned on ๐ซถ
This is the default on some targets.
-fcse-follow-jumpsโ in common subexpression elimination (CSE), it scans through jump instructions when the jump's target isn't reached by any other path. For example, when CSE hits an"if"statement with an"else"clause, it follows the jump when the condition tested is false ๐ฆ
Enabled at levels -O2, -O3, -Os.
-fcse-skip-blocksโ this is similar to-fcse-follow-jumps, but it makes CSE follow jumps that conditionally skip over blocks. When CSE hits a simple"if"statement with no else clause,-fcse-skip-blocksmakes CSE follow the jump around the body of the"if"๐
Enabled at levels -O2, -O3, -Os.
-frerun-cse-after-loopโ re-runs common subexpression elimination after the loop optimizations are done ๐
Enabled at levels -O2, -O3, -Os.
-fgcseโ performs a global common subexpression elimination pass. This pass also does global constant and copy propagation โจ
Note: When compiling a program using computed gotos, a GCC extension, you may get better run-time performance if you disable the global common subexpression elimination pass by adding -fno-gcse to the command line. ๐
Enabled at levels -O2, -O3, -Os.
-fgcse-lmโ when-fgcse-lmis enabled, global CSE tries to move loads that are only killed by stores into themselves. This lets a loop containing a load/store sequence become a load outside the loop, plus a copy/store inside the loop ๐
Enabled by default when -fgcse is enabled.
-fgcse-smโ when-fgcse-smis enabled, a store motion pass runs after global CSE. It tries to move stores out of loops. Used together with-fgcse-lm, loops containing a load/store sequence can become a load before the loop and a store after the loop ๐ง
Not enabled at any optimization level.
-fgcse-lasโ when-fgcse-lasis enabled, the global CSE pass wipes out redundant loads that come after stores to the same memory location, both partial and full redundancies ๐งน
Not enabled at any optimization level.
-fgcse-after-reloadโ when-fgcse-after-reloadis enabled, a redundant load elimination pass runs after reload. Its whole purpose is to clean up redundant spilling ๐งฝ
Enabled by -fprofile-use and -fauto-profile.
-faggressive-loop-optimizationsโ this tells the loop optimizer to use language constraints to figure out bounds for the number of iterations of a loop ๐ฅ It assumes that loop code doesn't invoke undefined behavior, by for example causing signed integer overflows or out-of-bound array accesses. Those bounds guide loop unrolling and peeling and loop exit test optimizations.
This option is enabled by default.
-funconstrained-commonsโ tells the compiler that variables declared in common blocks (e.g. Fortran) may later get overridden with longer trailing arrays. This stops certain optimizations that depend on knowing the array bounds ๐ โโ๏ธ-fcrossjumpingโ performs cross-jumping. This unifies equivalent code and saves code size. The resulting code may or may not perform better than without cross-jumping ๐คทโโ๏ธ
Enabled at levels -O2, -O3, -Os.
-fauto-inc-decโ combines increments or decrements of addresses with memory accesses. This pass is always skipped on architectures that don't have instructions to support this ๐โโ๏ธ
Enabled by default at -O and higher on architectures that support this.
-fdceโ performs dead code elimination (DCE) on RTL ๐๏ธ
Enabled by default at -O and higher.
-fdseโ performs dead store elimination (DSE) on RTL ๐๏ธ
Enabled by default at -O and higher.
-fif-conversionโ attempts to transform conditional jumps into branch-less equivalents. This includes conditional moves, min, max, set flags and abs instructions, and some tricks doable with standard arithmetic ๐ช Whether conditional execution gets used on chips that have it is controlled by-fif-conversion2.
Enabled at levels -O, -O2, -O3, -Os, but not with -Og.
-fif-conversion2โ uses conditional execution (where available) to transform conditional jumps into branch-less equivalents ๐ช
Enabled at levels -O, -O2, -O3, -Os, but not with -Og.
-fdeclone-ctor-dtorโ okay, the C++ ABI requires multiple entry points for constructors and destructors: one for a base subobject, one for a complete object, and one for a virtual destructor that callsoperator deleteafterwards ๐งฉ For a hierarchy with virtual bases, the base and complete variants are clones, which means two copies of the function. With this option, those variants become thunks that call a common implementation.
Enabled by -Os.
-fdelete-null-pointer-checksโ assumes that programs can't safely dereference null pointers, and that no code or data element lives at address zero ๐ This option enables simple constant folding optimizations at all optimization levels. On top of that, other optimization passes in GCC use this flag to control global dataflow analyses that eliminate useless checks for null pointers. Those analyses assume that a memory access to address zero always results in a trap, so if a pointer is checked after it has already been dereferenced, it can't be null.
Note however that in some environments this assumption is not true. Use -fno-delete-null-pointer-checks to disable this optimization for programs that depend on that behavior. โ ๏ธ
This option is enabled by default on most targets. On Nios II ELF, it defaults to off. On AVR, CR16, and MSP430, this option is completely disabled.
Passes that use the dataflow information are enabled independently at different optimization levels.
-fdevirtualizeโ attempts to convert calls to virtual functions into direct calls ๐ This is done both within a procedure and interprocedurally, as part of indirect inlining (-findirect-inlining) and interprocedural constant propagation (-fipa-cp).
Enabled at levels -O2, -O3, -Os.
-fdevirtualize-speculativelyโ attempts to convert calls to virtual functions into speculative direct calls ๐ฏ Based on the analysis of the type inheritance graph, it figures out the set of likely targets for a given call. If the set is small, preferably of size 1, the call becomes a conditional that decides between a direct and an indirect call. The speculative calls enable more optimizations, like inlining. When they seem useless after further optimization, they get converted back into their original form.-fdevirtualize-at-ltransโ streams the extra information needed for aggressive devirtualization when running the link-time optimizer in local transformation mode ๐ฆ This enables more devirtualization, but it significantly increases the size of the streamed data. For this reason it's disabled by default.-fexpensive-optimizationsโ performs a bunch of minor optimizations that are relatively expensive ๐ธ
Enabled at levels -O2, -O3, -Os.
-freeโ attempts to remove redundant extension instructions ๐งน This is especially helpful for the x86-64 architecture, which implicitly zero-extends in 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++, the value of an object is only affected by changes within its lifetime. When the constructor begins, the object has an indeterminate value, and any changes during the object's lifetime are dead once it's destroyed โณ Normally dead store elimination takes advantage of this. If your code relies on the value of the object storage persisting beyond the object's lifetime, you can use this flag to disable the optimization.
To keep stores made before the constructor starts (e.g. 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โ attempts to decrease register pressure through register live range shrinkage ๐ท This is helpful for fast processors with small or moderate-size register sets.-fira-algorithm=algorithmโ okay so this lets you pick the coloring algorithm for the integrated register allocator ๐จ.prioritygives you Chow's priority coloring, andCBgives you Chaitin-Briggs coloring. Chaitin-Briggs isn't built for every architecture, but on the targets that do support it, it's the default because it makes better code ๐-fira-region=regionโ pick which regions the integrated register allocator uses ๐ฆ Theregionargument should be one of these:allโ every loop becomes a register allocation region. This can give the best results on machines with a small and/or irregular register set ๐mixedโ every loop except the ones with small register pressure becomes a region. This is usually the best pick for most cases and most architectures, and it's on by default when you compile with optimization for speed (-O,-O2, ...) โจoneโ all functions get treated as a single region. This typically gives the smallest code size, and it's the default for-Osor-O0๐ง
-fira-hoist-pressureโ use IRA to check register pressure during the code hoisting pass when deciding whether to hoist expressions ๐ธ This usually gives you smaller code, but it can slow the compiler down ๐ข
This option is enabled at level -Os for all targets.
-fira-loop-pressureโ use IRA to check register pressure inside loops when deciding whether to move loop invariants ๐ This usually gives faster and smaller code on machines with big register files (>= 32 registers), but it can slow the compiler down too.
This option is enabled at level -O3 for some targets.
-fno-ira-share-save-slotsโ turns off sharing of stack slots used to save 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โ turns off sharing of stack slots allocated for pseudo-registers ๐ซถ Every pseudo-register that doesn't get a hard register gets its own stack slot, so function stack frames end up bigger.
-flra-rematโ turns on CFG-sensitive rematerialization in LRA ๐ฅ Instead of reloading the values of spilled pseudos, LRA tries to rematerialize (recalculate) them when that's profitable.
Enabled at levels -O2, -O3, -Os.
-fdelayed-branchโ if the target machine supports it, the compiler tries to reorder instructions so it can use the instruction slots available after delayed branch instructions ๐
Enabled at levels -O, -O2, -O3, -Os, but not at -Og.
-fschedule-insnsโ if the target machine supports it, the compiler reorders instructions to dodge execution stalls caused by data that isn't ready yet โณ This helps machines with slow floating point or memory load instructions, since other instructions can get issued while the load or floating-point result is still on its way.
Enabled at levels -O2, -O3.
-fschedule-insns2โ basically the same vibe as-fschedule-insns, but it asks for an extra round of instruction scheduling after register allocation is done ๐ This is especially useful 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โ turns off instruction scheduling across basic blocks ๐ซ This is normally on when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher.-fno-sched-specโ turns off speculative motion of non-load instructions ๐ This is normally on when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher.-fsched-pressureโ enables register pressure sensitive instruction scheduling before register allocation ๐ This only makes sense when pre-allocation scheduling is turned on, i.e. with-fschedule-insnsor at-O2or higher. It can improve the generated code and shrink its size by stopping register pressure from climbing above the number of available hard registers, which means fewer spills later in register allocation.-fsched-spec-loadโ allows speculative motion of some load instructions ๐ This only makes sense when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher.-fsched-spec-load-dangerousโ allows speculative motion of more load instructions ๐ This only makes sense when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher.-fsched-stalled-insns,-fsched-stalled-insns=nโ controls how many instructions (if any) can be moved early from the queue of stalled instructions into the ready list during the second scheduling pass โญ-fno-sched-stalled-insnsmeans no instructions get moved early.-fsched-stalled-insns=0means there's no limit on how many queued instructions 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โ defines how many instruction groups (cycles) get checked for a dependency on a stalled instruction that's a candidate for being moved early ๐ This 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, use superblock scheduling ๐ This allows motion across basic block boundaries, which can give faster schedules.
โ ๏ธ This option is experimental! Not all machine descriptions GCC uses model the CPU closely enough to avoid unreliable results from the algorithm, so be careful bestie ๐ซฃ
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 ๐ง This one favors the instruction that belongs to a schedule group. It's on 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 ๐ฃ๏ธ This one favors instructions on the critical path. It's on 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 ๐ฏ This one favors speculative instructions with greater dependency weakness. It's on 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 ๐ This one favors the instruction that belongs to a basic block with greater size or frequency. It's on 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 ๐ซง This one favors the instruction that depends less on the last instruction scheduled. It's on 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 ๐ This one favors the instruction that has more instructions depending on it. It's on 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, and this option is how you control that behavior.-fselective-schedulingโ schedules instructions using the selective scheduling algorithm ๐งฉ Selective scheduling runs instead of the first scheduler pass.-fselective-scheduling2โ schedules instructions using the selective scheduling algorithm ๐งฉ Selective scheduling runs instead of the second scheduler pass.-fsel-sched-pipeliningโ enables software pipelining of innermost loops during selective scheduling ๐ฅ This option has no effect unless-fselective-schedulingor-fselective-scheduling2is turned on.-fsel-sched-pipelining-outer-loopsโ when pipelining loops during selective scheduling, also pipeline the outer loops too ๐ช This option 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 that for symbols exported from the DSO, the compiler can't do interprocedural propagation, inlining, or other optimizations, because the function or variable might get swapped out for something else. This is super useful for stuff like rewriting memory allocation functions with a debugging implementation, but it's pricey in terms of code quality ๐ญ
With -fno-semantic-interposition, the compiler assumes that if interposition happens for functions, the overwriting function will have precisely the same semantics (and side effects). Similarly, if interposition happens for variables, the constructor of the variable will be the same. This flag has no effect for functions explicitly declared inline, where interposition is never allowed 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 very top of the function ๐ This flag is enabled by default at-Oand higher.-fshrink-wrap-separateโ shrink-wraps the prologue and epilogue parts separately, so each part only runs when it's 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โ okay so this one lets GCC park values in registers that function calls would normally trash ๐ , and then it sneaks in extra instructions to save and restore those registers around the calls. It only does this when it seems to give better code, so no pointless drama โจ
This option is always on 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โ it keeps track of stack adjustments (pushes and pops) plus stack memory references, then tries to smoosh them together into something neater ๐ง
Enabled by default at -O1 and higher.
-fipa-raโ this one lets GCC use the caller-save registers for allocation as long as none of the functions being called are using them ๐ฆ. That means no need to save and restore them around calls.
This only works if the called functions are in the same compilation unit as the current function and they get compiled first ๐
Enabled at levels -O2, -O3, -Os, but it's switched off if the generated code will be instrumented for profiling (-p, or -pg) or if the callee's register usage can't be known exactly. That second one happens on targets that don't expose prologues and epilogues in RTL ๐ญ
-fconserve-stackโ the vibe here is "save every byte" ๐. GCC tries to use less stack space, even if the program ends up running slower. This option implies setting thelarge-stack-frameparameter to100and thelarge-stack-frame-growthparameter to400๐-ftree-reassocโ performs reassociation on trees ๐ Enabled by default at-Oand higher.-fcode-hoistingโ code hoisting tries to move the evaluation of expressions that run on all paths to the function exit as early as possible โญ It's especially useful as a code size optimization, but it often helps code speed too ๐
This flag is enabled by default at -O2 and higher.
-ftree-preโ performs partial redundancy elimination (PRE) on trees ๐ง Enabled by default at-O2and-O3.-ftree-partial-preโ makes partial redundancy elimination (PRE) more aggressive ๐ค Enabled by default at-O3.-ftree-forwpropโ performs forward propagation on trees ๐ฆ Enabled by default at-Oand higher.-ftree-freโ performs full redundancy elimination (FRE) on trees ๐ The difference between FRE and PRE is that FRE only considers expressions computed on all paths leading to the redundant computation. This analysis 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-Oand higher.-fhoist-adjacent-loadsโ speculatively hoists loads from both branches of an if-then-else, but only if the loads come from adjacent locations in the same structure and the target architecture has a conditional move instruction ๐ซถ
This flag is enabled by default at -O2 and higher.
-ftree-copy-propโ performs copy propagation on trees, which basically means it cleans up unnecessary copy operations ๐งน This pass is enabled by default at-Oand higher.-fipa-pure-constโ discovers which functions are pure or constant ๐ฎ Enabled by default at-Oand higher.-fipa-referenceโ discovers which static variables don't escape the compilation unit ๐ Enabled by default at-Oand higher.-fipa-reference-addressableโ discovers read-only, write-only, and non-addressable static variables ๐ธ Enabled by default at-Oand higher.-fipa-stack-alignmentโ reduces stack alignment on call sites where possible ๐ Enabled by default.-fipa-ptaโ performs interprocedural pointer analysis and interprocedural modification and reference analysis ๐ง
This one can cause excessive memory and compile-time usage on large compilation units, so be careful, bestie ๐
It is not enabled by default at any optimization level.
-fipa-profileโ performs interprocedural profile propagation ๐ Functions called only from cold functions get marked as cold. Functions executed once (such as "cold", "noreturn", static constructors or destructors) are also 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 one analyzes the program to figure 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 ๐ฅ
This flag is 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 a function when an externally visible function can be called with constant arguments. Because this can create multiple copies of functions, it may significantly increase code size (see--param ipa-cp-unit-growth=value) ๐
This flag is 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 ๐งฉ This flag is enabled by default at-O2and by-fprofile-useand-fauto-profile. It requires that-fipa-cpis enabled.-fipa-vrpโ when enabled, performs interprocedural propagation of value ranges ๐ This flag is enabled by default at-O2. It requires that-fipa-cpis enabled.-fipa-icfโ performs Identical Code Folding for functions and read-only variables ๐ช This shrinks code size, but it may disturb unwind stacks by replacing a function with an equivalent one that has a different name ๐ต The optimization 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 aren't the same. There are equivalences that only GCC finds, and equivalences that only Gold finds ๐ค
This flag is enabled by default at -O2 and -Os.
-flive-patching=levelโ controls GCC's optimizations so the output is suitable for live-patching ๐ฉน
Okay, so if the compiler's optimization uses a function's body (or info pulled from its body) to optimize or change another function, that other one is called an impacted function of the first. If a function gets patched, its impacted functions should be patched too ๐ซถ
The impacted functions are determined by the compiler's interprocedural optimizations. For example, a caller is impacted when a function gets inlined into it, when a function is cloned and its caller is changed to call the new clone, or when a function's pureness or constness info is extracted to optimize its direct or indirect callers.
Usually, the more IPA optimizations are enabled, the bigger the number of impacted functions for each function. To control that number and make the list of impacted functions easier to compute, IPA optimizations can be partially enabled at two different levels.
The level argument should be one of the following:
inline-cloneโ only enables inlining and cloning optimizations, which includes inlining, cloning, interprocedural scalar replacement of aggregates, and partial inlining. As a result, when patching a function, all its callers and its clones' callers are impacted, so they need to be patched too ๐
-flive-patching=inline-clone disables the following optimization flags: -fwhole-program -fipa-pta -fipa-reference -fipa-ra -fipa-icf -fipa-icf-functions -fipa-icf-variables -fipa-bit-cp -fipa-vrp -fipa-pure-const -fipa-reference-addressable -fipa-stack-alignment
inline-only-staticโ only enables inlining of static functions. As a result, when patching a static function, all its callers are impacted and so need to be patched too ๐ท
In addition to all the flags that -flive-patching=inline-clone disables, -flive-patching=inline-only-static disables these extra optimization flags: -fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp
When -flive-patching is specified without any value, the default value is inline-clone ๐ง
This flag is disabled by default.
Note that-flive-patchingis not supported with link-time optimization (-flto). Don't mix them, babe ๐ โโ๏ธ
-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 the erroneous or undefined behavior into a trap ๐ชค
This flag is 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 because a null value is used in a way forbidden by a "returns_nonnull" or "nonnull" attribute ๐ซ It isolates those paths from the main control flow and turns the statement with the 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-Oand higher.-ftree-bit-ccpโ performs sparse conditional bit constant propagation on trees and propagates pointer alignment information ๐ข This pass only operates on local scalar variables and is enabled by default at-O1and higher, except for-Og. It requires that-ftree-ccpis enabled.-ftree-ccpโ performs sparse conditional constant propagation (CCP) on trees ๐ This pass only operates on local scalar variables and is enabled by default at-Oand higher.-fssa-backpropโ propagates information about uses of a value up the definition chain so the definitions can be simplified ๐ช For example, this pass strips sign operations if the sign of a value never matters. Enabled by default at-Oand higher.-fssa-phioptโ okay so this one does pattern matching on SSA PHI nodes to tidy up conditional code โจ It's on by default at-O1and higher, except for-Og๐ธ-ftree-switch-conversionโ it turns simple initializations inside a switch into initializations from a scalar array ๐ On by default at-O2and higher ๐-ftree-tail-mergeโ this one hunts for identical code sequences ๐ฏ When it finds a match, it replaces one copy with a jump to the other. This is called tail merging or cross jumping ๐ฆ On by default at-O2and higher. You can cap how long this pass runs with themax-tail-merge-comparisonsparameter and themax-tail-merge-iterationsparameter โฑ๏ธ-ftree-dceโ dead code elimination (DCE) on trees, aka getting rid of code that never actually does anything ๐ On by default at-Oand higher.-ftree-builtin-call-dceโ conditional DCE for calls to built-in functions that may seterrnobut are otherwise free of side effects ๐ On by default at-O2and higher, if-Osisn't also specified ๐ง-ffinite-loopsโ this assumes a loop with an exit will eventually take the exit and won't loop forever ๐ That lets the compiler remove loops that have no side effects, without treating endless looping as one ๐ This option is on by default at-O2for C++ with-std=c++11or higher ๐-ftree-dominator-optsโ a bunch of simple scalar cleanups โจ That's constant/copy propagation, redundancy elimination, range propagation and expression simplification, all based on a dominator tree traversal. It also does jump threading (to reduce jumps to jumps) ๐ฆ On by default at-Oand higher.-ftree-dseโ dead store elimination (DSE) on trees ๐ A dead store is a store into a memory location that gets overwritten by another store later, with no loads in between ๐ญ The earlier store can be deleted ๐๏ธ On by default at-Oand higher.-ftree-chโ loop header copying on trees ๐ It's beneficial because it boosts code motion optimizations, and it saves one jump too. On by default at-Oand higher, but it's not enabled for-Os, since it usually increases code size ๐-ftree-loop-optimizeโ loop optimizations on trees ๐ On 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 is enabled โ๏ธ-fgraphite-identityโ enables the identity transformation for graphite ๐ช For every SCoP, we generate the polyhedral representation and transform it back to gimple. With this one you can check the costs or benefits of theGIMPLE -> GRAPHITE -> GIMPLEtransformation ๐ Some minimal optimizations also happen in the code generator isl, like index splitting and dead code elimination in loops ๐ง-floop-nest-optimizeโ turns on the isl based loop nest optimizer ๐งฉ It's a generic loop nest optimizer based on the Pluto optimization algorithms, and it calculates a loop structure that's optimized for data-locality and parallelism ๐ This option is experimental โ ๏ธ-floop-parallelize-allโ uses Graphite data dependence analysis to identify loops that can be parallelized ๐งต It parallelizes all the loops that can be analyzed as not containing loop carried dependences, without checking whether it's actually profitable to do so ๐ซ-ftree-coalesce-varsโ when transforming the program out of SSA form, this tries to cut down on copying by coalescing versions of different user-defined variables, not just compiler temporaries ๐งฉ In the negated form, this flag prevents SSA coalescing of user variables ๐ It's on by default if optimization is enabled, and does very little otherwise ๐ค
Heads up, bestie: this may severely limit your ability to debug an optimized program compiled with -fno-var-tracking-assignments ๐ญ
-ftree-loop-if-convertโ tries to transform conditional jumps in the innermost loops into branch-less equivalents ๐ The goal is to remove control flow from the innermost loops so the vectorization pass can handle them better ๐ช It's enabled by default if vectorization is enabled ๐ธ-ftree-loop-distributionโ performs loop distribution ๐ฐ This can improve cache performance on big loop bodies and open the door for further loop optimizations, like parallelization or vectorization ๐ช Check out this glow-up, where the loop:
DO I = 1, N
A(I) = B(I) + C
D(I) = E(I) * F
ENDDO
gets transformed into:
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-O2and higher, and by-fprofile-useand-fauto-profile๐ซถ
This pass distributes the initialization loops and generates a call to memset zero ๐งธ For example, the loop:
DO I = 1, N
A(I) = 0
B(I) = A(I) + I
ENDDO
is transformed to:
DO I = 1, N
A(I) = 0
ENDDO
DO I = 1, N
B(I) = A(I) + I
ENDDO
and the initialization loop is transformed into a call to memset zero. This flag is enabled by default at -O3. It's also enabled by -fprofile-use and -fauto-profile ๐
-floop-interchangeโ performs loop interchange outside of graphite ๐ This can improve cache performance on loop nests and let vectorization and other loop optimizations take place ๐ For example, this loop:
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
for (int k = 0; k < N; k++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
is transformed to:
for (int i = 0; i < N; i++)
for (int k = 0; k < N; k++)
for (int j = 0; j < N; j++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
This flag is enabled by default at -O3. It'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, this unrolls the outer loop by some factor and fuses the resulting multiple inner loops ๐ซง This flag is enabled by default at-O3. It's also enabled by-fprofile-useand-fauto-profile๐-ftree-loop-imโ performs loop invariant motion on trees ๐ This pass only moves invariants that are hard to handle at the RTL level, like function calls or operations that expand into nontrivial sequences of insns ๐ฆ With-funswitch-loops, it 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 that out takes complicated analysis ๐ข Later optimizations may then determine the number easily, which is especially useful 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, provided it's sufficiently cheap ๐ธ This reduces data dependencies and may unlock more simplifications ๐ฆ Enabled by default at-Oand higher.-fivoptsโ performs 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 innthreads ๐งต This is only possible for loops whose iterations are independent and can be arbitrarily reordered ๐ It's only profitable on multiprocessor machines, for CPU-intensive loops rather than loops constrained by, e.g., memory bandwidth ๐ฅ๏ธ This option implies-pthread, so it's only supported on targets that have support for-pthread๐-ftree-ptaโ performs function-local points-to analysis on trees ๐ฏ On by default at-O1and higher, except for-Og๐-ftree-sraโ performs scalar replacement of aggregates ๐งฉ It swaps structure references for scalars so structures don't get committed to memory too early ๐ค On by default at-O1and higher, except for-Og๐ธ-fstore-mergingโ merges narrow stores to consecutive memory addresses ๐ฆ It squishes contiguous stores of immediate values that are narrower than a word into fewer, wider stores to cut down on instructions โ๏ธ On by default at-O2and higher, as well as-Os๐-ftree-terโ performs temporary expression replacement during theSSA->normalphase ๐ Single use/single def temporaries get replaced at their use location with their defining expression ๐ฏ This results in non-GIMPLE code, but it gives the expanders much more complex trees to work on, which leads to better RTL generation โจ Enabled by default at-Oand higher.-ftree-slsrโ performs straight-line strength reduction on trees ๐ It recognizes related expressions involving multiplications and replaces them with less expensive calculations when possible ๐ธ Enabled by default at-Oand higher.-ftree-vectorizeโ performs vectorization on trees ๐ This flag enables-ftree-loop-vectorizeand-ftree-slp-vectorizeif they aren't explicitly specified ๐-ftree-loop-vectorizeโ performs loop vectorization on trees ๐ This flag is enabled by default at-O3, and by-ftree-vectorize,-fprofile-use, and-fauto-profiletoo ๐-ftree-slp-vectorizeโ okay bestie, this one turns on basic block vectorization on trees ๐ธ It's on by default at-O3, and you also get it from-ftree-vectorize,-fprofile-use, and-fauto-profileโจ-fvect-cost-model=modelโ this lets you change the cost model GCC uses for vectorization ๐ The model has to beunlimited,dynamic, orcheap:unlimitedassumes the vectorized code path is profitable, no questions asked ๐dynamicputs a runtime check in front of the vectorized path so it only runs for iteration counts that will likely go faster than the original scalar loop ๐ฆcheapskips vectorizing loops where that would be cost-prohibitive, like when it needs runtime checks for data dependence or alignment. Otherwise it's the same asdynamic๐ซถ
The default cost model depends on your other optimization flags, and it's either dynamic or cheap ๐ฅ
-fsimd-cost-model=modelโ same energy, but for loops marked with the OpenMPsimddirective ๐ The model can beunlimited,dynamic, orcheap, and all of them mean exactly what they do in-fvect-cost-model๐ By default, if you've set a cost model with-fvect-cost-model, that's the one it uses โจ-ftree-vrpโ enables Value Range Propagation on trees ๐ง It's kind of like constant propagation, except instead of tracking single values it propagates whole ranges of values ๐ That lets the optimizers yeet unnecessary range checks, like array bound checks and null pointer checks ๐ It's enabled by default at-O2and higher.
Heads up: null pointer check elimination only happens if -fdelete-null-pointer-checks is enabled ๐
-fsplit-pathsโ splits paths leading to loop backedges ๐ This can improve dead code elimination and common subexpression elimination ๐ It's enabled by default at-O3and above โจ-fsplit-ivs-in-unrollerโ okay so this one lets the compiler express the values of induction variables in later iterations of an unrolled loop, using the value from the first iteration ๐ฆ It's lowkey genius, because it breaks long dependency chains, which makes the scheduling passes more efficient ๐ฅ
Real talk, a combination of -fweb and CSE is often enough to get the same effect ๐ธ But it's not reliable when the loop body is more complicated than a single basic block ๐ And it doesn't work at all on some architectures because of restrictions in the CSE pass ๐
This optimization is enabled by default โจ
-fvariable-expansion-in-unrollerโ when unrolling a loop, this makes multiple copies of some local variables, which can result in superior code ๐ It's enabled by default for PowerPC targets, but disabled by default otherwise ๐-fpartial-inliningโ inlines parts of functions ๐งฉ This only has an effect when inlining itself is turned on by-finline-functionsor-finline-small-functions๐ซถ
Enabled at levels -O2, -O3, -Os ๐
-fpredictive-commoningโ performs predictive commoning, which is basically reusing computations (especially memory loads and stores) from previous iterations of loops ๐ง
It's enabled at level -O3. It's also enabled by -fprofile-use and -fauto-profile ๐
-fprefetch-loop-arraysโ if the target machine supports it, this generates instructions to prefetch memory, which can help loops that access large arrays go brr ๐๏ธ
This option may generate better 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โ don't substitute constants for the known return value of formatted output functions like"sprintf","snprintf","vsprintf", and"vsnprintf"(but not"printf"or"fprintf") ๐ This lets GCC optimize or even eliminate branches based on the known return value, when the arguments are constant or their values are known to be in a range that makes the exact return value possible โจ
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 yields the best results with -O2 and above. It works in tandem with the -Wformat-overflow and -Wformat-truncation options. The -fprintf-return-value option is enabled by default ๐ธ
-fno-peephole,-fno-peephole2โ disables any machine-specific peephole optimizations ๐ฆ The difference between them is 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โ don't 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", then the heuristics are used to guess branch probabilities for the rest of the control flow graph, taking the "__builtin_expect" info into account ๐ซถ The interactions between the heuristics and "__builtin_expect" can get pretty complex, so sometimes it's useful to disable the heuristics so the effects of "__builtin_expect" are easier to understand ๐
It's also possible to 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 ๐ง The algorithm can besimple, which doesn't increase code size (except sometimes due to secondary effects like alignment), orstc, the "software trace cache" algorithm, which tries to put all the often-executed code together, minimizing the number of branches executed by making extra copies of code ๐ฅ
The default is simple at levels -O and -Os, and stc at levels -O2 and -O3 ๐
-freorder-blocks-and-partitionโ in addition to reordering basic blocks, this partitions hot and cold basic blocks into separate sections of the assembly and.ofiles, to improve paging and cache locality performance ๐
This optimization is automatically turned off in the presence of exception handling or unwind tables (on targets using setjump/longjump or target specific scheme), for linkonce sections, for functions with a user-defined section attribute, and on any architecture that doesn't support named sections ๐ซ
When -fsplit-stack is used, this option isn't enabled by default (to avoid linker errors), but it may be enabled explicitly if you're using a working linker ๐งต
Enabled for x86 at levels -O2, -O3, -Os ๐ฆ
-freorder-functionsโ reorders functions in the object file to improve code locality ๐๏ธ This is done using special subsections:.text.hotfor the most frequently executed functions and.text.unlikelyfor the unlikely-executed ones ๐ฅ
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โ lets the compiler assume the strictest aliasing rules that apply to the language being compiled ๐ง For C (and C++), this turns on optimizations based on the type of expressions. An object of one type is assumed to never reside at the same address as an object of a different type, unless the types are almost the same. For example, an"unsigned int"can alias an"int", but not a"void*"or a"double". A character type may alias any other type ๐
Pay special attention to code like this ๐
union a_union {
int i;
double d;
};
int f() {
union a_union t;
t.d = 3.0;
return t.i;
}
The practice of reading from a different union member than the one most recently written to (called "type-punning") is common. Even with -fstrict-aliasing, type-punning is allowed, provided the memory is accessed through the union type. So, the code above works as expected. However, this code might not:
int f() {
union a_union t;
int* ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}
Similarly, access by taking the address, casting the resulting pointer, and dereferencing the result has undefined behavior, even if the cast uses a union type, e.g.:
int f() {
double d = 3.0;
return ((union a_union *) &d)->i;
}
Careful, bestie: that last one has undefined behavior ๐
The -fstrict-aliasing option is enabled at levels -O2, -O3, -Os ๐ฅ
-falign-functions,-falign-functions=n,-falign-functions=n:m,-falign-functions=n:m:n2,-falign-functions=n:m:n2:m2โ aligns the start of functions to the next power-of-two that's greater than or equal to n, skipping up to m-1 bytes ๐ This makes sure at least the first m bytes of the function can be fetched by the CPU without crossing an n-byte alignment boundary ๐
If m isn't specified, it defaults to n ๐
Examples:
-falign-functions=32aligns functions to the next 32-byte boundary-falign-functions=24aligns to the next 32-byte boundary only if this can be done by skipping 23 bytes or less-falign-functions=32:7aligns to the next 32-byte boundary only if this can be done by skipping 6 bytes or less โจ
The second pair, n2:m2, gives you a secondary alignment ๐
โจ So -falign-functions=64:7:32:3 means: go to the next 64-byte boundary if you can get there by skipping 6 bytes or fewer, and otherwise go to the next 32-byte boundary if that only costs you 2 bytes or fewer ๐ฆ. If m2 isn't specified, it just defaults to n2 ๐ซถ.
Some assemblers only accept this flag when n is a power of two ๐ค. When that's the case, the value gets rounded up ๐ธ.
-fno-align-functions and -falign-functions=1 are the same thing, and both mean functions don't get aligned at all ๐
โโ๏ธ.
If n isn't specified or is zero, you get a machine-dependent default ๐ง. The biggest n you can use is 65536 ๐.
Enabled at levels -O2, -O3 ๐.
-flimit-function-alignmentโ If this is on, the compiler tries not to overalign functions for no reason ๐. It asks the assembler to align by whatever-falign-functionssays, but it won't skip more bytes than the size of the function itself ๐.
-falign-labels
-falign-labels
-falign-labels=n
-falign-labels=n:m
-falign-labels=n:m:n2
-falign-labels=n:m:n2:m2
Aligns all branch targets to a power-of-two boundary ๐.
The parameters work just like -falign-functions ๐ฆ. -fno-align-labels and -falign-labels=1 are equivalent and mean labels don't get aligned ๐
โโ๏ธ.
If -falign-loops or -falign-jumps apply and their values are bigger than this one, then their values get used instead ๐.
If n isn't specified or is zero, you get a machine-dependent default that's very likely to be 1, which means no alignment at all ๐ง. The maximum allowed n is 65536.
Enabled at levels -O2, -O3 ๐.
-falign-loops
-falign-loops
-falign-loops=n
-falign-loops=n:m
-falign-loops=n:m:n2
-falign-loops=n:m:n2:m2
Aligns loops to a power-of-two boundary ๐. If the loops run a ton of times, the padding instructions that get executed are totally worth it ๐.
If -falign-labels is bigger than this value, then its value gets used instead ๐.
The parameters are analogous to -falign-functions โจ. -fno-align-loops and -falign-loops=1 are equivalent and mean loops don't get aligned ๐
โโ๏ธ. The maximum allowed n is 65536.
If n isn't specified or is zero, you get a machine-dependent default ๐ง.
Enabled at levels -O2, -O3 ๐.
-falign-jumps
-falign-jumps
-falign-jumps=n
-falign-jumps=n:m
-falign-jumps=n:m:n2
-falign-jumps=n:m:n2:m2
Aligns branch targets to a power-of-two boundary ๐ฆ, but only for the ones that can only be reached by jumping. In that case, no dummy operations need to run ๐ง.
If -falign-labels is bigger than this value, then its value gets used instead ๐.
The parameters are analogous to -falign-functions ๐. -fno-align-jumps and -falign-jumps=1 are equivalent and mean that loops are not aligned ๐. If n isn't specified or is zero, you get a machine-dependent default ๐ง. The maximum allowed n is 65536.
Enabled at levels -O2, -O3 ๐.
-fno-allocation-dceโ Don't remove unused C++ allocations during dead code elimination ๐๏ธโจ.-fallow-store-data-racesโ Lets the compiler introduce brand-new data races on stores ๐ญ. Enabled at level-Ofast.
Bestie, new data races are not a vibe ๐. Only turn this on if you really know what you're doing.
-funit-at-a-timeโ This one's just here for compatibility reasons ๐ฐ๏ธ.-funit-at-a-timehas no effect, but-fno-unit-at-a-timeimplies-fno-toplevel-reorderand-fno-section-anchors. Enabled by default ๐ .-fno-toplevel-reorderโ Don't reorder top-level functions, variables, andasmstatements ๐. They get output in the same order they show up in the input file. With this on, unreferenced static variables are not removed ๐. It's meant for existing code that depends on a specific ordering. For new code, it's better to use attributes when you can ๐ซถ.
-ftoplevel-reorder is the default at -O1 and higher, and also at -O0 if -fsection-anchors is explicitly requested ๐ง. Also, -fno-toplevel-reorder implies -fno-section-anchors ๐.
-fwebโ Constructs webs like the ones commonly used for register allocation, and gives each web its own individual pseudo register ๐ธ๏ธ. This lets the register allocation pass work on pseudos directly, and it also strengthens a few other optimization passes, like CSE, the loop optimizer, and the trivial dead code remover ๐ช. Enabled by default with-funroll-loops๐ธ.
Heads up, babe: this one can make debugging basically impossible, since variables no longer stay in a "home register" ๐ญ.
-fwhole-programโ Assumes the current compilation unit is the whole program being compiled ๐. All public functions and variables, exceptmainand anything merged by the attributeexternally_visible, become static functions and get optimized more aggressively by interprocedural optimizers ๐ฅ.
Don't combine this with -flto ๐
โโ๏ธ. Relying on a linker plugin instead should give you safer and more precise information.
-flto[=n]
This option runs the standard link-time optimizer ๐ฆ. When you invoke it with source code, it generates GIMPLE (one of GCC's internal representations) and writes it into special ELF sections in the object file โจ. When the object files get linked together, all the function bodies are read back from those ELF sections and instantiated as if they were part of the same translation unit ๐ซถ.
To use the link-time optimizer, you need -flto and your optimization options at compile time and during the final link ๐
. It's recommended that you compile every file in the same link with the same options, and also pass 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 that GIMPLE bytecode from foo.o and bar.o, merges the two files into a single internal image, and compiles the result as usual ๐ง. Since both get 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 from bar.o into functions in foo.o and vice-versa ๐ฅ.
Another (simpler) way to turn on link-time optimization is:
gcc -o myprog -flto -O2 foo.c bar.c
That one 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 big thing to remember is that you need to use the GCC driver to do the link step ๐ง. GCC automatically performs link-time optimization if any of the objects involved were compiled with the -flto command-line option ๐. You can always override that automatic decision by passing -fno-lto to the link command ๐
โโ๏ธ.
To make whole program optimization actually effective, you have to make certain whole program assumptions ๐ค. The compiler needs to know which functions and variables can be accessed by libraries and runtime outside of the link-time optimized unit ๐. When the linker supports it, the linker plugin (see -fuse-linker-plugin) passes that info to the compiler about used and externally visible symbols ๐ฆ. When the linker plugin isn't available, use -fwhole-program so the compiler can make those assumptions, which leads to more aggressive optimization decisions ๐ฅ.
When a file is compiled with -flto and without -fuse-linker-plugin, the generated object file is bigger than a regular one ๐ฆ. That's because it contains GIMPLE bytecodes and the usual final code (see -ffat-lto-objects). This means object files with LTO information can be linked as normal object files ๐ซถ. If -fno-lto is passed to the linker, though, no interprocedural optimizations get applied ๐ญ.
Note that when -fno-fat-lto-objects is enabled, the compile stage is faster, but you cannot perform a regular, non-LTO link on them ๐.
When producing the final binary, GCC only applies link-time optimizations to the files that contain bytecode ๐ง . So you can mix and match object files and libraries with GIMPLE bytecodes and final object code ๐ธ. GCC automatically picks which files get optimized in LTO mode and which ones just get linked without any further processing โจ.
Generally, options given at link time override the ones given at compile time ๐. In some cases, though, GCC tries to infer link-time options from the settings used to compile the input files ๐.
If you don't specify an optimization level option -O at link time, then GCC uses the highest optimization level used when compiling the object files ๐ง. Also, it's generally ineffective to specify an optimization level only at link time and not at compile time ๐, for two reasons. First, compiling without optimization suppresses the compiler passes that gather the info 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 have to match in all compilation units, and if you try to override them at link time with a conflicting value, it gets ignored ๐ซ. This includes options like -freg-struct-return and -fpcc-struct-return ๐.
Other options, such as -ffp-contract, -fno-strict-overflow, -fwrapv, -fno-trapv or -fno-strict-aliasing, get passed through to the link stage and merged conservatively for conflicting translation units ๐ฆ. Specifically, -fno-strict-overflow, -fwrapv and -fno-trapv take precedence, and for example -ffp-contract=off takes precedence over -ffp-contract=fast ๐. You can override them at link time โจ.
Okay so bestie, diagnostic options like -Wstringop-overflow get passed through to the link stage ๐
, and their setting matches the compile step at function granularity ๐ฆ. ngl this only matters for diagnostics emitted during optimization โจ. Also, code transforms like inlining can switch warnings on or off for regions of code that don't match the setting used at compile time ๐, so keep an eye out.
When you need to pass options to the assembler with -Wa or -Xassembler, make sure you either compile those translation units with -fno-lto or use the same assembler options on every translation unit ๐ง. You can also specify assembler options at LTO link time instead ๐.
To turn on debug info generation, you need to supply -g at compile time ๐. If any input files at link time were built with debug info generation enabled, the link will turn on debug info generation too โจ. Fancy debug info settings, like the dwarf level -gdwarf-5, need to be explicitly repeated on the linker command line, and mixing different settings across translation units is discouraged ๐ญ.
If LTO runs into objects with C linkage declared with incompatible types in separate translation units being linked together (undefined behavior according to ISO C99 6.2.7) ๐, it may issue a non-fatal diagnostic. The behavior is still undefined at run time, so no cheating ๐ . Similar diagnostics may be raised for other languages.
Another feature of LTO is that you can apply interprocedural optimizations to files written in different languages ๐:
gcc -c -flto foo.c
g++ -c -flto bar.cc
gfortran -c -flto baz.f90
g++ -o myprog -flto -O3 foo.o bar.o baz.o -lgfortran
Notice that the final link is done with g++ to get the C++ runtime libraries, and -lgfortran gets added to get the Fortran runtime libraries ๐. In general, when mixing languages in LTO mode, use the same link command options you'd use when mixing languages in a regular (non-LTO) compilation ๐ซถ.
If object files containing GIMPLE bytecode are stored in a library archive, say libfoo.a, you can extract and use them in an LTO link as long as you're using a linker with plugin support ๐ฆ. To create static libraries that work with LTO, use gcc-ar and gcc-ranlib instead of ar and ranlib, and to show the symbols of object files with GIMPLE bytecode, use gcc-nm. Those commands require that ar, ranlib and nm have been compiled with plugin support. At link time, use the flag -fuse-linker-plugin so the library participates in the LTO optimization process:
gcc -o myprog -O2 -flto -fuse-linker-plugin a.o b.o -lfoo
With the linker plugin enabled, the linker extracts the needed GIMPLE files from libfoo.a and passes them to the running GCC so they become part of the aggregated GIMPLE image to be optimized โจ.
If you're not using a linker with plugin support and/or don't enable the linker plugin ๐ฅฒ, the objects inside libfoo.a are extracted and linked as usual, but they do not participate in the LTO optimization process. To make a static library suitable for both LTO optimization and usual linkage, compile its object files with -flto -ffat-lto-objects ๐.
Link-time optimizations don't need the whole program to be present in order to work ๐ธ. If the program doesn't require any symbols to be exported, you can combine -flto and -fwhole-program so the interprocedural optimizers can use more aggressive assumptions, which may lead to better optimization opportunities. Using -fwhole-program isn't needed when the linker plugin is active (see -fuse-linker-plugin).
The current implementation of LTO makes no attempt to generate bytecode that's portable between different types of hosts ๐ซ. The bytecode files are versioned and there's a strict version check, so bytecode files generated by one version of GCC won't work with an older or newer version of GCC.
Link-time optimization doesn't play nicely with generating debugging information on systems other than those using a combination of ELF and DWARF ๐ญ.
If you specify the optional n, the optimization and code generation done at link time runs in parallel using n jobs by utilizing an installed make program ๐โโ๏ธ. Want a different make? The environment variable MAKE lets you override the program used ๐ง.
You can also specify -flto=jobserver to use GNU make's job server mode to figure out the number of parallel jobs ๐ง. This is super useful when the Makefile calling GCC is already running in parallel. You must prepend a + to the command recipe in the parent Makefile for this to work. This option likely only works if MAKE is GNU make. Even without the option value, GCC tries to automatically detect a running GNU make's job server ๐.
Use -flto=auto to use GNU make's job server, if it's available, or otherwise fall back to autodetecting the number of CPU threads in your system ๐.
-flto-partition=algโ Pick the partitioning algorithm the link-time optimizer uses ๐งฉ. The value is either1to1, which mirrors the original source files,balanced, which splits things into equally sized chunks (whenever possible), ormax, which creates a new partition for every symbol where possible. Specifyingnoneas the algorithm disables partitioning and streaming completely. The default value isbalanced.1to1can be used as a workaround for various code ordering issues, butmaxpartitioning is intended for internal testing only ๐. The valueonespecifies that exactly one partition should be used, while the valuenonebypasses partitioning and runs the link-time optimization step directly from the WPA phase.-flto-compression-level=nโ Sets how much compression gets used for the intermediate language written to LTO object files ๐๏ธ. This is only meaningful together with LTO mode (-flto). Valid values are0(no compression) to9(maximum compression). Values outside this range are clamped to either0or9. If you don't give the option, a default balanced compression setting is used.-fuse-linker-pluginโ Turns on the linker plugin during link-time optimization ๐. This relies on plugin support in the linker, which is available ingoldor in GNU ld 2.21 or newer. It enables the extraction of object files with GIMPLE bytecode out of library archives, which improves optimization quality by exposing more code to the link-time optimizer. This also tells the optimizer which symbols can be accessed externally (by a non-LTO object or during dynamic linking). The code quality improvements on binaries (and shared libraries that use hidden visibility) are similar to-fwhole-program. See-fltofor a description of what this flag does and how to use it. This option is enabled by default when LTO support in GCC is enabled and GCC was configured for use with a linker that supports plugins (GNU ld 2.21 or newer, orgold) ๐.-ffat-lto-objectsโ Fat LTO objects are object files that contain both the intermediate language and the object code ๐ฑ. That makes them usable for both LTO linking and normal linking. This option only takes effect when compiling with-flto, and it's ignored at link time.
-fno-fat-lto-objects improves compilation time over plain LTO, but it requires the complete toolchain to be aware of LTO ๐ ๏ธ. It requires a linker with linker plugin support for basic functionality. Additionally, nm, ar and ranlib need to support linker plugins to allow a full-featured build environment (capable of building static libraries, etc). GCC provides the gcc-ar, gcc-nm, gcc-ranlib wrappers to pass the right options to these tools. With non-fat LTO, makefiles need to be modified to use them.
Note that modern binutils provide a plugin auto-load mechanism. Installing the linker plugin into $libdir/bfd-plugins has the same effect as using the command wrappers (gcc-ar, gcc-nm and gcc-ranlib) โจ.
The default is -fno-fat-lto-objects on targets with linker plugin support.
-fcompare-elimโ After register allocation and post-register-allocation instruction splitting, this identifies 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 runs a copy-propagation pass to try to reduce scheduling dependencies and occasionally eliminate the copy ๐. Enabled at levels-O,-O2,-O3,-Os.-fprofile-correctionโ Profiles collected using an instrumented binary for multi-threaded programs can be inconsistent because of missed counter updates ๐งต. When you specify this option, GCC uses heuristics to correct or smooth out those inconsistencies. By default, GCC emits an error message when an inconsistent profile is detected ๐จ. This option is enabled by-fauto-profile.-fprofile-partial-trainingโ With-fprofile-use, all portions of programs not executed during the train run get optimized aggressively for size rather than speed ๐. In some cases it's not practical to train every possible hot path in the program. (For example, a program may contain functions specific to a given hardware, and training may not cover every hardware configuration the program runs on.) With-fprofile-partial-training, profile feedback is ignored for all functions not executed during the train run, so they get optimized as if they were compiled without profile feedback ๐งธ. This leads to better performance when the train run isn't representative, but it also leads to significantly bigger code ๐.-fprofile-use,-fprofile-use=pathโ Enable profile feedback-directed optimizations, plus the following optimizations, many of which are generally only profitable when profile feedback is available ๐ฅ:
And here's the rest of the squad that -fprofile-use brings along for the ride ๐ง:
-fbranch-probabilities -fprofile-values -funroll-loops
-fpeel-loops -ftracer -fvpt -finline-functions -fipa-cp
-fipa-cp-clone -fipa-bit-cp -fpredictive-commoning -fsplit-loops
-funswitch-loops -fgcse-after-reload -ftree-loop-vectorize
-ftree-slp-vectorize -fvect-cost-model=dynamic
-ftree-loop-distribute-patterns -fprofile-reorder-functions
Before you can use this option, you must first generate profiling information. No skipping that step, bestie ๐ โโ๏ธ
By default, GCC gets big mad ๐ and throws an error if the feedback profiles don't match your source code. If you're feeling chaotic, you can downgrade that to a warning with -Wno-error=coverage-mismatch.
Heads up: doing that may result in poorly optimized code.
Also, by default, GCC will warn you if the feedback profiles don't exist at all (see -Wmissing-profile) ๐
If you give it a path, GCC goes digging there to find the profile feedback data files ๐ฆ See -fprofile-dir.
-fauto-profile, -fauto-profile=path
Okay so this turns on sampling-based feedback-directed optimizations, plus a whole crew of other optimizations that are mostly only worth it when profile feedback is around ๐
-fbranch-probabilities -fprofile-values -funroll-loops
-fpeel-loops -ftracer -fvpt -finline-functions -fipa-cp
-fipa-cp-clone -fipa-bit-cp -fpredictive-commoning -fsplit-loops
-funswitch-loops -fgcse-after-reload -ftree-loop-vectorize
-ftree-slp-vectorize -fvect-cost-model=dynamic
-ftree-loop-distribute-patterns -fprofile-correction
path is the name of a file holding AutoFDO profile info ๐ If you leave it out, it defaults to fbdata.afdo in the current directory.
Making an AutoFDO profile data file means running your program with the perf utility on a supported GNU/Linux target system. For more info, check out <https://perf.wiki.kernel.org/> โจ
E.g. ๐
perf record -e br_inst_retired:near_taken -b -o perf.data \
-- your_program
Next, use the create_gcov tool to convert that raw profile data into a format GCC can actually use. You also have to hand this tool the unstripped binary for your program. See <https://github.com/google/autofdo> ๐ธ
E.g.
create_gcov --binary=your_program.unstripped --profile=perf.data \
--gcov=profile.afdo
Next up are the options that control compiler behavior around floating-point arithmetic. โ๏ธ These options trade speed against correctness, so all of them must be specifically enabled. Choose wisely, besties ๐
-ffloat-store
Basically, this tells the compiler not to keep your float variables chilling in registers, and to stop any other options from swapping whether a float comes from a register or from memory ๐
โโ๏ธ It prevents that undesirable excess precision on machines like the 68000, where the floating registers (of the 68881) keep more precision than a double is supposed to have. Same story on the x86 architecture. For most programs, the excess precision only does good, but a few programs rely on the precise definition of IEEE floating point. For those, use -ffloat-store after you've modified them to store all pertinent intermediate computations into variables.
-fexcess-precision=style
This one gives you more control over excess precision on machines where floating-point operations happen in a format with more precision or range than the IEEE standard and interchange floating-point types ๐งฎ By default, -fexcess-precision=fast is in effect, which means operations may run in a wider precision than the types in your source if that makes the code faster. It's unpredictable when the rounding to your source types actually happens, so, hmm, bestie, that's a vibe ๐
When compiling C, if you specify -fexcess-precision=standard, excess precision follows the rules in ISO C99. Casts and assignments both cause values to be rounded to their semantic types (whereas -ffloat-store only affects assignments). This is enabled by default for C if a strict conformance option such as -std=c99 is used. -ffast-math enables -fexcess-precision=fast by default, no matter whether a strict conformance option is used.
-fexcess-precision=standard is not implemented for languages other than C. On the x86, it has no effect if -mfpmath=sse or -mfpmath=sse+387 is specified. In the former case, IEEE semantics apply without excess precision, and in the latter, rounding is unpredictable.
-ffast-math
This one sets -fno-math-errno, -funsafe-math-optimizations, -ffinite-math-only, -fno-rounding-math, -fno-signaling-nans, -fcx-limited-range and -fexcess-precision=fast all at once ๐ฅ It also causes the preprocessor macro "__FAST_MATH__" to be defined.
It's not turned on by any -O option besides -Ofast, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions.
It may, however, yield faster code for programs that don't need the guarantees of those specifications. Use with care, bestie ๐
-fno-math-errno
Don't set errno after calling math functions that run as a single instruction, like sqrt ๐ง A program that relies on IEEE exceptions for math error handling may want this flag for speed while still keeping IEEE arithmetic compatibility.
It's not turned on by any -O option, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need those guarantees.
The default is -fmath-errno.
On Darwin systems, the math library never sets errno. So there's no reason for the compiler to consider that it might, and -fno-math-errno is the default ๐
-funsafe-math-optimizations
Allow optimizations for floating-point arithmetic that (a) assume arguments and results are valid and (b) may violate IEEE or ANSI standards. Lowkey dangerous energy ๐ญ When used at link time, it may include libraries or startup files that change the default FPU control word or other similar optimizations.
It's not turned on by any -O option, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need those guarantees. It enables -fno-signed-zeros, -fno-trapping-math, -fassociative-math and -freciprocal-math.
The default is -fno-unsafe-math-optimizations.
-fassociative-math
This lets you re-associate operands in a series of floating-point operations ๐ It violates the ISO C and C++ language standard by possibly changing the computation result. NOTE: re-ordering may change the sign of zero, ignore NaNs, and inhibit or create underflow or overflow. So it can't be used on code that relies on rounding behavior like (x + 2**52) - 2**52. It may also reorder floating-point comparisons, so it may not be used when ordered comparisons are required.
This option requires that both -fno-signed-zeros and -fno-trapping-math be in effect. Moreover, it doesn't make much sense with -frounding-math. For Fortran, the option is automatically enabled when both -fno-signed-zeros and -fno-trapping-math are in effect.
The default is -fno-associative-math.
-freciprocal-math
This allows the reciprocal of a value to be used instead of dividing by the value, if that enables optimizations โจ For example, x / y can be replaced with x * (1/y), which is useful if (1/y) is subject to common subexpression elimination. Note that this loses precision and increases the number of flops operating on the value.
The default is -fno-reciprocal-math.
-ffinite-math-only
This allows optimizations for floating-point arithmetic that assume arguments and results are never NaNs or +-Infs ๐
It's not turned on by any -O option, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that don't need those guarantees.
The default is -fno-finite-math-only.
-fno-signed-zeros
This allows optimizations for floating-point arithmetic that ignore the signedness of zero ๐ง IEEE arithmetic specifies the behavior of distinct +0.0 and -0.0 values, which then prohibits simplification of expressions such as x+0.0 or 0.0*x (even with -ffinite-math-only). This option implies that the sign of a zero result isn't significant.
The default is -fsigned-zeros.
-fno-trapping-math
This tells the compiler to assume floating-point operations cannot generate user-visible traps ๐ฆ These traps include division by zero, overflow, underflow, inexact result and invalid operation. This option requires that -fno-signaling-nans be in effect. Setting it may allow faster code if you rely on "non-stop" IEEE arithmetic, for example.
This option should never be turned on by any -O option, since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions.
The default is -ftrapping-math.
-frounding-math
This disables transformations and optimizations that assume the default floating-point rounding behavior ๐ That default is round-to-zero for all floating point to integer conversions, and round-to-nearest for all other arithmetic truncations. Specify it for programs that change the FP rounding mode dynamically, or that may be executed with a non-default rounding mode. It also disables constant folding of floating-point expressions at compile time (which may be affected by rounding mode), plus arithmetic transformations that are unsafe in the presence of sign-dependent rounding modes.
The default is -fno-rounding-math.
This option is experimental and does not currently guarantee to disable all GCC optimizations that are affected by rounding mode. Future versions of GCC may provide finer control of this setting using C99'sFENV_ACCESSpragma. This command-line option will be used to specify the default state forFENV_ACCESS.
-fsignaling-nansโ okay so this one tells GCC to compile your code assuming IEEE signaling NaNs can cause user-visible traps during floating-point operations ๐ญ. Turning it on disables optimizations that might change how many exceptions show up with signaling NaNs ๐ซ. It also implies-ftrapping-math, and it makes GCC define the preprocessor macro__SUPPORT_SNAN__โจ. The default is-fno-signaling-nans๐ธ.
This option is experimental ๐งช, and it does not currently guarantee to disable all GCC optimizations that affect signaling NaN behavior ๐.
-fno-fp-int-builtin-inexactโ bestie, this stops the built-inceil,floor,roundandtruncfunctions (plus theirfloatandlong doublevariants) from generating code that raises the "inexact" floating-point exception for noninteger arguments ๐ โโ๏ธ. ISO C99 and C11 let these functions raise that exception, but ISO/IEC TS 18661-1:2014, the C bindings to IEEE 754-2008 as integrated into ISO C2X, does not. The default is-ffp-int-builtin-inexact, which allows the exception to be raised, unless C2X or a later C standard is selected. This option does nothing unless-ftrapping-mathis in effect ๐ค. Even if you use-fno-fp-int-builtin-inexact, if the functions generate a call to a library function, the "inexact" exception may still be raised if that library doesn't follow TS 18661 ๐ซ .-fsingle-precision-constantโ treats floating-point constants as single precision, instead of quietly converting them to double-precision constants ๐.-fcx-limited-rangeโ when this is on, GCC assumes complex division doesn't need a range reduction step โ๏ธ. It also skips checking whether a complex multiplication or division result is "NaN + I*NaN" and trying to rescue it ๐. The default is-fno-cx-limited-range, but-ffast-mathturns it on ๐. This option controls the default setting of the ISO C99CX_LIMITED_RANGEpragma, but it applies to all languages anyway ๐.-fcx-fortran-rulesโ complex multiplication and division follow Fortran rules ๐ง. Range reduction gets done as part of complex division, but there's still no checking whether the result of a complex multiplication or division is "NaN + I*NaN", and no attempt to rescue it in that case ๐ซถ. The default is-fno-cx-fortran-rules๐.
Next up are the optimizations that can improve performance but aren't turned on by any -O options ๐. Heads up: this section also includes experimental options that might produce broken code โ ๏ธ๐, so proceed with main character caution ๐
.
-fbranch-probabilitiesโ after you run a program compiled with-fprofile-arcs, compile it a second time with-fbranch-probabilitiesto improve optimizations based on how many times each branch was taken ๐. When a program compiled with-fprofile-arcsexits, it saves arc execution counts to a file calledsourcename.gcdafor each source file ๐พ. The info in that data file is super dependent on the structure of the generated code, so you must use the same source code and the same optimization options for both compilations ๐. With-fbranch-probabilities, GCC puts aREG_BR_PROBnote on eachJUMP_INSNandCALL_INSN, and these can be used to improve optimization ๐. Right now they're only used in one place: inreorg.c. Instead of guessing which path a branch is most likely to take, theREG_BR_PROBvalues are used to exactly determine which path is taken more often ๐. Enabled by-fprofile-useand-fauto-profileโจ.-fprofile-valuesโ if you combine this with-fprofile-arcs, it adds code to gather data about the values of expressions in your program ๐งฎ. With-fbranch-probabilities, 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 executes, then orders those functions in ascending order ๐โโ๏ธ. Enabled with-fprofile-use๐ฆ.-fvptโ if you combine this with-fprofile-arcs, it tells the compiler to add code that gathers information about values of expressions ๐ต๏ธโโ๏ธ. With-fbranch-probabilities, it reads that data back and actually performs optimizations based on it. Right now those optimizations include specialization of division operations using knowledge about the value of the denominator โ. Enabled with-fprofile-useand-fauto-profile๐.-frename-registersโ tries to avoid false dependencies in scheduled code by using registers left over after register allocation ๐. This most benefits processors with lots of registers ๐ช. Depending on the debug information format the target uses, though, it can make debugging impossible, since variables no longer stay in a "home register" ๐ญ. Enabled by default with-funroll-loops๐ .-fschedule-fusionโ performs a target-dependent pass over the instruction stream to schedule instructions of the same type together ๐งฉ. The target machine can run them more efficiently if they're adjacent in the instruction flow โก. Enabled at levels-O2,-O3,-Os๐.-ftracerโ performs tail duplication to enlarge superblock size ๐ช. This transformation simplifies the control flow of the function, which lets other optimizations do a better job ๐. Enabled by-fprofile-useand-fauto-profile๐ซถ.-funroll-loopsโ unrolls loops whose number of iterations can be determined at compile time or upon entry to the loop ๐.-funroll-loopsimplies-frerun-cse-after-loop,-fweband-frename-registers. It also turns on complete loop peeling, which means completely removing loops with a small constant number of iterations ๐ฐ. This option makes code larger, and it may or may not make the code run faster ๐คทโโ๏ธ. Enabled by-fprofile-useand-fauto-profile๐ธ.-funroll-all-loopsโ unrolls all loops, even if their number of iterations is uncertain when the loop is entered ๐. This usually makes programs run more slowly ๐ข.-funroll-all-loopsimplies the same options as-funroll-loops๐ง.-fpeel-loopsโ peels loops for which there's enough information that they don't roll much, based on profile feedback or static analysis ๐. It also turns on complete loop peeling, which is complete removal of loops with a small constant number of iterations ๐งน. Enabled by-O3,-fprofile-use, and-fauto-profile๐.-fmove-loop-invariantsโ enables the loop invariant motion pass in the RTL loop optimizer ๐. Enabled at level-O1and higher, except for-Og๐ซง.-fsplit-loopsโ splits a loop into two if it contains a condition that's always true for one side of the iteration space and false for the other โ๏ธ. Enabled by-fprofile-useand-fauto-profile๐ฆ.-funswitch-loopsโ moves branches with loop-invariant conditions out of the loop ๐. There are duplicates of the loop on both branches, modified according to the result of the condition ๐ช. Enabled by-fprofile-useand-fauto-profile๐.-fversion-loops-for-stridesโ if a loop iterates over an array with a variable stride, GCC creates another version of the loop that assumes the stride is always one ๐โโ๏ธ. For example, this:
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
becomes this:
if (stride == 1)
for (int i = 0; i < n; ++i)
x[i] = ...;
else
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
This is particularly useful for assumed-shape arrays in Fortran, where (for example) it allows better vectorization by assuming contiguous accesses ๐ง . This flag is enabled by default at -O3 ๐. It is also enabled by -fprofile-use and -fauto-profile โจ.
-ffunction-sections,-fdata-sectionsโ places each function or data item into its own section in the output file, if the target supports arbitrary sections ๐ง. The name of the function or the name of the data item determines the section's name in the output file ๐ท๏ธ.- Use these on systems where the linker can perform optimizations to improve locality of reference in the instruction space ๐. Most systems using the ELF object format have linkers with such optimizations. On AIX, the linker rearranges sections (CSECTs) based on the call graph, and the performance impact varies ๐ข.
- Together with a linker garbage collection (
linker --gc-sectionsoption), these options may lead to smaller statically-linked executables (after stripping) ๐ชถ. - On ELF/DWARF systems, these options do not degenerate the quality of the debug information. There could be issues with other object files and debug info formats ๐.
- Only use these options when there are significant benefits from doing so ๐ง. When you specify them, the assembler and linker create larger object and executable files and are also slower ๐. These options affect code generation. They prevent optimizations by the compiler and assembler from using relative locations inside a translation unit, since those locations are unknown until link time ๐ฅบ. An example of such an optimization is relaxing calls to short call instructions ๐.
-fstdarg-optโ optimizes the prologue of variadic argument functions with respect to how those arguments are 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 reduce the number of symbolic address calculations by using shared "anchor" symbols to address nearby objects ๐ธ. This transformation can help reduce the number of GOT entries and GOT accesses on some targets ๐ฆ. For example, here's the implementation of the following function "foo" ๐:
static int a, b, c;
int foo (void) { return a + b + c; }
It usually calculates the addresses of all three variables. But if you compile it with -fsection-anchors, it accesses the variables from a common anchor point instead ๐ซถ. The effect is similar to the following 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, so check that your target actually supports it before you get your hopes up ๐
--param name=valueโ okay, this one is lowkey iconic ๐ . GCC uses a bunch of little internal constants to decide how much optimization to do. For example, it won't inline a function that has more than a certain number of instructions. You can tweak some of these constants from the command line with--param.
The names of specific parameters, and what their values mean, are tied to the compiler's internals. They can change without notice in future releases, so don't build your whole personality around them ๐ฅฒ
If you want the minimal, maximal and default value of a parameter, you can use the --help=param -Q options ๐
Every value is an integer โจ These names are recognized for all targets:
predictable-branch-outcomeโ when a branch is predicted to be taken with a probability lower than this threshold (in percent), it's considered well predictable ๐ฎmax-rtl-if-conversion-insnsโ RTL if-conversion tries to remove conditional branches around a block and swap them for conditionally executed instructions. This is 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โ same if-conversion vibe, but these set the maximum permissible cost for the sequence that if-conversion would generate. It depends on whether the branch is statically determined to be predictable or not. The units match the GCC internalseq_costmetric, and the compiler will try to pick a reasonable default for this using theBRANCH_COSTtarget macro ๐ฐmax-crossjump-edgesโ the maximum number of incoming edges to consider for cross-jumping. The algorithm used by-fcrossjumpingisO(N^2)in the number of edges incoming to each block. Higher values mean more aggressive optimization, so compile time goes up for a probably small improvement in executable size ๐ขmin-crossjump-insnsโ the minimum number of instructions that must match at the end of two blocks before cross-jumping happens on them. This value is ignored when all instructions in the block being cross-jumped from are matched ๐คทโโ๏ธmax-grow-copy-bb-insnsโ the maximum code size expansion factor when copying basic blocks instead of jumping. The expansion is relative to a jump instruction ๐max-goto-duplication-insnsโ the maximum number of instructions to duplicate into a block that jumps to a computed goto. To avoidO(N^2)behavior in a number of passes, GCC factors computed gotos early in compilation and unfactors them as late as possible. Only computed jumps at the end of a basic block with no more thanmax-goto-duplication-insnsget unfactored ๐max-delay-slot-insn-searchโ the maximum number of instructions to consider when looking for an instruction to fill a delay slot. If more than this arbitrary number gets searched, the time savings from filling the delay slot are minimal, so GCC stops searching. Higher values mean more aggressive optimization, with compile time going up for a probably small improvement in execution time ๐ฐ๏ธmax-delay-slot-live-searchโ when trying to fill delay slots, the maximum number of instructions to consider when searching for a block with valid live register information. Raising this arbitrarily chosen value means more aggressive optimization and longer compile time. This parameter should be removed once the delay slot code is rewritten to maintain the control-flow graph ๐๏ธmax-gcse-memoryโ the approximate maximum amount of memory that can be allocated for global common subexpression elimination. If more memory than specified is required, the optimization just doesn't happen ๐งmax-gcse-insertion-ratioโ if the ratio of expression insertions to deletions is larger than this value for any expression, RTL PRE inserts or removes the expression. That leaves partially redundant computations in the instruction stream ๐ซmax-pending-list-lengthโ the maximum number of pending dependencies scheduling allows before it flushes the current state and starts over. Large functions with few branches or calls can build up excessively large lists that needlessly eat memory and resources ๐ฐmax-modulo-backtrack-attemptsโ the maximum number of backtrack attempts the scheduler should make when modulo scheduling a loop. Larger values can exponentially increase compilation time ๐max-inline-insns-singleโ several parameters control the tree inliner. This one sets the maximum number of instructions (counted in GCC's internal representation) in a single function that the tree inliner considers for inlining. It only affects functions declared inline and methods implemented in a class declaration (C++) ๐max-inline-insns-autoโ when you use-finline-functions(included in-O3), a lot of functions that otherwise wouldn't be considered for inlining get investigated. For those, a different and more restrictive limit than the one for functions declared inline can be applied (--param max-inline-insns-auto) ๐max-inline-insns-smallโ the bound applied to calls that are considered relevant with-finline-small-functions๐ฑmax-inline-insns-sizeโ the bound applied to calls that are optimized for size. A small growth may be desirable to anticipate optimization opportunities exposed by inlining โ๏ธuninlined-function-insnsโ the number of instructions the inliner counts for function overhead, such as the function prologue and epilogue ๐งพuninlined-function-timeโ the extra time the inliner counts for function overhead, such as the time needed to execute the function prologue and epilogue โฑ๏ธinline-heuristics-hint-percentโ the scale (in percent) applied toinline-insns-single,inline-insns-single-O2andinline-insns-autowhen inline heuristics hint that inlining is very profitable (it will enable later optimizations) ๐uninlined-thunk-insns,uninlined-thunk-timeโ the same as--param uninlined-function-insnsand--param uninlined-function-time, but applied to function thunks ๐งตinline-min-speedupโ when the estimated performance improvement of caller + callee runtime exceeds this threshold (in percent), the function can be inlined regardless of the limit set by--param max-inline-insns-singleand--param max-inline-insns-auto๐large-function-insnsโ the limit that defines really large functions. For functions larger than this after inlining, inlining is constrained by--param large-function-growth. This parameter is mainly useful for avoiding extreme compile times caused by the non-linear algorithms the back end uses ๐large-function-growthโ the maximal growth of a large function caused by inlining, in percent. For example, the value 100 limits large function growth to 2.0 times the original size ๐large-unit-insnsโ the limit that defines a large translation unit. Growth caused by inlining units larger than this is limited by--param inline-unit-growth. For small units that might be too tight. Consider a unit made of function A (which is inline) and B, which just calls A three times. If B is small relative to A, the growth of the unit is 300% and yet that inlining is totally sane. For very large units full of small inlineable functions, though, the overall unit growth limit is needed to prevent an exponential explosion of code size. So for smaller units, the size is increased to--param large-unit-insnsbefore--param inline-unit-growthgets applied ๐งฉinline-unit-growthโ the maximal overall growth of the compilation unit caused by inlining. For example, the value 20 limits unit growth to 1.2 times the original size. Cold functions (either marked cold via an attribute or by profile feedback) aren't counted in the unit size ๐ฅถipa-cp-unit-growthโ the maximal overall growth of the compilation unit caused by interprocedural constant propagation. For example, the value 10 limits 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 maximal growth of large stack frames caused by inlining, in percent. For example, the value 1000 limits large stack frame growth to 11 times the original size ๐ฆmax-inline-insns-recursive,max-inline-insns-recursive-autoโ the maximum number of instructions an out-of-line copy of a self-recursive inline function can grow into by performing recursive inlining.--param max-inline-insns-recursiveapplies to functions declared inline. For functions not declared inline, recursive inlining only happens when-finline-functions(included in-O3) is enabled, and--param max-inline-insns-recursive-autoapplies instead ๐max-inline-recursive-depth,max-inline-recursive-depth-autoโ the maximum recursion depth used for recursive inlining ๐ช
--param max-inline-recursive-depth is the one for functions declared inline ๐. For functions that aren't declared inline, recursive inlining only happens when -finline-functions is enabled (it's already included in -O3 โจ), and then --param max-inline-recursive-depth-auto is the one that applies ๐ฆ.
Here are the rest of the --param knobs, bestie ๐
min-inline-recursive-probabilityโ recursive inlining is only worth it for functions that recurse deeply on average ๐. For functions with shallow recursion it can backfire by making the prologue bigger or the function body more complicated for other optimizers ๐ญ. With profile feedback (see-fprofile-generate), the real recursion depth can be guessed from how likely a function is to recurse through a given call expression ๐ฎ. This param only lets inlining touch call expressions whose probability goes over the threshold, measured in percents ๐.early-inlining-insnsโ how much growth the early inliner is allowed to make ๐. Basically it boosts the amount of inlining for code with a large abstraction penalty ๐ง.max-early-inliner-iterationsโ caps how many iterations the early inliner runs ๐. This bounds how many nested indirect calls it can resolve, and deeper chains get handled by late inlining instead ๐ซถ.comdat-sharing-probabilityโ the probability, in percent, that C++ inline functions with comdat visibility get shared across multiple compilation units ๐ธ.profile-func-internal-idโ controls whether the function's internal id gets used in profile database lookups ๐ชช. When the value is0, the compiler uses an id based on the function's assembler name and filename, which keeps old profile data more forgiving when source changes happen, like function reordering ๐ฆ.min-vect-loop-boundโ the minimum number of iterations below which loops won't get vectorized when-ftree-vectorizeis used ๐. The number of iterations after vectorization has to be greater than this value for vectorization to happen โจ.gcse-cost-distance-ratioโ a scaling factor for figuring out the maximum distance an expression can be moved by GCSE optimizations ๐. It's only supported in the code hoisting pass right now ๐งน. The bigger the ratio, the more aggressively simple expressions get hoisted, meaning expressions that cost less thangcse-unrestricted-cost๐ฅ. Setting it to0disables hoisting of simple expressions ๐.gcse-unrestricted-costโ the cost, roughly measured as a single typical machine instruction, at which GCSE optimizations stop constraining how far an expression can travel ๐โโ๏ธ. Also only supported in the code hoisting pass ๐ . The lower the cost, the more aggressive the hoisting is, and0lets every expression travel unrestricted distances ๐.max-hoist-depthโ how deep the search goes in the dominator tree for expressions to hoist ๐ณ. This keeps the hoisting algorithm from going quadratic ๐ค. A value of0means there's no limit on the search, but compiling huge functions might get slower ๐ข.max-tail-merge-comparisonsโ the maximum number of similar bbs a bb gets compared against ๐ง. This stops tree tail merging from going quadratic ๐.max-tail-merge-iterationsโ the maximum number of passes over a function โฑ๏ธ. It limits compilation time in tree tail merging ๐.store-merging-allow-unalignedโ lets the store merging pass introduce unaligned stores, but only if that's legal ๐งฑ.max-stores-to-mergeโ the maximum number of stores the store merging pass will try to fold into wider stores ๐ง.max-unrolled-insnsโ the maximum number of instructions a loop can have and still get unrolled ๐. If the loop does get unrolled, this same number also decides how many times the loop body gets unrolled ๐.max-average-unrolled-insnsโ like the one above, but counts instructions biased by how probable their execution is ๐. If a loop gets unrolled, this value also sets how many times the loop code is unrolled ๐ซง.max-unroll-timesโ the maximum number of unrollings for a single loop ๐.max-peeled-insnsโ the maximum number of instructions a loop can have and still get peeled ๐. If it's peeled, this also decides how many times the loop code gets peeled ๐ง .max-peel-timesโ the maximum number of peelings for a single loop ๐.max-peel-branchesโ the maximum number of branches on the hot path through the peeled sequence ๐ค๏ธ.max-completely-peeled-insnsโ the maximum number of insns a completely peeled loop can have ๐ญ.max-completely-peel-timesโ the maximum number of loop iterations for a loop to qualify for complete peeling ๐ฏ.max-completely-peel-loop-nest-depthโ the maximum depth of a loop nest that's suitable for complete peeling ๐ช.max-unswitch-insnsโ the maximum number of insns an unswitched loop can have ๐.max-unswitch-levelโ the maximum number of branches unswitched in a single loop ๐๏ธ.lim-expensiveโ the minimum cost for an expression to count as expensive in loop invariant motion ๐ธ.min-loop-cond-split-probโ when FDO profile information is available, this sets the minimum probability a semi-invariant condition statement needs before it triggers a loop split โ๏ธ.iv-consider-all-candidates-boundโ the bound on the number of candidates for induction variables. Below this number, every candidate gets considered for each use in induction variable optimizations ๐. Above it, only the most relevant ones get considered, so the time complexity doesn't go quadratic ๐ซ .iv-max-considered-usesโ induction variable optimizations give up on loops that contain more induction variable uses than this ๐ โโ๏ธ.iv-always-prune-cand-set-boundโ if the candidate set is smaller than this value, the compiler always tries to remove unnecessary ivs from the set whenever it adds a new one ๐งน.avg-loop-niterโ the average number of iterations of a loop ๐ข.dse-max-object-sizeโ the maximum size, in bytes, of objects tracked bytewise by dead store elimination ๐ฆ. Bigger values can mean longer compilation times ๐.dse-max-alias-queries-per-storeโ the maximum number of queries into the alias oracle per store ๐ฎ. Bigger values mean longer compilation times, but they might remove more dead stores ๐๏ธ.scev-max-expr-sizeโ the bound on how big expressions can be in the scalar evolutions analyzer ๐. Large expressions slow the analyzer down ๐ฉ.scev-max-expr-complexityโ the bound on how complex expressions can be in the scalar evolutions analyzer ๐งฉ. Complex expressions slow it down too ๐.max-tree-if-conversion-phi-argsโ the maximum number of arguments in a PHI supported by tree if conversion, unless the loop is marked with simd pragma ๐ท๏ธ.vect-max-version-for-alignment-checksโ the maximum number of run-time checks the vectorizer can perform when it does loop versioning for alignment ๐งญ.vect-max-version-for-alias-checksโ the maximum number of run-time checks the vectorizer can perform when it does loop versioning for alias ๐ฏ.vect-max-peeling-for-alignmentโ the maximum number of loop peels the vectorizer can use to improve access alignment ๐ก. A value of-1means no limit โพ๏ธ.max-iterations-to-trackโ the maximum number of loop iterations the brute-force algorithm for counting loop iterations will try to evaluate ๐ต๏ธโโ๏ธ.hot-bb-count-fractionโ the denominator n of the fraction 1/n of the maximal execution count of a basic block in the entire program. A basic block needs at least this to count as hot ๐ฅ. The default is10000, so a basic block is hot if its execution count is greater than 1/10000 of the maximal execution count ๐ฏ.0means it's never considered hot. This is used in non-LTO mode ๐ซถ.hot-bb-count-ws-permilleโ the number of most-executed permilles, from0to1000, of the profiled execution of the entire program that a basic block's execution count has to be part of to be considered hot ๐ก๏ธ. The default is990, so a basic block is hot if its count contributes to the upper 990 permilles, or 99.0%, of the profiled execution ๐ง.0means it's never considered hot. This is used in LTO mode ๐.hot-bb-frequency-fractionโ the denominator n of the fraction 1/n of the execution frequency of a function's entry block that a basic block in that function needs to have to be considered hot ๐. The default is1000, so a basic block is hot in a function if it runs more often than 1/1000 of the entry block's frequency ๐ง.0means it's never considered hot ๐ซ.unlikely-bb-count-fractionโ the denominator n of the fraction 1/n of the number of profiled runs of the entire program. If a basic block's execution count falls below that, the block is considered unlikely to execute ๐ฅถ. The default is20, so a block is unlikely if it runs in fewer than 1/20, or 5%, of the program's runs ๐.0means it's always considered unlikely to execute ๐.max-predicted-iterationsโ the maximum number of loop iterations the compiler predicts statically ๐ฎ. This helps when a function has one loop with a known bound and another with an unknown bound ๐คทโโ๏ธ. The known count gets predicted correctly, but the unknown count averages to roughly10, so the unbounded loop looks artificially cold next to the other one ๐ฅถโจ.builtin-expect-probabilityโ ๐ Sets how likely the expression is to have the specified value. It takes a percentage (so0...100) as input.builtin-string-cmp-inline-lengthโ โจ The biggest a constant string can be in a builtin string cmp call and still be eligible for inlining, bestie.align-thresholdโ ๐ Picks a fraction of the maximal frequency of executions of a basic block in a function, which decides whether that basic block gets aligned.align-loop-iterationsโ ๐ฆ A loop that's expected to iterate at least the selected number of iterations gets aligned. Main character loops, honestly.tracer-dynamic-coverage,tracer-dynamic-coverage-feedbackโ ๐ธ This value caps superblock formation once the given percentage of executed instructions is covered, so the code doesn't balloon for no reason. Thetracer-dynamic-coverage-feedbackone is only used when profile feedback is available. Real profiles aren't as balanced as statically estimated ones, so the threshold can be a larger value.tracer-max-code-growthโ ๐ง Stops tail duplication once code growth has reached the given percentage. Ngl this is a pretty artificial limit, since most of the duplicates get eliminated 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 is less than this threshold, measured in percent.tracer-min-branch-probability,tracer-min-branch-probability-feedbackโ ๐ Stops forward growth if the best edge has a probability lower than this threshold. Same deal as tracer-dynamic-coverage: there are two of them.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โ ๐ก๏ธ Specifies the size of the operating system provided stack guard as 2 raised to num bytes. Higher values may reduce the number of explicit probes, but a value larger than the operating system provided guard will leave code vulnerable to stack clash style attacks. ๐stack-clash-protection-probe-intervalโ ๐ฅ Stack clash protection involves probing stack space as it gets allocated. This param controls the maximum distance between probes into the stack as 2 raised to num bytes. Higher values may reduce the number of explicit probes, but a value larger than the operating system provided guard will leave code vulnerable to stack clash style attacks.max-cse-path-lengthโ ๐ The maximum number of basic blocks on a path that CSE considers.max-cse-insnsโ ๐ The maximum number of instructions CSE processes before flushing.ggc-min-expandโ ๐ง GCC uses a garbage collector to manage its own memory allocation. This parameter sets the minimum percentage by which the garbage collector's heap is allowed to expand between collections. Tuning it may improve compilation speed, but it has no effect on code generation.
The default is 30% + 70% * (RAM/1GB) with an upper bound of 100% when RAM >= 1GB. If getrlimit is available, the notion of "RAM" is the smallest of actual RAM and RLIMIT_DATA or RLIMIT_AS. If GCC can't calculate RAM on a particular platform, the lower bound of 30% is used. Setting this parameter and ggc-min-heapsize to zero causes a full collection to occur at every opportunity.
This is extremely slow, but it can be useful for debugging. ๐ญ
ggc-min-heapsizeโ ๐ซง The minimum size of the garbage collector's heap before it starts bothering to collect garbage. The first collection happens after the heap expands byggc-min-expand% beyondggc-min-heapsize. Again, tuning this may improve compilation speed, and it has no effect on code generation.
The default is the smaller of RAM/8, RLIMIT_RSS, or a limit that tries to ensure RLIMIT_DATA or RLIMIT_AS aren't exceeded, but with a lower bound of 4096 (four megabytes) and an upper bound of 131072 (128 megabytes). If GCC can't calculate RAM on a particular platform, the lower bound is used. Setting this parameter very large effectively disables garbage collection. Setting this parameter and ggc-min-expand to zero causes a full collection to occur at every opportunity.
max-reload-search-insnsโ ๐ The maximum number of instructions reload should look backward through to find an equivalent register. Increasing this means more aggressive optimization, making compilation time go up with probably slightly better performance.max-cselib-memory-locationsโ ๐ง The maximum number of memory locations cselib should take into account. Increasing this means more aggressive optimization, making compilation time go up with probably slightly better performance.max-sched-ready-insnsโ ๐ The maximum number of instructions ready to be issued that the scheduler should consider at any given time during the first scheduling pass. Increasing this means more thorough searches, making compilation time go up with probably little benefit.max-sched-region-blocksโ ๐งฉ The maximum number of blocks in a region to be considered for interblock scheduling.max-pipeline-region-blocksโ ๐ฅ The maximum number of blocks in a region to be considered for pipelining in the selective scheduler.max-sched-region-insnsโ ๐ท The maximum number of insns in a region to be considered for interblock scheduling.max-pipeline-region-insnsโ ๐ญ The maximum number of insns in a region to 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 maximum number of iterations through the CFG to extend regions. A value of0disables region extensions.max-sched-insn-conflict-delayโ โณ The maximum conflict delay for an insn to be considered for speculative motion.sched-spec-prob-cutoffโ โ๏ธ The minimal probability of speculation success (in percents) so that speculative insns get scheduled.sched-state-edge-prob-cutoffโ ๐ช The minimum probability an edge must have for the scheduler to save its state across it.sched-mem-true-dep-costโ โฑ๏ธ The minimal distance (in CPU cycles) between a store and a load targeting the same memory locations.selsched-max-lookaheadโ ๐ The maximum size of the lookahead window of selective scheduling. It's a depth of search for available instructions.selsched-max-sched-timesโ ๐ The maximum number of times an instruction is scheduled during selective scheduling. This is the limit on the number of iterations through which the instruction may be pipelined.selsched-insns-to-renameโ โ๏ธ The maximum number of best instructions in the ready list that are considered for renaming in the selective scheduler.sms-min-scโ ๐งฎ The minimum value of stage count that the swing modulo scheduler generates.max-last-value-rtlโ ๐ The maximum size, measured as the number of RTLs, that can be recorded in an expression in the combiner for a pseudo register as the last known value of that register.max-combine-insnsโ ๐ง The maximum number of instructions the RTL combiner tries to combine.integer-share-limitโ ๐ค Small integer constants can use a shared data structure, which reduces the compiler's memory usage and increases its speed. This sets the maximum value of a shared integer constant.ssp-buffer-sizeโ ๐๏ธ The minimum size of buffers (i.e. arrays) that receive stack smashing protection when-fstack-protectionis used.
The default before Ubuntu 10.10 was "8". Currently it is "4", to increase the number of functions protected by the stack protector. ๐
min-size-for-stack-sharingโ ๐ฆ The minimum size of variables taking part in stack slot sharing when not optimizing.max-jump-thread-duplication-stmtsโ ๐งต The maximum number of statements allowed in a block that needs to be duplicated when threading jumps.max-fields-for-field-sensitiveโ ๐๏ธ The maximum number of fields in a structure treated in a field-sensitive manner during pointer analysis.prefetch-latencyโ ๐ An estimate of the average number of instructions executed before a prefetch finishes. The distance prefetched ahead is proportional to this constant. Increasing this number may also lead to fewer streams being prefetched (seesimultaneous-prefetches).simultaneous-prefetchesโ ๐ฆ The maximum 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 are non-constant. In some cases this may be beneficial, though the fact that the stride is non-constant may make it hard to predict when there's a clear benefit to issuing these hints.
Set to 1 if the prefetch hints should be issued for non-constant strides. Set to 0 if prefetch hints should be issued only for strides that are known to be constant and below prefetch-minimum-stride.
prefetch-minimum-strideโ ๐ The minimum constant stride, in bytes, to start using prefetch hints for. If the stride is less than this threshold, prefetch hints won't be issued.
This one is giving hardware prefetcher drama ๐ฅ Some processors have their own hardware prefetchers, and those can clash with the software prefetchers ๐ If the hardware prefetchers have a maximum stride they can handle, that number belongs here so the software prefetchers can actually be useful โจ
A value of -1 means there's no threshold, so prefetch hints can be issued for any constant stride ๐ฆ
This setting only matters for strides that are known and constant ๐
loop-interchange-max-num-stmtsโ the max number of stmts a loop can have and still get 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 of instructions to prefetches needed before prefetching gets switched on in a loop ๐ธprefetch-min-insn-to-mem-ratioโ same energy, but for memory references: the minimum ratio of instructions to memory references needed to enable prefetching in a loop ๐งuse-canonical-typesโ whether the compiler uses the "canonical" type system. It should always be1, because that's the more efficient internal way to compare 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 optimizing at-O3and above. Some source code can make this optimization run away and eat all the memory on the host machine ๐ญ This param caps the set lengths so that doesn't happen. Setting it to0allows an unlimited set length ๐ซถrpo-vn-max-loop-depthโ the max loop depth that gets value-numbered optimistically. When the limit hits, the innermostrpo-vn-max-loop-depthloops and the outermost loop in the loop nest are value-numbered optimistically, and the remaining ones are not ๐sccvn-max-alias-queries-per-accessโ the max number of alias-oracle queries performed when hunting for redundancies in loads and stores. If this limit is hit, the search is aborted and the load or store is not considered redundant. The number of queries is algorithmically limited to the number of stores on all paths from the load to the function entry ๐ira-max-loops-numโ IRA uses regional register allocation by default. If a function has more loops than this number, only at most this many of the most frequently executed loops form regions for regional register allocation ๐ira-max-conflict-table-sizeโ IRA has a super smart way to compress the conflict table, but huge functions can still need excessive memory. If a function's conflict table could be bigger than this many MB, the register allocator switches to a faster, simpler, lower-quality algorithm that doesn't build a pseudo-register conflict table ๐ขira-loop-reserved-regsโ IRA can evaluate more accurate register pressure in loops when deciding whether to move loop invariants (see-O3). This is the number of available registers reserved for other purposes. The default is the best value found from numerous experiments ๐งชlra-inheritance-ebb-probability-cutoffโ LRA tries to reuse values reloaded into registers in subsequent insns. That's called inheritance, and EBB is the region used for it. This parameter is the minimal fall-through edge probability, in percentage, used to add a BB to the inheritance EBB in LRA. The default was chosen from numerous runs of SPEC2000 on x86-64 ๐loop-invariant-max-bbs-in-loopโ loop invariant motion can be very expensive in both compilation time and compile-time memory for very large loops. Loops with more basic blocks than this parameter won't have loop invariant motion performed on them ๐ซloop-max-datarefs-for-datadepsโ building data dependencies is expensive for very large loops. This limits the number of data references in loops considered for data dependence analysis. These large loops are not handled by optimizations that use loop data dependencies ๐max-vartrack-sizeโ the max number of hash table slots to use during variable tracking dataflow analysis of any function. If this limit is exceeded with variable tracking at assignments enabled, analysis for that function is retried without it, after removing all debug insns from the function. If the limit is still exceeded without debug insns, var tracking analysis is completely disabled for the function. Setting this to zero makes it unlimited โพ๏ธmax-vartrack-expr-depthโ the max number of recursion levels when mapping variable names or debug temporaries to value expressions. This trades compilation time for more complete debug information. If it's set too low, value expressions that are available and could be represented in debug information may not get used. Setting it higher may let the compiler find more complex debug expressions, but compile time and memory use may grow ๐max-debug-marker-countโ a threshold on the number of debug markers (e.g. begin stmt markers) to avoid complexity explosion at inlining or expanding to RTL. If a function has more such 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 parameter are used for nondebug insns. The range below it is reserved exclusively for debug insns created by-fvar-tracking-assignments, but debug insns may get (non-overlapping) uids above it if the reserved range is exhausted ๐ipa-sra-ptr-growth-factorโ IPA-SRA only replaces a pointer to an aggregate with one or more new parameters when their cumulative size is less than or equal toipa-sra-ptr-growth-factortimes the size of the original pointer parameter ๐ipa-sra-max-replacementsโ the max number of pieces of an aggregate that IPA-SRA tracks. As a consequence, it's also the max number of replacements of a formal parameter ๐งฉsra-max-scalarization-size-Ospeed,sra-max-scalarization-size-Osizeโ the two Scalar Reduction of Aggregates passes (SRA and IPA-SRA) aim to replace scalar parts of aggregates with uses of independent scalar variables. These control the max size, in storage units, of an aggregate considered for replacement when compiling for speed (sra-max-scalarization-size-Ospeed) or for size (sra-max-scalarization-size-Osize), respectively ๐๏ธ๐ฆsra-max-propagationsโ the max number of artificial accesses that Scalar Replacement of Aggregates (SRA) will track per local variable, so it can facilitate copy propagation ๐tm-max-aggregate-sizeโ when making copies of thread-local variables in a transaction, this is the size in bytes after which variables are saved with the logging functions instead of save/restore code sequence pairs. This option only applies when using-fgnu-tm๐งตgraphite-max-nb-scop-paramsโ to avoid exponential effects in the Graphite loop transforms, the number of parameters in a Static Control Part (SCoP) is bounded. A value of0lifts the bound. A variable whose value is unknown at compile time and defined outside a SCoP counts as a parameter of the SCoP ๐loop-block-tile-sizeโ loop blocking or strip mining transforms, enabled with-floop-blockor-floop-strip-mine, strip mine each loop in the loop nest by a given number of iterations. The strip length can be changed using this parameter ๐งฑipa-cp-value-list-sizeโ IPA-CP tries to track all possible values and types passed to a function's parameter so it can propagate them and perform devirtualization. This is the max number of values and types it stores per formal parameter of a function ๐ipa-cp-eval-thresholdโ IPA-CP calculates its own score for its cloning profitability heuristics and performs the cloning opportunities whose scores exceedipa-cp-eval-threshold๐ฏipa-cp-max-recursive-depthโ the max depth of recursive cloning for a self-recursive function ๐ipa-cp-min-recursive-probabilityโ recursive cloning only happens when the probability of the call being executed exceeds this parameter ๐ฒipa-cp-recursion-penaltyโ the percentage penalty recursive functions receive when they're evaluated for cloning ๐ipa-cp-single-call-penaltyโ the percentage penalty functions containing a single call to another function receive when they're evaluated for cloning ๐ipa-max-agg-itemsโ IPA-CP can also propagate a number of scalar values passed in an aggregate. This controls the max number of such values per parameter ๐ipa-cp-loop-hint-bonusโ okay so when IPA-CP realizes a cloning candidate would make a loop's number of iterations known, it gives that candidate a bonus ofipa-cp-loop-hint-bonuson top of its profitability score ๐โจipa-max-aa-stepsโ IPA-CP uses alias analysis to track the values that function parameters point to ๐. But it won't burn all its time on huge functions, so after checkingipa-max-aa-stepsstatements that modify memory, it gives up and treats all memory as clobbered ๐ipa-max-switch-predicate-boundsโ the max number of boundary endpoints in a switch statement's case ranges ๐. If a switch goes over this limit, IPA-CP won't build the cloning cost predicate (the thing it uses to estimate cloning benefit) for that switch's default case ๐ipa-max-param-expr-opsโ IPA-CP checks conditionals that reference a function parameter to see if cloning for a certain constant value is worth it ๐ง . But if a parameter expression has more operations thanipa-max-param-expr-ops, it's considered too complicated and IPA analysis just skips it ๐ซlto-partitionsโ the desired number of partitions during WHOPR compilation ๐งฉ. It should be more than the number of CPUs being used for compilation ๐ปlto-min-partitionโ the minimum partition size for WHOPR, measured in estimated instructions ๐ธ. This keeps tiny programs from getting chopped into way too many partitions ๐ โโ๏ธlto-max-partitionโ the max partition size for WHOPR, also in estimated instructions ๐ฆ. It sets an upper bound on how big any single partition can get, and it's only meant for use with balanced partitioning โ๏ธlto-max-streaming-parallelismโ the max number of parallel processes used for LTO streaming ๐cxx-max-namespaces-for-diagnostic-helpโ when C++ name lookup fails for an identifier, this is how many namespaces GCC will check for suggestions ๐sink-frequency-thresholdโ the max relative execution frequency (in percent) of the target block compared to a statement's original block, which decides whether that statement can get sunk ๐. Bigger numbers mean more aggressive sinking ๐ฅ. A small positive adjustment is applied to statements with memory operands, since sinking those is even more profitable ๐max-stores-to-sinkโ the max number of conditional store pairs that can be sunk ๐ชฃ. Set to 0 if either vectorization (-ftree-vectorize) or if-conversion (-ftree-loop-if-convert) is disabled ๐case-values-thresholdโ the smallest number of different values where a jump table is better than a tree of conditional branches ๐ณ. If it's 0, the machine's default is used ๐ชjump-table-max-growth-ratio-for-sizeโ the max code size growth ratio (in percent) when expanding into a jump table ๐. This one is used when optimizing for size ๐คjump-table-max-growth-ratio-for-speedโ the same max code size growth ratio (in percent) when expanding into a jump table โก. This one is used when optimizing for speed ๐๏ธtree-reassoc-widthโ sets the max number of instructions executed in parallel in a reassociated tree ๐. If it has a non-zero value, it overrides the target-dependent heuristics that would be used by default โจsched-pressure-algorithmโ lets you pick between the two implementations of-fsched-pressure๐ญ. Algorithm 1 is the original and is more likely to stop instructions from getting reordered ๐ง. Algorithm 2 was designed as a compromise between the pretty conservative algorithm 1 and the rather aggressive default scheduler ๐ค. It leans more heavily on having a regular register file and accurate register pressure classes ๐. Seehaifa-sched.cin the GCC sources for more details ๐งพ
The default choice depends on the target ๐ฏ
max-slsr-cand-scanโ the max number of existing candidates 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 objects protection, use--param asan-globals=0๐ โโ๏ธasan-stackโ turns on buffer overflow detection for stack objects ๐ฅ. It's on by default when using-fsanitize=address๐. To turn off stack protection, use--param asan-stack=0option ๐asan-instrument-readsโ turns on buffer overflow detection for memory reads ๐. It's on by default when using-fsanitize=address๐. To turn off memory reads protection, use--param asan-instrument-reads=0๐ซasan-instrument-writesโ turns on buffer overflow detection for memory writes โ๏ธ. It's on by default when using-fsanitize=address๐. To turn off memory writes protection, use--param asan-instrument-writes=0option ๐ โโ๏ธasan-memintrinโ turns on detection for built-in functions ๐ ๏ธ. It's on by default when using-fsanitize=address๐. To turn off built-in functions protection, use--param asan-memintrin=0๐ซasan-use-after-returnโ turns on detection of use-after-return ๐. It's on by default when using the-fsanitize=addressoption ๐. To turn it off, use--param asan-use-after-return=0๐ โโ๏ธ
Note: by default this check is disabled at run time ๐ญ. To enable it, add"detect_stack_use_after_return=1"to the environment variableASAN_OPTIONS๐
asan-instrumentation-with-call-thresholdโ if the function being instrumented has a number of memory accesses that's greater than or equal to this number, GCC uses callbacks instead of inline checks ๐. For example, to disable inline code, use--param asan-instrumentation-with-call-threshold=0๐use-after-scope-direct-emission-thresholdโ if a local variable's size in bytes is smaller than or equal to this number, shadow memory is poisoned (or unpoisoned) directly ๐ช. That means no run-time callbacks are used ๐max-fsm-thread-path-insnsโ the max number of instructions copied 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 created 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 ๐ . The options arestatic,dynamic,guided,auto, andruntime๐parloops-min-per-threadโ the minimum number of iterations per thread of an innermost parallelized loop where the parallel version is preferred over the single-threaded one ๐งต. 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 analyzed while hunting for a must-def that shows the dynamic type of an object making a virtual call we might speculatively devirtualize ๐ต๏ธโโ๏ธmax-vrp-switch-assertionsโ the max number of assertions added along the default edge of a switch statement during VRP ๐งชunroll-jam-min-percentโ the minimum percentage of memory references that have to 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 cost you'll accept for the sequence the RTL if-conversion pass generates 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 variable gets expanded during loop unrolling ๐ทtracer-min-branch-probability-feedbackโ stop forward growth if the best edge's probability is below this threshold (in percent) ๐. It's used when profile feedback is available ๐partial-inlining-entry-probabilityโ the max probability (in percent, relative to the function's entry BB) of the entry BB of a split region 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 that the copy loop headers pass is allowed to duplicate ๐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 can be considered for SLP vectorization ๐งavoid-fma-max-bitsโ the max number of bits for which GCC avoids creating FMAs ๐ โโ๏ธ๐sms-loop-average-count-thresholdโ a threshold on the average loop count that the swing modulo scheduler takes into account ๐sms-dfa-historyโ how many cycles the swing modulo scheduler looks at when it checks for conflicts using DFA ๐งmax-inline-insns-recursive-autoโ the max number of instructions a non-inline function can grow to through recursive inlining ๐ฑgraphite-allow-codegen-errorsโ whether codegen errors should count as ICEs when-fcheckingis on ๐sms-max-ii-factorโ a tuning factor for the upper bound the swing modulo scheduler uses when it schedules a loop โญlra-max-considered-reload-pseudosโ the max number of reload pseudos that get considered while spilling a non-reload pseudo ๐งmax-pow-sqrt-depthโ the max depth of sqrt chains used when synthesizing exponentiation by a real constant ๐ฅmax-dse-active-local-storesโ the max number of active local stores in RTL dead store elimination ๐asan-instrument-allocasโ turns on asan allocas/VLAs protection ๐ก๏ธmax-iterations-computation-costโ a bound on how expensive an expression can be when computing 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 ๐ฆtracer-dynamic-coverage-feedbackโ the percentage of a function, weighted by execution frequency, that trace formation must cover. This is only used when profile feedback is available ๐max-inline-recursive-depth-autoโ the max depth of recursive inlining for non-inline functions ๐fsm-scale-path-stmtsโ a scale factor applied to the number of statements in a threading path when it gets compared to the number of (scaled) blocks โ๏ธfsm-maximum-phi-argumentsโ the max number of arguments a PHI can have before the FSM threader gives up on threading through its block ๐ซuninit-control-dep-attemptsโ the max number of nested calls used to search for control dependencies during uninitialized variable analysis ๐sra-max-scalarization-size-Osizeโ the max size, in storage units, of an aggregate that should be considered for scalarization when compiling for size ๐ฆfsm-scale-path-blocksโ a scale factor applied to the number of blocks in a threading path when it gets compared to the number of (scaled) statements โ๏ธsched-autopref-queue-depthโ a control flag for the hardware autoprefetcher scheduler model. It sets how many lookahead cycles the model peeks into, and at' 'only the instruction sorting heuristic is turned on ๐loop-versioning-max-inner-insnsโ the max number of instructions an inner loop can have before the loop versioning pass decides it's too big to copy ๐ซถloop-versioning-max-outer-insnsโ the max number of instructions an outer loop can have before the loop versioning pass decides it's too big to copy. Any instructions in inner loops that directly benefit from versioning don't count toward this ๐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 ๐ชstore-merging-max-sizeโ the max size of a single store merging region, in bytes ๐พhash-table-verification-limitโ the number of elements that get hash table verification for each element searched ๐ทmax-find-base-term-valuesโ the max number ofVALUEs handled during a singlefind_base_termcall ๐analyzer-max-enodes-per-program-pointโ the max number of exploded nodes per program point in the analyzer. Once that's hit, analysis of that point wraps up โจanalyzer-min-snodes-for-call-summaryโ the min number of supernodes a function needs before the analyzer will bother summarizing its effects at call sites ๐analyzer-max-recursion-depthโ the max number of times a callsite can show up in a call stack within the analyzer. Once it's reached, analysis of any call that would recurse deeper gets terminated ๐gimple-fe-computed-hot-bb-thresholdโ the number of executions a basic block needs before it counts as hot. This one is only used in the GIMPLE FE ๐ฅanalyzer-bb-explosion-factorโ the max number of 'after supernode' exploded nodes per supernode in the analyzer. Past that, analysis stops ๐ฅ
The following choices of name are available on AArch64 targets ๐
aarch64-sve-compare-costsโ when vectorizing for SVE, this considers using "unpacked" vectors for smaller elements and lets the cost model pick the cheapest approach. It also uses the cost model to choose between SVE and Advanced SIMD vectorization ๐ง
Using unpacked vectors means storing smaller elements in larger containers and accessing elements with extending loads and truncating stores.
aarch64-float-recp-precisionโ the number of Newton iterations used to calculate the reciprocal for the float type. The precision of division scales with this param when division approximation is enabled. The default value is1๐ฏaarch64-double-recp-precisionโ the number of Newton iterations used to calculate the reciprocal for the double type. The precision of division scales with this param when division approximation is enabled. The default value is2๐ซaarch64-autovec-preferenceโ forces an ISA selection strategy for auto-vectorization. It accepts values from0to4, inclusive ๐ฆ0โ use the default heuristics1โ use only Advanced SIMD for auto-vectorization2โ use only SVE for auto-vectorization3โ use both Advanced SIMD and SVE, preferring Advanced SIMD when the costs are deemed equal4โ use both Advanced SIMD and SVE, preferring SVE when the costs are deemed equal
The default value is 0 ๐ธ
โจ Program Instrumentation Options โจ
GCC has a bunch of command-line options that bolt run-time instrumentation onto the code it normally spits out ๐. One reason to instrument is to collect profiling stats so you can hunt down program hot spots, do code coverage analysis, or set up profile-guided optimizations ๐. Another kind is run-time checking, which catches programming mistakes like invalid pointer dereferences or out-of-bounds array accesses, plus sneaky attacks like stack smashing or C++ vtable hijacking ๐ก๏ธ. There's also a general hook for other forms of tracing or function-level instrumentation, for debugging or program analysis ๐ง.
-p,-pgโ generates extra code that writes profile information for the analysis programprof(with-p) orgprof(with-pg) ๐. You have to use this option when compiling the source files you want data about, and you have to use it when linking too ๐ซถ.
You can use the function attribute no_instrument_function to skip profiling for individual functions when compiling with these options ๐.
-fprofile-arcsโ adds code so program flow arcs get instrumented ๐น. While the program runs, it records how many times each branch and call gets executed, and how many times each one is taken or returns ๐. On targets that support constructors with priority support, profiling handles constructors, destructors, and C++ constructors (and destructors) of classes that are used as the type of a global variable properly ๐.
When the compiled program exits, it saves this data to a file called auxname.gcda for each source file ๐พ. That data can feed profile-directed optimizations (-fbranch-probabilities) or test coverage analysis (-ftest-coverage) ๐. Each object file's auxname comes from the output file's name if you explicitly specified one and it's not the final executable. Otherwise it comes from the basename of the source file. Either way, any suffix gets removed. For example, you'd get foo.gcda for the input file dir/foo.c, or dir/foo.gcda for an output file specified as -o dir/foo.o ๐ฆ.
--coverageโ this is the one to use when you want to compile and link code instrumented for coverage analysis ๐. It's a synonym for-fprofile-arcs -ftest-coveragewhen compiling and-lgcovwhen linking. Check the docs for those options for more details ๐.- Compile the source files with
-fprofile-arcs, plus your optimization and code generation options. For test coverage analysis, add the extra-ftest-coverageoption. You don't need to profile every source file in a program ๐ . - Compile the source files with
-fprofile-abs-pathtoo, so the.gcnofiles get absolute path names. That waygcovcan find the right sources in projects where compilations happen from 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 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 get detected and handled correctly without double counting ๐ด. - For profile-directed optimizations, compile the source files again with the same optimization and code generation options, plus
-fbranch-probabilitiesโก. - For test coverage analysis, use
gcovto produce human-readable information from the.gcnoand.gcdafiles. Check the gcov documentation for more info ๐.
- Compile the source files with
Okay so with -fprofile-arcs, GCC builds a program flow graph for every function in your program, then finds a spanning tree for it ๐ณ. Only the arcs that are not on that tree need instrumenting, which is lowkey genius, because the compiler just sneaks in counting code for those arcs ๐ข. If an arc is the only exit or the only entrance to a block, the counter can go right inside that block ๐. Otherwise GCC has to make a brand new basic block just to hold the instrumentation code ๐งฑ.
-ftest-coverageโ Produces a notes file that the gcov code-coverage utility can read to show program coverage ๐. Each source file's note file is namedauxname.gcno. For whatauxnamemeans and how to generate test coverage data, look back at-fprofile-arcsabove ๐. Coverage data matches your source more closely if you don't optimize ๐ .-fprofile-abs-pathโ Automatically turns relative source file names into absolute path names inside the.gcnofiles ๐บ๏ธ. This helps gcov find the right sources in projects that compile from different working directories ๐ซถ.-fprofile-dir=pathโ Sets the directory where profile data files get searched for, topath๐. This only affects profile data made by-fprofile-generate,-ftest-coverage, and-fprofile-arcs, and used by-fprofile-use,-fbranch-probabilities, and their related options ๐. Absolute and relative paths both work ๐ธ. By default GCC uses the current directory, so the profile data file lands in the same folder as the object file ๐. To stop file names from clashing, if the object file name isn't an absolute path, GCC mangles the absolute path of thesourcename.gcdafile and uses that as the.gcdafile name ๐. See the similar option-fprofile-noteโจ.
When an executable runs in a massive parallel environment, it's recommended to save profiles into different folders ๐ง. You can do that with variables inside path that get exported at run-time:
%pโ process ID.%q{VAR}โ value of the environment variableVAR๐.
-fprofile-generate,-fprofile-generate=pathโ Turns on the options you'd normally use to instrument an app, so it produces a profile you can use later to recompile with profile feedback based optimization ๐ฅ. You must use-fprofile-generateboth when compiling and when linking, or it won't work right ๐.
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 actually optimize using the profile you collected, use -fprofile-use ๐.
-fprofile-note=pathโ Ifpathis specified, GCC saves the.gcnofile into that location ๐. If you combine this with multiple source files, the.gcnofile gets overwritten ๐.-fprofile-prefix-path=pathโ Use this withprofile-generate=profile_dirandprofile-use=profile_dirto tell GCC where the base directory of your built source tree is ๐ท. By default,profile_dirholds files with mangled absolute paths of every object file in the build ๐ตโ๐ซ. That's a problem when the directory you built the instrumented binary in is different from the one you used for the optimized build, because then the profile data won't be found during the optimized build ๐ญ. In that situation,-fprofile-prefix-path=pathwithpathpointing to the base build directory strips out the irrelevant part and keeps every file name relative to the main build directory ๐งธ.-fprofile-update=methodโ Changes how an instrumented app updates its profile data ๐.methodshould be one ofsingle,atomic, orprefer-atomic.singleis great for single-threaded apps, whileatomicstops profile corruption by emitting thread-safe code ๐งต.
Warning: If an app doesn't properly join all of its threads (or it creates a detached thread), the profile file can still get corrupted ๐จ.
Using prefer-atomic becomes atomic when the target supports it, and falls back to single otherwise ๐ฆ. The GCC driver picks prefer-atomic automatically when -pthread is on the command line ๐.
-fprofile-filter-files=regexโ Only instruments functions from files whose names match any of the regular expressions, separated by a semicolon ๐ฏ. For example,-fprofile-filter-files=main.c;module.*.cinstruments onlymain.cand every C file starting with 'module' ๐.-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/*stops every file in the/usr/folder from being instrumented ๐ซ.-fprofile-reproducible=[multithreaded|parallel-runs|serial]โ Controls how reproducible the profile from-fprofile-generateis ๐. This lets you rebuild a program and get the same outcome, which is super useful for things like distribution packages ๐ฆ.
With -fprofile-reproducible=serial, the profile is reproducible as long as the trained program behaves the same on every invocation of the train run, isn't multi-threaded, and always streams profile data in the same order ๐. Profile streaming happens at the end of the program run, but also before the fork function is invoked ๐ด.
Heads up, though: it's pretty common for execution counts in parts of a program to depend on things like the length of temporary file names or memory space randomization, which can change hash-table collision rates ๐ฒ. That non-reproducible part can be marked with the no_instrument_function function attribute ๐ท๏ธ. You can use gcov-dump with -l to dump the gathered data and check that it really is reproducible ๐.
With -fprofile-reproducible=parallel-runs, the collected profile stays reproducible no matter what order the data gets streamed into the gcda files ๐งฉ. This setting lets you run multiple instances of the instrumented program in parallel, like with make -j ๐โโ๏ธ. The tradeoff is that the quality of the gathered data drops, especially for indirect call profiling ๐.
-fsanitize=addressโ Enables AddressSanitizer, a fast memory error detector ๐ต๏ธโโ๏ธ. Memory access instructions get instrumented to catch out-of-bounds and use-after-free bugs ๐ฅ. This option also enables-fsanitize-address-use-after-scopeโจ. For more details, check <https://github.com/google/sanitizers/wiki/AddressSanitizer> ๐.
You can influence the run-time behavior with the ASAN_OPTIONS environment variable ๐. When it's set to help=1, the available options get shown when the instrumented program starts up ๐. For a list of supported options, see <https://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 ๐ง. For more details, see <https://github.com/google/kasan/wiki> ๐ซถ.-fsanitize=pointer-compareโ Instruments comparison operations (<,<=,>,>=) that have pointer operands ๐. This option has to be combined with either-fsanitize=kernel-addressor-fsanitize=address๐ . It cannot be combined with-fsanitize=thread๐ซ.
Note: The check is disabled at run time by default ๐ด. To turn it on, add detect_invalid_pointer_pairs=2 to the ASAN_OPTIONS environment 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 has to be combined with either-fsanitize=kernel-addressor-fsanitize=address๐. It cannot be combined with-fsanitize=thread๐ซ.
Note: The check is disabled at run time by default ๐ด. To enable it, add detect_invalid_pointer_pairs=2 to the ASAN_OPTIONS environment variable ๐ธ. Using detect_invalid_pointer_pairs=1 only detects invalid operations when both pointers are non-null ๐.
-fsanitize=threadโ Enables ThreadSanitizer, a fast data race detector ๐งต. Memory access instructions get instrumented to catch data race bugs ๐. For more details, see <https://github.com/google/sanitizers/wiki#threadsanitizer> ๐. The run-time behavior can be influenced with theTSAN_OPTIONSenvironment variable ๐๏ธ. For a list of supported options, check <https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags> ๐. This option cannot be combined with-fsanitize=address,-fsanitize=leak๐ซ.
Heads up: sanitized atomic builtins can't throw exceptions when they operate on invalid memory addresses with non-call exceptions (-fnon-call-exceptions) ๐ญ.
-fsanitize=leakโ Enables LeakSanitizer, a memory leak detector ๐ชฃ. This option only matters when linking executables, and when the executable is linked against a library that overridesmallocand other allocator functions ๐ง . For more details, see <https://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 โ๏ธ. For more details, see <https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html> ๐ฆ. The run-time behavior can be influenced with theUBSAN_OPTIONSenvironment variable ๐. The current suboptions are:-fsanitize=shiftโ Enables checking that the result of a shift operation isn't undefined ๐ซง. What counts as undefined differs slightly between C and C++, and also between ISO C90 and C99, and so on ๐ค. This option has two suboptions,-fsanitize=shift-baseand-fsanitize=shift-exponent๐งฉ.-fsanitize=shift-exponentโ Enables checking that the second argument of a shift operation isn't negative and is smaller than the precision of the promoted first argument ๐ข.
-fsanitize=shift-baseโ ๐ okay so if the second argument of a shift is within range, the compiler checks that the result of the shift isn't undefined. Heads up: what counts as undefined is slightly different between C and C++, and also between ISO C90 and C99, etc. โจ-fsanitize=integer-divide-by-zeroโ ๐งฎ catches integer division by zero, plus the sneakyINT_MIN / -1division.-fsanitize=unreachableโ ๐ with this on, the compiler turns the__builtin_unreachablecall into a diagnostics message call instead. When you reach__builtin_unreachable, the behavior is undefined, so this is the warning you want.-fsanitize=vla-boundโ ๐ checks that the size of a variable length array is positive.-fsanitize=nullโ ๐ซ pointer checking, bestie! Your app will throw an error if it tries to dereference aNULLpointer, if a reference (possibly an rvalue reference) gets bound to aNULLpointer, or if a method gets invoked on an object pointed to by aNULLpointer.-fsanitize=returnโ ๐ return statement checking. Programs built with this on will throw an error message when the end of a non-void function is reached without actually returning a value. This one only works in C++.-fsanitize=signed-integer-overflowโ โ signed integer overflow checking. It checks that the result of+,*, and both unary and binary-doesn't overflow in signed arithmetic. Integer promotion rules totally count here! For example, this is not an overflow:
signed char a = SCHAR_MAX;
a++;
-fsanitize=boundsโ ๐ฆ enables instrumentation of array bounds, so various out of bounds accesses get detected. Flexible array members, flexible array member-like arrays, and initializers of variables with static storage are not instrumented.-fsanitize=bounds-strictโ ๐ the stricter version! Most out of bounds accesses get detected, including flexible array members and flexible array member-like arrays. Initializers of variables with static storage still aren't instrumented.-fsanitize=alignmentโ ๐งฑ checks pointer alignment when they're 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, so various out of bounds pointer accesses are 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 legit way of getting infinities and NaNs. ๐-fsanitize=float-cast-overflowโ ๐ enables floating-point type to integer conversion checking. It checks that the result of the conversion doesn't overflow. Unlike other similar options, this one is NOT enabled by-fsanitize=undefined. โ ๏ธ This option does not work well withFE_INVALIDexceptions enabled.-fsanitize=nonnull-attributeโ ๐ instruments calls and checks 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 returning null values from those functions gets detected.-fsanitize=boolโ ๐ instruments loads frombool. If a value other than0/1gets 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โ ๐งฌ C++ only, bestie! It instruments 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 gets passed to those arguments, a run-time error is issued. E.g. passing0as the argument to__builtin_ctzor__builtin_clzinvokes undefined behavior and is 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, so don't even try it ๐ญ-fasan-shadow-offset=numberโ ๐งช forces GCC to use a custom shadow offset in AddressSanitizer checks. It's useful for experimenting with different shadow memory layouts in Kernel AddressSanitizer. ๐ง-fsanitize-sections=s1,s2,...โ ๐๏ธ sanitizes global variables in selected user-defined sections. si may contain wildcards.-fsanitize-recover[=opts]โ ๐ controls the error recovery mode for the sanitizers in the comma-separated list of opts. Turning this on for a sanitizer makes it try to keep the program running as if no error happened. That means multiple runtime errors can get reported in one run, and the exit code might say success even when errors were reported. The-fno-sanitize-recover=option can alter this: only the first detected error gets reported, and then the program exits with a non-zero exit code. ๐ค
Currently this feature only works for -fsanitize=undefined (and its suboptions except for -fsanitize=unreachable and -fsanitize=return), -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero, -fsanitize=bounds-strict, -fsanitize=kernel-address and -fsanitize=address. For these sanitizers, error recovery is turned on by default, except for -fsanitize=address, where this feature is experimental. -fsanitize-recover=all and -fno-sanitize-recover=all are also accepted: the former enables recovery for all sanitizers that support it, and the latter disables recovery for all sanitizers that support it.
Even if a recovery mode is turned on 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? Thelibubsanlibrary isn't needed and isn't linked in, so this is usable even in freestanding environments. ๐ฆ-fsanitize-coverage=trace-pcโ ๐ต๏ธ enables coverage-guided fuzzing code instrumentation. It inserts a call to__sanitizer_cov_trace_pcinto every basic block.-fsanitize-coverage=trace-cmpโ ๐งฒ enables dataflow guided fuzzing code instrumentation. It inserts a call to:__sanitizer_cov_trace_cmp1,__sanitizer_cov_trace_cmp2,__sanitizer_cov_trace_cmp4or__sanitizer_cov_trace_cmp8for integral comparisons with both operands variable__sanitizer_cov_trace_const_cmp1,__sanitizer_cov_trace_const_cmp2,__sanitizer_cov_trace_const_cmp4or__sanitizer_cov_trace_const_cmp8for integral comparisons with one operand constant__sanitizer_cov_trace_cmpfor__sanitizer_cov_trace_cmpdfor float or double comparisons__sanitizer_cov_trace_switchfor switch statements
-fcf-protection=[full|branch|return|none|check]โ ๐ก๏ธ enables code instrumentation of control-flow transfers to boost program security by checking that target addresses of control-flow transfer instructions (such as indirect function call, function return, indirect jump) are valid. This stops control from being diverted to an unexpected target, and it's meant to protect against threats like Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP). ๐branchโ checks validity of control-flow transfer at the point of indirect branch instructions, i.e.call/jmpinstructions.returnโ checks validity at the point of returning from a function.fullโ an alias for specifying bothbranchandreturn.noneโ turns off instrumentation.checkโ used for the final link with link-time optimization (LTO). An error is issued if LTO object files are compiled with different-fcf-protectionvalues. Thecheckvalue is ignored at compile time.
The macro __CET__ is defined when -fcf-protection is used. The first bit of __CET__ is set to 1 for the value branch, and the second bit of __CET__ is set to 1 for return. ๐
Bestie, the nocf_check attribute is your escape hatch ๐ฆ Use it to mark which functions and calls should get skipped from instrumentation, no cap.
Right now the x86 GNU/Linux target has its own version built on Intel Control-flow Enforcement Technology (CET), and it works on i686 processors or newer ๐
NOTE: In Ubuntu 19.10 and later versions,-fcf-protectionis turned on by default for C, C++, ObjC, ObjC++, if none of-fno-cf-protectionnor-fcf-protection=*are found. ๐
-fstack-protector
Okay so this one adds extra code to check for buffer overflows, like stack smashing attacks ๐ก๏ธ It works by slipping a guard variable into any function with vulnerable objects. That includes functions that call alloca, and functions with buffers larger than or equal to 8 bytes. The guards get set up when a function is entered and then checked when it exits. If a guard check fails, an error message gets printed and the program exits. Only variables that are actually allocated on the stack count here, so optimized away variables or variables allocated in registers don't count. ๐
-fstack-protector-all
Same energy as -fstack-protector, except now EVERY function gets protected ๐
-fstack-protector-strong
This is -fstack-protector but with extra functions added to the protected list: the ones that have local array definitions, or that have references to local frame addresses. Same rule as before though, only variables that are actually allocated on the stack are considered, and optimized away variables or variables allocated in registers don't count. โจ
-fstack-protector-explicit
Like -fstack-protector, but it only protects the functions that have the stack_protect attribute. ๐
-fstack-check
Generate code to verify that you don't go past the boundary of the stack ๐ง You should turn this on if you're running in an environment with multiple threads. In a single-threaded environment you only rarely need it, because stack overflow is automatically detected on nearly all systems if there's only one stack.
Note that this switch doesn't actually do the checking itself. The operating system or the language runtime has to do that. What the switch does is generate code so they can see the stack being extended.
You can also tack on a string parameter, and the options are:
nomeans no checkinggenericmeans force the use of old-style checkingspecificmeans use the best checking method, and it's 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 are 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 is topped by a particular function, stack checking is not reliable and a warning is issued by the compiler.
- Inefficiency: because of both the modified allocation strategy and the generic implementation, code performance is hampered.
Also, old-style stack checking is 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, and specific is an excellent choice when compiling Ada code. It's not generally sufficient to protect against stack-clash attacks though. For those, you want -fstack-clash-protection. ๐ฆ
-fstack-clash-protection
Generate code to prevent stack clash style attacks. When this is enabled, the compiler only allocates one page of stack space at a time, and each page gets accessed right after allocation. That means allocations can't jump over any stack guard page the operating system provides. ๐
Most targets don't fully support stack clash protection. On those targets, though, -fstack-clash-protection will protect dynamic stack allocations. It may also give limited protection for static stack allocations if the target supports -fstack-check=specific.
NOTE: In Ubuntu 19.10 and later versions,-fstack-clash-protectionis enabled by default for C, C++, ObjC, ObjC++, unless-fno-stack-clash-protectionis found.
-fstack-limit-register=reg / -fstack-limit-symbol=sym / -fno-stack-limit
Generate code to make sure the stack doesn't grow beyond a certain value, either the value of a register or the address of a symbol. If a larger stack is needed, a signal gets raised at run time. On most targets the signal is raised before the stack overruns the boundary, so you can catch it without taking 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
Generate code to automatically split the stack before it overflows. The result is a discontiguous stack that can only overflow if the program can't allocate any more memory. This is most useful with threaded programs, since you no longer have to figure out a good stack size to use for each thread ๐ง This is currently only implemented for the x86 targets running GNU/Linux.
When code compiled with -fsplit-stack calls code compiled without -fsplit-stack, there may not be much stack space left for that latter code to run in. If compiling all code, including library code, with -fsplit-stack isn't an option, the linker can fix up those calls so the code compiled without -fsplit-stack always gets a large stack. Support for this is implemented in the gold linker in GNU binutils release 2.21 and later.
-fvtable-verify=[std|preinit|none]
Only available when compiling C++ code, this one turns on the security feature that checks at run time, for every virtual call, that the vtable pointer used for the call is valid for the type of the object and hasn't been corrupted or overwritten. Using -fvtable-verify=none turns it off instead ๐ฅ If an invalid vtable pointer is detected at run time, an error is reported and the program's execution is immediately halted.
This option builds run-time data structures at program startup, and those are what get used to verify the vtable pointers. The std and preinit options control the timing of when they're built. In both cases the data structures are built before execution reaches main. With -fvtable-verify=std they're built after shared libraries have been loaded and initialized. With -fvtable-verify=preinit they're built before shared libraries have been loaded and initialized. ๐
If this option shows up multiple times on the command line with different values, none takes highest priority over both std and preinit, and preinit takes priority over std. ๐
-fvtv-debug
Used together with -fvtable-verify=std or -fvtable-verify=preinit, this makes the debug versions of the runtime functions for the vtable verification feature get called. It also makes the compiler log which vtable pointers it finds for each class. That info gets written to a file named vtv_set_ptr_data.log in the directory named by the environment variable VTV_LOGS_DIR if it's defined, or in 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, bestie ๐ Used with -fvtable-verify=std or -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 that it inserts, and logs all of this for each compilation unit. The info is written to a file named vtv_count_data.log in the directory named by the environment variable VTV_LOGS_DIR if that's defined, or the current working directory otherwise. It also counts the size of the vtable pointer sets for each class and writes that to vtv_class_set_sizes.log in 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
Generate instrumentation calls for entry and exit to functions. Just after function entry and just before function exit, the following profiling functions get called with the address of the current function and its call site. (On some platforms, __builtin_return_address doesn'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 can be looked up exactly in the symbol table. ๐ง
This instrumentation also happens for functions expanded inline in other functions. The profiling calls show where, conceptually, the inline function is entered and exited. That means addressable versions of those functions have to be available. If all your uses of a function get expanded inline, this may mean an extra expansion of code size. If you use extern inline in your C code, an addressable version of such functions must be provided. (This is normally the case anyway, but if you get lucky and the optimizer always expands the functions inline, you might have gotten away without providing static copies.) ๐
Okay so a function can wear the attribute "no_instrument_function" ๐, and when it does, GCC just skips instrumenting it. Bestie, that's a VIP pass ๐ง It's super useful for the profiling functions listed above, high-priority interrupt routines, and any functions that can't safely call the profiling functions (like signal handlers, if the profiling routines generate output or allocate memory). Those functions get to stay off the radar, no cap ๐ฆ
-finstrument-functions-exclude-file-list=file,file,...โ This is the bouncer list for files ๐ซถ Give it a list, and any function defined in a file that matches one of those entries gets left out of instrumentation (same deal as-finstrument-functions, see above). Matching is done on substrings, so if thefileparameter is a substring of the file name, it counts as a match. โจ
Here's a lil example ๐
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
That one excludes any inline function defined in files whose pathnames contain /bits/stl or include/sys. Bestie, that's a whole lot of stuff gone in one line ๐ญ
Okay, now the tricky part ๐ If, for some reason, you want to include a literal comma in one of the sym entries, you write two commas, ,,. For example, -finstrument-functions-exclude-file-list=',,tmp' (note the single quote surrounding the option).
-finstrument-functions-exclude-function-list=sym,sym,...โ This is the sibling of the file list, but it goes by function names instead ๐ The name it matches is the user-visible name, like"vector<int> blah(const vector<int> &)", not the internal mangled name (e.g.,"_Z4blahRSt6vectorIiSaIiEE"). Same vibe as before: substring matching, so if thesymparameter is a substring of the function name, it's a match. For C99 and C++ extended identifiers, the function name has to be given in UTF-8, not using universal character names. ๐-fpatchable-function-entry=N[,M]โ GenerateNNOPs right at the beginning of each function, with the function entry point before theMth NOP. IfMis omitted, it defaults to0, so the function entry points to the address just at the first NOP. These NOP instructions reserve extra space that can be used to patch in any desired instrumentation at run time, provided that the code segment is writable ๐ฅ The amount of space is controllable indirectly via the number of NOPs. The NOP instruction used corresponds to the instruction emitted by the internal GCC back-end interface"gen_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 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 is run on each C source file before actual compilation.
If you use the -E option, nothing is done except preprocessing. Some of these options make sense only together with -E, because they cause the preprocessor output to be unsuitable for actual compilation.
In addition to the options listed here, there are a number 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โ Predefinenameas a macro, with the definition1โจ-D name=definitionโ The contents ofdefinitionget tokenized and processed as if they appeared during translation phase three in a#definedirective. Basically, the definition gets truncated by any 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 the shell syntax. ๐
If you wanna define a function-like macro on the command line, write its argument list with surrounding parentheses before the equals sign (if any). Parentheses mean something to most shells, so you should quote the option. With sh and csh, -D'name(args...)=definition' works ๐
-D and -U options are processed in the order they're given on the command line. All -imacros file and -include file options are processed after all -D and -U options. ๐ฆ
-U nameโ Cancel any previous definition ofname, whether it was built in or provided with a-Doption ๐-include fileโ Processfileas if#include "file"appeared as the first line of the primary source file. However, the first directory searched forfileis the preprocessor's working directory, instead of the directory containing the main source file. If it's not found there, it gets searched for in the remainder of the#include "..."search chain as normal.
If multiple -include options are given, the files are included in the order they appear on the command line ๐
-imacros fileโ Exactly like-include, except any output produced by scanningfileis thrown away. Macros it defines remain defined. This lets you grab all the macros from a header without also processing its declarations ๐
All files specified by -imacros are processed before all files specified by -include.
-undefโ Do not predefine any system-specific or GCC-specific macros. The standard predefined macros remain defined ๐-pthreadโ Define additional macros required for using the POSIX threads library. You should use this option consistently for both compilation and linking ๐งต This option is supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets. ๐-Mโ Instead of outputting the result of preprocessing, output a rule suitable formakedescribing the dependencies of the main source file. The preprocessor outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from-includeor-imacroscommand-line options.
Unless specified explicitly (with -MT or -MQ), the object file name consists of the name of the source file with any suffix replaced with 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"#include"directive, without prepending any path.
-MG also suppresses preprocessed output, since a missing header file renders that useless. This feature is used in automatic updating of makefiles ๐ ๏ธ
-MPโ This option instructs CPP to add a phony target for each dependency other than the main file, causing each to depend on nothing. These dummy rules work around errorsmakegives if you remove header files without updating the Makefile to match. This is typical output:
test.o: test.c test.h
test.h:
-MT targetโ Change 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 ๐ฅ
-MDโ-MDis equivalent to-M -MF file, except that-Eis not implied. The driver determinesfilebased on whether an-ooption is given. If it is, the driver uses its argument but with a suffix of.d. Otherwise, it takes the name of the input file, removes any directory components and suffix, and applies a.dsuffix.
If -MD is used in conjunction with -E, any -o switch is understood to specify the dependency output file. But if used without -E, each -o is understood to specify a target object file.
Since -E is not implied, -MD can be used to generate a dependency output file as a side effect of the compilation process ๐
-MMDโ Like-MD, except mention only user header files, not system header files ๐ธ-fpreprocessedโ ๐ง This tells the preprocessor the input file is already preprocessed, so it skips macro expansion, trigraph conversion, escaped newline splicing, and most directives. It still spots and removes comments, so a file made with-Cwon't cause drama when you hand it to the compiler. In this mode the integrated preprocessor is basically just a tokenizer for the front ends ๐ . It's switched on automatically for input files ending in.i,.iior.mi, which are the extensions GCC uses for preprocessed files made by-save-tempsโจ.-fdirectives-onlyโ ๐ฆ When preprocessing, this handles directives but leaves macros alone. How it acts depends on-Eand-fpreprocessed, so pay attention:- With
-E, it only handles directives like"#define","#ifdef", and"#error". Macro expansion and trigraph conversion are skipped, and-dDgets turned on automatically ๐ธ. - With
-fpreprocessed, predefining command-line macros and most builtin macros is turned off. Contextual macros like__LINE__still get handled normally. This is how you compile files that were previously run through-E -fdirectives-only๐. - With both
-Eand-fpreprocessed, the-fpreprocessedrules win. That lets you fully preprocess files that were earlier run through-E -fdirectives-only๐.
- With
-fdollars-in-identifiersโ ๐ Lets$show up inside identifiers.-fextended-identifiersโ ๐ Lets identifiers use universal character names and extended characters. It's on by default for C99 (and later C standards) and for C++, so you're probably already getting it ๐ .-fno-canonical-system-headersโ ๐ When preprocessing, this stops system header paths from being shortened through canonicalization.-fmax-include-depth=depthโ ๐ซถ Sets how deep nested#includes can go. The default is200โจ.-ftabstop=widthโ ๐ Sets the distance between tab stops. This helps the preprocessor report the right column numbers in warnings and errors even when tabs are on the line ๐ธ. If the value is less than1or greater than100, the option gets ignored ๐. The default is8.-ftrack-macro-expansion[=level]โ ๐ This tracks where tokens come from across macro expansions. When an error happens inside a macro, the compiler can then show you the current macro expansion stack, which is so helpful ๐ญ. The catch is that it makes the preprocessor and compiler use more memory. The level parameter lets you pick how precisely tokens get tracked, so you can cut memory use if you need to:- Level
0turns this option off ๐. - Level
1tracks in a degraded mode for minimal memory overhead. In this mode, every token that comes from expanding an argument of a function-like macro has the same location. - Level
2tracks token locations completely. It's the most memory hungry option ๐ฅ. - If you give the option with no argument, the level defaults to
2.
- Level
Also, -ftrack-macro-expansion=2 is on by default, so it's already doing its thing ๐.
-fmacro-prefix-map=old=newโ ๐บ๏ธ When preprocessing files living in directory old,__FILE__and__BASE_FILE__expand as if those files lived in directory new instead. You can use.for new to flip an absolute path into a relative one, which can lead to more reproducible, location-independent builds ๐ฆ. This also changes__builtin_FILE()during compilation. See also-ffile-prefix-map.-fexec-charset=charsetโ ๐ฌ Sets the execution character set, which covers string and character constants. The default isUTF-8. charset can be any encoding your system'siconvlibrary routine supports โจ.-fwide-exec-charset=charsetโ ๐ Sets the wide execution character set, used for wide string and character constants. The default is whichever ofUTF-32BE,UTF-32LE,UTF-16BE, orUTF-16LEmatches the width ofwchar_tand the byte order (big-endian or little-endian) being used for code generation ๐ง . Just like-fexec-charset, charset can be any encodingiconvsupports, but be warned: you'll have problems with encodings that don't fit exactly inwchar_t๐ฌ.-finput-charset=charsetโ ๐ฅ Sets the input character set, which translates the input file's characters into the source character set GCC uses. If the locale doesn't say anything, or GCC can't get that info from the locale, the default isUTF-8. The locale or this command-line option can override it, and if they conflict, the command-line option wins right now ๐ . charset can be any encodingiconvsupports.-fpch-depsโ ๐๏ธ When you're using precompiled headers, this makes the dependency-output flags also list files from the precompiled header's own dependencies. Without it, only the precompiled header gets listed, not the files that were used to make it, because those files aren't consulted when a precompiled header is in use ๐.-fpch-preprocessโ ๐งฉ This lets you use a precompiled header together with-E. It drops a special#pragma,#pragma GCC pch_preprocess "filename", into the output to mark where the precompiled header was found and what its filename is. When-fpreprocessedis in play, GCC recognizes that#pragmaand loads the PCH ๐. It's off by default, since the preprocessed output is really only good as input to GCC.-save-tempsswitches it on.
You should not write this #pragma in your own code. It is safe to edit the filename, though, if the PCH file lives in a different spot. The filename can be absolute, or relative to GCC's current directory โ ๏ธ.
-fworking-directoryโ ๐ Turns on linemarkers in the preprocessor output so the compiler knows the working directory at the time of preprocessing. With this on, after the initial linemarker, the preprocessor emits a second linemarker with the current working directory followed by two slashes. When that directory shows up in the preprocessed input, GCC uses it as the working directory in some debugging information formats ๐. This is implicitly enabled when debugging info is on, but you can block it with the negated form-fno-working-directory. If-Pis on the command line, this option does nothing, because no#linedirectives get emitted whatsoever ๐ซ.-A predicate=answerโ ๐ฏ Makes an assertion with the predicate predicate and the answer answer. This form is the preferred one over the older-A predicate(answer)form. The older form still works, but the new one is better because it doesn't use shell special characters ๐ .-A -predicate=answerโ โ Cancels an assertion with the predicate predicate and the answer answer ๐ฅ.-Cโ ๐ฌ Keeps comments, so they don't get discarded. All comments pass through to the output file, except the ones inside processed directives, which get deleted along with the directive โจ.
Be prepared for side effects when you use-C. It makes the preprocessor treat comments as tokens in their own right. For example, a comment at the start of what would be a directive line turns that line into an ordinary source line, since the first token on the line is no longer a#๐ญ.
-CCโ ๐ง Keeps comments even during macro expansion. It's like-C, except comments inside macros also get passed through to the output wherever the macro is expanded ๐. On top of everything-Cdoes,-CCconverts all C++-style comments inside a macro into C-style comments. That stops a later use of the macro from accidentally commenting out the rest of the source line ๐ โโ๏ธ.-CCis generally used to support lint comments ๐ซง.-Pโ ๐ค Stops linemarkers from showing up in the preprocessor output. This could be handy when you're running the preprocessor on something that isn't C code and sending it to a program that might get confused by linemarkers ๐ธ.-traditional,-traditional-cppโ ๐ฐ๏ธ These try to copy the behavior of pre-standard C preprocessors, instead of the ISO C ones. Check the GNU CPP manual for the details ๐.
GCC doesn't try to emulate a pre-standard C compiler in any other way. These options only work with the -E switch, or when you invoke CPP explicitly ๐.
-trigraphsโ ๐บ Supports ISO C trigraphs. These are three-character sequences that all start with??, and ISO C defines them 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โ ๐๏ธ Turns on special code to work around file systems that only allow super short file names, like MS-DOS ๐พ.-Hโ ๐ณ Prints the name of each header file used, along with all the other normal activities ๐. Each name gets indented to show how deep it sits in the#includestack. Precompiled header files get printed too, even when they turn out to be invalid. An invalid precompiled header shows up with...x, and a valid one shows up with...!๐ฅ.-dlettersโ ๐ ๏ธ Asks GCC to make debugging dumps during compilation, as specified by letters. The flags documented here are the ones relevant to the preprocessor ๐ง . Other letters are interpreted by the compiler proper, or reserved for future versions of GCC, so they get silently ignored ๐คซ. If you specify letters whose behaviors conflict, the result is undefined ๐.-dMโ โจ Instead of the normal output, this generates a list of#definedirectives for all the macros defined while the preprocessor runs, including the predefined ones. It's a great way to find out what's predefined in your version of the preprocessor ๐ฎ. Assuming you have no filefoo.h, the command
touch foo.h; cpp -dM foo.h
Okay so touch foo.h; cpp -dM foo.h shows all the predefined macros ๐โจ (the whole list just pops up, it's giving everything).
๐ If you use-dMwithout the-Eoption,-dMgets interpreted as a synonym for-fdump-rtl-mach. Bestie, read that twice.
-dDโ Basically-dM, but with two differences ๐ฆ. It does not include the predefined macros, and it outputs both the#definedirectives and the result of preprocessing. Both kinds of output go to the standard output file.-dNโ Same energy as-dD, but it only spits out the macro names ๐ธ, not their expansions.-dIโ Outputs#includedirectives on top of the preprocessing result ๐.-dUโ Like-dD, but way more selective ๐ . Only macros that are expanded, or whose definedness is tested in preprocessor directives, get output. The output is delayed until the macro is used or tested, and#undefdirectives are also output for macros that were tested but were undefined at the time.-fdebug-cppโ Only useful if you're debugging GCC itself ๐ง. When used from CPP or with-E, it dumps debugging info about location maps. Every token in the output is preceded by the dump of the map its location belongs to.
When used from GCC without -E, this option has no effect.
-Wp,optionโ You can use this to bypass the compiler driver and passoptionstraight through to the preprocessor ๐. Ifoptioncontains commas, it gets split into multiple options at the commas.
โ ๏ธ Many options get modified, translated, or interpreted by the compiler driver before they reach the preprocessor, and-Wpforcibly skips that phase. The preprocessor's direct interface is undocumented and subject to change, so whenever possible, avoid-Wpand let the driver handle the options instead ๐ฅบ.
-Xpreprocessor optionโ Passesoptionalong to the preprocessor ๐. Use this for system-specific preprocessor options that GCC doesn't recognize.
If you want to pass an option that takes an argument, you must use -Xpreprocessor twice, once for the option and once for the argument ๐.
-no-integrated-cppโ Preprocessing happens as a separate pass before compilation ๐. By default, GCC preprocesses as an integrated part of input tokenization and parsing. If this option is provided, the appropriate language front end (cc1,cc1plus, orcc1objfor C, C++, and Objective-C, respectively) gets invoked twice: once for preprocessing only, and once for actual compilation of the preprocessed input. This can be useful together with the-Bor-wrapperoptions to specify an alternate preprocessor or to do extra processing of the program source between normal preprocessing and compilation ๐.
โจ Passing Options to the Assembler โจ
You can pass options to the assembler ๐ซถ.
-Wa,optionโ Passesoptionto the assembler ๐ฆ. Ifoptioncontains commas, it gets split into multiple options at the commas.-Xassembler optionโ Passesoptionto the assembler too ๐. You can use this to supply system-specific assembler options that GCC doesn't recognize.
If you want to pass an option that takes an argument, you must use -Xassembler twice, once for the option and once for the argument ๐ญ.
โจ 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โ A file name that doesn't end in a special recognized suffix is considered to name an object file or library ๐ฆ. (The linker tells object files apart from libraries by looking at the file contents.) If linking is done, these object files are used as input to the linker.-c,-S,-Eโ If any of these options is used, the linker is not run, and object file names should not be used as arguments ๐ โโ๏ธ.-flinker-output=typeโ This option controls code generation of the link-time optimizer โจ. By default, the linker output is automatically determined by the linker plugin. For debugging the compiler, or if you want incremental linking with a non-LTO object file, it may be useful to control the type manually ๐ง .execโ Code generation produces a static binary ๐ชจ. In this case,-fpicand-fpieare both disabled.dynโ Code generation produces a shared library ๐ธ. In this case,-fpicor-fPICis preserved, but not enabled automatically. This allows building shared libraries without position-independent code on architectures where that's possible, i.e. on x86.pieโ Code generation produces an-fpieexecutable ๐. This results in similar optimizations asexec, except that-fpieis not disabled if it was specified at compilation time.relโ The compiler assumes incremental linking is happening ๐งฉ. The sections containing intermediate code for link-time optimization are merged, pre-optimized, and output to the resulting object file. In addition, if-ffat-lto-objectsis specified, binary code is produced for future non-LTO linking. The object file produced by incremental linking is smaller than a static library produced from the same object files. At link time, the result of incremental linking also loads faster than a static library, assuming that the majority of objects in the library are used.nolto-relโ Configures the compiler for incremental linking where code generation is forced, a final binary is produced, and the intermediate code for later link-time optimization is stripped ๐ช. When multiple object files are linked together, the resulting code is better optimized than with link-time optimizations disabled (for example, cross-module inlining happens), but most of the benefits of whole program optimizations are lost.
During the incremental link (by -r), the linker plugin defaults to rel. With current interfaces to GNU Binutils, it is however not possible to incrementally link LTO objects and non-LTO objects into a single mixed object file ๐ตโ๐ซ. If any of the object files in an incremental link cannot be used for link-time optimization, the linker plugin issues a warning and uses nolto-rel. To maintain whole program optimization, it's recommended to link such objects into a static library instead. Alternatively, it is possible to use H.J. Lu's binutils with support for mixed objects ๐ฅ.
-fuse-ld=bfdโ Use the bfd linker instead of the default linker ๐ ๏ธ.-fuse-ld=goldโ Use the gold linker instead of the default linker ๐ฅ.-fuse-ld=lldโ Use the LLVM lld linker instead of the default linker ๐ซ.-fuse-ld=moldโ Use the Modern Linker (mold) instead of the default linker โก.-llibrary,-l libraryโ Searches the library namedlibrarywhen linking ๐. (The second alternative, with the library as a separate argument, is only there for POSIX compliance and isn't recommended, ngl.)
The -l option is passed directly to the linker by GCC ๐ซ . Refer to your linker documentation for the exact details. The general description below applies to the GNU linker.
The linker searches a standard list of directories for the library. The directories searched include several standard system directories, plus any that you specify with -L ๐๏ธ.
Static libraries are archives of object files, and have file names like liblibrary.a. Some targets also support shared libraries, which typically have names like liblibrary.so. If both static and shared libraries are found, the linker gives preference to linking with the shared library unless the -static option is used ๐ฏ.
It makes a difference where in the command you write this option ๐. The linker searches and processes libraries and object files in the order they're specified. So foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded ๐ฑ.
-lobjcโ You need this special case of the-loption to link an Objective-C or Objective-C++ program ๐.-nostartfilesโ Don't use the standard system startup files when linking ๐ซ. The standard system libraries are still used normally, unless-nostdlib,-nolibc, or-nodefaultlibsis used.-nodefaultlibsโ Don't use the standard system libraries when linking ๐ . Only the libraries you specify are passed to the linker, and options specifying linkage of the system libraries, such as-static-libgccor-shared-libgcc, are ignored. The standard startup files are still used normally, unless-nostartfilesis used.
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified ๐งฏ.
-nolibcโ Don't use the C library, or the system libraries tightly coupled with it, when linking ๐ง. You still link with the startup files, libgcc, or toolchain-provided language support libraries such aslibgnat,libgfortran, orlibstdc++, unless options preventing their inclusion are used as well. This typically removes-lcfrom the link command line, along with system libraries that normally go with it and become meaningless when the absence of a C library is assumed, for example-lpthreador-lmin some configurations. This is intended for bare-board targets where there really is no C library available ๐ค.-nostdlibโ Don't use the standard system startup files or libraries when linking ๐. No startup files are used, and only the libraries you specify are passed to the linker. Options specifying linkage of the system libraries, such as-static-libgccor-shared-libgcc, are ignored.
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified ๐ซฃ.
๐ One of the standard libraries bypassed by-nostdliband-nodefaultlibsislibgcc.a, a library of internal subroutines which GCC uses to overcome shortcomings of particular machines, or special needs for some languages.
In most cases, you still need libgcc.a even when you're trying to dodge the other standard libraries ๐ซถ so when you go with -nostdlib or -nodefaultlibs, you should usually add -lgcc too. That way you won't end up with unresolved references to GCC's internal library subroutines โจ (an example is __main, which makes sure C++ constructors get called ๐
)
-e entry,--entry=entryโ okay so this sets the program entry point to entry. The linker is the one who reads it, and the GNU linker takes either a symbol name or an address ๐ฆ-pieโ makes a dynamically linked position independent executable on targets that support it ๐
For predictable results, you must also specify the same set of options used for compilation (-fpie,-fPIE, or model suboptions) when you use this linker option. Don't skip this, bestie ๐ญ
-no-pieโ the opposite energy: no dynamically linked position independent executable for you ๐ โโ๏ธ-static-pieโ a static position independent executable on targets that support it ๐ธ It's similar to a static executable, but it can be loaded at any address without a dynamic linker, which is so iconic ๐
Same rule applies: for predictable results, you must also specify the same set of options used for compilation (-fpie,-fPIE, or model suboptions) when you use this linker option.
-pthreadโ links with the POSIX threads library ๐งต This one is supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets. On some targets it also sets flags for the preprocessor, so use it consistently for both compilation and linking, periodt โจ-rโ produces a relocatable object as output. This is also known as partial linking ๐งฉ-rdynamicโ passes the flag-export-dynamicto the ELF linker on targets that support it. This tells the linker to add all symbols, not just the used ones, to the dynamic symbol table ๐ It's needed for some uses ofdlopenor to get backtraces from inside a program, so it's giving very necessary energy ๐-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 has no effect, so don't stress ๐-sharedโ produces a shared object that can then be linked with other objects to form an executable ๐ฆ Not all systems support this one.
For predictable results, you must also specify the same set of options used for compilation (-fpic,-fPIC, or model suboptions) when you use this linker option.[1]
-shared-libgcc,-static-libgccโ on systems that provide libgcc as a shared library, these force the use of either the shared or the static version, respectively. If no shared version of libgcc was built when the compiler was configured, these do nothing ๐
Okay, so there are a few situations where an app should use the shared libgcc instead of the static one. The biggest one is when the app wants to throw and catch exceptions across different shared libraries. In that case, each of the libraries and the app itself should use the shared libgcc ๐ซถ
That's why the G++ driver automatically adds -shared-libgcc whenever you build a shared library or a main executable. C++ programs typically use exceptions, so this is the right move, fr fr โจ
If you use the GCC driver to make shared libraries instead, they might not always get linked with the shared libgcc. If GCC finds at configuration time that you have a non-GNU linker, or a GNU linker that doesn't support 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, linking with the static version of libgcc by default instead. This lets exceptions propagate through those shared libraries without incurring relocation costs at library load time ๐ธ
But 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 it gets linked with the shared libgcc. No skipping 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 against 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 against 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 against 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 against 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 against 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 overridden by the link editor option-Xlinker -z -Xlinker defs). Only a few systems support this one ๐-T scriptโ uses script as the linker script ๐ This is supported by most systems using the GNU linker. On some targets, like bare-board targets without an operating system,-Tmay be required when linking to avoid references to undefined symbols.-Xlinker optionโ passes option to the linker as an option ๐ ๏ธ Use this to supply system-specific linker options that GCC doesn't recognize, lowkey a lifesaver ๐
If you want to pass an option that takes a separate argument, you have to use -Xlinker twice: once for the option and once for the argument. For example, to pass -assert definitions, you must write -Xlinker -assert -Xlinker definitions. Writing -Xlinker "-assert definitions" does not work, because that passes the entire string as one single argument, which is not what the linker expects ๐
With the GNU linker, it's usually more convenient to pass arguments using the option=value syntax instead of separate arguments. For example, you can write -Xlinker -Map=output.map rather than -Xlinker -Map -Xlinker output.map. Other linkers may not support this syntax for command-line options โจ
-Wl,optionโ passes option to the linker too ๐ If option contains commas, it gets split into multiple options at the commas. You can use this syntax to pass an argument to the option. For example,-Wl,-Map,output.mappasses-Map output.mapto the linker. With the GNU linker, you can also get the same effect with-Wl,-Map=output.map๐ง
NOTE: In Ubuntu 8.10 and later versions, for LDFLAGS, the option-Wl,-z,relrois used. To disable it, use-Wl,-z,norelro.
-u symbolโ pretends the symbol symbol is undefined, to force linking of 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 on to the linker along with the keyword keyword. Check the section in your linker's documentation for permitted values and what they mean ๐
โจ Options for Directory Search โจ
These options specify directories to search for header files, for libraries, and for parts of the compiler ๐๏ธ
-I dir,-iquote dir,-isystem dir,-idirafter dirโ adds the directory dir to the list of directories searched for header files during preprocessing ๐ If dir begins with=or$SYSROOT, then the=or$SYSROOTis replaced by the sysroot prefix. See--sysrootand-isysroot.
Directories specified with -iquote only apply to the quote form of the directive, #include "file". Directories specified with -I, -isystem, or -idirafter apply to lookup for both the #include "file" and #include <file> directives ๐
You can specify any number or combination of these options on the command line to search for header files in several directories. The lookup order goes like this ๐งญ
- For the quote form of the include directive, the directory of the current file is searched first.
- For the quote form of the include directive, the directories specified by
-iquoteoptions are searched in left-to-right order, as they appear on the command line. - Directories specified with
-Ioptions are scanned in left-to-right order. - Directories specified with
-isystemoptions are scanned in left-to-right order. - Standard system directories are scanned.
- Directories specified with
-idirafteroptions are scanned in left-to-right order.
Okay bestie, so you can totally use -I to override a system header file ๐ by swapping in your own version, because these directories get searched before the standard system header directories โจ. BUT (big but) don't use this option to add directories full of vendor-supplied system headers ๐. Use -isystem for that ๐
.
The -isystem and -idirafter options also mark the directory as a system directory ๐ฆ, so it gets the same VIP treatment as the standard system directories ๐.
If a standard system include directory, or a directory given with -isystem, is also given with -I, the -I gets ignored ๐. The directory is still searched, just as a system directory at its normal spot in the system include chain ๐ง. This is so GCC's procedure to fix buggy system headers and the ordering for the "#include_next" directive don't get messed up by accident ๐ซถ. If you really need to change the search order for system directories, go with the -nostdinc and/or -isystem options ๐ฅ.
-I-โ Split the include path ๐ธ. This one is deprecated, so please use-iquoteinstead for the-Idirectories that come before the-I-, and then remove the-I-option.- Any directories given with
-Ioptions before-I-only get searched for headers requested with"#include "file"". They don't get searched for"#include <file>". - If more directories are given with
-Ioptions after the-I-, those get searched for all#includedirectives. -I-also stops the directory of the current file from being used as the first search directory for"#include "file"". There's no way to override this effect of-I-๐.
- Any directories given with
-iprefix prefixโ Pickprefixas the prefix for the later-iwithprefixoptions ๐ง. If the prefix represents a directory, make sure you include the final/๐.-iwithprefix dir,-iwithprefixbefore dirโ Tackdironto the prefix you set earlier with-iprefix, and add the result to the include search path ๐ฃ๏ธ.-iwithprefixbeforeputs it in the same spot-Iwould, while-iwithprefixputs it where-idirafterwould ๐.-isysroot dirโ This is basically the--sysrootoption, but it only applies to header files ๐. The exception is Darwin targets, where it applies to both header files and libraries. Check out--sysrootfor more info ๐ .-imultilib dirโ Usediras a subdirectory of the directory that holds the target-specific C++ headers ๐.-nostdincโ Don't search the standard system directories for header files ๐ . Only the directories given with-I,-iquote,-isystem, and/or-idirafter(plus the current file's directory, if that's appropriate) get searched โจ.-nostdinc++โ Skip the C++-specific standard directories when searching for headers, but keep searching the other standard directories ๐. (This one gets used when building the C++ library ๐.)-iplugindir=dirโ Set the directory to search for plugins that get passed with-fplugin=nameinstead of-fplugin=path/name.so๐. This isn't really meant for you to use ๐. Only the driver passes it along ๐.-Ldirโ Add directorydirto the list of directories searched for-l๐.-Bprefixโ This tells the compiler where to find its own executables, libraries, include files, and data files ๐ง.- The compiler driver runs one or more of the subprograms
cpp,cc1,as, andld๐. It triesprefixas a prefix for each program it runs, both with and withoutmachine/version/for the corresponding target machine and compiler version. - For each subprogram, the driver first tries the
-Bprefix, if there is one. If that name isn't found, or if-Bisn't specified, the driver tries two standard prefixes,/usr/lib/gcc/and/usr/local/lib/gcc/. If neither of those turns up a file that's found, the unmodified program name gets searched for using the directories in yourPATHenvironment variable ๐บ๏ธ. - The compiler checks whether the path given by
-Brefers to a directory, and if needed it adds a directory separator character to 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 this 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 are tried, and that's all ๐. The file is left out of the link if it isn't found by those means. - Another way to specify a prefix much like the
-Bprefix is to use the environment variableGCC_EXEC_PREFIX๐ท. - As a special kludge ๐ ๏ธ, if the path given by
-Bis[dir/]stageN/, whereNis a number in the range 0 to 9, then it gets replaced by[dir/]include. This is to help with boot-strapping the compiler ๐ฅพ.
- The compiler driver runs one or more of the subprograms
-no-canonical-prefixesโ Don't expand any symbolic links ๐, don't resolve references to/../or/./, and don't make the path absolute when generating a relative prefix ๐ .--sysroot=dirโ Usediras the logical root directory for headers and libraries ๐. For example, if the compiler normally searches for headers in/usr/includeand libraries in/usr/lib, it searchesdir/usr/includeanddir/usr/libinstead.- If you use both this option and
-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 aspect of
--sysrootstill works, but the library aspect doesn't ๐ญ.
- If you use both this option and
--no-sysroot-suffixโ For some targets, a suffix gets added to the root directory given with--sysroot, depending on the other options you used ๐ง. So headers might be found indir/suffix/usr/includeinstead ofdir/usr/include. This option turns off adding that suffix ๐ซ.
๐ Options for Code Generation Conventions ๐
These machine-independent options control the interface conventions used in code generation ๐ง .
Most of them have both positive and negative forms, and the negative form of -ffoo is -fno-foo ๐. In the list below, only one of the forms is listed, the one that is not the default. You can figure out the other form by either removing no- or adding it ๐งฉ.
-fstack-reuse=reuse-levelโ This option controls stack space reuse for user declared local/auto variables and compiler generated temporaries ๐งบ.reuse_levelcan beall,named_vars, ornone.allenables stack reuse for all local variables and temporaries,named_varsenables reuse only for user defined local variables with names, andnonedisables stack reuse completely ๐. The default value isall. The 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 lifetime of a variable ends, and if the variable lives in memory, the optimizing compiler has the freedom to reuse its stack space with other temporaries or scoped local variables whose live range does not overlap with it.
Legacy code extending local lifetime is likely to break with the stack reuse optimization ๐ญ.
For example,
int *p;
{
int local1;
p = &local1;
local1 = 10;
....
}
{
int local2;
local2 = 20;
...
}
if (*p == 10) // out of scope use of local1
{
}
Another example:
struct A
{
A(int k) : i(k), j(k) { }
int i;
int j;
};
A *ap;
void foo(const A& ar)
{
ap = &ar;
}
void bar()
{
foo(A(10)); // temp object's lifetime ends when foo returns
{
A a(20);
....
}
ap->i+= 10; // ap references out of scope temp whose space
// is reused with a. What is the value of ap->i?
}
The lifetime of a compiler generated temporary is well defined by the C++ standard ๐. When a lifetime of a temporary ends, and if the temporary lives in memory, the optimizing compiler has the freedom to reuse its stack space with other temporaries or scoped local variables whose live range does not overlap with it. However, some of the legacy code relies on the behavior of older compilers in which temporaries' stack space is not reused, and the aggressive stack reuse can lead to runtime errors ๐. This option is used to control the temporary stack reuse optimization โจ.
-ftrapvโ This option generates traps for signed overflow on addition, subtraction, and multiplication operations ๐จ. The options-ftrapvand-fwrapvoverride each other, so using-ftrapv -fwrapvon the command-line results in-fwrapvbeing effective. Note that only active options override, so using-ftrapv -fwrapv -fno-wrapvon the command-line results in-ftrapvbeing effective.-fwrapvโ This option tells the compiler to assume that signed arithmetic overflow of addition, subtraction, and multiplication wraps around using twos-complement representation ๐. This flag enables some optimizations and disables others ๐๏ธ. The options-ftrapvand-fwrapvoverride each other, so using-ftrapv -fwrapvon the command-line results in-fwrapvbeing effective. Note that only active options override, so using-ftrapv -fwrapv -fno-wrapvon the command-line results in-ftrapvbeing effective.-fwrapv-pointer: okay bestie, this one tells the compiler to assume pointer arithmetic overflow on addition and subtraction just wraps around using twos-complement representation ๐โจ It also turns off some optimizations that would otherwise assume pointer overflow is invalid ๐-fstrict-overflow: lowkey the opposite energy ๐ It implies-fno-wrapv -fno-wrapv-pointer. When you negate it (-fno-strict-overflow), it implies-fwrapv -fwrapv-pointerinstead ๐ฆ-fexceptions: enables exception handling ๐ It generates the extra code needed to propagate exceptions. On some targets it also means GCC generates frame unwind information for every function, which can add significant data size overhead (it doesn't touch execution, though ๐ฆ).
If you don't specify it, 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 usually need it. You might still need to enable it when compiling C code that has to interoperate with exception handlers written in C++ ๐ซถ And you might wanna disable it if you're compiling older C++ programs that don't use exception handling ๐
-fnon-call-exceptions: makes trapping instructions able to throw exceptions ๐งจ Heads up, this needs platform-specific runtime support that doesn't exist everywhere. It only lets trapping instructions throw exceptions (so memory references or floating-point instructions). It can't throw exceptions out of arbitrary signal handlers like"SIGALRM", so don't even try ๐ โโ๏ธ-fdelete-dead-exceptions: instructions that might throw exceptions but don't otherwise contribute to the program's execution can get optimized away ๐๏ธ This is on by default for the Ada front end, which the Ada language specification permits. The optimization passes that remove dead exceptions are enabled independently at different optimization levels.-funwind-tables: basically-fexceptions, except it only generates any needed static data and doesn't change the generated code in any other way ๐ You usually don't need to turn this on yourself, because a language processor that needs this handling enables it for you ๐ง-fasynchronous-unwind-tables: generates an unwind table in DWARF format, if the target machine supports it ๐บ๏ธ The table is exact at every instruction boundary, so it can be used for stack unwinding from asynchronous events, like a debugger or a garbage collector ๐ซง-fno-gnu-unique: okay this one is a little messy ๐ฅด With a recent GNU assembler and C library, the C++ compiler uses the"STB_GNU_UNIQUE"binding so template static data members and static local variables in inline functions stay unique even with"RTLD_LOCAL". That's needed so a library used by two different"RTLD_LOCAL"plugins doesn't end up disagreeing about the symbol's binding.
The catch? This makes dlclose get ignored for affected DSOs. If your program relies on reinitializing a DSO through dlclose and dlopen, you can use -fno-gnu-unique ๐
-fpcc-struct-return: returnsshortstructandunionvalues in memory, like the longer ones, instead of in registers ๐งฑ It's less efficient, but it lets GCC-compiled files play nicely with files built by other compilers, especially the Portable C Compiler (pcc) ๐ค
The exact convention for returning structures in memory depends on the target configuration macros. Short structures and unions are the ones whose size and alignment match some integer type.
Warning: code compiled with-fpcc-struct-returnis not binary compatible with code compiled with-freg-struct-return. Only use it to conform to a non-default application binary interface โ ๏ธ
-freg-struct-return: returnsstructandunionvalues in registers whenever possible ๐๏ธ It's more efficient for small structures than-fpcc-struct-return.
If you specify neither flag, GCC goes with whatever convention is standard for the target. If there's no standard convention, it defaults to -fpcc-struct-return, except on targets where GCC is the principal compiler. In those cases GCC gets to choose the standard, and it picked the more efficient register return option ๐
Warning: code compiled with-freg-struct-returnis not binary compatible with code compiled with-fpcc-struct-return. Only use it to conform to a non-default application binary interface โ ๏ธ
-fshort-enums: anenumtype only gets as many bytes as it needs for its declared range of values ๐ข Specifically, theenumtype ends up equivalent to the smallest integer type that has enough room.
Warning: -fshort-enums makes GCC generate code that is not binary compatible with code generated without it. Only use it to conform to a non-default application binary interface โ ๏ธ
-fshort-wchar: overrides the underlying type ofwchar_tto beshort unsigned intinstead of the target's default ๐ธ This is handy for building programs that run under WINE.
Warning: -fshort-wchar makes GCC generate code that is not binary compatible with code generated without it. Only use it to conform to a non-default application binary interface โ ๏ธ
-fcommon: in C code, this controls where global variables defined without an initializer get placed. These are called tentative definitions in the C standard ๐ They're different from declarations using theexternkeyword, which don't allocate any storage.
The default is -fno-common, which puts uninitialized global variables in the BSS section of the object file. That stops the linker from merging tentative definitions, so if the same variable is accidentally defined in more than one compilation unit, you get a multiple-definition error. Good for catching mistakes ๐
-fcommon puts uninitialized global variables in a common block instead. That lets the linker resolve all the tentative definitions of the same variable across different compilation units to the same object, or to a non-tentative definition. This behavior is inconsistent with C++, and on many targets it costs a speed and code size penalty on global variable references. It's mainly useful for getting legacy code to link without errors ๐ฆ
-fno-ident: ignores the#identdirective ๐-finhibit-size-directive: don't output a.sizeassembler directive, or anything else that would cause trouble if the function gets split in the middle with the two halves placed far apart in memory ๐งฉ This one is used when compilingcrtstuff.c, so you probably won't need it for anything else.-fverbose-asm: adds extra commentary to the generated assembly so it's easier to read ๐ This is mostly for people who actually need to read generated assembly, like when debugging the compiler itself ๐งโ๐ป
-fno-verbose-asm, the default, leaves that extra info out, which is useful when you're comparing two assembler files โ๏ธ
The added comments include:
- information on the compiler version and command-line options,
- the source code lines associated with the assembly instructions, in the form
FILENAME:LINENUMBER:CONTENT OF LINE, - hints on which high-level expressions correspond to the various assembly instruction operands.
For example, given this C source file:
int test (int n)
{
int i;
int total = 0;
for (i = 0; i < n; i++)
total += i * i;
return total;
}
Compiling it to (x86_64) assembly with -S and sending the result straight to stdout with -o - looks like this:
gcc -S test.c -fverbose-asm -Os -o -
That gives output similar to this ๐
.file "test.c"
# GNU C11 (GCC) version 7.0.0 20160809 (experimental) (x86_64-pc-linux-gnu)
[...snip...]
# options passed:
[...snip...]
.text
.globl test
.type test, @function
test:
.LFB0:
.cfi_startproc
# test.c:4: int total = 0;
xorl %eax, %eax # <retval>
# test.c:6: for (i = 0; i < n; i++)
xorl %edx, %edx # i
.L2:
# test.c:6: for (i = 0; i < n; i++)
cmpl %edi, %edx # n, i
jge .L5 #,
# test.c:7: total += i * i;
movl %edx, %ecx # i, tmp92
imull %edx, %ecx # i, tmp92
# test.c:6: for (i = 0; i < n; i++)
incl %edx # i
# test.c:7: total += i * i;
addl %ecx, %eax # tmp92, <retval>
jmp .L2 #
.L5:
# test.c:10: }
ret
.cfi_endproc
.LFE0:
.size test, .-test
.ident "GCC: (GNU) 7.0.0 20160809 (experimental)"
.section .note.GNU-stack,"",@progbits
The comments are meant for humans rather than machines, so the precise format of them is subject to change ๐
-frecord-gcc-switches: records the command line used to invoke the compiler into the object file being created ๐๏ธ This is only implemented on some targets, and the exact format depends on the target and binary file format, but it usually takes the form of a section containing ASCII text. It's related to-fverbose-asm, but that one only records info as comments in the assembler output file, so it never reaches the object file. See also-grecord-gcc-switchesfor another way of storing compiler options in the object file โจ-fpicโ okay bestie, this one spits out position-independent code (PIC) that's ready to live in a shared library ๐, if your target machine supports it โจ. Every constant address gets accessed through a global offset table (GOT). The dynamic loader fills in the GOT entries when the program starts (the dynamic loader is not part of GCC, it's part of the operating system ๐). If the GOT size for the linked executable goes over a machine-specific maximum, the linker throws an error saying-fpicdoes not work, and then you just recompile with-fPICinstead ๐ . (These maximums are 8k on the SPARC, 28k on AArch64 and 32k on the m68k and RS/6000. The x86 has no such limit ๐ซถ.)- Position-independent code needs special support, so it only works on certain machines ๐ฆ. For the x86, GCC supports PIC for System V but not for the Sun 386i ๐. Code generated for the IBM RS/6000 is always position-independent ๐.
- When this flag is set, the macros
__pic__and__PIC__are defined to 1 โจ.
-fPICโ if the target machine supports it, this emits position-independent code that's suitable for dynamic linking and has no limit on the size of the global offset table ๐. This one actually makes a difference on AArch64, m68k, PowerPC and SPARC ๐.- Position-independent code needs special support, so it only works on certain machines.
- When this flag is set, the macros
__pic__and__PIC__are defined to 2.
-fpie,-fPIEโ these are giving the same energy as-fpicand-fPIC, BUT the PIC they generate can only be linked into executables ๐ง. Usually you'd use these to compile code that's getting linked with the-pieGCC option.-fpieand-fPIEboth define the macros__pie__and__PIE__. The macros have the value 1 for-fpieand 2 for-fPIE.
-fno-pltโ don't 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 because it kills the PLT stubs and exposes GOT loads to optimizations ๐ฅ. On architectures like 32-bit x86, where PLT stubs expect the GOT pointer in a specific register, this gives the compiler more register allocation freedom ๐ . Lazy binding needs the PLT, so with-fno-pltall external symbols get resolved at load time โฐ.- Alternatively, the function attribute
nopltcan be used to avoid calls through the PLT for specific external functions ๐. - In position-dependent code, a few targets also convert calls to functions that are marked to not use the PLT so they use the GOT instead โจ.
- Alternatively, the function attribute
-fno-jump-tablesโ don't use jump tables for switch statements, even where they'd be more efficient than other code generation strategies ๐. This is handy alongside-fpicor-fPICwhen you're building code that forms part of a dynamic linker and can't reference the address of a jump table. On some targets, jump tables don't require a GOT, so this option isn't needed there ๐.
-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 must be the name of a register. The accepted register names are machine-specific and are defined in the
REGISTER_NAMESmacro in the machine description macro file. - This flag doesn't have a negative form, because it specifies a three-way choice.
- reg must be the name of a register. The accepted register names are machine-specific and are defined in the
-fcall-used-regโ treat the register named reg as an allocable register that gets clobbered by function calls ๐ซ. It may be allocated for temporaries or variables that don't live across a call. Functions compiled this way do not save and restore the register reg.- It is an error to use this flag with the frame pointer or stack pointer. Using it for other registers that have fixed pervasive roles in the machine's execution model produces disastrous results ๐.
- This flag doesn't have a negative form, because it specifies a three-way choice.
-fcall-saved-regโ treat the register named reg as an allocable register that'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 reg if they use it.- It is an error to use this flag with the frame pointer or stack pointer. Using it for other registers that have fixed pervasive roles in the machine's execution model produces disastrous results ๐.
- A different sort of disaster results from using this flag for a register where function values may be returned ๐ญ.
- This flag doesn't have a negative form, because it specifies a three-way choice.
-fpack-struct[=n]โ without a value, pack all structure members together without holes ๐ฆ. When you give a value (which must be a small power of two), members get packed according to that value, which is the maximum alignment (that is, objects with default alignment requirements larger than this are output potentially unaligned at the next fitting location.
Warning: the -fpack-struct switch causes GCC to generate code that is not binary compatible with code generated without that switch. Additionally, it makes the code suboptimal. Use it to conform to a non-default application binary interface. ๐จ
-fleading-underscoreโ this one and its counterpart,-fno-leading-underscore, forcibly change the way C symbols are represented in the object file ๐. One use is to help link with legacy assembly code.
Warning: the -fleading-underscore switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to conform to a non-default application binary interface. Not all targets provide complete support for this switch. โ ๏ธ
-ftls-model=modelโ alter the thread-local storage model that gets used ๐งต. The model argument should be one ofglobal-dynamic,local-dynamic,initial-execorlocal-exec. The choice is subject to optimization: the compiler may use a more efficient model for symbols not visible outside of the translation unit, or if-fpicis not given on the command line.- The default without
-fpicisinitial-exec; with-fpicthe default isglobal-dynamic.
- The default without
-ftrampolinesโ for targets that normally need trampolines for nested functions, always generate them instead of using descriptors ๐งฉ. Otherwise, for targets that don't need them, like HP-PA or IA-64, it does nothing.- A trampoline is a small piece of code that's created at run time on the stack when the address of a nested function is taken, and it's used to call the nested function indirectly. Therefore, it requires the stack to be made executable in order for the program to work properly ๐ฑ.
-fno-trampolinesis enabled by default on a language-by-language basis to let the compiler avoid generating them, if it computes that this is safe, and replace them with descriptors. Descriptors are made up of data only, but the generated code must be prepared to deal with them. As of this writing,-fno-trampolinesis enabled by default only for Ada.- Code compiled with
-ftrampolinesand code compiled with-fno-trampolinesare not binary compatible if nested functions are present. This option must therefore be used on a program-wide basis and be manipulated with extreme care ๐ซฃ.
-fvisibility=[default|internal|hidden|protected]โ set the default ELF image symbol visibility to the specified option. All symbols are marked with this unless overridden within the code ๐. Using this feature can substantially improve linking and load times of shared object libraries, produce more optimized code, provide near-perfect API export and prevent symbol clashes. It's strongly recommended that you use this in any shared objects you distribute ๐ซถ.- Despite the nomenclature,
defaultalways means public; i.e., available to be linked against from outside the shared object.protectedandinternalare pretty useless in real-world usage, so the only other commonly used option ishidden. The default if-fvisibilityisn't specified isdefault, i.e., make every symbol public. - A good explanation of the benefits offered by ensuring ELF symbols have the correct visibility is given by "How To Write Shared Libraries" by Ulrich Drepper (which can be found at
https://www.akkadia.org/drepper/). However, a superior solution made possible by this option, to marking things hidden when the default is public, is to make the default hidden and mark things public. This is the norm with DLLs on Windows, and with-fvisibility=hiddenand__attribute__ ((visibility("default")))instead of__declspec(dllexport)you get almost identical semantics with identical syntax. This is a great boon to those working with cross-platform projects ๐ธ. - For those adding visibility support to existing code, you may find
#pragma GCC visibilityof use. This works by enclosing the declarations you wish to set visibility for with (for example)#pragma GCC visibility push(hidden)and#pragma GCC visibility pop. Bear in mind that symbol visibility should be viewed as part of the API interface contract, and thus all new code should always specify visibility when it is not the default; i.e., declarations only for use within the local DSO should always be marked explicitly as hidden so as to avoid PLT indirection overheads. Making this abundantly clear also aids readability and self-documentation of the code. Note that due to ISO C++ specification requirements,operator newandoperator deletemust always be of default visibility. - Be aware that headers from outside your project, in particular system headers and headers from any other library you use, may not be expecting to be compiled with visibility other than the default. You may need to explicitly say
#pragma GCC visibility push(default)before including any such headers.
- Despite the nomenclature,
๐ Continuing the -fvisibility tea โ
Okay, bestie, extern declarations are not affected by -fvisibility ๐ So a lot of code can be recompiled with -fvisibility=hidden with zero modifications โจ BUT, and this is a big but, calls to extern functions with no explicit visibility go through the PLT. So it's way more effective to use __attribute ((visibility)) and/or #pragma GCC visibility to tell the compiler which extern declarations should be treated as hidden ๐
Also, -fvisibility does affect C++ vague linkage entities ๐ง That means an exception class that gets thrown between DSOs must be explicitly marked with default visibility, so the type_info nodes get unified between the DSOs. Main character energy for real ๐
An overview of all these techniques, what they're good for, and how to use them lives at http://gcc.gnu.org/wiki/Visibility ๐
๐ฆ -fstrict-volatile-bitfields
Use this one if you want accesses to volatile bit-fields (or other structure fields, though the compiler usually respects those types anyway) to be a single access of the field's type width, aligned to a natural alignment when possible ๐ Like, targets with memory-mapped peripheral registers might need every access to be 16 bits wide. With this flag you can declare all the peripheral bit-fields as unsigned short (assuming short is 16 bits on those targets) and force GCC to use 16-bit accesses instead of a more efficient 32-bit one ๐
If this option is disabled, the compiler picks the most efficient instruction ๐ซถ In that example, that might be a 32-bit load, even though it touches bytes that have no part of the bit-field in them, or memory-mapped registers that have nothing to do with the one being updated. Yikes ๐
In some cases, like when the packed attribute is applied to a structure field, it might not be possible to access the field with one read or write that's correctly aligned for the target machine. When that happens, GCC falls back to generating multiple accesses, instead of code that would 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. So it's recommended to define all the bits of the field's type as bit-field members ๐
The default value of this option is determined by the application binary interface for the target processor ๐ธ
โจ -fsync-libcalls
This option controls whether any out-of-line instance of the __sync family of functions can be used to implement the C++11 __atomic family of functions ๐
The default is enabled, so the only useful form of this option is -fno-sync-libcalls ๐ฅ It's used in the implementation of the libatomic runtime library, so you know it's serious business ๐
๐ GCC Developer Options ๐
Okay so this section is all about command-line options that are mostly for GCC developers ๐ง That includes options for compiler testing, digging into compiler bugs, and checking compile-time performance problems. You'll find options that produce debug dumps at various points in compilation, options that print stats like memory use and execution time, and options that print info about GCC's configuration, like where it searches for libraries ๐ Real talk: you should rarely need any of these for ordinary compiling 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 left out, GCC builds a default dump file name 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 if you explicitly specified one and it's not an executable. Otherwise it's the source file name. The pass number is determined by the order passes get registered with the compiler's pass manager. That's usually the same as execution order, BUT passes registered by plugins, target-specific passes, or passes that are otherwise registered late get numbered higher than the pass named final, even if they actually run earlier ๐ญ The phase letter is one of i (inter-procedural analysis), l (language-specific), r (RTL), or t (tree). The files get created in the directory of the output file ๐
๐ธ -fcallgraph-info, -fcallgraph-info=MARKERS
These make the compiler output callgraph information for your program, on a per-object-file basis ๐ธ๏ธ The info is generated in the common VCG format. You can decorate it with extra per-node and/or per-edge information by passing a comma-separated list of markers. When the su marker is specified, the callgraph gets decorated with stack usage information, which is equivalent to -fstack-usage ๐ When the da marker is specified, the callgraph gets decorated with info about dynamically allocated objects ๐
When you compile with -flto, no callgraph information is output along with the object file ๐ At LTO link time, -fcallgraph-info may generate multiple callgraph information files next to the intermediate LTO output files.
๐ฎ -dletters, -fdump-rtl-pass, -fdump-rtl-pass=filename
These say to make debugging dumps during compilation at the times specified by letters ๐งช This is used for debugging the RTL-based passes of the compiler, so it's giving nerdy and iconic ๐ค
Some -dletters switches mean something different when -E is used for preprocessing ๐ซถ
You can enable debug dumps with a -fdump-rtl switch or with some -d option letters. Here are the possible letters you can use in pass and letters, and what they mean ๐
-fdump-rtl-alignmentsโ Dump after branch alignments have been computed. ๐-fdump-rtl-asmconsโ Dump after fixing RTL statements that have unsatisfied in/out constraints. ๐-fdump-rtl-auto_inc_decโ Dump after auto-inc-dec discovery. This pass only runs on architectures that have auto inc or auto dec instructions. โจ-fdump-rtl-barriersโ Dump after cleaning up the barrier instructions. ๐งน-fdump-rtl-bbpartโ Dump after partitioning hot and cold basic blocks. ๐ฅ-fdump-rtl-bbroโ Dump after block reordering. ๐-fdump-rtl-btl1,-fdump-rtl-btl2โ These enable dumping after the two branch target load optimization passes. ๐ฏ-fdump-rtl-bypassโ Dump after jump bypassing and control flow optimizations. ๐ฆ-fdump-rtl-combineโ Dump after the RTL instruction combination pass. ๐งฉ-fdump-rtl-compgotosโ Dump after duplicating the computed gotos. ๐-fdump-rtl-ce1,-fdump-rtl-ce2,-fdump-rtl-ce3โ These enable dumping after the three if conversion passes. ๐-fdump-rtl-cprop_hardregโ Dump after hard register copy propagation. ๐-fdump-rtl-csaโ Dump after combining stack adjustments. ๐ฅ-fdump-rtl-cse1,-fdump-rtl-cse2โ These enable dumping after the two common subexpression elimination passes. ๐ธ-fdump-rtl-dceโ Dump after the standalone dead code elimination passes. ๐๏ธ-fdump-rtl-dbrโ Dump after delayed branch scheduling. โณ-fdump-rtl-dce1,-fdump-rtl-dce2โ These enable dumping after the two dead store elimination passes. ๐-fdump-rtl-ehโ Dump after finalization of EH handling code. ๐-fdump-rtl-eh_rangesโ Dump after conversion of EH handling range regions. ๐-fdump-rtl-expandโ Dump after RTL generation. ๐ฑ-fdump-rtl-fwprop1,-fdump-rtl-fwprop2โ These enable dumping after the two forward propagation passes. โก๏ธ-fdump-rtl-gcse1,-fdump-rtl-gcse2โ These enable dumping after global common subexpression elimination. ๐-fdump-rtl-init-regsโ Dump after the initialization of the registers. ๐-fdump-rtl-initvalsโ Dump after the computation of the initial value sets. ๐งฎ-fdump-rtl-into_cfglayoutโ Dump after converting to cfglayout mode. ๐บ๏ธ-fdump-rtl-iraโ Dump after iterated register allocation. ๐จ-fdump-rtl-jumpโ Dump after the second jump optimization. ๐ฆ-fdump-rtl-loop2โ This enables dumping after the RTL loop optimization passes. ๐-fdump-rtl-machโ Dump after performing the machine dependent reorganization pass, if that pass exists. ๐ ๏ธ-fdump-rtl-mode_swโ Dump after removing redundant mode switches. โ๏ธ-fdump-rtl-rnregโ Dump after register renumbering. ๐ข-fdump-rtl-outof_cfglayoutโ Dump after converting from cfglayout mode. ๐-fdump-rtl-peephole2โ Dump after the peephole pass. ๐-fdump-rtl-postreloadโ Dump after post-reload optimizations. ๐-fdump-rtl-pro_and_epilogueโ Dump after generating the function prologues and epilogues. ๐ฌ-fdump-rtl-sched1,-fdump-rtl-sched2โ These enable dumping after the basic block scheduling passes. ๐๏ธ-fdump-rtl-reeโ Dump after sign/zero extension elimination. ๐ข-fdump-rtl-seqabstrโ Dump after common sequence discovery. ๐งฌ-fdump-rtl-shortenโ Dump after shortening branches. ๐-fdump-rtl-siblingโ Dump after sibling call optimizations. ๐ฏ-fdump-rtl-split1,-fdump-rtl-split2,-fdump-rtl-split3,-fdump-rtl-split4,-fdump-rtl-split5โ These options enable dumping after five rounds of instruction splitting. โ๏ธ-fdump-rtl-smsโ Dump after modulo scheduling. This pass only runs on some architectures. ๐ถ-fdump-rtl-stackโ Dump after converting GCC's "flat register file" registers to the x87's stack-like registers. This pass only runs on x86 variants. ๐ฅ-fdump-rtl-subreg1,-fdump-rtl-subreg2โ These enable dumping after the two subreg expansion passes. ๐งฉ-fdump-rtl-unshareโ Dump after all RTL has been unshared. ๐ซง-fdump-rtl-vartrackโ Dump after variable tracking. ๐ต๏ธโโ๏ธ-fdump-rtl-vregsโ okay so this one drops a dump right after the virtual registers get swapped out for 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โ ngl these are defined, but they always produce empty files ๐ literally nothing in them, bestie ๐ญ-da,-fdump-rtl-allโ produces all the dumps listed above ๐ the full buffet ๐-dAโ annotates the assembler output with miscellaneous debugging info ๐ธ-dDโ dumps all macro definitions at the end of preprocessing, on top of the normal output ๐-dHโ produces a core dump whenever an error occurs ๐ iconic behaviour, no notes-dpโ annotates the assembler output with a comment showing which pattern and alternative got used ๐ it also prints the length and cost of each instruction, so it's giving detail ๐ฅ-dPโ dumps the RTL in the assembler output as a comment before each instruction ๐ it also turns on-dpannotation, so you get both-dxโ just generates RTL for a function instead of compiling it ๐ง usually used with-fdump-rtl-expand-fdump-debugโ dumps the debugging info generated during the debug generation phase ๐โจ-fdump-earlydebugโ dumps the debugging info generated during the early debug generation phase ๐-fdump-noaddrโ when doing debugging dumps, suppresses the address output ๐ซถ this makes it way easier todiffyour dumps when you're comparing compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations-freport-bugโ collects and dumps debug info into a temporary file if an internal compiler error (ICE) happens ๐ญ so you have receipts-fdump-unnumberedโ when doing debugging dumps, suppresses instruction numbers and address output ๐ this makesdiffway more feasible for dumps from different options, especially with and without-g-fdump-unnumbered-linksโ when doing debugging dumps (see the-doption above), suppresses the 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, so the language tree lands in a file ๐ the file name is your source file name with a switch-specific suffix appended, and it gets created in the same directory as the output file. the dumps you can ask for are:allโ enables all inter-procedural analysis dumps ๐cgraphโ dumps info about call-graph optimization, unused function removal, and inlining decisions ๐ธ๏ธinlineโ dumps after function inlining ๐ธ
on top of that, you can add -optimized, -missed, -note, and -all, which mean the same thing as they do for -fopt-info, and they default to -optimized if you don't pick one ๐
for example, -fdump-ipa-inline-optimized-missed will emit info on the callsites that got inlined, along with the callsites that didn't. by default the dump has messages about successful optimizations (same as -optimized) plus the 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 info ๐ the options and filename parts work exactly like they do in the-fdump-treeoption. the switch values you can use are:allโ enables all language-specific dumps ๐classโ dumps class hierarchy info ๐ฆ virtual table info gets emitted unless you specifyslim. this one is C++ onlyrawโ dumps the raw internal tree data ๐ง this one is C++ only too
-fdump-passesโ prints on stderr the list of optimization passes that get turned on and off by your current command-line options ๐-fdump-statistics-optionโ enables and controls dumping of pass statistics into a separate file ๐ the file name is made by appending a suffix ending in.statisticsto the source file name, and it's created in the same directory as the output file. with the-optionform,-statssums the counters over the whole compilation unit, while-detailsdumps every event as the passes generate them. with no option, the default is to sum the 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, straight to a file ๐ณ if you use the-optionsform,optionsis a list of-separated options that control the details of the dump. not every option works with every dump, and the ones that don't make sense just get ignored ๐ here's the lineup:addressโ prints the address of each node ๐ usually not meaningful, since it changes depending on the environment and source file. its main use is tying a dump file to a debug environmentasmnameโ 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 backwards from mangled names in the assembly fileslimโ when dumping front-end intermediate representations, stops members of a scope or a function body from getting dumped just because that scope was reached ๐งน only items directly reachable by some other path get dumped. when dumping pretty-printed trees, this inhibits dumping the bodies of control structures. when dumping RTL, it prints in slim (condensed) form instead of the default LISP-like representationrawโ prints a raw representation of the tree ๐งพ by default, trees get pretty-printed into a C-like representationdetailsโ enables more detailed dumps (not every dump option honours this) and also includes info from the optimization passes ๐ฌstatsโ enables dumping various statistics about the pass (again, not every dump option honours this) ๐blocksโ enables showing basic block boundaries (disabled in raw dumps) ๐งฑgraphโ for each of the other indicated dump files (-fdump-rtl-pass), dumps a representation of the control flow graph tofile.passid.pass.dot, which is suitable for viewing with GraphViz ๐ธ๏ธ each function in the file gets pretty-printed as a subgraph, so GraphViz can render them all in one plot. this option only works for RTL dumps, and the RTL is always dumped in slim formvopsโ enables showing virtual operands for every statement ๐งฉlinenoโ enables showing line numbers for statements ๐uidโ enables showing the unique ID (DECL_UID) for each variable ๐verboseโ enables showing the tree dump for each statement ๐ehโ enables showing the EH region number holding each statement ๐scevโ enables showing scalar evolution analysis details ๐optimizedโ enables showing optimization info (only available in certain passes) โmissedโ enables showing missed optimization info (only available in certain passes) โnoteโ enables other detailed optimization info (only available in certain passes) ๐๏ธallโ turns on all options, exceptraw,slim,verbose, andlineno๐optallโ turns on all optimization options, i.e.,optimized,missed, andnote๐
now, if you want to figure out which tree dumps are available, or find the dump for a pass you care about, follow these steps ๐ต๏ธโโ๏ธ
- Invoke GCC with
-fdump-passes, then look in the stderr output for a code that matches the pass you want. for example, the codestree-evrp,tree-vrp1, andtree-vrp2correspond to the three Value Range Propagation passes. the number at the end tells apart 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 can specify the name of the dump file. if you don't, GCC creates one as described below ๐ - Find the pass dump in a file whose name is made 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 ๐ฏ
โ ๏ธ bestie, the numeric codes are not stable, so they may change from one version of GCC to another. don't hardcode them ๐ โโ๏ธ
-fopt-info,-fopt-info-options,-fopt-info-options=filenameโ this controls optimization dumps from the various optimization passes โจ if you use the-optionsform,optionsis a list of-separated option keywords that select the dump details and optimizations ๐
the options split into three groups:
- options describing what kinds of messages should be emitted ๐ฌ
- options describing the verbosity of the dump ๐
- options describing which optimizations should be included ๐ ๏ธ
you can freely mix options from each group, since they don't overlap ๐ซถ but if there's ever a conflict, the later options on the command line override the earlier ones, so the last one wins ๐
the following options control which kinds of messages get emitted:
optimizedโ prints info when an optimization is successfully applied โ it's up to each pass to decide what info is relevant. for example, the vectorizer passes print the source location of loops that were successfully vectorized ๐missedโ prints info about missed optimizations โ individual passes control which information gets included in the output
noteโ okay so this one is the chatty mode ๐ฃ๏ธ It prints verbose info about optimizations, like certain transformations and more detailed messages about the decisions the compiler makes โจallโ the full send ๐ It dumps detailed optimization info, which coversoptimized,missed, andnoteall in one go ๐
Next up is the option that controls how much detail the dump spills ๐ซ
internalsโ by default you only get the "high-level" messages ๐ Turn this on and you'll get extra, more detailed messages that are mostly only of interest to GCC developers ๐งโ๐ป
Now for the keyword squad ๐ฏโโ๏ธ You can grab dumps for a whole group of optimizations at once by using one or more of these:
ipaโ dumps from all interprocedural optimizations ๐loopโ dumps from all loop optimizations ๐inlineโ dumps from all inlining optimizations ๐ฆompโ dumps from all OMP (Offloading and Multi Processing) optimizations ๐งvecโ dumps from all vectorization optimizations ๐ฆoptallโ the everything bagel ๐ฅฏ Dumps from every optimization, and it's a superset of all the groups above ๐
If you leave options out, it defaults to optimized-optall. That means you get messages about successful optimizations from all the passes, minus anything treated as "internals" ๐ซถ
If you give it a filename, the dumps from every applicable optimization get concatenated into that file. If you don't, the dump goes to stderr ๐ You can use multiple -fopt-info options, but only one of them can include a filename. If you pass other filenames, 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 a combined output from several translation units, use stderr instead ๐จ
Here's the first example, where the optimization info goes to stderr ๐
gcc -O3 -fopt-info
This one outputs a 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 ๐ธ Fun fact: -fopt-info-vec-missed is equivalent to -fopt-info-missed-vec, and the order of the group names and message types after -fopt-info doesn't matter ๐ค
gcc -O2 -ftree-vectorize -fopt-info-vec-missed
Another one, outputting missed optimizations plus optimized locations from all the inlining passes into inline.txt ๐
gcc -O3 -fopt-info-inline-optimized-missed=inline.txt
Finally, the plot twist ๐ญ Here the two output filenames, vec.miss and loop.opt, are in conflict, 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 ๐
gcc -fopt-info-vec-missed=vec.miss -fopt-info-loop-optimized=loop.opt
-fsave-optimization-recordโ this one writes aSRCFILE.opt-record.json.gzfile ๐ It details 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 ๐งช
It's roughly a machine-readable version of -fopt-info-all, organized as a collection of messages with source file, line number, and column number. Each message also carries these extra goodies โจ
- the execution count of the code being optimized, plus metadata about whether it came from actual profile data or just an estimate, so consumers can prioritize messages by code hotness ๐ฅ
- the function name of the code being optimized, where applicable ๐ฏ
- the "inlining chain" for the code being optimized, so when a function gets inlined into several different places (which might themselves be inlined), you can tell the copies apart ๐ช
- objects identifying the parts of the message that refer to expressions, statements, or symbol-table nodes, which of 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 within other messages, reflecting implementation details of the optimization passes ๐ช
-fsched-verbose=nโ for targets that use instruction scheduling, this controls how much debugging output the scheduler dumps into the dump files ๐- For
ngreater than zero, it outputs the same info as-fdump-rtl-sched1and-fdump-rtl-sched2. - For
ngreater than one, it also outputs basic block probabilities, detailed ready list 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 ๐ฅต
- For
-fenable-kind-passand-fdisable-kind-pass=range-listโ this is a whole set of options for explicitly disabling or enabling optimization passes ๐๏ธ They're meant for debugging GCC itself, so regular compiler users should stick with the normal options for enabling and disabling passes instead ๐-fdisable-ipa-passโ disables the IPA pass calledpass, wherepassis the pass name. If the same pass is statically invoked in the compiler multiple times, append a sequential number to the pass name, starting from 1.-fdisable-rtl-pass/-fdisable-rtl-pass=range-listโ disables the RTL pass calledpass. Same deal with the sequential numbering for repeated passes.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, the number pair can be simplified to a single number. If the function's call graph node uid falls within one of the specified ranges, the pass is disabled for that function. You can find the uid in the function header of a dump file, and you can dump the pass names with-fdump-passes๐-fdisable-tree-pass/-fdisable-tree-pass=range-listโ disables the tree pass calledpass. See-fdisable-rtlfor how the option arguments work ๐ณ-fenable-ipa-passโ enables the IPA pass calledpass. Same sequential numbering for repeated passes ๐ซ-fenable-rtl-pass/-fenable-rtl-pass=range-listโ enables the RTL pass calledpass. See-fdisable-rtlfor the option argument description and examples ๐ช-fenable-tree-pass/-fenable-tree-pass=range-listโ enables the tree pass calledpass. See-fdisable-rtlfor the description of option arguments ๐ฒ
Here are some examples showing how these options get used ๐ง
# 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
-fcheckingand-fchecking=nโ turns on internal consistency checking ๐ก๏ธ The default depends on how the compiler was configured.-fchecking=2enables further internal consistency checking that might affect code generation ๐ง-frandom-seed=stringโ this gives GCC a seed to use instead of random numbers when it generates certain symbol names that have to be different in every compiled file ๐ฒ It's also used to place unique stamps in coverage data files and in the object files that produce them. Use-frandom-seedif you want reproducibly identical object files ๐
The string can be a number (decimal, octal, or hex), or an arbitrary string, which gets converted to a number by computing CRC32 ๐ข
The string should be different for every file you compile ๐ซต
-save-tempsand-save-temps=cwdโ store the usual "temporary" intermediate files permanently ๐พ They go in the current directory and get named after the source file. So compilingfoo.cwith-c -save-tempsproducesfoo.iandfoo.s, as well asfoo.o. That creates a preprocessedfoo.ioutput file even though the compiler now normally uses an integrated preprocessor ๐งผ
When you combine it with the -x command-line option, -save-temps is smart enough to avoid overwriting an input source file that has the same extension as an intermediate file. If you need that intermediate file, rename the source file before using -save-temps ๐ง
Be careful if you invoke GCC in parallel ๐จ Compiling several different source files that share a common base name in different subdirectories, or the same source file compiled for multiple output destinations, means the parallel compilers will likely interfere with each other and overwrite the temporary files. For instance:
gcc -save-temps -o outdir1/foo.o indir1/foo.c&
gcc -save-temps -o outdir2/foo.o indir2/foo.c&
That might result in foo.i and foo.o being written to simultaneously by both compilers ๐ฑ
-save-temps=objโ stores the usual "temporary" intermediate files permanently too ๐ฆ If the-ooption is used, the temporary files are based on the object file. If-oisn't used,-save-temps=objbehaves just 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
-time[=file]โ okay bestie, this one tells you how much CPU time each subprocess in the compile chain ate ๐ For C source files that's the compiler proper and the assembler (plus the linker if linking happens) โจ
Without an output file, you get output that 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 time spent running the program itself. The second is "system time", which is time spent in operating system routines on the program's behalf. Both are in seconds โฑ๏ธ
With an output file, the info gets appended to that file instead, and it looks like this:
0.12 0.01 cc1 <options>
0.00 0.01 as <options>
Now the "user time" and "system time" get moved in front of the program name, and the options passed to each program get shown too, so you can later figure out which file was compiled and with what options ๐๐
-fdump-final-insns[=file]โ dumps the final internal representation (RTL) into file ๐๏ธ If you leave off the optional argument (or file is.), the dump file name is made by tacking.gkdonto the compilation output file name.-fcompare-debug[=opts]โ this one is lowkey a whole vibe ๐งช If nothing errors during compilation, GCC runs the compiler a second time, adding opts and-fcompare-debug-secondto the arguments for that second go. It dumps the final internal representation in both compilations and prints an error if they don't match.
If the equal sign is left out, the default -gtoggle is used.
The environment variable GCC_COMPARE_DEBUG, if it's defined, non-empty and nonzero, implicitly enables -fcompare-debug. If GCC_COMPARE_DEBUG is set to a string starting with a dash, that string is used for opts. Otherwise the default -gtoggle is used.
-fcompare-debug=, with the equal sign but 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 ๐
โโ๏ธ
Want full coverage during -fcompare-debug testing? Set GCC_COMPARE_DEBUG to -fcompare-debug-not-overridden. GCC rejects that as an invalid option in any actual compilation (rather than preprocessing, assembly or linking). If you only want a warning, setting GCC_COMPARE_DEBUG to -w%n-fcompare-debug not overridden will do the trick ๐ฏ
-fcompare-debug-secondโ this gets passed to the compiler implicitly for the second compilation requested by-fcompare-debug๐ซถ It comes along with options to silence warnings, and it leaves out any other options that would make the compiler write output to files or to standard output as a side effect. During that second compilation, dump files and preserved temporary files get renamed to include the additional.gkextension, so they don't overwrite the ones from the first run.
When you pass this option to the compiler driver, it makes the first compilation get skipped ๐ That makes it pretty much only useful for debugging the compiler proper.
-gtoggleโ turns off debug info generation if leaving out this option would generate it, or turns it on at level 2 otherwise ๐ Where it sits on the command line doesn't matter. It takes effect after all other options are processed, and it only does its thing once, no matter how many times you give it. This one is mainly meant to be used with-fcompare-debug.-fvar-tracking-assignments-toggleโ toggles-fvar-tracking-assignments, the same way-gtoggletoggles-g๐ฆ-Qโ makes the compiler print out each function name as it gets compiled, and print some statistics about each pass when it finishes ๐-ftime-reportโ makes the compiler print some stats about the time each pass consumed when it's done โฐ-ftime-report-detailsโ records the time consumed by infrastructure parts separately for each pass ๐งฉ-fira-verbose=nโ controls how verbose the dump file for the integrated register allocator is ๐ฃ๏ธ The default value is5. If the value n is greater than or equal to10, the dump output gets sent to stderr, using the same format as n minus 10.-flto-reportโ prints a report with internal details on how the link-time optimizer is working ๐ฌ The contents of this report vary from version to version. It's meant to be useful to GCC developers when they're processing object files in LTO mode (via-flto).
Disabled by default.
-flto-report-wpaโ same as-flto-report, but it only prints for the WPA phase of link-time optimization ๐-fmem-reportโ makes the compiler print some statistics about permanent memory allocation when it finishes ๐ง-fmem-report-wpaโ makes the compiler print some statistics about permanent memory allocation for the WPA phase only ๐ง-fpre-ipa-mem-report,-fpost-ipa-mem-reportโ makes the compiler print some statistics about permanent memory allocation either before or after interprocedural optimization ๐ธ-fprofile-reportโ makes the compiler print some statistics about how consistent the (estimated) profile is, and what effect each individual pass has ๐-fstack-usageโ makes the compiler output stack usage info for your 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 isn't an executable. Otherwise it's the basename of the source file.
Each entry has three fields:
- The name of the function.
- A number of bytes.
- One or more qualifiers: "static", "dynamic", "bounded".
The qualifier "static" means the function manipulates the stack statically. A fixed number of bytes gets allocated for the frame on function entry and released on function exit, and no other stack adjustments are made in the function. The second field is this fixed number of bytes ๐งฑ
The qualifier "dynamic" means the function manipulates the stack dynamically. On top of the static allocation described above, stack adjustments get made in the body of the function, for example to push and pop arguments around function calls ๐ If the qualifier "bounded" is also present, the amount of these adjustments is bounded at compile time, and the second field is an upper bound on the total amount of stack the function uses. If it's not present, the amount of these adjustments isn't bounded at compile time, and the second field only represents the bounded part.
-fstatsโ emits statistics about front-end processing at the end of compilation ๐ This option is only supported by the C++ front end, and the info is generally only useful to the G++ development team ๐-fdbg-cnt-listโ prints the name and the counter upper bound for all debug counters ๐ข-fdbg-cnt=counter-value-listโ sets the internal debug counter lower and upper bounds ๐๏ธ counter-value-list is a comma-separated list ofname:lower_bound1-upper_bound1 [:lower_bound2-upper_bound2...]tuples, which set the name of the counter and a list of closed intervals. The lower_bound is optional, and it's zero initialized if it isn't set. For example, with-fdbg-cnt=dce:2-4:10-11,tail_call:10,dbg_cnt(dce)returns true only for the second, third, fourth, tenth and eleventh invocation. Fordbg_cnt(tail_call), true is returned for the first 10 invocations ๐-print-file-name=libraryโ prints the full absolute name of the library file library that would be used when linking, and then stops there ๐ With this option, GCC doesn't compile or link anything. It just prints the file name.-print-multi-directoryโ prints the directory name that matches the multilib selected by any other switches on the command line ๐ This directory is supposed to exist inGCC_EXEC_PREFIX.-print-multi-libโ prints the mapping from multilib directory names to the compiler switches that enable them ๐บ๏ธ The directory name is separated from the switches by;, and each switch starts with an@instead of the-, with no spaces between multiple switches. This is supposed to make shell processing easier.-print-multi-os-directoryโ prints the path to OS libraries for the selected multilib, relative to somelibsubdirectory ๐ If OS libraries are 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,../libor../lib32. If OS libraries are present inlib/subdirsubdirectories, it prints something likeamd64,sparcv9orev6.-print-multiarchโ prints the path to OS libraries for the selected multiarch, relative to somelibsubdirectory ๐น-print-prog-name=programโ like-print-file-name, but it searches for a program such ascpp๐-print-libgcc-file-nameโ same as-print-file-name=libgcc.a๐ง
This is handy when you use -nostdlib or -nodefaultlibs but still want to link with libgcc.a. You can do:
gcc -nostdlib <files>... `gcc -print-libgcc-file-name`
-print-search-dirsโ prints the name of the configured installation directory, plus a list of the program and library directoriesgccsearches, and then stops ๐๏ธ
This is useful when gcc prints the error message installation problem, cannot exec cpp0: No such file or directory. To fix that, you either need to put cpp0 and the other compiler components where gcc expects to find them, or you can set the environment variable GCC_EXEC_PREFIX to the directory where you installed them. Don't forget the trailing / ๐จ
-print-sysrootโ prints the target sysroot directory that gets used during compilation ๐ This is the target sysroot specified either at configure time or with the--sysrootoption, possibly with an extra suffix that depends on compilation options. If no target sysroot is specified, the option prints nothing.-print-sysroot-headers-suffixโ prints the suffix added to the target sysroot when searching for headers, or gives an error if the compiler isn't configured with such a suffix, and then stops ๐ง-dumpmachineโ okay bestie, this one just spills the compiler's target machine (likei686-pc-linux-gnu) and then immediately bounces. Nothing else happens ๐-dumpversionโ prints the compiler version (like3.0,6.3.0or7) and then dips, no extra steps ๐ซถ This is the version that shows up in filesystem paths and specs, and depending on how the compiler was configured, it can be one number (major version), two numbers with a dot (major and minor), or three numbers with dots (major, minor and patchlevel) โจ-dumpfullversionโ prints the full compiler version and then leaves, no cap ๐ฅ The output is always three numbers separated by dots: major, minor and patchlevel version ๐ธ-dumpspecsโ prints the compiler's built-in specs and then stops, nothing else ๐ง (This one is mostly used when GCC itself is being built, so it's giving behind-the-scenes energy ๐)
๐ฆ Machine-Dependent Options ๐ฆ
okay so every target machine that GCC supports can have its own options ๐ Like, you might want to compile for a specific processor variant or ABI, or tweak optimizations that are specific to that machine. By convention, machine-specific option names start with -m ๐
Some configurations also have extra target-specific options, usually so they can play nice with 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 ๐ The valid values areilp32, which is the SysV-like model whereint,long intand pointers are 32 bits, andlp64, which is also SysV-like butintstays 32 bits whilelong intand pointers go up to 64 bits ๐ฆ
The default depends on your specific target configuration ๐ซถ
โ ๏ธ Heads up: the LP64 and ILP32 ABIs are not link-compatible. You have to compile your entire program with the same ABI and link it against a compatible set of libraries, or things get messy fr fr ๐
-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 the addresses and sizes of sections. Programs can only be statically linked. The-mcmodel=largeoption is incompatible with-mabi=ilp32,-fpicand-fPIC๐-mstrict-align,-mno-strict-alignโ lets you avoid (or allow) memory accesses that might not be aligned on a natural object boundary, as described in the architecture specification ๐-momit-leaf-frame-pointer,-mno-omit-leaf-frame-pointerโ omits or keeps the frame pointer in leaf functions ๐ฆ The former behavior is the default ๐-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ generates stack protection code using a canary atguard๐ก๏ธ The supported locations areglobalfor a global canary, orsysregfor a canary in an appropriate system register ๐
With the latter choice, the options -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 use. 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โ okay this exact block shows up twice in the original page, so I'm keeping it twice ๐ It does the same thing: it generates stack protection code using a canary atguard. Supported locations areglobalfor a global canary orsysregfor a canary in an appropriate system register ๐
With the latter choice, the options -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset furthermore specify which system register to use as base register for reading the canary, and from what offset from that base register. There is no default register or offset as 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,32,48๐ธ 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 erratum workaround is made at link time, and this option will only pass the corresponding flag to the linker ๐-mlow-precision-recip-sqrt,-mno-low-precision-recip-sqrtโ enables or disables the reciprocal square root approximation โจ This option only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces the precision of reciprocal square root results to about 16 bits for single precision and to 32 bits for double precision ๐ซ-mlow-precision-sqrt,-mno-low-precision-sqrtโ enables or disables the square root approximation ๐ This option only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces the precision of square root results to about 16 bits for single precision and to 32 bits for double precision. If enabled, it implies-mlow-precision-recip-sqrt๐-mlow-precision-div,-mno-low-precision-divโ enables or disables the division approximation โ This option only has an effect if-ffast-mathor-funsafe-math-optimizationsis used as well. Enabling it reduces the precision of division results to about 16 bits for single precision and to 32 bits for double precision ๐-mtrack-speculation,-mno-track-speculationโ enables or disables generating additional code to track speculative execution through conditional branches ๐ต๏ธ The tracking state can then be used by the compiler when expanding calls to"__builtin_speculation_safe_copy", so it can generate a more efficient code sequence ๐ง-moutline-atomics,-mno-outline-atomicsโ enables or disables calls to out-of-line helpers that implement atomic operations ๐งฉ These helpers figure out at runtime whether the LSE instructions from ARMv8.1-A can be used. If they can't, they use the load/store-exclusive instructions that are present in the base ARMv8.0 ISA ๐
This option only applies when you're compiling for the base ARMv8.0 instruction set. If you're using a later revision, like -march=armv8.1-a or -march=armv8-a+lse, the ARMv8.1-Atomics instructions get used directly. The same goes for -mcpu= when the selected CPU supports the lse feature. This option is on by default ๐
-march=nameโ specifies the name of the target architecture and, optionally, one or more feature modifiers ๐๏ธ This option has the form-march=arch{+[no]feature}*.
The table below sums up the valid values for arch, plus the features each one turns on by default ๐
arch value : Architecture : Includes by default
armv8-a : Armv8-A : +fp, +simd
armv8.1-a : Armv8.1-A : armv8-a, +crc, +lse, +rdma
armv8.2-a : Armv8.2-A : armv8.1-a
armv8.3-a : Armv8.3-A : armv8.2-a
armv8.4-a : Armv8.4-A : armv8.3-a, +fp16fml, +dotprod
armv8.5-a : Armv8.5-A : armv8.4-a, +sb, +ssbs, +predres
armv8.6-a : Armv8.6-A : armv8.5-a, +bf16, +i8mm
The value native is available on native AArch64 GNU/Linux and makes the compiler pick the architecture of the host system ๐ฅ๏ธ This option has no effect if the compiler is unable to recognize the architecture of the host system,
The valid 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 the one that gets used ๐
GCC uses name to figure out what kind of instructions it's allowed to emit when generating assembly code ๐งพ If -march is specified without either -mtune or -mcpu also being specified, the code is tuned to perform well across a range of target processors that implement the target architecture ๐
-mtune=nameโ specifies the name of the target processor that GCC should tune the performance of the code for ๐ฏ The permissible values for this option are:
generic, cortex-a35, cortex-a53, cortex-a55, cortex-a57,
cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae,
cortex-a77, cortex-a65, cortex-a65ae, cortex-a34, ares, exynos-m1,
emag, falkor, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-v1,
neoverse-v2, neoverse-512tvb, qdf24xx, saphira, phecda, xgene1,
vulcan, octeontx, octeontx81, octeontx83, octeontx2, octeontx2t98,
octeontx2t96 octeontx2t93, octeontx2f95, octeontx2f95n,
octeontx2f95mm, a64fx, thunderx, thunderxt88, thunderxt88p1,
thunderxt81, tsv110, thunderxt83, thunderx2t99, thunderx3t110, zeus,
cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35,
cortex-a73.cortex-a53, cortex-a75.cortex-a55, cortex-a76.cortex-a55,
ampere1, ampere1a, native.
The values cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55, cortex-a76.cortex-a55 tell GCC to tune for a big.LITTLE system ๐พ
The value neoverse-512tvb tells GCC to tune for Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits per cycle ๐ฆ. So bestie, these cores 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 below ๐.
Also, on native AArch64 GNU/Linux systems, the value native tunes performance to the host system โจ. This option has no effect if the compiler can't recognize the processor of the host system ๐.
If none of -mtune=, -mcpu= or -march= are specified, the code is tuned to perform well across a range of target processors ๐.
This option cannot be suffixed by feature modifiers ๐ .
-mcpu=nameโ Pick the target processor, optionally with one or more feature modifiers tacked on ๐. The form is-mcpu=cpu{+[no]feature}*, where the allowed values forcpuare the same as for-mtune. The allowed values forfeatureare documented in the sub-section onaarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. If you specify conflicting feature modifiers, the right-most one wins ๐ซถ.
GCC uses name to figure out what kinds of instructions it's allowed to 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 options take precedence over the matching part of this option ๐.
-mcpu=neoverse-512tvb is special, because it doesn't point at one specific core. Instead it covers all Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits a cycle ๐ง. Unless 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 does ๐
.
-moverride=stringโ Overrides the tuning decisions the back-end makes in response to a-mtune=switch ๐.
The syntax, semantics, and accepted values for string are not guaranteed to stay consistent across releases โ ๏ธ.
This option is only meant to be useful when developing GCC ๐.
-mverbose-cost-dumpโ Turns on verbose cost model dumping in the debug dump files ๐. This one exists for debugging the compiler itself ๐งช.-mpc-relative-literal-loads,-mno-pc-relative-literal-loadsโ Turn PC-relative literal loads on or off ๐ฆ. With this option on, literal pools are accessed using a single instruction and emitted after each function ๐ธ. The catch is that it limits the maximum size of functions to 1MB ๐ฌ. It's enabled by default for-mcmodel=tinyโจ.-msign-return-address=scopeโ Picks the function scope that return address signing gets applied to ๐. The allowed values arenone, which disables return address signing;non-leaf, which enables pointer signing for functions that aren't leaf functions; andall, which enables pointer signing for all functions ๐. The default isnone๐.
This option has been deprecated by -mbranch-protection ๐ฅ.
-mbranch-protection=none|standard|pac-ret[+leaf+b-key]|btiโ Picks the 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, signing functions that save the return address to memory (non-leaf functions will practically always do this) using thea-key๐๏ธ. The optionalleafargument extends the signing to include leaf functions ๐ฟ. The optionalb-keyargument signs the functions with the B-key instead of the A-key ๐.btiturns on the branch target identification mechanism ๐ฏ.-mharden-sls=optsโ Enables compiler hardening against straight line speculation (SLS) ๐งฑ.optsis a comma-separated list of the following options:retbrblr
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 ๐. This only does anything when SVE is enabled ๐.
GCC supports two forms of SVE code generation. There's "vector-length agnostic" output, which works with any size of vector register, and "vector-length specific" output, which lets GCC make assumptions about the vector length when that helps 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 for big-endian targets ๐ค. Every other value generates 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 each one also has an inverse, nofeature ๐
โจ.
crcโ Enables the CRC extension. This is on by default for-march=armv8.1-a๐.cryptoโ Enables the Crypto extension. This also enables Advanced SIMD and floating-point instructions ๐.fpโ Enables floating-point instructions. This is on by default for all possible values for options-marchand-mcpu๐ฅ.simdโ Enables Advanced SIMD instructions. This also enables floating-point instructions. This is on by default for all possible values for options-marchand-mcpu๐ถ.sveโ Enables Scalable Vector Extension instructions. This also enables Advanced SIMD and floating-point instructions ๐.lseโ Enables Large System Extension instructions. This is on by default for-march=armv8.1-a๐งฉ.rdmaโ Enables Round Double Multiply Accumulate instructions. This is on by default for-march=armv8.1-aโ๏ธ.fp16โ Enables the FP16 extension. This also enables floating-point instructions ๐ท.fp16fmlโ Enables the FP16 fmla extension. This also enables FP16 extensions and floating-point instructions. This option is enabled by default for-march=armv8.4-a. Using this option with architectures prior to Armv8.2-A is not supported ๐ โโ๏ธ.rcpcโ Enables the RcPc extension. This doesn't change code generation from GCC, but it gets passed on to the assembler, so inline asm statements can use instructions from the RcPc extension ๐งต.dotprodโ Enables the Dot Product extension. This also enables Advanced SIMD instructions ๐ฒ.aesโ Enables the Armv8-aaesandpmullcrypto extension. This also enables Advanced SIMD instructions ๐.sha2โ Enables the Armv8-asha2crypto extension. This also enables Advanced SIMD instructions ๐ง.sha3โ Enables thesha512andsha3crypto extension. This also enables Advanced SIMD instructions. Using this option with architectures prior to Armv8.2-A is not supported ๐.sm4โ Enables thesm3andsm4crypto extension. This also enables Advanced SIMD instructions. Using this option with architectures prior to Armv8.2-A is not supported ๐.profileโ Enables the Statistical Profiling extension. This option only enables the extension at the assembler level and doesn't affect code generation ๐.rngโ Enables the Armv8.5-a Random Number instructions. This option only enables the extension at the assembler level and doesn't affect code generation ๐ฐ.memtagโ Enables the Armv8.5-a Memory Tagging Extensions. Using this option with architectures prior to Armv8.5-A is not supported ๐ท๏ธ.sbโ Enables the Armv8-a Speculation Barrier instruction. This option only enables the extension at the assembler level and doesn't affect code generation. It's enabled by default for-march=armv8.5-a๐ง.ssbsโ Enables the Armv8-a Speculative Store Bypass Safe instruction. This option only enables the extension at the assembler level and doesn't affect code generation. It's enabled by default for-march=armv8.5-a๐.predresโ Enables the Armv8-a Execution and Data Prediction Restriction instructions. This option only enables the extension at the assembler level and doesn't affect code generation. It's enabled by default for-march=armv8.5-a๐ฎ.sve2โ Enables the Armv8-a Scalable Vector Extension 2. This also enables SVE instructions ๐.sve2-bitpermโ Enables SVE2 bitperm instructions. This also enables SVE2 instructions ๐ช.sve2-sm4โ Enables SVE2 sm4 instructions. This also enables SVE2 instructions ๐ฒ.sve2-aesโ Enables SVE2 aes instructions. This also enables SVE2 instructions ๐๏ธ.sve2-sha3โ Enables SVE2 sha3 instructions. This also enables SVE2 instructions ๐บ.tmeโ Enables the Transactional Memory Extension ๐ง .i8mmโ Enables 8-bit Integer Matrix Multiply instructions. This also enables Advanced SIMD and floating-point instructions. This option is enabled by default for-march=armv8.6-a. Using this option with architectures prior to Armv8.2-A is not supported ๐งฎ.f32mmโ Enables 32-bit Floating point Matrix Multiply instructions. This also enables SVE instructions. Using this option with architectures prior to Armv8.2-A is not supported ๐.f64mmโ Enables 64-bit Floating point Matrix Multiply instructions. This also enables SVE instructions. Using this option with architectures prior to Armv8.2-A is not supported ๐งท.bf16โ Enables brain half-precision floating-point instructions. This also enables Advanced SIMD and floating-point instructions. This option is enabled by default for-march=armv8.6-a. Using this option with architectures prior to Armv8.2-A is not supported ๐ง ๐.
Okay so crypto pulls in aes, sha2, and simd, and simd pulls in fp ๐ฅ. Going the other way, nofp drags along nosimd, which drags along nocrypto, noaes, and nosha2 ๐. It's a whole domino situation, bestie ๐ง
โจ Adapteva Epiphany Options โจ
These -m options are specific to the Adapteva Epiphany ๐ฆ
-mhalf-reg-fileโ Don't hand out any register fromr32...r63๐ธ. That way your code can run on chips that don't have those registers at all.-mprefer-short-insn-regsโ Prefers registers that let the compiler emit short instructions โจ. Heads up, this can bump up the instruction count, so overall code size might go down or up ๐.-mbranch-cost=numโ Sets the cost of branches to roughlynum"simple" instructions. It's only a heuristic, so don't expect the same results across releases ๐.-mcmoveโ Turns on conditional moves ๐.-mnops=numโ EmitsnumNOPs before every other generated instruction ๐ญ.-mno-soft-cmpsfโ For single-precision float comparisons, this emits anfsuband checks the flags. It's faster than a software comparison, but it can give wrong answers with NaNs, or when two different small numbers subtract to zero. The default is-msoft-cmpsf, which is slower but IEEE-compliant software comparison ๐ .-mstack-offset=numโ Sets the offset between the top of the stack and the stack pointer. For example, a value of 8 means the eight bytes in the rangesp+0...sp+7can be used by leaf functions without stack allocation. Values other than 8 or 16 are untested and unlikely to work ๐.
This option changes the ABI, so compiling with a different stack offset than the libraries were built with generally doesn't work ๐
โโ๏ธ. It's handy for checking whether a different offset gives you better code, but if you want to actually build working programs with a different offset, configure the toolchain with the right --with-stack-offset=num option instead.
-mno-round-nearestโ Makes the scheduler assume the rounding mode is set to truncating. The default is-mround-nearest๐.-mlong-callsโ Unless an attribute says otherwise, this assumes every call might be out of range of theb/blinstructions. So it loads the function address into a register before making the (otherwise direct) call. This is the default ๐.-mshort-callsโ Unless an attribute says otherwise, this assumes direct calls are within range of theb/blinstructions, so those get used for direct calls. The default is-mlong-callsโจ.-msmall16โ Assumes addresses can be loaded as 16-bit unsigned values. This doesn't apply to function addresses where-mlong-callssemantics are in effect ๐ง.-mfp-mode=modeโ Sets the prevailing mode of the floating-point unit, which decides the FP mode that's provided and expected at function call and return time. Matching this to the mode you mostly need at function start can make your programs smaller and faster by skipping unnecessary mode switches ๐ฅ.modecan be one of the following values:callerโ Any mode at function entry is valid, and it gets retained or restored when the function returns and when it calls other functions. This is great for libraries or other compilation units you want to drop into programs with different FPU modes. Being able to use one object file is worth the extra switching overhead ๐ซถ.truncateโ The mode used for FP calculations with truncating rounding (round towards zero). That includes converting from floating point to integer.round-nearestโ The mode used for FP calculations with round-to-nearest-or-even rounding.intโ The mode used to do integer calculations in the FPU, like integer multiply or integer multiply-and-accumulate.
The default is -mfp-mode=caller ๐.
-mno-split-lohi,-mno-postinc,-mno-postmodifyโ Code generation tweaks that turn off, respectively, splitting of 32-bit loads, generation of post-increment addresses, and generation of post-modify addresses. The defaults aremsplit-lohi,-mpost-inc, and-mpost-modify๐.-mnovect-doubleโ Switches 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.numcan be 4 or 8, and the default is 8. This is an ABI change, though plenty of library function interfaces are unaffected if they don't use SIMD vector modes in places that affect the size 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 the case ๐ญ.-m1reg-regโ Picks a register to hold the constant -1, which makes loading small negative constants and certain bitmasks faster โญ. Allowable values forregarer43andr63, which use that register as a fixed register, andnone, which means no register is used for this purpose. The default is-m1reg-none๐.
๐ AMD GCN Options ๐
These options are defined specifically for the AMD GCN port ๐
-march=gpu,-mtune=gpuโ Sets the architecture type or tuning forgpu. The supported values forgpuare:fijiโ Compile for GCN3 Fiji devices (gfx803) ๐.gfx900โ Compile for GCN5 Vega 10 devices (gfx900) โจ.gfx906โ Compile for GCN5 Vega 20 devices (gfx906) ๐ฅ.
-mstack-size=bytesโ Specifies how many bytes of stack space get requested for each GPU thread (wave-front). Beware, there may be a lot of threads and limited memory available ๐. The size of the stack allocation can also affect run-time performance. The default is 32KB when using OpenACC or OpenMP, and 1MB otherwise ๐ง.
๐ธ ARC Options ๐ธ
These options control which architecture variant your code gets compiled for ๐ฆ
-mbarrel-shifterโ Generates instructions supported by the barrel shifter. This is the default unless-mcpu=ARC601or-mcpu=ARCEMis in effect โจ.-mjli-alwaysโ Forces a function call to use thejli_sinstruction. This option is only valid for the ARCv2 architecture ๐ .-mcpu=cpuโ Sets the architecture type, register usage, and instruction scheduling parameters forcpu. Shortcut alias options also exist for backward compatibility and convenience. The supported values forcpuare:arc600โ Compile for ARC600. Aliases:-mA6,-mARC600.arc601โ Compile for ARC601. Alias:-mARC601.arc700โ Compile for ARC700. Aliases:-mA7,-mARC700. This is the default when configured with--with-cpu=arc700๐.arcemโ Compile for ARC EM.archsโ Compile for ARC HS.emโ Compile for ARC EM CPU with no hardware extensions.em4โ Compile for ARC EM4 CPU.em4_dmipsโ Compile for ARC EM4 DMIPS CPU.em4_fpusโ Compile for ARC EM4 DMIPS CPU with the single-precision floating-point extension.em4_fpudaโ Compile for ARC EM4 DMIPS CPU with single-precision floating-point and double assist instructions.hsโ Compile for ARC HS CPU with no hardware extensions except the atomic instructions.hs34โ Compile for ARC HS34 CPU.hs38โ Compile for ARC HS38 CPU.hs38_linuxโ Compile for ARC HS38 CPU with all hardware extensions on.arc600_normโ Compile for ARC 600 CPU withnorminstructions enabled.arc600_mul32x16โ Compile for ARC 600 CPU withnormand 32x16-bit multiply instructions enabled.arc600_mul64โ Compile for ARC 600 CPU withnormandmul64-family instructions enabled.arc601_normโ Compile for ARC 601 CPU withnorminstructions enabled.arc601_mul32x16โ Compile for ARC 601 CPU withnormand 32x16-bit multiply instructions enabled.arc601_mul64โ Compile for ARC 601 CPU withnormandmul64-family instructions enabled.nps400โ Compile for ARC 700 on the NPS400 chip.em_miniโ Compile for the ARC EM minimalist configuration, which features 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โ Stopslrandsrinstructions from using FPX extension aux registers ๐.-meaโ Generates extended arithmetic instructions. Right now onlydivaw,adds,subs, andsat16are supported. This is only valid for-mcpu=ARC700๐ฅ.-mno-mpyโ Doesn't generatempy-family instructions for ARC700. This option is deprecated ๐.-mmul32x16โ Generates 32x16-bit multiply and multiply-accumulate instructions ๐ฆ.-mmul64โ Generatesmul64andmulu64instructions. This is only valid for-mcpu=ARC600๐.-mnormโ Generatesnorminstructions. This is the default if-mcpu=ARC700is in effect ๐.-mspfp,-mspfp-compactโ Generates single-precision FPX instructions, tuned for the compact implementation ๐.-mspfp-fastโ Generates single-precision FPX instructions, tuned for the fast implementation โจ.-msimdโ Enables ARC SIMD instructions through target-specific builtins. This is only valid for-mcpu=ARC700๐ง.-msoft-floatโ This option is ignored. It's only here for compatibility. Software floating-point code is emitted by default, and you can override that default with FPX options:-mspfp,-mspfp-compact, or-mspfp-fastfor single precision, and-mdpfp,-mdpfp-compact, or-mdpfp-fastfor double precision ๐ซถ.-mswapโ okay bestie, this one tells the compiler to generateswapinstructions ๐โจ-matomicโ this unlocks the locked load/store conditional extension so the atomic memory built-in functions can actually work ๐๐ Not available for ARC6xxor ARCEMcores, so don't even try it there ๐ โโ๏ธ-mdiv-remโ enables thedivandreminstructions for ARCv2 cores ๐งฎ๐-mcode-densityโ enables code density instructions for ARCEM๐ธ It's on by default for ARCHS, so you're already set if that's your chip ๐-mll64โ enables double load/store operations for ARCHScores ๐ฅ-mtp-regno=regnoโ lets you specify the thread pointer register number ๐งต-mmpy-option=multoโ compiles ARCv2 code with a multiplier design option ๐ข You can pick the option with either a string or a numeric value formulto, andwlh1is the default ๐ Here's the menu:0ornoneโ no multiplier available ๐ซฅ1orwโ 16x16 multiplier, fully pipelined. This enablesmpywandmpyuwโจ2orwlh1โ 32x32 multiplier, fully pipelined (1 stage). On top of the above, this addsmpy,mpyu,mpym,mpymu, andmpy_s๐ This is the default!3orwlh2โ 32x32 multiplier, fully pipelined (2 stages). Also addsmpy,mpyu,mpym,mpymu, andmpy_s๐4orwlh3โ two 16x16 multipliers, blocking, sequential. Also addsmpy,mpyu,mpym,mpymu, andmpy_s๐งฉ5orwlh4โ one 16x16 multiplier, blocking, sequential. Also addsmpy,mpyu,mpym,mpymu, andmpy_s๐ข6orwlh5โ one 32x4 multiplier, blocking, sequential. Also addsmpy,mpyu,mpym,mpymu, andmpy_s๐7orplus_dmpyโ ARCHSSIMD support ๐ฆ8orplus_macdโ ARCHSSIMD support ๐9orplus_qmacwโ ARCHSSIMD support โญ
This option is only available for ARCv2 cores, so keep that in mind ๐ซถ
-mfpu=fpuโ turns on support for specific floating-point hardware extensions on ARCv2 cores ๐ฆ These are the validfpuvalues:fpusโ single-precision floating-point hardware extensions ๐ซfpudโ double-precision floating-point hardware extensions. The single-precision extension comes along for the ride too. Not available for ARCEM๐ โโ๏ธfpudaโ double-precision extensions using double-precision assist instructions, plus the single-precision extension. This is only available for ARCEM๐ทfpuda_divโ double-precision extensions using double-precision assist instructions, plus the single-precision, square-root, and divide extensions. Only for ARCEMโfpuda_fmaโ double-precision extensions using double-precision assist instructions, plus the single-precision and fused multiply and add extensions. Only for ARCEMโ๏ธโfpuda_allโ double-precision extensions using double-precision assist instructions, and all the single-precision extensions too. Only for ARCEM๐fpus_divโ single-precision floating-point, square-root, and divide extensions โโจfpud_divโ double-precision floating-point, square-root, and divide extensions. This one includesfpus_div. Not available for ARCEM๐fpus_fmaโ single-precision floating-point and fused multiply and add extensions ๐ฏfpud_fmaโ double-precision floating-point and fused multiply and add extensions. This one includesfpus_fma. Not available for ARCEM๐งfpus_allโ every single-precision floating-point extension ๐fpud_allโ every single- and double-precision floating-point extension. Not available for ARCEM๐
-mirq-ctrl-saved=register-range, blink, lp_countโ specifies the general-purpose registers the processor automatically saves and restores on interrupt entry and exit ๐ Theregister-rangeis two registers separated by a dash. It always starts withr0, and the upper limit is thefpregister.blinkandlp_countare optional ๐ซง This option is only valid for ARCEMand ARCHScores.-mrgf-banked-regs=numberโ specifies how many registers get replicated in the second register bank when entering a fast interrupt โก Fast interrupts are the ones with the highest priority level,P0. They only save thePCandSTATUS32registers so there are no memory transactions during entry and exit ๐โโ๏ธ Use this when you're using fast interrupts on an ARCV2family processor. Permitted values are4,8,16, and32.-mlpc-width=widthโ sets the width of thelp_countregister ๐ Valid values are8,16,20,24,28, and32bits, and the default is fixed at 32 bits. If the width is less than 32, the compiler won't try to transform your loops into the zero-delay loop mechanism unless it knowslp_countcan hold the loop-counter value ๐ Depending on the width, the compiler and run-time library might still use the loop mechanism for various needs. This option defines the macro__ARC_LPC_WIDTH__with the value ofwidth๐ง-mrf16โ tells the compiler to generate code for a 16-entry register file ๐๏ธ This option defines the__ARC_RF16__preprocessor macro ๐-mbranch-indexโ enables use ofbiorbihinstructions to implement jump tables ๐ฆ
The following options are passed through to the assembler, and they also define preprocessor macro symbols ๐จ
-mdsp-packaโ passed down to the assembler to enable the DSP Pack A extensions. It also sets the preprocessor symbol__Xdsp_packa. This option is deprecated, so it's on its way out ๐-mdvbfโ passed down to the assembler to enable the dual Viterbi butterfly extension. It also sets the preprocessor symbol__Xdvbf. This option is deprecated ๐ฅ-mlockโ passed down to the assembler to enable the locked load/store conditional extension. It also sets the preprocessor symbol__Xlock๐-mmac-d16โ passed down to the assembler, and sets the preprocessor symbol__Xxmac_d16. This option is deprecated ๐ซ-mmac-24โ passed down to the assembler, and sets the preprocessor symbol__Xxmac_24. This option is deprecated ๐ซ-mrtscโ passed down to the assembler to enable the 64-bit time-stamp counter extension instruction. It also sets the preprocessor symbol__Xrtsc. This option is deprecated โฐ-mswapeโ passed down to the assembler to enable the swap byte ordering extension instruction. It also sets the preprocessor symbol__Xswape๐-mtelephonyโ passed down to the assembler to enable dual- and single-operand instructions for telephony. It also sets the preprocessor symbol__Xtelephony. This option is deprecated ๐-mxyโ passed down to the assembler to enable the XY memory extension. It also sets the preprocessor symbol__Xxy๐ง
The following options control how the assembly code is annotated ๐
-misizeโ annotates assembler instructions with estimated addresses ๐-mannotate-alignโ explains what alignment considerations led to deciding whether an instruction is short or long ๐
The following options are passed through to the linker ๐
-marclinuxโ passed through to the linker to specify use of thearclinuxemulation. This is enabled by default in tool chains built forarc-linux-uclibcandarceb-linux-uclibctargets when profiling is not requested ๐ง-marclinux_profโ passed through to the linker to specify use of thearclinux_profemulation. This is enabled by default in tool chains built forarc-linux-uclibcandarceb-linux-uclibctargets when profiling is requested ๐
The following options control the semantics of generated code ๐ง ๐
-mlong-callsโ generates calls as register indirect calls, which gives access to the full 32-bit address range ๐-mmedium-callsโ doesn't use less than a 25-bit addressing range for calls, which is the offset available for an unconditional branch-and-link instruction. Conditional execution of function calls is suppressed so the 25-bit range can be used, instead of the 21-bit range you get with conditional branch-and-link. This is the default for tool chains built forarc-linux-uclibcandarceb-linux-uclibctargets ๐ฆ-G numโ puts definitions of externally-visible data in a small data section if that data is no bigger thannumbytes ๐ฑ The default value ofnumis 4 for any ARC configuration, or 8 when you have double load/store operations ๐-mno-sdataโ doesn't generate sdata references. This is the default for tool chains built forarc-linux-uclibcandarceb-linux-uclibctargets ๐ซ-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 generation of these instructions driven by the combiner pass ๐ โโ๏ธโจ-mcase-vector-pcrel: okay bestie, this one uses PC-relative switch case tables to turn on case table shortening ๐ It's the default for-Osโจ-mcompact-casesi: turns on the compactcasesipattern ๐ฆ It's the default for-Os, but it's only available for ARCv1 cores, and it's deprecated ๐-mno-cond-exec: this one turns OFF the ARCompact-specific pass that generates conditional execution instructions ๐ The target-independent pass is often lacking because of delay slot scheduling and interactions between operand numbers, literal sizes, instruction lengths, and the support for conditional execution. So the ARC port keeps a special pass that hunts for more conditional execution chances after register allocation, branch shortening, and delay slot scheduling are done. It generally (not always!) improves performance and code size, but it costs extra compilation time, which is why there's a switch to turn it off ๐ซถ
If you're having problems with call instructions going past their allowable offset range because they got conditionalized, try -mmedium-calls instead โจ
-mearly-cbranchsi: enables pre-reload use of thecbranchsipattern ๐ธ-mexpand-adddi: expandsadddi3andsubdi3at RTL generation time intoadd.f,adcetc. ๐ง This one is deprecated.-mindexed-loads: enables indexed loads ๐ This can be problematic, because some optimizers then assume indexed stores exist, which is not the case ๐-mlra: enables Local Register Allocation ๐งช It's still experimental for ARC, so by default the compiler uses standard reload (i.e.-mno-lra) ๐-mlra-priority-none: no priority gets indicated for target registers ๐-mlra-priority-compact: indicates target register priority forr0..r3/r12..r15๐-mlra-priority-noncompact: reduces target register priority forr0..r3/r12..r15๐ซ-mmillicode: when you're optimizing for size with-Os, prologues and epilogues that have to save or restore a big pile of registers often get shortened by calling a special function in libgcc. That's called a millicode call โจ These calls can cause performance issues, and/or linking issues when you link in a nonstandard way, so this option lets you turn millicode call generation on or off ๐ฅ-mcode-density-frame: lets the compiler emitenterandleaveinstructions ๐ง These are only valid for CPUs with the code-density feature ๐-mmixed-code: tweaks register allocation to help 16-bit instruction generation ๐ฆ This usually brings the average instruction size down, while bumping up the instruction count ๐ซถ-mq-class: deprecated ๐ Enables q instruction alternatives. This is the default for-Osโจ-mRcq: enables Rcq constraint handling ๐ Most short code generation depends on this, and it's the default ๐-mRcw: enables Rcw constraint handling ๐ Most ccfsm condexec mostly depends on this, and it's the default ๐-msize-level=level: fine-tunes size optimization with regards to instruction lengths and alignment ๐ The recognized values forlevelare:0: no size optimization. This level is deprecated and treated like1๐1: short instructions get used opportunistically ๐ธ2: in addition, alignment of loops and of code after barriers gets dropped ๐3: in addition, optional data alignment gets dropped, and the optionOsis enabled ๐ฅ
This defaults to 3 when -Os is in effect. Otherwise, when it's not 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 standard multiplier block ๐ชARC700-xmac: tunes for the ARC700 CPU with XMAC block ๐ชARC725D: tunes for the ARC725D CPU ๐ทARC750D: tunes for the ARC750D CPU ๐ท
-mmultcost=num: the cost to assume for a multiply instruction, with4being equal to a normal instruction ๐งฎ-munalign-prob-threshold=probability: sets the probability threshold for unaligning branches ๐ง When tuning for ARC700 and optimizing for speed, branches without a filled delay slot are preferably emitted unaligned and long, unless profiling shows the probability for the branch to be taken is belowprobability. The default is(REG_BR_PROB_BASE/2), i.e.5000๐
The following options are maintained for backward compatibility, but they're now deprecated and will be removed in a future release ๐ฅ
-margonaut: obsolete FPX ๐ชฆ-mbig-endian,-EB: compiles code for big-endian targets. Using these is now deprecated ๐ Big-endian code is supported by configuring GCC to buildarceb-elf32andarceb-linux-uclibctargets, 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, where little endian is the default โจ-mbarrel_shifter: got a glow-up, it's now-mbarrel-shifter๐-mdpfp_compact: got a glow-up, it's now-mdpfp-compact๐-mdpfp_fast: got a glow-up, it's now-mdpfp-fast๐-mdsp_packa: got a glow-up, it's now-mdsp-packa๐-mEA: got a glow-up, it's now-mea๐-mmac_24: got a glow-up, it's now-mmac-24๐-mmac_d16: got a glow-up, it's now-mmac-d16๐-mspfp_compact: got a glow-up, it's now-mspfp-compact๐-mspfp_fast: got a glow-up, it's now-mspfp-fast๐-mtune=cpu: the valuesarc600,arc601,arc700andarc700-xmacforcpuare nowARC600,ARC601,ARC700andARC700-xmacrespectively ๐ค-multcost=num: got a glow-up, it's now-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's not strictly necessary for the code to run correctly ๐๏ธ Specifying-fomit-frame-pointerwith this option means stack frames don't get 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: stops the reordering of instructions in the function prologue, and stops them from being merged with the instructions in the function's body ๐ This means all functions start with a recognizable set of instructions (or one of a small set of different function prologues), so that info can be used to locate where functions start inside an executable piece of code ๐ The default is-msched-prologโจ-mfloat-abi=name: specifies which floating-point ABI to use ๐งฎ Permissible values aresoft,softfpandhard.softmakes GCC generate output containing library calls for floating-point operations.softfpallows code using hardware floating-point instructions, but still uses the soft-float calling conventions.hardallows floating-point instructions and uses FPU-specific calling conventions ๐ฅ The default depends on the specific target configuration. Heads up: the hard-float and soft-float ABIs are not link-compatible ๐ซ You have to compile your entire program with the same ABI, and link with a compatible set of libraries ๐ซถ-mgeneral-regs-only: generates code that only uses the general-purpose registers ๐ฏ This stops the compiler from using floating-point and Advanced SIMD registers, but it won't put any restrictions on the assembler ๐ง-mlittle-endian: generates code for a processor running in little-endian mode ๐ This is the default for all standard configurations โจ-mbig-endian: generates code for a processor running in big-endian mode ๐ The default is to compile for a little-endian processor ๐-mbe8,-mbe32: when linking a big-endian image, selects between BE8 and BE32 formats ๐งฉ This has no effect on little-endian images, which it ignores. 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 figure out what kinds of instructions it can emit when generating assembly code. This option can be used in conjunction with, or instead of, the-mcpu=option ๐ค
Permissible names are: armv4t, armv5t, armv5te, armv6, armv6j, armv6k, armv6kz, armv6t2, armv6z, armv6zk, armv7, armv7-a, armv7ve, armv8-a, armv8.1-a, armv8.2-a, armv8.3-a, armv8.4-a, armv8.5-a, armv8.6-a, armv7-r, armv8-r, armv6-m, armv6s-m, armv7-m, armv7e-m, armv8-m.base, armv8-m.main, armv8.1-m.main, iwmmxt and iwmmxt2 ๐
Additionally, the following architectures, which lack support for the Thumb execution state, are recognized but support is deprecated: armv4 ๐ฅ
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 literally the same as -march=armv7-a+vfpv4 ๐
because the +nofp that comes after +simd wipes +simd out completely. Order matters, bestie ๐ซถ
Most extension names sound generic, but what they actually do depends on which architecture you stick them on ๐ฆ For example, +simd works on both armv7-a and armv8-a, but on armv7-a it turns on the original ARMv7-A Advanced SIMD (Neon) stuff, while on armv8-a you get the ARMv8-A version ๐คฏ
Here's the full menu of what each architecture supports ๐ If an architecture isn't mentioned below, it doesn't support any extensions at all, so don't even try ๐
armv5te, armv6, armv6j, armv6k, armv6kz, armv6t2, armv6z, armv6zk
+fpโ The VFPv2 floating-point instructions ๐ธ+vfpv2works as an alias for this one.+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.+vfpv3-d16is an alias for this one. Heads up: floating-point isn't supported by the base ARMv7-M architecture, but it's compatible with both ARMv7-A and ARMv7-R ๐+nofpโ Disable the floating-point instructions
armv7-a
+mpโ The multiprocessing extension ๐ง+secโ The security extension ๐+fpโ The VFPv3 floating-point instructions, with 16 double-precision registers.+vfpv3-d16is an alias for this one.+simdโ The Advanced SIMD (Neon) v1 and VFPv3 floating-point instructions.+neonand+neon-vfpv3are both aliases for this one ๐ฅ+vfpv3โ The VFPv3 floating-point instructions, with 32 double-precision registers+vfpv3-d16-fp16โ The VFPv3 floating-point instructions, with 16 double-precision registers and the half-precision floating-point conversion operations+vfpv3-fp16โ The VFPv3 floating-point instructions, with 32 double-precision registers and the half-precision floating-point conversion operations+vfpv4-d16โ The VFPv4 floating-point instructions, with 16 double-precision registers+vfpv4โ The VFPv4 floating-point instructions, with 32 double-precision registers+neon-fp16โ The Advanced SIMD (Neon) v1 and VFPv3 floating-point instructions, with the half-precision floating-point conversion operations+neon-vfpv4โ The Advanced SIMD (Neon) v2 and VFPv4 floating-point instructions+nosimdโ Disable the Advanced SIMD instructions (this does not disable floating point) ๐ โโ๏ธ+nofpโ Disable the floating-point and Advanced SIMD instructions
armv7ve
The extended version of the ARMv7-A architecture, with support for virtualization ๐
+fpโ The VFPv4 floating-point instructions, with 16 double-precision registers.+vfpv4-d16is an alias for this one.+simdโ The Advanced SIMD (Neon) v2 and VFPv4 floating-point instructions.+neon-vfpv4is an alias for this one.+vfpv3-d16โ The VFPv3 floating-point instructions, with 16 double-precision registers+vfpv3โ The VFPv3 floating-point instructions, with 32 double-precision registers+vfpv3-d16-fp16โ The VFPv3 floating-point instructions, with 16 double-precision registers and the half-precision floating-point conversion operations+vfpv3-fp16โ The VFPv3 floating-point instructions, with 32 double-precision registers and the half-precision floating-point conversion operations+vfpv4-d16โ The VFPv4 floating-point instructions, with 16 double-precision registers+vfpv4โ The VFPv4 floating-point instructions, with 32 double-precision registers+neonโ The Advanced SIMD (Neon) v1 and VFPv3 floating-point instructions.+neon-vfpv3is an alias for this one.+neon-fp16โ The Advanced SIMD (Neon) v1 and VFPv3 floating-point instructions, with the half-precision floating-point conversion operations+nosimdโ Disable the Advanced SIMD instructions (this does not disable floating point)+nofpโ Disable the floating-point and Advanced SIMD instructions
armv8-a
+crcโ The Cyclic Redundancy Check (CRC) instructions ๐งฎ+simdโ The ARMv8-A Advanced SIMD and floating-point instructions+cryptoโ The cryptographic instructions ๐+nocryptoโ Disable the cryptographic instructions+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions+sbโ 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 enables the Advanced SIMD and floating-point instructions too ๐+nocryptoโ Disable the cryptographic instructions+nofpโ Disable 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โ Enable the Dot Product extension. This also enables Advanced SIMD instructions ๐ฏ+nocryptoโ Disable the cryptographic extension+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions+sbโ The Speculation Barrier Instruction ๐ก๏ธ+predresโ The Execution and Data Prediction Restriction Instructions+i8mmโ The 8-bit Integer Matrix Multiply instructions. This also enables Advanced SIMD and floating-point instructions ๐งฑ+bf16โ The Brain half-precision floating-point instructions. This also enables Advanced SIMD and floating-point instructions ๐ง
armv8.4-a
+fp16โ The half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions, as well as the Dot Product extension and the half-precision floating-point fmla extension ๐+simdโ The ARMv8.3-A Advanced SIMD and floating-point instructions, as well as the Dot Product extension+cryptoโ The cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions, as well as the Dot Product extension+nocryptoโ Disable the cryptographic extension+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions+sbโ The Speculation Barrier Instruction ๐ก๏ธ+predresโ The Execution and Data Prediction Restriction Instructions+i8mmโ The 8-bit Integer Matrix Multiply instructions. This also enables Advanced SIMD and floating-point instructions ๐งฑ+bf16โ The Brain half-precision floating-point instructions. This also enables Advanced SIMD and floating-point instructions ๐ง
armv8.5-a
+fp16โ The half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions, as well as the Dot Product extension and the half-precision floating-point fmla extension ๐+simdโ The ARMv8.3-A Advanced SIMD and floating-point instructions, as well as the Dot Product extension+cryptoโ The cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions, as well as the Dot Product extension+nocryptoโ Disable the cryptographic extension+nofpโ Disable the floating-point, Advanced SIMD and cryptographic instructions+i8mmโ The 8-bit Integer Matrix Multiply instructions. This also enables Advanced SIMD and floating-point instructions ๐งฑ+bf16โ The Brain half-precision floating-point instructions. This also enables Advanced SIMD and floating-point instructions ๐ง
๐ armv8.6-a
+fp16โ okay so this one unlocks the half-precision floating-point data processing instructions ๐ฅ It also turns on the Advanced SIMD and floating-point instructions, plus the Dot Product extension and the half-precision floating-pointfmlaextension โจ+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, plus the Dot Product extension ๐+cryptoโ the cryptographic instructions ๐ This one also gives you the Advanced SIMD and floating-point instructions and the Dot Product extension ๐ฆ+nocryptoโ disables the cryptographic extension ๐+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions all at once ๐+i8mmโ 8-bit Integer Matrix Multiply instructions ๐ง also enables Advanced SIMD and floating-point instructions+bf16โ Brain half-precision floating-point instructions ๐ธ also enables Advanced SIMD and floating-point instructions
๐ armv7-r
+fp.spโ the single-precision VFPv3 floating-point instructions ๐ The extension+vfpv3xdcan be used as an alias for this one+fpโ the VFPv3 floating-point instructions with 16 double-precision registers ๐ The extension+vfpv3-d16can be used as an alias for this one+vfpv3xd-d16-fp16โ the single-precision VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations ๐ฆ+vfpv3-d16-fp16โ the VFPv3 floating-point instructions with 16 double-precision registers, plus the half-precision floating-point conversion operations โจ+nofpโ disables the floating-point extension ๐+idivโ the ARM-state integer division instructions ๐ฅ+noidivโ disables the ARM-state integer division extension ๐
๐ธ armv7e-m
+fpโ the single-precision VFPv4 floating-point instructions ๐+fpv5โ the single-precision FPv5 floating-point instructions ๐ง+fp.dpโ the single- and double-precision FPv5 floating-point instructions ๐+nofpโ disables the floating-point extensions ๐
๐ฆ armv8.1-m.main
+dspโ the DSP instructions ๐+mveโ the M-Profile Vector Extension (MVE) integer instructions ๐+mve.fpโ the M-Profile Vector Extension (MVE) integer and single precision floating-point instructions ๐ฅ+fpโ the single-precision floating-point instructions โญ+fp.dpโ the single- and double-precision floating-point instructions ๐+nofpโ disables the floating-point extension ๐+cdecp0,+cdecp1, ... ,+cdecp7โ enables the Custom Datapath Extension (CDE) on selected coprocessors, going by the numbers you give in the options, in the range 0 to 7 ๐ง
๐ armv8-m.main
+dspโ the DSP instructions ๐+nodspโ disables the DSP extension ๐+fpโ the single-precision floating-point instructions โญ+fp.dpโ the single- and double-precision floating-point instructions ๐+nofpโ disables the floating-point extension ๐+cdecp0,+cdecp1, ... ,+cdecp7โ enables the Custom Datapath Extension (CDE) on selected coprocessors, going by the numbers you give in the options, in the range 0 to 7 ๐ง
๐ armv8-r
+crcโ the Cyclic Redundancy Check (CRC) instructions ๐ฅ+fp.spโ the single-precision FPv5 floating-point instructions ๐ธ+simdโ the ARMv8-A Advanced SIMD and floating-point instructions ๐+cryptoโ the cryptographic instructions ๐+nocryptoโ disables the cryptographic instructions ๐+nofpโ disables the floating-point, Advanced SIMD and cryptographic instructions ๐
-march=native tells the compiler to auto-detect the architecture of the build computer โจ Lowkey the best part is that you don't have to type it out yourself.
โ ๏ธ bestie, this one is picky. It's only supported on GNU/Linux right now, and not every architecture gets recognized. If the auto-detect doesn't work out, the option just has no effect ๐
-mtune=name
This option tells GCC which target ARM processor to tune the performance of your code for ๐ For some ARM implementations you can get better performance by using it. The permissible names are:
arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm740t, strongarm, strongarm110, strongarm1100, 0strongarm1110, arm8, arm810, arm9, arm9e, arm920, arm920t, arm922t, arm946e-s, arm966e-s, arm968e-s, arm926ej-s, arm940t, arm9tdmi, arm10tdmi, arm1020t, arm1026ej-s, arm10e, arm1020e, arm1022e, arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1156t2-s, arm1156t2f-s, arm1176jz-s, arm1176jzf-s, generic-armv7-a, cortex-a5, cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17, cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, ares, cortex-r4, cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, cortex-m0, cortex-m0plus, cortex-m1, cortex-m3, cortex-m4, cortex-m7, cortex-m23, cortex-m33, cortex-m35p, cortex-m55, cortex-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
Okay, and get this, -mtune can also tell GCC to tune for a big.LITTLE system ๐ญ The permissible names for that are:
cortex-a15.cortex-a7, cortex-a17.cortex-a7, cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a72.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55, cortex-a76.cortex-a55
-mtune=generic-arch tells GCC to tune for a blend of processors within the architecture arch ๐ฆ The goal is code that runs well on the most popular processors right now, balancing the optimizations that help some CPUs in the range while dodging the performance pitfalls of the others. Heads up, the effects of this option may change in future GCC versions as CPU models come and go ๐ธ
-mtune takes the same extension options as -mcpu, but the extension options don't change how the generated code gets tuned ๐
โ ๏ธ -mtune=native tells the compiler to auto-detect the CPU of the build computer. Same deal as before: it's only supported on GNU/Linux, not every architecture is recognized, and if the auto-detect fails the option has no effect ๐
-mcpu=name[+extension...]
This one specifies the name of the target ARM processor ๐ GCC uses that name to figure out the target ARM architecture (as if you'd passed -march) and the ARM processor type to tune for (as if you'd passed -mtune). If you use this option alongside -march or -mtune, those options take precedence over the matching part of this one ๐
A lot of the supported CPUs have optional architectural extensions ๐ง When that's the case, those extensions are normally enabled by default. If there are implementations that lack the extension, you can use the extension syntax to disable the ones that have been left out. For floating-point and Advanced SIMD (Neon) instructions, you also have to think about -mfloat-abi and -mfpu. Floating-point and Advanced SIMD instructions only get used if -mfloat-abi is not set to soft, and any setting of -mfpu other than auto will override the available floating-point and SIMD extension instructions ๐ฅ
For example, cortex-a9 shows up in three major configurations: integer only, with just a floating-point unit, or with floating-point and Advanced SIMD. The default enables all the instructions, but you can use +nosimd and +nofp to disable just the SIMD instructions, or both the SIMD and floating-point instructions, respectively ๐
The permissible names for this option are the same as the ones for -mtune ๐
The following extension options are common to the listed CPUs:
+nodspโ disables the DSP instructions oncortex-m33,cortex-m35p๐+nofpโ disables the floating-point instructions onarm9e,arm946e-s,arm966e-s,arm968e-s,arm10e,arm1020e,arm1022e,arm926ej-s,arm1026ej-s,cortex-r5,cortex-r7,cortex-r8,cortex-m4,cortex-m7,cortex-m33andcortex-m35p๐ It also disables the floating-point and SIMD instructions 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๐+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 (but not floating-point) instructions ongeneric-armv7-a,cortex-a5,cortex-a7andcortex-a9๐ง+cryptoโ enables the cryptographic instructions oncortex-a32,cortex-a35,cortex-a53,cortex-a55,cortex-a57,cortex-a72,cortex-a73,cortex-a75,exynos-m1,xgene1,cortex-a57.cortex-a53,cortex-a72.cortex-a53,cortex-a73.cortex-a35,cortex-a73.cortex-a53andcortex-a75.cortex-a55๐
Additionally, the generic-armv7-a pseudo target defaults to VFPv3 with 16 double-precision registers ๐ It supports these extension options: mp, sec, vfpv3-d16, vfpv3, vfpv3-d16-fp16, vfpv3-fp16, vfpv4-d16, vfpv4, neon, neon-vfpv3, neon-fp16, neon-vfpv4. The meanings are the same as for the extensions to -march=armv7-a โจ
-mcpu=generic-arch is also permissible, and it's equivalent to -march=arch -mtune=generic-arch ๐ซถ Check out -mtune for more info.
So -mcpu=native is giving auto-detect energy โจ. The compiler sniffs out the CPU of the build computer ๐ฅ๏ธ so you don't have to. Lowkey this only works on GNU/Linux right now, and not every architecture gets recognized ๐. If the auto-detect doesn't work out, the option has no effect ๐ซ .
-mfpu=nameโ tells the compiler what floating-point hardware (or hardware emulation) the target has ๐งฎ. Permissible names are:auto,vfpv2,vfpv3,vfpv3-fp16,vfpv3-d16,vfpv3-d16-fp16,vfpv3xd,vfpv3xd-fp16,neon-vfpv3,neon-fp16,vfpv4,vfpv4-d16,fpv4-sp-d16,neon-vfpv4,fpv5-d16,fpv5-sp-d16,fp-armv8,neon-fp-armv8andcrypto-neon-fp-armv8. Note thatneonis an alias forneon-vfpv3andvfpis an alias forvfpv2๐ซถ.- The setting
autois the default and it's super special ๐. It makes the compiler pick the floating-point and Advanced SIMD instructions based on-mcpuand-march. - If the floating-point hardware you pick has the NEON extension (e.g.
-mfpu=neon), heads up bestie ๐จ: floating-point operations are not generated by GCC's auto-vectorization pass unless-funsafe-math-optimizationsis also specified. Why? 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 may lead to a loss of precision ๐ญ. - You can also set the fpu name at function level using the
target("fpu=")function attributes or pragmas ๐.
- The setting
-mfp16-format=nameโ sets the format of the"__fp16"half-precision floating-point type ๐ธ. Permissible names arenone,ieee, andalternative. The default isnone, and in that case the"__fp16"type is not defined ๐.-mstructure-size-boundary=nโ rounds the sizes of all structures and unions up to a multiple of the number of bits you set ๐. Permissible values are8,32and64. The default varies between toolchains. For the COFF targeted toolchain the default is8. A value of64is only allowed if the underlying ABI supports it ๐ง.- A larger number can produce faster, more efficient code ๐๏ธ, but it can also increase the size of the program ๐.
- Different values are potentially incompatible ๐. Code compiled with one value cannot necessarily expect to work with code or libraries compiled with another value, if they exchange information using structures or unions.
โ ๏ธ This option is deprecated, bestie ๐.
-mabort-on-noreturnโ generates a call to the functionabortat the end of anoreturnfunction ๐. It is executed if the function tries to return.-mlong-calls,-mno-long-callsโ tells the compiler to make function calls by first loading the address of the function into a register, then doing a subroutine call on that register ๐. This switch is needed if the target function lies outside the 64-megabyte addressing range of the offset-based version of the subroutine call instruction ๐บ๏ธ.- Even with this switch on, not every function call becomes a long call ๐
. Static functions, functions with the
short_callattribute, functions inside the scope of a#pragma no_long_callsdirective, and functions whose definitions have already been compiled within the current compilation unit stay as regular calls. The exceptions are always long calls ๐ : weak function definitions, functions with thelong_callattribute or thesectionattribute, and functions inside the scope of a#pragma long_callsdirective. - This feature is not enabled by default.
-mno-long-callsrestores the default behavior, as does placing the function calls within the scope of a#pragma long_calls_offdirective ๐. Note these switches have no effect on how the compiler generates code to handle function calls via function pointers ๐.
- Even with this switch on, not every function call becomes a long call ๐
. Static functions, functions with the
-msingle-pic-baseโ treats the register used for PIC addressing as read-only ๐, instead of loading it in the prologue for each function. The runtime system is responsible for initializing this register with an appropriate value before execution begins ๐.-mpic-register=regโ specifies the register to be used for PIC addressing ๐ฏ. For the standard PIC base case, the default is any suitable register determined by the compiler. For the single PIC base case, the default isR9if the target is EABI based or stack-checking is enabled, otherwise the default isR10.-mpic-data-is-text-relativeโ assumes the displacement between the text and data segments is fixed at static link time ๐งฉ. This permits using PC-relative addressing operations to access data known to be in the data segment. For non-VxWorks RTP targets, this option is enabled by default. When it's disabled on such targets, it will enable-msingle-pic-baseby default ๐.-mpoke-function-nameโ writes the name of each function into the text section, directly preceding the function prologue โ๏ธ. The generated code is similar to 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 performing a stack backtrace, code can inspect the value of pc stored at fp + 0. If the trace function then looks at location pc - 12 and the top 8 bits are set, then we know there is a function name embedded immediately preceding this location, and it has length ((pc[-3]) & 0xff000000) ๐ต๏ธโโ๏ธ.
-mthumb,-marmโ lets you pick between generating code that executes in ARM and Thumb states ๐งต. The default for most configurations is ARM state, but you can change that default by configuring GCC with the--with-mode=stateconfigure option โ๏ธ.- You can also override ARM and Thumb mode for each function using the
target("thumb")andtarget("arm")function attributes or pragmas ๐ช.
- You can also override ARM and Thumb mode for each function using the
-mflip-thumbโ switches ARM/Thumb modes on alternating functions ๐. It's provided for regression testing of mixed Thumb/ARM code generation, and it is not intended for ordinary code compiling ๐ซ.-mtpcs-frameโ generates a stack frame that complies with the Thumb Procedure Call Standard for all non-leaf functions. (A leaf function is one that does not call any other functions ๐.) The default is-mno-tpcs-frame.-mtpcs-leaf-frameโ generates a stack frame that complies with the Thumb Procedure Call Standard for all leaf functions. (A leaf function is one that does not call any other functions.) The default is-mno-apcs-leaf-frame.-mcallee-super-interworkingโ gives all externally visible functions in the file being compiled an ARM instruction set header that switches to Thumb mode before executing the rest of the function ๐. This lets them be called from non-interworking code. This option is not valid in AAPCS configurations, because interworking is enabled by default ๐ซ.-mcaller-super-interworkingโ lets calls via function pointers (including virtual functions) execute correctly, whether or not the target code was compiled for interworking ๐ค. There's a small overhead in the cost of executing a function pointer when this option is enabled ๐ข. This option is not valid in AAPCS configurations, because interworking is enabled by default ๐ซ.-mtp=nameโ specifies the access model for the thread local storage pointer ๐งต. The valid models aresoft, which generates calls to"__aeabi_read_tp";cp15, which fetches the thread pointer fromcp15directly (supported in thearm6karchitecture); andauto, which uses the best available method for the selected processor. The default setting isauto.-mtls-dialect=dialectโ specifies the dialect to use for accessing thread local storage ๐. Two dialects are supportedโgnuandgnu2. Thegnudialect selects the original GNU scheme for supporting local and global dynamic TLS models. Thegnu2dialect selects the GNU descriptor scheme, which provides better performance for shared libraries ๐. The GNU descriptor scheme is compatible with the original scheme, but it does require new assembler, linker and library support. Initial and local exec TLS models are unaffected by this option and always use the original scheme.-mword-relocationsโ only generates absolute relocations on word-sized values (i.e.R_ARM_ABS32) ๐ฏ. This is enabled by default on targets (uClinux, SymbianOS) where the runtime loader imposes this restriction, and when-fpicor-fPICis specified. This option conflicts with-mslow-flash-dataโ ๏ธ.-mfix-cortex-m3-ldrdโ some Cortex-M3 cores can cause data corruption whenldrdinstructions with overlapping destination and base registers are used ๐ฑ. This option avoids generating these instructions. It is enabled by default when-mcpu=cortex-m3is specified ๐.-munaligned-access,-mno-unaligned-accessโ enables (or disables) reading and writing of 16- and 32-bit values from addresses that are not 16- or 32-bit aligned ๐. By default, unaligned access is disabled for all pre-ARMv6, all ARMv6-M and for ARMv8-M Baseline architectures, and enabled for all other architectures. If unaligned access is not enabled, then words in packed data structures are accessed a byte at a time ๐ข.- The ARM attribute
"Tag_CPU_unaligned_access"is set in the generated object file to either true or false, depending on the setting of this option. If unaligned access is enabled, then the preprocessor symbol"__ARM_FEATURE_UNALIGNED"is also defined ๐ง .
- The ARM attribute
-mneon-for-64bitsโ this option is deprecated and has no effect ๐.-mslow-flash-dataโ assumes loading data from flash is slower than fetching instructions ๐. Therefore, literal loads are minimized for better performance โก. This option is only supported when compiling for ARMv7 M-profile and it's off by default. It conflicts with-mword-relocationsโ ๏ธ.
-masm-syntax-unified ๐ Okay so this one is about inline assembler syntax, bestie ๐ By default it's currently off, which means you get divided syntax. This option has no impact on Thumb2 ๐ฆ But heads up, GCC might change this in future releases, and divided syntax is considered deprecated, so like, don't get too attached ๐ญ
-mrestrict-it ๐ธ This one restricts how IT blocks get generated so they follow the ARMv8-A rules. An IT block can only contain a single 16-bit instruction from a specific set of instructions โจ It's on by default for ARMv8-A Thumb mode, so you're already set ๐
-mprint-tune-info ๐ง This prints CPU tuning information as a comment in the assembler file ๐ Real talk, it's only for regression testing of the compiler, not for normal code compiling ๐ It's disabled by default, so you don't need to do anything.
-mverbose-cost-dump ๐ฅ This enables verbose cost model dumping in the debug dump files. It's provided for debugging the compiler itself, so it's giving compiler-dev energy ๐
-mpure-code ๐ซถ This one doesn't allow constant data to be placed in code sections. Also, when you're compiling for ELF object format, it gives all text sections the ELF processor-specific section attribute SHF_ARM_PURECODE ๐ It's only available when you're generating non-PIC code for M-profile targets, so keep that in mind, bestie โญ
-mcmse ๐ This generates secure code following the "ARMv8-M Security Extensions: Requirements on Development Tools Engineering Specification" ๐ You can find that spec at <https://developer.arm.com/documentation/ecm0359818/latest/> ๐ฆ
-mfix-cmse-cve-2021-35465 ๐
This one mitigates a potential security issue with the "VLLDM" instruction on some M-profile devices when you're using CMSE (CVE-2021-365465) ๐ญ It's enabled by default when -mcpu= is used with "cortex-m33", "cortex-m35p" or "cortex-m55". If you want to turn the mitigation off, you can use -mno-fix-cmse-cve-2021-35465 ๐
-mfdpic -mno-fdpic ๐ Okay this one is the FDPIC ABI, which uses 64-bit function descriptors to represent pointers to functions โจ When the compiler is configured for "arm-*-uclinuxfdpiceabi" targets, -mfdpic is on by default and implies -fPIE if none of the PIC/PIE-related options is provided. On other targets, it only enables the FDPIC-specific code generation features, so you have to explicitly provide the PIC/PIE-related options yourself, as needed ๐
Static linking is not supported ๐ซ It would still involve the dynamic linker when the program self-relocates. If that behavior is acceptable to you, use-staticand-Wl,-dynamic-linkeroptions.
The opposite, -mno-fdpic, is useful (and required) for building the Linux kernel with the same ("arm-*-uclinuxfdpiceabi") toolchain you used to build your userland programs ๐ง๐
AVR Options ๐ฆ
These options are defined for AVR implementations ๐
-mmcu=mcu ๐ฅ Specify Atmel AVR instruction set architectures (ISA) or MCU type ๐ The default for this option is avr2.
GCC supports the following AVR devices and ISAs, and I'm obsessed with how many there are ๐ญ
avr2โ "Classic" devices with up to 8 KiB of program memory. MCUs:"attiny22","attiny26","at90s2313","at90s2323","at90s2333","at90s2343","at90s4414","at90s4433","at90s4434","at90c8534","at90s8515","at90s8535"โจavr25โ "Classic" devices with up to 8 KiB of program memory and with the "MOVW" instruction. 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"๐ธavr3โ "Classic" devices with 16 KiB up to 64 KiB of program memory. MCUs:"at76c711","at43usb355"๐avr31โ "Classic" devices with 128 KiB of program memory. MCUs:"atmega103","at43usb320"๐avr35โ "Classic" devices with 16 KiB up to 64 KiB of program memory and with the "MOVW" instruction. MCUs:"attiny167","attiny1634","atmega8u2","atmega16u2","atmega32u2","ata5505","ata6617c","ata664251","at90usb82","at90usb162"๐ฆ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"๐งavr5โ "Enhanced" devices with 16 KiB up to 64 KiB of program memory. MCUs:"atmega16","atmega16a","atmega16hva","atmega16hva2","atmega16hvb","atmega16hvbrevb","atmega16m1","atmega16u4","atmega161","atmega162","atmega163","atmega164a","atmega164p","atmega164pa","atmega165","atmega165a","atmega165p","atmega165pa","atmega168","atmega168a","atmega168p","atmega168pa","atmega168pb","atmega169","atmega169a","atmega169p","atmega169pa","atmega32","atmega32a","atmega32c1","atmega32hvb","atmega32hvbrevb","atmega32m1","atmega32u4","atmega32u6","atmega323","atmega324a","atmega324p","atmega324pa","atmega325","atmega325a","atmega325p","atmega325pa","atmega328","atmega328p","atmega328pb","atmega329","atmega329a","atmega329p","atmega329pa","atmega3250","atmega3250a","atmega3250p","atmega3250pa","atmega3290","atmega3290a","atmega3290p","atmega3290pa","atmega406","atmega64","atmega64a","atmega64c1","atmega64hve","atmega64hve2","atmega64m1","atmega64rfr2","atmega640","atmega644","atmega644a","atmega644p","atmega644pa","atmega644rfr2","atmega645","atmega645a","atmega645p","atmega649","atmega649a","atmega649p","atmega6450","atmega6450a","atmega6450p","atmega6490","atmega6490a","atmega6490p","ata5795","ata5790","ata5790n","ata5791","ata6613c","ata6614q","ata5782","ata5831","ata8210","ata8510","ata5702m322","at90pwm161","at90pwm216","at90pwm316","at90can32","at90can64","at90scr100","at90usb646","at90usb647","at94k","m3000"๐avr51โ "Enhanced" devices with 128 KiB of program memory. MCUs:"atmega128","atmega128a","atmega128rfa1","atmega128rfr2","atmega1280","atmega1281","atmega1284","atmega1284p","atmega1284rfr2","at90can128","at90usb1286","at90usb1287"๐avr6โ "Enhanced" devices with 3-byte PC, i.e. with more than 128 KiB of program memory. MCUs:"atmega256rfr2","atmega2560","atmega2561","atmega2564rfr2"โญavrxmega2โ "XMEGA" devices with more than 8 KiB and up to 64 KiB of program memory. MCUs:"atxmega8e5","atxmega16a4","atxmega16a4u","atxmega16c4","atxmega16d4","atxmega16e5","atxmega32a4","atxmega32a4u","atxmega32c3","atxmega32c4","atxmega32d3","atxmega32d4","atxmega32e5"๐avrxmega3โ "XMEGA" devices with up to 64 KiB of combined program memory and RAM, and with program memory visible in the RAM address space. MCUs:"attiny202","attiny204","attiny212","attiny214","attiny402","attiny404","attiny406","attiny412","attiny414","attiny416","attiny417","attiny804","attiny806","attiny807","attiny814","attiny816","attiny817","attiny1604","attiny1606","attiny1607","attiny1614","attiny1616","attiny1617","attiny3214","attiny3216","attiny3217","atmega808","atmega809","atmega1608","atmega1609","atmega3208","atmega3209","atmega4808","atmega4809"๐ซถavrxmega4โ "XMEGA" devices with more than 64 KiB and up to 128 KiB of program memory. MCUs:"atxmega64a3","atxmega64a3u","atxmega64a4u","atxmega64b1","atxmega64b3","atxmega64c3","atxmega64d3","atxmega64d4"๐avrxmega5โ "XMEGA" devices with more than 64 KiB and up to 128 KiB of program memory and more than 64 KiB of RAM. MCUs:"atxmega64a1","atxmega64a1u"๐avrxmega6โ "XMEGA" devices with more than 128 KiB of program memory. MCUs:"atxmega128a3","atxmega128a3u","atxmega128b1","atxmega128b3","atxmega128c3","atxmega128d3","atxmega128d4","atxmega192a3","atxmega192a3u","atxmega192c3","atxmega192d3","atxmega256a3","atxmega256a3b","atxmega256a3bu","atxmega256a3u","atxmega256c3","atxmega256d3","atxmega384c3","atxmega384d3"๐ฅavrxmega7โ "XMEGA" devices with more than 128 KiB of program memory and more than 64 KiB of RAM. MCUs:"atxmega128a1","atxmega128a1u","atxmega128a4u"โจavrtinyโ "TINY" Tiny core devices with 512 B up to 4 KiB of program memory. MCUs:"attiny4","attiny5","attiny9","attiny10","attiny20","attiny40"๐ธavr1โ This ISA is implemented by the minimal AVR core and supported for assembler only. MCUs:"attiny11","attiny12","attiny15","attiny28","at90s1200"๐
-mabsdata ๐
Assume that all data in static storage can be accessed by LDS / STS instructions. This option only has an effect on reduced Tiny devices like ATtiny40 ๐ญ See also the "absdata" AVR Variable Attributes, variable attribute.
-maccumulate-args ๐ฆ This accumulates outgoing function arguments and acquires/releases the needed stack space for them once, in the function prologue/epilogue ๐ซถ Without this option, outgoing arguments are pushed before calling a function and popped afterwards.
Popping the arguments after the call can be expensive on AVR, so accumulating the stack space might lead to smaller executables, since arguments don't need to be removed from the stack after the call ๐ง This can reduce code size for functions that make several calls to functions taking their arguments on the stack, like printf-like functions ๐
-mbranch-cost=cost ๐ This sets the branch costs for conditional branch instructions to cost. Reasonable values for cost are small, non-negative integers. The default branch cost is 0 โญ
-mcall-prologuesโ ๐ Function prologues and epilogues get expanded as calls to the right subroutines instead of inline code, so your code size comes out smaller โจ-mdouble=bits-mlong-double=bitsโ ๐ These set the size, in bits, of thedoubleorlong doubletype. The only possible values are32and64. Whether a value is allowed depends on the--with-double=and--with-long-double=configure options (https://gcc.gnu.org/install/configure.html#avr), and the same goes for the defaults of these options.-mgas-isr-prologuesโ ๐ฆ Interrupt service routines (ISRs) can use the__gcc_isrpseudo instruction, which GNU Binutils supports. If this option is on, you can still turn the feature off for individual ISRs with theno_gccisrfunction attribute from AVR Function Attributes. It's switched on by default when optimization is on (but not with-Og,@pxref{Optimize Options}), and only if GNU Binutils supports PR21683 (https://sourceware.org/PR21683).-mint8โ ๐ง This makesintan 8-bit integer, which changes the sizes of every type: acharis 1 byte, anintis 1 byte, alongis 2 bytes, and along longis 4 bytes. Heads up, this is not C standard compliant, but the code ends up smaller ngl ๐-mmain-is-OS_taskโ ๐mainwon't save registers. It does the same thing as slapping theOS_taskattribute from AVR Function Attributes ontomain. It's on by default when optimization is on.-mn-flash=numโ ๐ธ Tells the compiler to assume the flash memory isnumtimes 64 KiB.-mno-interruptsโ ๐ The generated code is not compatible with hardware interrupts. The upside is that the code size gets smaller.-mrelaxโ โจ This tries to swapCALLorJMPfor the shorterRCALLorRJMPwhen that's allowed. All it really does is add--mlink-relaxto the assembler's command line and--relaxto the linker's command line.
Jump relaxing happens in the linker, because jump offsets aren't known until the code gets placed. So the assembler code the compiler generates stays the same, but the instructions in the executable might look different from the assembler code. ๐ซถ
You have to turn relaxing on if linker stubs are needed. Check out the section on "EIND" and linker stubs below.
-mrmwโ ๐ฅ Assumes the device supports the Read-Modify-Write instructionsXCH,LAC,LASandLAT.-mshort-callsโ ๐ฆ Assumes thatRJMPandRCALLcan reach the whole program memory.
This one is used internally for multilib selection. It's not an optimization option, so you don't need to set it yourself, bestie ๐
-msp8โ ๐ Treats the stack pointer register as an 8-bit register, which basically means it assumes the high byte of the stack pointer is zero. Generally you don't need to set this one by hand.
The compiler uses this internally to pick and build multilibs for the avr2 and avr25 architectures. Those architectures mix devices that have SPH with devices that don't. For any setting other than -mmcu=avr2 or -mmcu=avr25, the compiler driver adds or removes this option from the compiler proper's command line. That's because the compiler already knows whether the device or architecture has an 8-bit stack pointer, and therefore no SPH register, or not. ๐ง
-mstrict-Xโ ๐ Uses theXaddress register the way the hardware intends. That meansXonly gets used for indirect, post-increment, or pre-decrement addressing.
Without this option, X can be used the same way as Y or Z, but then it gets emulated with extra instructions. For example, loading a value with X+const addressing, where const is small, non-negative and const < 64, into a register Rn is done like this:
adiw r26, const ; X += const
ld <Rn>, X ; <Rn> = *X
sbiw r26, const ; X -= const
-mtiny-stackโ ๐ Only the lower 8 bits of the stack pointer get changed.-mfract-convert-truncateโ โจ Lets you use truncation instead of rounding toward zero for fractional fixed-point types.-nodevicelibโ ๐ Don't link against AVR-LibC's device-specific librarylib<mcu>.a.-nodevicespecsโ ๐ Stops the compiler driver from adding-specs=device-specs/specs-mcuto its command line. This means you are responsible for giving the subprocesses (the compiler proper, the assembler, and the linker) the right command line options. You'll have to supply your own private device specs file with-specs=path-to-specs-file. Once you do that, there's no more need for-mmcu=mcu๐ซถ
This option also works as a replacement for the older way of specifying custom device-specs files. The old way needed -B some-path to point at a directory containing a folder named device-specs, and that folder had to contain a specs file named specs-mcu, where mcu was the value given with -mmcu=mcu. That's a lot of setup, so this option is way more iconic โจ
-Waddr-space-convertโ โญ Warns about conversions between address spaces when the resulting address space is not contained in the incoming address space.-Wmisspelled-isrโ ๐ฅ Warns if an ISR is misspelled, meaning it's missing the__vectorprefix. This one is enabled by default.
โจ "EIND" and Devices With More Than 128 Ki Bytes of Flash โจ
Pointers in the implementation are 16 bits wide. The address of a function or label is represented as a word address, so indirect jumps and calls can target any code address in the range of 64 Ki words. ๐ง
To make indirect jumps work on devices with more than 128 Ki bytes of program memory space, there's a special function register called EIND. It serves as the most significant part of the target address when EICALL or EIJMP instructions are used. ๐
Indirect jumps and calls on these devices are handled as follows by the compiler, and they come with some limitations:
- The compiler never sets
EIND. - The compiler uses
EINDimplicitly inEICALL/EIJMPinstructions, or it might readEINDdirectly in order to emulate an indirect call/jump by means of aRETinstruction. - The compiler assumes that
EINDnever changes during the startup code or during the application. In particular,EINDis not saved or restored in function or interrupt service routine prologues and epilogues. - For indirect calls to functions and computed gotos, the linker generates stubs. Stubs are jump pads, sometimes also called trampolines. So the indirect call or jump actually jumps to such a stub, and the stub contains a direct jump to the desired address. ๐ฆ
- Linker relaxation must be turned on so the linker generates the stubs correctly in all situations. See the compiler option
-mrelaxand the linker option--relax. Watch out, though: there are corner cases where the linker is supposed to generate stubs but aborts without relaxation and without a helpful error message. ๐ญ - The default linker script is arranged for code with
EIND = 0. If your code is supposed to work withEIND != 0, you'll need a custom linker script to place the sections whose names start with.trampolinesinto the segment thatEINDpoints to. ๐ - The startup code from libgcc never sets
EIND. Notice that the startup code is a blend of code from libgcc and AVR-LibC. For the impact of AVR-LibC onEIND, see the AVR-LibC user manual (http://nongnu.org/avr-libc/user-manual/). ๐ - It's totally legit for user-specific startup code to set up
EINDearly, for example with initialization code located in section.init3. That code runs before the general startup code that initializes RAM and calls constructors, but after the bit of AVR-LibC startup code that setsEINDto the segment where the vector table is located. ๐ซถ
#include <avr/io.h>
static void __attribute__((section(".init3"),naked,used,no_instrument_function)) init3_set_eind (void) { __asm volatile ("ldi r24,pm_hh8(__trampolines_start)\n\t" "out %i0,r24" :: "n" (&EIND) : "r24","memory"); }
The __trampolines_start symbol is defined in the linker script. ๐
- Stubs are generated automatically by the linker if both of the following 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
gsmodifiers for code labels in the following situations:- Taking the address of a function or code label.
- Computed goto.
- If a prologue-save function is used, see the
-mcall-prologuescommand-line option. - Switch/case dispatch tables. If you don't want such dispatch tables, you can specify the
-fno-jump-tablescommand-line option. - C and C++ constructors and destructors called during startup or shutdown.
- If the tools hit a
gs()modifier explained above.
- Jumping to non-symbolic addresses like this is not supported ๐ โโ๏ธ
int main (void) { /* Call function at word address 0x2 / return ((int()(void)) 0x2)(); }
Instead, you have to set up a stub, meaning the function has to be called through a symbol (func_4 in the example):
int main (void) { extern int func_4 (void);
/* Call function at byte address 0x4 */ return func_4(); }
And the application has to be linked with -Wl,--defsym,func_4=0x4. Alternatively, func_4 can be defined in the linker script. ๐ธ
โจ Handling of the RAMPD, RAMPX, RAMPY and RAMPZ Special Function Registers โจ
Some AVR devices support memories larger than the 64 KiB range that can be accessed with 16-bit pointers. To reach memory locations outside this 64 KiB range, the contents of a RAMP register are used as the high part of the address. The X, Y, and Z address registers are concatenated with the RAMPX, RAMPY, and RAMPZ special function registers, respectively, to get a wide address. Similarly, RAMPD is used together with direct addressing. ๐
- The startup code initializes the
RAMPspecial function registers with zero. ๐
Okay so we're picking up mid-thought with the RAMPZ stuff, and the rules are kinda intense ๐
- If you use a named address space that isn't generic or
"__flash",RAMPZgets set up as needed before the operation ๐ธ - If the device has more than 64 KiB of RAM and the compiler needs to change
RAMPZfor an operation,RAMPZgets reset to zero afterwards ๐ - If the device has a specific
RAMPregister, the ISR prologue/epilogue saves and restores that SFR, and sets it to zero in case the ISR code might (implicitly) use it โจ - RAM larger than 64 KiB is NOT supported by GCC for AVR targets ๐ If you use inline assembler to read from locations outside the 16-bit address range and change one of the
RAMPregisters, you have to reset it to zero after the access. No skipping this, bestie ๐
๐ธ AVR Built-in Macros ๐ธ
GCC defines a bunch of built-in macros so your code can check whether certain features are there or not, and honestly it's giving very helpful energy ๐ง Almost all of the following are deduced from device capabilities, so they get triggered by the -mmcu= command-line option.
For even more AVR-specific built-in macros, see AVR Named Address Spaces and AVR Built-in Functions ๐
"__AVR_ARCH__"โ a built-in macro that resolves to a decimal number identifying the architecture, which 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
mcuspecifies a device, this macro gets set accordingly. For example, with-mmcu=atmega8the macro is defined to4๐ฆ
"__AVR_Device__"โ setting-mmcu=devicedefines this macro, which reflects the device's name. For example,-mmcu=atmega8defines"__AVR_ATmega8__", and-mmcu=attiny261adefines"__AVR_ATtiny261A__", etc. โจ- The names follow the scheme
"__AVR_Device__", where Device is the device name as written in the AVR user manual. The difference between Device in the macro and device in-mmcu=deviceis that the latter is always lowercase. - If device isn't an actual device but just a core architecture like
avr51, this macro is not defined.
- The names follow the scheme
"__AVR_DEVICE_NAME__"โ setting-mmcu=devicedefines this macro to the device's name. For example, with-mmcu=atmega8the macro is defined to"atmega8"๐- If device is only a core architecture like
avr51and not a device, this macro is not defined.
- If device is only a core architecture like
"__AVR_XMEGA__"โ the device or architecture belongs to the XMEGA family of devices ๐"__AVR_HAVE_ELPM__"โ the device has theELPMinstruction ๐"__AVR_HAVE_ELPMX__"โ the device has theELPM Rn,ZandELPM Rn,Z+instructions ๐"__AVR_HAVE_MOVW__"โ the device has theMOVWinstruction for 16-bit register-to-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. It also means the program counter (PC) is 3 bytes wide ๐ง"__AVR_2_BYTE_PC__"โ the program counter (PC) is 2 bytes wide. This is the case for devices with up to 128 KiB of program memory ๐"__AVR_HAVE_8BIT_SP__"and"__AVR_HAVE_16BIT_SP__"โ the compiler treats the stack pointer (SP) register as an 8-bit or 16-bit register, respectively. Defining 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. Defining these macros is affected by-mmcu=, and in the cases of-mmcu=avr2and-mmcu=avr25also by-msp8๐"__AVR_HAVE_RAMPD__","__AVR_HAVE_RAMPX__","__AVR_HAVE_RAMPY__", and"__AVR_HAVE_RAMPZ__"โ the device has theRAMPD,RAMPX,RAMPY, andRAMPZspecial function registers, respectively ๐"__NO_INTERRUPTS__"โ this macro reflects the-mno-interruptscommand-line option ๐"__AVR_ERRATA_SKIP__"and"__AVR_ERRATA_SKIP_JMP_CALL__"โ some AVR devices (AT90S8515, ATmega103) must not skip 32-bit instructions because of a hardware erratum. The skip instructions areSBRS,SBRC,SBIS,SBIC, andCPSE. The second macro is only defined if"__AVR_HAVE_JMP_CALL__"is also set ๐"__AVR_ISA_RMW__"โ the device has Read-Modify-Write instructions (XCH,LAC,LAS, andLAT) ๐ฅ"__AVR_SFR_OFFSET__=offset"โ instructions that can address I/O special function registers directly, likeIN,OUT,SBI, etc., may use a different address than an instruction accessing RAM, likeLDorSTS. This offset depends on the device architecture and has to be subtracted from the RAM address to get the respective I/O address ๐ฆ"__AVR_SHORT_CALLS__"โ the-mshort-callscommand-line option is set ๐"__AVR_PM_BASE_ADDRESS__=addr"โ some devices can read from flash memory usingLD*instructions. The flash memory shows up in the data address space at an offset of"__AVR_PM_BASE_ADDRESS__". If this macro isn't defined, the feature isn't available. If it is defined, the address space is linear and there's no need to put.rodatainto RAM. The default linker description file handles this, and it's currently available foravrtinyandavrxmega3. Even more convenient, there's no need for address spaces like"__flash"or the attributeprogmemandpgm_read_*๐ธ"__WITH_AVRLIBC__"โ the compiler is configured to be used together with AVR-Libc. See the--with-avrlibcconfigure option ๐ง"__HAVE_DOUBLE_MULTILIB__"โ defined if-mdouble=acts as a multilib option ๐"__HAVE_DOUBLE32__"and"__HAVE_DOUBLE64__"โ defined if the compiler supports 32-bit double or 64-bit double, respectively. The actual layout is specified by option-mdouble=โจ"__DEFAULT_DOUBLE__"โ the size in bits ofdoubleif-mdouble=isn't set. To test the layout ofdoublein a program, use the built-in macro"__SIZEOF_DOUBLE__"๐"__HAVE_LONG_DOUBLE32__","__HAVE_LONG_DOUBLE64__","__HAVE_LONG_DOUBLE_MULTILIB__", and"__DEFAULT_LONG_DOUBLE__"โ same as above, but forlong doubleinstead ofdouble๐"__WITH_DOUBLE_COMPARISON__"โ reflects the--with-double-comparison={tristate|bool|libf7}configure option (https://gcc.gnu.org/install/configure.html#avr) and is defined to 2 or 3 ๐"__WITH_LIBF7_LIBGCC__","__WITH_LIBF7_MATH__", and"__WITH_LIBF7_MATH_SYMBOLS__"โ reflect the--with-libf7={libgcc|math|math-symbols}configure option (https://gcc.gnu.org/install/configure.html#avr) ๐ฅ
๐ฆ Blackfin Options ๐ฆ
-mcpu=cpu[-sirevision]โ specifies the name of the target Blackfin processor. Right now,cpucan be one ofbf512, bf514, bf516, bf518, bf522, bf523, bf524, bf525, bf526, bf527, bf531, bf532, bf533, bf534, bf536, bf537, bf538, bf539, bf542, bf544, bf547, bf548, bf549, bf542m, bf544m, bf547m, bf548m, bf549m, bf561, bf592๐ง- The optional
sirevisionspecifies the silicon revision of the target Blackfin processor. Any workarounds available for that silicon revision get enabled. Ifsirevisionisnone, no workarounds are enabled. Ifsirevisionisany, all workarounds for the targeted processor are enabled. - The
"__SILICON_REVISION__"macro is defined to two hexadecimal digits representing the major and minor numbers in the silicon revision. Ifsirevisionisnone,"__SILICON_REVISION__"is not defined. Ifsirevisionisany,"__SILICON_REVISION__"is defined to be0xffff. - If this optional
sirevisionisn't used, GCC assumes the latest known silicon revision of the targeted Blackfin processor. - GCC defines a preprocessor macro for the specified
cpu. For thebfin-elftoolchain, this option causes the hardware BSP provided by libgloss to be linked in if-msimisn't given. - Without this option,
bf532is used as the processor by default. - Note that support for
bf561is incomplete. Forbf561, only the preprocessor macro is defined ๐
- The optional
-msimโ specifies that the program will run on the simulator, which causes the simulator BSP provided by libgloss to be linked in. This option only has an effect for thebfin-elftoolchain. Certain other options, such as-mid-shared-libraryand-mfdpic, imply-msim๐ธ-momit-leaf-frame-pointerโ don't keep the frame pointer in a register for leaf functions. This skips the instructions that save, set up, and restore frame pointers, and makes an extra register available in leaf functions ๐-mspecld-anomalyโ when enabled, the compiler makes sure the generated code doesn't contain speculative loads after jump instructions. If this option is used,"__WORKAROUND_SPECULATIVE_LOADS"is defined ๐ฅ-mno-specld-anomalyโ don't generate extra code to prevent speculative loads from happening ๐-mcsync-anomalyโ when enabled, the compiler makes sure the generated code doesn't containCSYNCorSSYNCinstructions too soon after conditional branches. If this option is used,"__WORKAROUND_SPECULATIVE_SYNCS"is defined ๐-mno-csync-anomalyโ don't generate extra code to preventCSYNCorSSYNCinstructions from happening too soon after a conditional branch ๐ซถ-mlow64kโ when enabled, the compiler is free to take advantage of the knowledge that the entire program fits into the low 64k of memory โจ-mno-low64kโ assume the program is arbitrarily large. This is the default ๐-mstack-check-l1โ do stack checking using information placed into L1 scratchpad memory by the uClinux kernel ๐-mid-shared-libraryโ generates code that supports shared libraries via the library ID method. This allows execute-in-place and shared libraries in an environment without virtual memory management. This option implies-fPIC. With abfin-elftarget, this option implies-msim๐-mno-id-shared-libraryโ Skip the assumption that ID-based shared libraries are in play. This is the default ๐ธ-mleaf-id-shared-libraryโ Support shared libraries through the library ID method, but assume 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 being compiled avoids linking against ID shared libraries. You get slower code for jump and call insns ๐ข-mshared-library-id=nโ Sets the identification number of the ID-based shared library being compiled. Passing0gives you more compact code. Any other value forces that number onto the current library, but it's no more space- or time-efficient than leaving this option out ๐-msep-dataโ Lets the data segment live in a different area of memory from the text segment. This allows execute in place in an environment without virtual memory management, because it gets rid of relocations against the text section ๐ฆ-mno-sep-dataโ Assumes the data segment follows the text segment. This is the default ๐-mlong-calls,-mno-long-callsโ The compiler makes function calls by loading the function's address into a register first, then doing a subroutine call on that register. You need this switch if the target function sits outside the 24-bit addressing range of the offset-based subroutine call instruction. It's not on by default, and-mno-long-callsputs you back to default behavior. These switches do nothing for function calls made through function pointers ๐-mfast-fpโ Links with the fast floating-point library. It loosens some of the IEEE floating-point standard's rules for checking inputs against Not-a-Number (NAN), all for the sake of speed ๐ฅ-minline-pltโ Inlines 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 uses the proper start files and link scripts for multicore and defines the macro"__BFIN_MULTICORE". It can only be used with-mcpu=bf561[-sirevision]๐- With
-mcoreaor-mcoreb, you get the one-application-per-core programming model. Without either one, you get the single-application/dual-core model, where Core B's main function should be named"coreb_main"๐ - If you skip this option entirely, you get the single-core application programming model ๐ง
- With
-mcoreaโ Builds a standalone application for Core A of BF561 in the one-application-per-core model. It uses the right start files and link scripts for Core A and defines"__BFIN_COREA". Only works alongside-mmulticore๐ซถ-mcorebโ Builds a standalone application for Core B of BF561 in the one-application-per-core model. It uses the right start files and link scripts for Core B and defines"__BFIN_COREB". When you use this,"coreb_main"replaces"main". Only works alongside-mmulticore๐-msdramโ Builds a standalone application for SDRAM. Start files and link scripts put the app into SDRAM and define"__BFIN_SDRAM". The loader needs to initialize SDRAM before loading the application ๐ง-micplbโ Assumes ICPLBs are enabled at run time. This affects certain anomaly workarounds. On Linux targets, the default is to assume ICPLBs are enabled. For standalone applications, it's off by default ๐
C6X Options
-march=nameโ Picks the target architecture. GCC uses this to figure out which instructions it's allowed to emit when generating assembly code. Valid names arec62x,c64x,c64x+,c67x,c67x+, andc674x๐ธ-mbig-endianโ Generates code for a big-endian target ๐-mlittle-endianโ Generates code for a little-endian target. This is the default ๐-msimโ Picks startup files and a linker script that work with the simulator ๐-msdata=defaultโ Puts small global and static data in the.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 big chunks of data are.fardata,.far, and.const๐ฆ-msdata=allโ Puts all data, not just the small stuff, into the small-data sections, and uses addressing relative to theB14register to get at it ๐ฅ-msdata=noneโ Doesn't use the small-data sections at all, and uses absolute addresses for all data. All initialized global and static data goes in.fardata, all uninitialized data goes in.far, and all constant data goes in.const๐
CRIS Options
These are defined specifically for the CRIS ports, so they're a special little club ๐ง
-march=architecture-type,-mcpu=architecture-typeโ Generates code for the architecture you pick. The choices for architecture-type arev3,v8, andv10, which map to ETRAX 4, ETRAX 100, and ETRAX 100 LX, respectively. The default isv0, except forcris-axis-linux-gnu, where the default isv10โจ-mtune=architecture-typeโ Tunes everything that applies to the generated code for the architecture you pick, except the ABI and the set of available instructions. The choices are the same as for-march=architecture-type๐-mmax-stack-frame=nโ Warns when a function's stack frame goes over n bytes ๐-metrax4,-metrax100โ These are synonyms for-march=v3and-march=v8, respectively ๐-mmul-bug-workaround,-mno-mul-bug-workaroundโ Works around a bug in themulsandmuluinstructions on CPU models where it applies. This one is active by default ๐ ๏ธ-mpdebugโ Turns on CRIS-specific verbose debug info in the assembly code. It also turns off the#NO_APPformatted-code indicator that the assembler normally gets at the top of the assembly file ๐-mcc-initโ Doesn't reuse condition-code results from earlier instructions. It always emits compare and test instructions before using condition codes ๐ซถ-mno-side-effectsโ Doesn't emit instructions with side effects in addressing modes other than post-increment ๐ธ-mstack-align,-mno-stack-align,-mdata-align,-mno-data-align,-mconst-align,-mno-const-alignโ These arrange (or, with theno-versions, un-arrange) alignment so the stack frame, individual data, and constants line up with the biggest single data access size for your chosen CPU model. The default is 32-bit alignment. ABI details like structure layout aren't affected by these ๐-m32-bit,-m16-bit,-m8-bitโ Like the stack, data, and const align options above, these make the stack frame, writable data, and constants 32-bit, 16-bit, or 8-bit aligned. The default is 32-bit alignment ๐ฆ-mno-prologue-epilogue,-mprologue-epilogueโ With-mno-prologue-epilogue, the normal function prologue and epilogue that set up the stack frame get dropped, and no return instructions or return sequences are generated. Only use this with visual inspection of the compiled code ๐
โ ๏ธ Heads up bestie: with -mno-prologue-epilogue, no warnings or errors come up when call-saved registers need saving or when storage for local variables needs allocating. You have to check it yourself ๐
-mno-gotplt,-mgotpltโ With-fpicand-fPIC,-mno-gotpltstops generating instruction sequences that load function addresses from the PLT part of the GOT, instead of calling through the PLT the traditional way used on other architectures.-mgotpltturns that back on. The default is-mgotplt๐-melfโ A legacy no-op, only recognized with thecris-axis-elfandcris-axis-linux-gnutargets ๐ง-mlinuxโ A 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 back to back ๐งช-sim2โ Like-sim, but passes linker options to put initialized data at0x40000000and zero-initialized data at0x80000000๐
CR16 Options
These are defined specifically for the CR16 ports, so they're another exclusive little group ๐ธ
-mmacโ Enables multiply-accumulate instructions. It's disabled by default ๐ฅ-mcr16cplus,-mcr16cโ Generates code for the CR16C or CR16C+ architecture. CR16C+ is the default โจ-msimโ Links the librarylibsim.a, which works with the simulator. This only applies to the ELF compiler ๐-mint32โ Makes the integer type 32-bit wide ๐-mbit-opsโ Generates"sbit"and"cbit"instructions for bit manipulations ๐ฆ-mdata-model=modelโ Picks a data model. The choices arenear,far, ormedium, andmediumis the default. Heads up though:farisn't valid with-mcr16c, because the CR16C architecture doesn't support the far data model ๐ โโ๏ธ
C-SKY Options
GCC supports these when compiling for C-SKY V2 processors ๐
-march=archโ Specifies the C-SKY target architecture. Valid values for arch areck801,ck802,ck803,ck807, andck810. The default isck810๐-mcpu=cpuโ okay bestie, this one lets you pick your C-SKY target processor ๐ The valid values for cpu areck801, ck801t, ck802, ck802t, ck802j, ck803, ck803h, ck803t, ck803ht, ck803f, ck803fh, ck803e, ck803eh, ck803et, ck803eht, ck803ef, ck803efh, ck803ft, ck803eft, ck803efht, ck803r1, ck803hr1, ck803tr1, ck803htr1, ck803fr1, ck803fhr1, ck803er1, ck803ehr1, ck803etr1, ck803ehtr1, ck803efr1, ck803efhr1, ck803ftr1, ck803eftr1, ck803efhtr1, ck803s, ck803st, ck803se, ck803sf, ck803sef, ck803seft, ck807e, ck807ef, ck807, ck807f, ck810e, ck810et, ck810ef, ck810eft, ck810, ck810v, ck810f, ck810t, ck810fv, ck810tv, ck810ft,andck810ftv๐ฅ-mbig-endian,-EB,-mlittle-endian,-ELโ pick your endian era ๐ You get big-endian or little-endian code, and little-endian is the default, so you're already winning ๐-mhard-float,-msoft-floatโ hardware or software floating-point, your call ๐ง Soft float is the default, so that's what you get unless you ask for more.-mdouble-float,-mno-double-floatโ when-mhard-floatis in effect, this turns on double-precision float instructions ๐ It's on by default except when you're compiling forCK803, so keep that in mind, bestie ๐-mfdivdu,-mno-fdivduโ when-mhard-floatis in effect, this lets the compiler generatefrecipd,fsqrtd, andfdivdinstructions โจ Same deal as above: it's the default except forCK803.-mfpu=fpuโ pick your floating-point processor ๐ฆ This one only works with-mhard-float. The values arefpv2_sf(basically the same as-mno-double-float -mno-fdivdu),fpv2(-mdouble-float -mno-divdu), andfpv2_divd(-mdouble-float -mdivdu).-melrw,-mno-elrwโ turns on the extendedlrwinstruction ๐ธ It's on forCK801and off for everything else.-mistack,-mno-istackโ enables interrupt stack instructions, and it's off by default ๐ Heads up: you need-mistackto handle theinterruptandisrfunction attributes, so don't skip it.-mmpโ enables multiprocessor instructions, off by default ๐-mcpโ enables coprocessor instructions, off by default ๐-mcacheโ also enables coprocessor instructions, off by default ๐-msecurityโ enables C-SKY security instructions, off by default ๐-mtrustโ enables C-SKY trust instructions, off by default ๐ซถ-mdsp,-medsp,-mvdspโ enable C-SKY DSP, Enhanced DSP, or Vector DSP instructions, respectively ๐ All three are off by default.-mdiv,-mno-divโ generates divide instructions, but it's off by default so you have to ask ๐-msmart,-mno-smartโ generates code for Smart Mode, which only uses registers0-7so you can use those cute 16-bit instructions ๐ง It's ignored forCK801(where this is required anyway), it's on by default forCK802, and it's off for other targets.-mhigh-registers,-mno-high-registersโ generates code that uses the high registers16-31โจ This isn't supported onCK801,CK802, orCK803, but it's on by default for other processors.-manchor,-mno-anchorโ generates code that uses global anchor symbol addresses ๐ฆ-mpushpop,-mno-pushpopโ generates code withpushandpopinstructions, and it's on by default ๐-mmultiple-stld,-mstm,-mno-multiple-stld,-mno-stmโ generates code usingstmandldminstructions ๐ฅ This isn't supported onCK801, 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 it's required for correct code generation onCK801andCK802, and it's optional on other processors.-mstack-size,-mno-stack-sizeโ emits.stack_sizedirectives for each function in the assembly output ๐ It's off by default.-mccrt,-mno-ccrtโ generates code for the C-SKY compiler runtime instead oflibgcc๐ It's off by default.-mbranch-cost=nโ sets the branch costs to roughly n instructions ๐ The default is1.-msched-prolog,-mno-sched-prologโ lets the scheduler mess with function prologue and epilogue sequences ๐ Okay, real talk: using this can give you code that isn't compliant with the C-SKY V2 ABI prologue requirements, and that code can't be debugged or backtraced. It's disabled by default.
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 one architecture GCC was built to target ๐
Apple's GCC on Darwin does make "fat" files if you use multiple -arch options. It does this by running the compiler or linker multiple times and then joining the results together with lipo ๐ฅ
The subtype of the file (like ppc7400 or ppc970 or i686) is decided by the flags that specify the ISA GCC is targeting, like -mcpu or -march โจ If you want to override that, the -force_cpusubtype_ALL option can do it.
The Darwin tools are kind of inconsistent 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 (like trying to put a ppc970 object file in a ppc7400 library). 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 front of the list of directories searched for header files ๐ง These directories get interleaved with the ones from-Ioptions and get scanned left to right.
A framework directory is just a directory full of frameworks ๐ A framework is a directory that has a Headers and/or PrivateHeaders directory sitting directly inside it and ends in .framework. The framework's name is the directory name without 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 can only show up in a header of the framework that contains the subframework, or in a sibling subframework header. Two subframeworks are siblings if they're in the same framework ๐ฏ A subframework shouldn't share a name with a framework, and if it does you'll get a warning ๐ Right now a subframework can't have subframeworks of its own, but that might change later. The standard frameworks live in /System/Library/Frameworks and /Library/Frameworks ๐ An example include looks like #include <Framework/header.h>, where Framework is the framework's name and header.h is found in the PrivateHeaders or Headers directory.
-iframeworkdirโ 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 constructs inside header files found throughdir. This option is only valid for the C family of languages.-gusedโ emits debugging information for symbols that are used ๐ฅ For the stabs debugging format, this turns on-feliminate-unused-debug-symbols. It's ON by default.-gfullโ emits debugging information for all symbols and types ๐-mmacosx-version-min=versionโ tells you the earliest version of MacOS X this executable will run on ๐ Typical values of version include10.1,10.2, and10.3.9.
If the compiler was built to use the system's headers by default, then the default for this option is whatever system version the compiler is running on ๐ Otherwise, the default is to make choices that are compatible with as many systems and code bases as possible.
-mkernelโ enables kernel development mode ๐ง This sets-static,-fno-common,-fno-use-cxa-atexit,-fno-exceptions,-fno-non-call-exceptions,-fapple-kext,-fno-weak, and-fno-rttiwhere applicable. For PowerPC targets, it also sets-mno-altivec,-msoft-float,-fno-builtin, and-mlong-branch๐ธ-mone-byte-boolโ overrides the defaults forboolso thatsizeof(bool)==1๐ By default,sizeof(bool)is4when compiling for Darwin/PowerPC and1when compiling for Darwin/x86, so this option does nothing on x86.
โ ๏ธ Warning, bestie: -mone-byte-bool makes GCC generate code that is not binary compatible with code generated without that switch ๐ญ You may need to recompile every other module in your program, including system libraries. Only use this to conform to a non-default data model.
-mfix-and-continue,-ffix-and-continue,-findirect-dataโ generates code for fast turnaround development, like letting GDB dynamically load.ofiles into programs that are already running ๐ฆ-findirect-dataand-ffix-and-continueare only here for backwards compatibility.-all_loadโ loads all members of static archive libraries ๐ฆ Seeman ld(1)for more information.-arch_errors_fatalโ makes errors about files with the wrong architecture fatal ๐-bind_at_loadโ marks the output file so the dynamic linker binds all undefined references when the file is loaded or launched โจ-bundleโ produces a Mach-o bundle format file ๐ Seeman ld(1)for more information.-bundle_loader executableโ specifies the executable that will load the build output file being linked ๐ง Seeman ld(1)for more information.-dynamiclibโ when you pass this, GCC makes 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๐
okay so the Darwin flags are a whole list ๐โจ every single one of these gets handed straight to the Darwin linker, bestie:
-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
Real talk: all of these get passed to the Darwin linker ๐ , and its man page is where you go for the full tea on each one ๐ซถ
โจ DEC Alpha Options โจ
These -m options are defined for the DEC Alpha implementations ๐ฆ
-mno-soft-float,-msoft-floatโ these two are opposites ๐-msoft-floatmeans GCC skips the hardware floating-point instructions, and-mno-soft-floatkeeps them. With-msoft-float, the floating-point operations go through functions inlibgcc.a. Unless those get replaced with routines that emulate the float ops (or get compiled to call those emulations), they'll still issue floating-point operations. So if you're compiling for an Alpha with no floating-point operations, you have to make sure the library is built so it doesn't call them ๐ญ Heads up: Alpha implementations without floating-point operations are still required to have floating-point registers.-mfp-reg,-mno-fp-regsโ-mfp-regmakes GCC generate code that uses the floating-point register set, and-mno-fp-regsmakes it not use it.-mno-fp-regsimplies-msoft-float. If the floating-point register set isn't used, floating-point operands get passed in integer registers as if they were integers, and floating-point results get passed back in$0instead of$f0. This is a non-standard calling sequence, so any function with a floating-point argument or return value that's called by code compiled with-mno-fp-regsmust also be compiled with that option โ ๏ธ A typical use of-mno-fp-regsis 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 tuned for max performance. It's mostly compliant with the IEEE floating-point standard, but full compliance needs software help. This option generates fully IEEE-compliant code, except that the inexact-flag isn't maintained (see below). Turning it on defines the preprocessor macro_IEEE_FPduring compilation. The result is less efficient, but it can correctly support denormalized numbers and exceptional IEEE values like not-a-number and plus/minus infinity. Other Alpha compilers call this option-ieee_with_no_inexact.-mieee-with-inexactโ this is like-mieee, except the generated code also maintains the IEEE inexact-flag ๐ Turning it on makes the code implement fully-compliant IEEE math. On top of_IEEE_FP, the preprocessor macro_IEEE_FP_EXACTis defined too. On some Alpha implementations, the code can run significantly slower than the default. There's very little code that depends on the inexact-flag, so you should normally not specify this option. Other Alpha compilers call this option-ieee_with_inexact.-mfp-trap-mode=trap-modeโ this controls which floating-point-related traps are enabled. Other Alpha compilers call this option-fptm trap-mode. The trap mode can be set to one of four values:nโ this is the default (normal) setting. The only traps enabled are the ones that can't be disabled in software (like the division by zero trap).uโ in addition to 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โ round towards minus infinity.cโ chopped rounding mode. Floating-point numbers are rounded towards zero.dโ dynamic rounding mode. A field in the floating-point control register (fpcr, see the Alpha architecture reference manual) controls the rounding mode in effect. The C library initializes this register for rounding towards plus infinity. So unless your program modifies thefpcr,dcorresponds to round towards plus infinity.
-mtrap-precision=trap-precisionโ in the Alpha architecture, floating-point traps are imprecise ๐ตโ๐ซ That means without software help, it's impossible to recover from a floating trap, and program execution normally has to be terminated. GCC can generate code that helps operating system trap handlers figure out the exact location that caused a floating-point trap. Depending on what your application needs, you can pick different levels of precision. Other Alpha compilers provide the equivalent options called-scope_safeand-resumption_safe.pโ program precision. This option is the default, and it means a trap handler can only identify which program caused a floating-point exception.fโ function precision. The trap handler can determine the function that caused a floating-point exception.iโ instruction precision. The trap handler can determine the exact instruction that caused a floating-point exception.
-mieee-conformantโ this marks the generated code as IEEE conformant.
Bestie, be careful: you must not use this option unless you also specify-mtrap-precision=iand either-mfp-trap-mode=suor-mfp-trap-mode=sui. Its only effect is to emit the line.eflag 48in the function prologue of the generated assembly file.
-mbuild-constantsโ normally, GCC looks at a 32- or 64-bit integer constant to see if it can construct it from smaller constants in two or three instructions. If it can't, it outputs the constant as a literal and generates code to load it from the data segment at run time. Use this option to require GCC to construct all integer constants using code, even if it takes more instructions (the maximum is six). You typically use this to build a shared library dynamic loader ๐ง Since it's itself a shared library, it has to relocate itself in memory before it can find the variables and constants in its own data segment.-mbwx,-mno-bwx,-mcix,-mno-cix,-mfix,-mno-fix,-mmax,-mno-maxโ these indicate whether GCC should generate code that uses the optional BWX, CIX, FIX and MAX instruction sets. The default is to use the instruction sets supported by the CPU type specified via the-mcpu=option, or the CPU GCC was built on if none is specified ๐-mfloat-vax,-mfloat-ieeeโ-mfloat-vaxgenerates code that uses VAX F and G floating-point arithmetic instead of IEEE single and double precision, and-mfloat-ieeegenerates code that does not use it ๐ธ-mexplicit-relocs,-mno-explicit-relocsโ older Alpha assemblers had no way to generate symbol relocations except through assembler macros, and using those macros doesn't allow optimal instruction scheduling. GNU binutils as of version 2.12 supports a new syntax that lets the compiler explicitly mark which relocations should apply to which instructions. This option is mostly useful for debugging, since GCC detects the capabilities of the assembler when it's built and sets the default accordingly.-msmall-data,-mlarge-dataโ when-mexplicit-relocsis in effect, static data is accessed via gp-relative relocations. When-msmall-datais used, objects 8 bytes long or smaller are placed in a small data area (the.sdataand.sbsssections) and are accessed via 16-bit relocations off of the$gpregister. This limits the size of the small data area to 64KB, but lets the variables be accessed directly via a single instruction. The default is-mlarge-data. With this option, the data area is limited to just below 2GB. Programs that need more than 2GB of data must usemallocormmapto allocate the data in the heap instead of in the program's data segment ๐ซฃ When generating code for shared libraries,-fpicimplies-msmall-dataand-fPICimplies-mlarge-data.-msmall-text,-mlarge-textโ when-msmall-textis used, the compiler assumes the code of the entire program (or shared library) fits in 4MB, so it's reachable with a branch instruction. When-msmall-datais used, the compiler can assume all local symbols share the same$gpvalue, which reduces the number of instructions required for a function call from 4 to 1 ๐ The default is-mlarge-text.-mcpu=cpu_typeโ sets the instruction set and instruction scheduling parameters for machine type cpu_type. You can specify either the EV style name or the corresponding chip number. GCC supports scheduling parameters for the EV4, EV5 and EV6 family of processors, and it picks the default instruction set values from the processor you specify. If you don't specify a processor type, GCC defaults to the processor the compiler was built on. Supported values for cpu_type are:ev4,ev45,21064โ schedules as an EV4 and has no instruction set extensions.
okay so the Alpha processor list is next, and bestie, these are the chip names you can hand to -mcpu= ๐
ev5or21164โ schedules as an EV5 and has no instruction set extensions ๐ธev56or21164aโ schedules as an EV5 and supports the BWX extension ๐ฆpca56,21164pc, or21164PCโ schedules as an EV5 and supports the BWX and MAX extensions ๐ev6or21264โ schedules as an EV6 and supports the BWX, FIX, and MAX extensions ๐ฅev67or21264aโ schedules as an EV6 and supports the BWX, CIX, FIX, and MAX extensions ๐
Native toolchains also get the value native, which picks the best architecture option for the host processor โจ -mcpu=native does absolutely nothing if GCC doesn't recognize the processor ๐
-mtune=cpu_typeโ sets only the instruction scheduling parameters for machine type cpu_type. The instruction set stays exactly the same ๐
Native toolchains also support native here, which selects the best architecture option for the host processor. -mtune=native has no effect if GCC doesn't recognize the processor ๐ง
-mmemory-latency=timeโ tells the scheduler what latency to assume for typical memory references the application makes. This number depends a lot on the app's memory access patterns and the size of the external cache on the machine ๐
Valid options for time are:
numberโ a decimal number of clock cycles ๐L1,L2,L3,mainโ the compiler has estimates of clock cycles for "typical" EV4 & EV5 hardware at the Level 1, 2 & 3 caches (also called Dcache, Scache, and Bcache), plus main memory. Heads up:L3is only valid for EV5 โ ๏ธ
๐ง eBPF Options ๐ง
-mframe-limit=bytesโ sets the hard limit for frame sizes, in bytes. Right now the value you give should be less than or equal to32767. By default it's whatever limit the targeted Linux kernel version imposes ๐-mkernel=versionโ the minimum kernel version that will run your compiled program. GCC uses it to decide which instructions to use, which kernel helpers to allow, and so on. Right now version can be one of4.0,4.1,4.2,4.3,4.4,4.5,4.6,4.7,4.8,4.9,4.10,4.11,4.12,4.13,4.14,4.15,4.16,4.17,4.18,4.19,4.20,5.0,5.1,5.2,latest, ornative๐-mbig-endianโ generates code for a big-endian target ๐ซถ-mlittle-endianโ generates code for a little-endian target. This is the default ๐-mxbpfโ generates code for an expanded version of BPF that relaxes some of the restrictions the BPF architecture puts on you ๐ฆ
-<Save and restore callee-saved registers at function entry and> exit, respectively.
๐ธ FR30 Options ๐ธ
These options are defined specifically for the FR30 port โจ
-msmall-modelโ uses the small address space model. This can produce smaller code, but it does assume that all symbolic values and addresses fit into a 20-bit range ๐-mno-lsimโ assumes runtime support has already been provided, so there's no need to include the simulator library (libsim.a) on the linker command line ๐
๐ฆ FT32 Options ๐ฆ
These options are defined specifically for the FT32 port ๐
-msimโ says the program will run on the simulator. This links in an alternate runtime startup and library.
๐จ Do NOT use this option when generating programs that will run on real hardware! You have to provide your own runtime library for whatever I/O functions you need.
-mlraโ enables Local Register Allocation. It's still experimental for FT32, so by default the compiler uses standard reload ๐ฅ-mnodivโ don't usedivandmodinstructions ๐-mft32bโ enables use of the extended instructions of the FT32B processor ๐-mcompressโ compresses all code using theFt32Bcode compression scheme ๐ง-mnopmโ don't generate code that reads program memory ๐
๐ FRV Options ๐
-mgpr-32โ only uses the first 32 general-purpose registers ๐-mgpr-64โ uses all 64 general-purpose registers ๐ฅ-mfpr-32โ uses only the first 32 floating-point registers ๐ธ-mfpr-64โ uses all 64 floating-point registers ๐-mhard-floatโ uses hardware instructions for floating-point operations โจ-msoft-floatโ uses library routines for floating-point operations instead ๐ซถ-malloc-ccโ dynamically allocates condition code registers ๐ฆ-mfixed-ccโ doesn't try to dynamically allocate condition code registers. It only usesicc0andfcc0๐-mdwordโ changes the ABI to use double word insns ๐-mno-dwordโ doesn't use double word instructions ๐-mdoubleโ uses floating-point double instructions ๐ฅ-mno-doubleโ doesn't use floating-point double instructions ๐-mmediaโ uses media instructions ๐-mno-mediaโ doesn't use media instructions ๐ฅ-mmuladdโ uses multiply and add/subtract instructions ๐-mno-muladdโ doesn't use multiply and add/subtract instructions ๐-mfdpicโ selects the FDPIC ABI, which uses function descriptors to represent pointers to functions. Without any PIC/PIE-related options, it implies-fPIE. With-fpicor-fpie, it assumes GOT entries and small data are within a 12-bit range from the GOT base address. With-fPICor-fPIE, GOT offsets are computed with 32 bits. With abfin-elftarget, this option implies-msim๐ง-minline-pltโ enables inlining of PLT entries in function calls to functions that aren't known to bind locally. It has no effect without-mfdpic. It's enabled by default if you're optimizing for speed and compiling for shared libraries (that's-fPICor-fpic), or when an optimization option like-O3or above is on the command line ๐-mTLSโ assumes a large TLS segment when generating thread-local code ๐ฆ-mtlsโ doesn't assume a large TLS segment when generating thread-local code ๐ธ-mgprel-roโ enables the use of "GPREL" relocations in the FDPIC ABI for data known to be in read-only sections. It's enabled by default, except for-fpicor-fpie. Even though it may help make the global offset table smaller, it trades 1 instruction for 4. With-fPICor-fPIE, it trades 3 instructions for 4, one of which may be shared by multiple symbols, and it avoids the need for a GOT entry for the referenced symbol, so it's more likely to be a win. If it isn't, you can use-mno-gprel-roto disable it ๐ซถ-multilib-library-picโ links with the (library, not FD) pic libraries. It's implied by-mlibrary-pic, and by-fPICand-fpicwithout-mfdpic. You should basically never have to use it explicitly ๐-mlinked-fpโ follows the EABI requirement of always creating a frame pointer whenever a stack frame is allocated. It's enabled by default and can be turned off with-mno-linked-fp๐-mlong-callsโ uses indirect addressing to call functions outside the current compilation unit. This lets the functions be placed anywhere within the 32-bit address space ๐-malign-labelsโ tries to align labels to an 8-byte boundary by inserting NOPs into the previous packet. This option only has an effect when VLIW packing is enabled. It doesn't create new packets; it just adds NOPs to existing ones ๐-mlibrary-picโ generates position-independent EABI code ๐-macc-4โ uses only the first four media accumulator registers ๐-macc-8โ uses all eight media accumulator registers ๐ฅ-mpackโ packs VLIW instructions โจ-mno-packโ doesn't pack VLIW instructions ๐ฅ-mno-eflagsโ doesn't mark ABI switches ine_flags๐ง-mcond-moveโ enables the use of conditional-move instructions (the default) ๐ฆ
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mno-cond-moveโ disables the use of conditional-move instructions ๐
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-msccโ enables the use of conditional set instructions (the default) ๐
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mno-sccโ disables the use of conditional set instructions ๐
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mcond-execโ enables the use of conditional execution (the default) ๐ธ
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mno-cond-execโ disables the use of conditional execution ๐ฅ
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mvliw-branchโ runs a pass to pack branches into VLIW instructions (the default) ๐
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mno-vliw-branchโ doesn't run a pass to pack branches into VLIW instructions ๐
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mmulti-cond-execโ enables optimization of&&and||in conditional execution (the default) ๐ซถ
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mno-multi-cond-execโ disables optimization of&&and||in conditional execution ๐
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mnested-cond-execโ enables nested conditional execution optimizations (the default) โจ
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-mno-nested-cond-execโ disables nested conditional execution optimizations ๐
๐ This switch is mainly for debugging the compiler and will likely be removed in a future version.
-moptimize-membarโ removes redundantmembarinstructions from the compiler-generated code. It's enabled by default ๐ง-mno-optimize-membarโ disables the automatic removal of redundantmembarinstructions from the generated code ๐-mtomcat-statsโ makesgasprint out tomcat statistics ๐-mcpu=cpuโ selects the processor type to generate code for. Possible values arefrv,fr550,tomcat,fr500,fr450,fr405,fr400,fr300, andsimple๐
๐ GNU/Linux Options ๐
Okay bestie, these -m options are defined for GNU/Linux targets ๐งโจ
-mglibcโ Uses the GNU C library ๐. It's the default, except on*-*-linux-*uclibc*,*-*-linux-*musl*and*-*-linux-*android*targets, so don't get it twisted ๐-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 turns on
-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default. When linking, it makes the GCC driver pass Android-specific options to the linker. Finally, it makes the preprocessor macro"__ANDROID__"get defined โจ
- When compiling, this option turns on
-tno-android-ccโ Turns off the compilation effects of-mandroid, so-mbionic,-fPIC,-fno-exceptionsand-fno-rttiare NOT enabled by default ๐ โโ๏ธ-tno-android-ldโ Turns off the linking effects of-mandroid, so the linker gets standard Linux linking options instead ๐
๐ฆ H8/300 Options ๐ฆ
Okay, these -m options are defined for the H8/300 implementations ๐ฆ:
-mrelaxโ Shortens some address references at link time, when it's possible. It does this by using 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 normal mode. This switch has to be used with either-mhor-ms, no cap ๐ง-ms2600โ Generates code for the H8S/2600. This switch has to be used with-ms๐ฅ-mexrโ Extended registers get stored on the stack before a function with the monitor attribute runs. The default is-mexr. This only works for H8S targets ๐-mno-exrโ Extended registers do NOT get stored on the stack before a function with the monitor attribute runs. The default is-mno-exr. This only works for H8S targets too ๐-mint32โ Makes"int"data 32 bits by default ๐-malign-300โ On the H8/300H and H8S, this uses the same alignment rules as the H8/300. The H8/300H and H8S normally align longs and floats on 4-byte boundaries, but-malign-300bumps them down to 2-byte boundaries. It has no effect on the H8/300 at all ๐ฆ
โก HPPA Options โก
Okay, these -m options are defined for the HPPA family of computers ๐ฅ๏ธ:
-march=architecture-typeโ Generates code for the architecture you pick. The choices for architecture-type are1.0for PA 1.0,1.1for PA 1.1, and2.0for PA 2.0 processors. Peek at/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 ones, but not the other way around, so keep that in mind ๐-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, because it isn't compatible with the default 32-bit runtime ๐ฌ. Only aggregates larger than eight bytes get passed by hidden reference though, and this option gives you better compatibility with OpenMP ๐ซถ-mjump-in-delayโ This one gets ignored. It's only here for compatibility purposes ๐-mdisable-fpregsโ Stops floating-point registers from being used in any way. This is necessary when compiling kernels that do lazy context switching of floating-point registers ๐ง. If you use this option and then try floating-point operations, the compiler aborts ๐-mdisable-indexingโ Stops the compiler from using indexing address modes. This dodges some rather obscure problems when compiling MIG generated code under MACH ๐ต๏ธโโ๏ธ-mno-space-regsโ Generates code that assumes the target has no space registers. This lets GCC make faster indirect calls and use unscaled index address modes โก- This kind of code is suitable for level 0 PA systems and kernels ๐ง
-mfast-indirect-callsโ Generates code that assumes calls never cross space boundaries. This lets GCC emit code with faster indirect calls ๐โโ๏ธ- ๐ This option does not work in the presence of shared libraries or nested functions, so watch out!
-mfixed-range=register-rangeโ Generates code that treats the given register range as fixed registers. A fixed register is one the register allocator isn't allowed to use. This is super useful when compiling kernel code ๐ ๏ธ. A register range is written as two registers separated by a dash, and you can list multiple ranges separated by a comma ๐-mlong-load-storeโ Generates 3-instruction load and store sequences, which the HP-UX 10 linker sometimes needs. This is the same as the+koption on the HP compilers ๐ฐ-mportable-runtimeโ Uses the portable calling conventions HP proposed for ELF systems ๐-mgasโ Lets you use assembler directives that only GAS understands โจ-mschedule=cpu-typeโ Schedules code based on the constraints for the machine type cpu-type. The choices are700 7100, 7100LC, 7200, 7300 and 8000. Check/usr/lib/sched.modelson an HP-UX system to find the right scheduling option for your machine ๐๏ธ. The default scheduling is8000๐-mlinker-optโ Turns on 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 throw bogus error messages when linking some programs ๐-msoft-floatโ Generates output that contains library calls for floating point ๐งฎ
โ ๏ธ Warning: the requisite libraries are not available for all HPPA targets. Normally the facilities of the machine's usual C compiler get used, but this can't be done directly in cross-compilation. You have to make your own arrangements to provide suitable library functions for cross-compilation, bestie ๐ค
-msoft-floatchanges the calling convention in the output file, so it's only useful if you compile all of a program with this option ๐ซ . In particular, you need to compilelibgcc.a, the library that comes with GCC, with-msoft-floatfor this to work ๐-msioโ Generates the predefine_SIOfor 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โ Uses options specific to GNU ld. This passes-sharedto ld when building a shared library. It's the default when GCC is configured (explicitly or implicitly) with the GNU linker ๐ฆ. This option doesn't change which ld gets called, it only changes what parameters get passed to that ld. The ld that gets called is decided by the--with-ldconfigure option, GCC's program search path, and finally the user'sPATH๐บ๏ธ. You can print the linker GCC uses with whichgcc -print-prog-name=ld. This option is only available on the 64-bit HP-UX GCC, i.e. configured withhppa*64*-*-hpux*๐-mhp-ldโ Uses options specific to HP ld. This passes-bto ld when building a shared library, and passes+Accept TypeMismatchto ld on all links ๐งฉ. It's the default when GCC is configured (explicitly or implicitly) with the HP linker. Same deal as before: this option doesn't change which ld gets called, only the parameters passed to it. The ld that gets called is decided by the--with-ldconfigure option, GCC's program search path, and finally the user'sPATH๐ค๏ธ. You can print the linker GCC uses with whichgcc -print-prog-name=ld. This option is only available on the 64-bit HP-UX GCC, i.e. configured withhppa*64*-*-hpux*๐-mlong-callsโ Generates code that uses long call sequences. This makes sure a call can always reach linker generated stubs ๐. By default, long calls only get generated when the distance from the call site to the beginning of the function or translation unit (whichever applies) goes past a limit set by the branch type being used. The limits for normal calls are 7,600,000 and 240,000 bytes, respectively for the PA 2.0 and PA 1.X architectures. Sibcalls are always limited at 240,000 bytes ๐- Distances are measured from the beginning of functions when you use the
-ffunction-sectionsoption, or when you use the-mgasand-mno-portable-runtimeoptions together under HP-UX with the SOM linker ๐ญ - You usually don't want this option, since 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, and the type of code being generated. The impact on systems that support long absolute calls, and long pic symbol-difference or pc-relative calls, should be pretty small. However, an indirect call is used on 32-bit ELF systems in pic code, and it's quite long ๐ข
- Distances are measured from the beginning of functions when you use the
-munix=unix-stdโ Generates compiler predefines and picks a startfile for the UNIX standard you specify. The choices for unix-std are93,95and98.93is supported 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=93gives you the same predefines as GCC 3.3 and 3.4.-munix=95adds predefines for"XOPEN_UNIX"and"_XOPEN_SOURCE_EXTENDED", plus the startfileunix95.o.-munix=98adds predefines for"_XOPEN_UNIX","_XOPEN_SOURCE_EXTENDED","_INCLUDE__STDC_A1_SOURCE"and"_INCLUDE_XOPEN_SOURCE_500", plus the startfileunix98.o๐ง- > ๐จ This option changes the interfaces for various library routines, and it also affects the operational behavior of the C library. So extreme care is needed when you use it, no cap.
- Library code that's meant to work with more than one UNIX standard has to test, set and restore the variable
__xpg4_extended_maskas appropriate. Most GNU software doesn't offer this capability ๐ซฅ
-nolibdldโ Suppresses the generation of link options that searchlibdld.slwhen the-staticoption is specified on HP-UX 10 and later ๐ซ-staticโ ๐ okay so the HP-UXsetlocalein libc depends onlibdld.sl, and there is no archive version of it, so-staticneeds some special link options to untangle that mess. On HP-UX 10 and later, the GCC driver adds the necessary options to link withlibdld.slwhenever you use-static, which means the binary ends up dynamic anyway ๐ซ . On the 64-bit port, the linkers make dynamic binaries by default regardless, so it's giving consistency. If you don't want the driver adding those link options, use-nolibdld๐ โโ๏ธ.-threadsโ ๐งต adds multithreading support with the dce thread library under HP-UX. It sets flags for both the preprocessor and the linker, so you get both at once. Main character energy โจ.
๐ฆ 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.-mgnu-asis the default โจ.-mgnu-ld,-mno-gnu-ldโ generates (or doesn't) code for the GNU linker.-mgnu-ldis the default ๐ .-mno-picโ generates code that does not use a global pointer register. The result is not position independent code, and it violates the IA-64 ABI ๐.
Heads up, bestie: -mno-pic gives you non-position-independent code and breaks the IA-64 ABI. Only reach for it if you know exactly why you need it ๐.
-mvolatile-asm-stop,-mno-volatile-asm-stopโ generates (or doesn't) a stop bit immediately before and after volatile asm statements ๐ฅ.-mregister-names,-mno-register-namesโ generates (or doesn't)in,loc, andoutregister names for the stacked registers. This can make the assembler output way more readable ๐.-mno-sdata,-msdataโ disables (or enables) optimizations that use the small data section. This can be handy for working around optimizer bugs ๐.-mconstant-gpโ generates code that uses a single constant global pointer value. Super useful when you're compiling kernel code ๐ง .-mauto-picโ generates code that is self-relocatable. This implies-mconstant-gp, and it's useful when compiling firmware code ๐ง.-minline-float-divide-min-latencyโ generates code for inline divides of floating-point values using the minimum latency algorithm โก.-minline-float-divide-max-throughputโ generates code for inline divides of floating-point values using the maximum throughput algorithm ๐.-mno-inline-float-divideโ no inline code for divides of floating-point values, period ๐ โโ๏ธ.-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โ no 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โ no inline code forsqrt๐ซ .-mfused-madd,-mno-fused-maddโ does (or doesn't) generate code that uses the fused multiply/add or multiply/subtract instructions. The default is to use these instructions ๐ฅ.-mno-dwarf2-asm,-mdwarf2-asmโ doesn't (or does) generate assembler code for the DWARF line number debugging info. This may be useful when you're not using the GNU assembler ๐ฆ.-mearly-stop-bits,-mno-early-stop-bitsโ allows stop bits to be placed earlier than immediately 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 can't use, which is 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 โจ.-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,long, and pointer to 32 bits. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits. These are HP-UX specific flags ๐.-mno-sched-br-data-spec,-msched-br-data-specโ (dis/en)ables data speculative scheduling before reload. This results 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โ (en/dis)ables 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โ (dis/en)ables control speculative scheduling. This feature is only available during region scheduling (i.e., before reload). It 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โ (en/dis)ables speculative scheduling of the instructions that depend on the data speculative loads before reload. This only works if-msched-br-data-specis enabled. The default setting is enabled ๐.-msched-ar-in-data-spec,-mno-sched-ar-in-data-specโ (en/dis)ables speculative scheduling of the instructions that depend on the data speculative loads after reload. This only works if-msched-ar-data-specis enabled. The default setting is enabled ๐.-msched-in-control-spec,-mno-sched-in-control-specโ (en/dis)ables speculative scheduling of the instructions that depend on the control speculative loads. This only works if-msched-control-specis enabled. The default setting is enabled ๐ธ.-mno-sched-prefer-non-data-spec-insns,-msched-prefer-non-data-spec-insnsโ if enabled, data-speculative instructions get scheduled only when there are no other choices at the moment. This makes data speculation much more conservative. The default setting is disabled ๐ข.-mno-sched-prefer-non-control-spec-insns,-msched-prefer-non-control-spec-insnsโ if enabled, control-speculative instructions get scheduled only when there are no other choices at the moment. This makes control speculation much more conservative. The default setting is disabled ๐ข.-mno-sched-count-spec-in-critical-path,-msched-count-spec-in-critical-pathโ if enabled, speculative dependencies are considered when computing instruction priorities. This makes speculation a bit more conservative. The default setting is disabled ๐ง.-msched-spec-ldcโ uses a simple data speculation check. This option is on by default โ .-msched-control-spec-ldcโ uses a simple check for control speculation. This option is on by default โ .-msched-stop-bits-after-every-cycleโ places a stop bit after every cycle when scheduling. This option is on by default โ .-msched-fp-mem-deps-zero-costโ assumes floating-point stores and loads are not likely to conflict when placed into the same instruction group. This option is disabled by default ๐ โโ๏ธ.-msel-sched-dont-check-control-specโ generates checks for control speculation in selective scheduling. This flag is disabled by default ๐ โโ๏ธ.-msched-max-memory-insns=max-insnsโ sets a limit on the number of memory insns per instruction group, giving lower priority to subsequent memory insns trying to schedule in the same group. This is often useful for preventing cache bank conflicts. The default value is1๐งฑ.-msched-max-memory-insns-hard-limitโ makes the limit set bymsched-max-memory-insnsa hard limit, so no more than that many get placed in an instruction group. Otherwise the limit is "soft", meaning non-memory operations are preferred once the limit is reached, but memory operations may still be scheduled ๐ซ .
๐ธ LM32 Options ๐ธ
These -m options are defined for the LatticeMico32 architecture ๐ท:
-mbarrel-shift-enabledโ enables barrel-shift instructions ๐.-mdivide-enabledโ enables divide and modulus instructions โ.-mmultiply-enabledโ enables multiply instructions โ๏ธ.-msign-extend-enabledโ enables sign extend instructions ๐งฉ.-muser-enabledโ enables user-defined instructions ๐.
๐ M32C Options ๐
-mcpu=nameโ selects the CPU that code is generated for.namecan ber8cfor the R8C/Tiny series,m16cfor the M16C (up to /60) series,m32cmfor the M16C/80 series, orm32cfor the M32C/80 series ๐.-msimโ tells GCC the program will run on the simulator. This links in an alternate runtime library that supports things like file I/O ๐ฅ๏ธ.
Bestie, never use -msim for programs that will run on real hardware. For that you have to provide your own runtime library for whatever I/O functions you need ๐.
-memregs=numberโ specifies the number of memory-based pseudo-registers GCC uses during code generation. These pseudo-registers get used like real registers, so there's a tradeoff between GCC's ability to fit code into the available registers and the performance penalty of using memory instead of registers โ๏ธ. All modules in a program must be compiled with the same value for this option ๐ซถ.
Also, you must not use -memregs with GCC's default runtime libraries. Super important, no cap ๐ญ.
๐ง 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โ ๐ This is the default and the cosy one! Every object is assumed to live in the lower 16MB of memory, so its address can be loaded with theld24instruction, and every subroutine is assumed reachable with theblinstruction. The addressability of a particular object can be set with themodelattribute. ๐-mmodel=mediumโ ๐ฆ Objects can be anywhere in the 32-bit address space, and the compiler generatesseth/add3instructions to load their addresses. Subroutines are still assumed reachable with theblinstruction.-mmodel=largeโ ๐ Objects can be anywhere in the 32-bit address space (the compiler generatesseth/add3instructions to load their addresses). Subroutines may not be reachable with theblinstruction, so the compiler generates the much slowerseth/add3/jlinstruction sequence. ๐ญ-msdata=noneโ ๐ Disables the small data area. Variables go into one of.data,.bss, or.rodata(unless thesectionattribute has been specified). This is the default. The small data area is made up of the.sdataand.sbsssections, and objects can be explicitly put in it with thesectionattribute using one of these sections. โจ-msdata=sdataโ ๐ง Puts small global and static data in the small data area, but doesn't generate any special code to reference them.-msdata=useโ ๐ฅ Puts small global and static data in the small data area and generates special instructions to reference them.-G numโ ๐ Puts global and static objects less than or equal tonumbytes into the small data or BSS sections instead of the normal data or BSS sections. The default value ofnumis8. The-msdataoption must be set to one ofsdataorusefor this option to have any effect.
All modules should be compiled with the same -G num value. Compiling with different values of num may or may not work. If it doesn't, the linker gives an error message---incorrect code is not generated. ๐ซถ
-mdebugโ ๐ Makes the M32R-specific code in the compiler display some statistics that might help in debugging programs.-malign-loopsโ ๐ธ Aligns all loops to a 32-byte boundary.-mno-align-loopsโ ๐ Doesn't enforce a 32-byte alignment for loops. This is the default.-missue-rate=numberโ โก Issuesnumberinstructions per cycle.numbercan only be1or2.-mbranch-cost=numberโ ๐numbercan only be1or2. If it's1, branches are preferred over conditional code. If it's2, the opposite applies.-mflush-trap=numberโ ๐ชค Specifies the trap number to use to flush the cache. The default is12. Valid numbers are between0and15inclusive.-mno-flush-trapโ ๐ซ Specifies that the cache cannot be flushed by using a trap.-mflush-func=nameโ ๐งน Specifies the name of the operating system function to call to flush the cache. The default is_flush_cache, but a function call is only used if a trap is not available.-mno-flush-funcโ ๐ Indicates that there is no OS function for flushing the cache.
โจ M680x0 Options โจ
These are the -m options defined for M680x0 and ColdFire processors. The default settings depend on which architecture was selected when the compiler was configured, so the defaults for the most common choices are given below. ๐ง
-march=archโ ๐๏ธ Generates code for a specific M680x0 or ColdFire instruction set architecture. Permissible values ofarchfor M680x0 architectures are:68000,68010,68020,68030,68040,68060andcpu32. ColdFire architectures are selected according to Freescale's ISA classification, and the permissible values are:isaa,isaaplus,isabandisac.- ๐ GCC defines a macro
__mcfarch__whenever it's generating code for a ColdFire target. Thearchin this macro is one of the-marcharguments given above. - ๐ค When used together,
-marchand-mtuneselect code that runs on a family of similar processors but that is optimized for a particular microarchitecture.
- ๐ GCC defines a macro
-mcpu=cpuโ ๐ฏ Generates code for a specific M680x0 or ColdFire processor. The M680x0 CPUs are:68000,68010,68020,68030,68040,68060,68302,68332andcpu32. The ColdFire CPUs are given by the table below, which also sorts them into families:
Family : -mcpu arguments
51 : 51 51ac 51ag 51cn 51em 51je 51jf 51jg 51jm 51mm 51qe 51qm
5206 : 5202 5204 5206
5206e : 5206e
5208 : 5207 5208
5211a : 5210a 5211a
5213 : 5211 5212 5213
5216 : 5214 5216
52235 : 52230 52231 52232 52233 52234 52235
5225 : 5224 5225
52259 : 52252 52254 52255 52256 52258 52259
5235 : 5232 5233 5234 5235 523x
5249 : 5249
5250 : 5250
5271 : 5270 5271
5272 : 5272
5275 : 5274 5275
5282 : 5280 5281 5282 528x
53017 : 53011 53012 53013 53014 53015 53016 53017
5307 : 5307
5329 : 5327 5328 5329 532x
5373 : 5372 5373 537x
5407 : 5407
5475 : 5470 5471 5472 5473 5474 5475 547x 5480 5481 5482 5483 5484
5485
-mcpu=cpu overrides -march=arch if arch is compatible with cpu. Other combinations of -mcpu and -march are rejected. ๐ซ
GCC defines the macro __mcf_cpu_cpu when a ColdFire target CPU is selected. It also defines __mcf_family_family, where the value of family is given by the table above. ๐
-mtune=tuneโ ๐ถ Tunes the code for a particular microarchitecture within the constraints set by-marchand-mcpu. The M680x0 microarchitectures are:68000,68010,68020,68030,68040,68060andcpu32. The ColdFire microarchitectures are:cfv1,cfv2,cfv3,cfv4andcfv4e.- ๐ช You can also use
-mtune=68020-40for code that needs to run relatively well on68020,68030and68040targets.-mtune=68020-60is similar but includes68060targets as well. These two options select the same tuning decisions as-m68020-40and-m68020-60respectively. - ๐ท๏ธ GCC defines the macros
__mcarchand__mcarch__when tuning for 680x0 architecturearch. It also definesmcarchunless either-ansior a non-GNU-stdoption is used. If GCC is tuning for a range of architectures, as selected by-mtune=68020-40or-mtune=68020-60, it defines the macros for every architecture in the range. - ๐ท๏ธ GCC also defines the macro
__muarch__when tuning for ColdFire microarchitectureuarch, whereuarchis one of the arguments given above.
- ๐ช You can also use
-m68000,-mc68000โ ๐ฃ Generates output for a 68000. This is the default when the compiler is configured for 68000-based systems. It's equivalent to-march=68000. Use this option for microcontrollers with a 68000 or EC000 core, including the 68008, 68302, 68306, 68307, 68322, 68328 and 68356.-m68010โ ๐ฑ Generates output for a 68010. This is the default when the compiler is configured for 68010-based systems. It's equivalent to-march=68010.-m68020,-mc68020โ ๐ฟ Generates output for a 68020. This is the default when the compiler is configured for 68020-based systems. It's equivalent to-march=68020.-m68030โ ๐ณ Generates output for a 68030. This is the default when the compiler is configured for 68030-based systems. It's equivalent to-march=68030.-m68040โ ๐ ๏ธ Generates output for a 68040. This is the default when the compiler is configured for 68040-based systems. It's equivalent to-march=68040. This option inhibits the use of 68881/68882 instructions that have to be emulated by software on the 68040. Use this option if your 68040 doesn't have code to emulate those instructions. ๐-m68060โ ๐ Generates output for a 68060. This is the default when the compiler is configured for 68060-based systems. It's equivalent to-march=68060. This option inhibits the use of 68020 and 68881/68882 instructions that have to be emulated by software on the 68060. Use this option if your 68060 doesn't have code to emulate those instructions. ๐-mcpu32โ ๐๏ธ Generates output for a CPU32. This is the default when the compiler is configured for CPU32-based systems. It's equivalent to-march=cpu32. Use this option for microcontrollers with a CPU32 or CPU32+ core, including the 68330, 68331, 68332, 68333, 68334, 68336, 68340, 68341, 68349 and 68360.-m5200โ ๐ Generates output for a 520X ColdFire CPU. This is the default when the compiler is configured for 520X-based systems. It's equivalent to-mcpu=5206, and is now deprecated in favor of that option. Use this option for microcontrollers with a 5200 core, including the MCF5202, MCF5203, MCF5204 and MCF5206. โ ๏ธ-m5206eโ ๐ฅ Generates output for a 5206e ColdFire CPU. This option is now deprecated in favor of the equivalent-mcpu=5206e.-m528xโ ๐ฅ Generates output for a member of the ColdFire 528X family. This option is now deprecated in favor of the equivalent-mcpu=528x.-m5307โ ๐ฅ Generates output for a ColdFire 5307 CPU. This option is now deprecated in favor of the equivalent-mcpu=5307.-m5407โ ๐ฅ Generates output for a ColdFire 5407 CPU. This option is now deprecated in favor of the equivalent-mcpu=5407.-mcfv4eโ ๐ Generates output for a ColdFire V4e family CPU (e.g. 547x/548x). This includes use of hardware floating-point instructions. The option is equivalent to-mcpu=547x, and is now deprecated in favor of that option.-m68020-40โ ๐งฉ Generates output for a 68040, without using any of the new instructions. This results in code that can run relatively efficiently on either a 68020/68881 or a 68030 or a 68040. The generated code does use the 68881 instructions that are emulated on the 68040. The option is equivalent to-march=68020 -mtune=68020-40.-m68020-60โ ๐งฉ Generates output for a 68060, without using any of the new instructions. This results in code that can run relatively efficiently on either a 68020/68881 or a 68030 or a 68040. The generated code does use the 68881 instructions that are emulated on the 68060. The option is equivalent to-march=68020 -mtune=68020-60.-mhard-float,-m68881โ โก Generates floating-point instructions. This is the default for 68020 and above, and for ColdFire devices that have an FPU. It defines the macro__HAVE_68881__on M680x0 targets and__mcffpu__on ColdFire targets.-msoft-floatโ okay so this one tells GCC to skip floating-point instructions entirely ๐ซถ and call library routines instead. It's the default for68000,68010, and68832targets, and also for ColdFire devices that have no FPU.-mdiv,-mno-divโ these let you turn ColdFire hardware divide and remainder instructions on (-mdiv) or off (-mno-div) ๐งฎ. 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, which is either the default CPU or whichever one you picked with-mcpu. For example, the default is "off" for-mcpu=5206and "on" for-mcpu=5206e.
GCC defines the macro __mcfhwdiv__ when this option is enabled โจ.
-mshortโ makes typeint16 bits wide, just likeshort int๐ . Parameters passed on the stack also get aligned to a 16-bit boundary, even on targets whose API mandates promotion to 32-bit.-mno-shortโ doesn't treatintas 16 bits wide. This is the default ๐ธ.-mnobitfield,-mno-bitfieldโ no bit-field instructions for you ๐ โโ๏ธ. The-m68000,-mcpu32and-m5200options imply-mnobitfield.-mbitfieldโ yes to bit-field instructions ๐ฆ. The-m68020option implies-mbitfield, and this is the default if you're using a configuration designed for a 68020.-mrtdโ this one switches to a different function-calling convention, where functions that take a fixed number of arguments return using thertdinstruction. That instruction pops their arguments on the way out, which saves one instruction in the caller since the caller doesn't have to pop them ๐ง .
๐จ This calling convention is incompatible with the one normally used on Unix, so you can't use it if you need to call libraries compiled with the Unix compiler.
You also have to provide function prototypes for all functions that take variable numbers of arguments (including printf). If you don't, GCC generates incorrect code for calls to those functions ๐ญ.
And seriously, seriously incorrect code results if you call a function with too many arguments. Normally extra arguments are harmlessly ignored, but not here ๐.
The rtd instruction is supported by the 68010, 68020, 68030, 68040, 68060 and CPU32 processors, but not by the 68000 or 5200.
The default is -mno-rtd.
-malign-int,-mno-align-intโ these control whether GCC alignsint,long,long long,float,double, andlong doublevariables on a 32-bit boundary (-malign-int) or a 16-bit boundary (-mno-align-int) ๐. Aligning on 32-bit boundaries gives you code that runs somewhat faster on processors with 32-bit busses, but you pay for it with more memory.
โ ๏ธ Warning: if you use the -malign-int switch, GCC aligns structures containing the above types differently than most published application binary interface specifications for the m68k.
-mno-strict-align,-mstrict-alignโ-mno-strict-alignmeans GCC does not assume that unaligned memory references are handled by the system, while-mstrict-alignmeans it does assume that ๐คทโโ๏ธ.-mpcrelโ uses the pc-relative addressing mode of the 68000 directly, instead of a global offset table ๐งญ. At the moment this option implies-fpic, which allows at most a 16-bit offset for pc-relative addressing.-fPICisn't supported with-mpcrelright now, though it could be supported for 68020 and higher processors.-msep-dataโ generates code that lets the data segment live in a different area of memory from the text segment ๐บ๏ธ. This allows execute-in-place in an environment without virtual memory management. This option implies-fPIC.-mno-sep-dataโ generates code that assumes the data segment follows the text segment. This is the default.-mid-shared-libraryโ generates code that supports shared libraries through the library ID method ๐. This allows execute-in-place and shared libraries in an environment without virtual memory management. This option implies-fPIC.-mno-id-shared-libraryโ generates code that doesn't assume ID-based shared libraries are being used. This is the default.-mshared-library-id=nโ specifies the identification number of the ID-based shared library being compiled ๐ข. A value of0generates more compact code. Other values force the allocation of that number to the current library, but that's no more space- or time-efficient than leaving this option out.-mxgot,-mno-xgotโ when you're generating position-independent code for ColdFire,-mxgotgenerates code that works even if the GOT has more than 8192 entries ๐ข. This code is larger and slower than code generated without this option. On M680x0 processors you don't need this option, since-fPICis enough.
GCC normally uses a single instruction to load values from the GOT. That's pretty efficient, but it only works if the GOT is smaller than about 64k. Anything bigger makes the linker report an error like this:
relocation truncated to fit: R_68K_GOT16O foobar
If you see that, recompile your code with -mxgot and it should work with very large GOTs. Just know that code generated with -mxgot is less efficient, since it takes 4 instructions to fetch the value of a global symbol ๐ฉ.
Some linkers, including newer versions of the GNU linker, can create multiple GOTs and sort GOT entries. If you have one of those, you should only need -mxgot when compiling a single object file that accesses more than 8192 GOT entries. Very few do.
These options have no effect unless GCC is generating position-independent code.
-mlong-jump-table-offsetsโ uses 32-bit offsets inswitchtables ๐. The default is 16-bit offsets.
๐ MCore Options
These are the -m options defined for the Motorola M*Core processors ๐ง.
-mhardlit,-mno-hardlitโ inlines constants into the code stream if it can be done in two instructions or less ๐งฉ.-mdiv,-mno-divโ uses the divide instruction. This is enabled by default โ.-mrelax-immediate,-mno-relax-immediateโ allows arbitrary-sized immediates in bit operations ๐.-mwide-bitfields,-mno-wide-bitfieldsโ always treats bit-fields asint-sized ๐ฆ.-m4byte-functions,-mno-4byte-functionsโ forces all functions to be aligned to a 4-byte boundary ๐งฑ.-mcallgraph-data,-mno-callgraph-dataโ emits callgraph information ๐ธ๏ธ.-mslow-bytes,-mno-slow-bytesโ prefers word access when reading byte quantities ๐พ.-mlittle-endian,-mbig-endianโ generates code for a little-endian target ๐.-m210,-m340โ generates code for the 210 processor ๐ฅ๏ธ.-mno-lsimโ assumes runtime support has already been provided, so the simulator library (libsim.a) gets left off the linker command line ๐ โโ๏ธ.-mstack-increment=sizeโ sets the maximum amount for a single stack increment operation ๐. Large values can speed up programs with functions that need a lot of stack space, but they can also trigger a segmentation fault if the stack gets extended too much ๐ฅ. The default value is0x1000.
๐ MeP Options
-mabsdiffโ enables theabsinstruction, which gives the absolute difference between two registers ๐งฎ.-mall-optsโ enables all the optional instructions: average, multiply, divide, bit operations, leading zero, absolute difference, min/max, clip, and saturation ๐.-maverageโ enables theaveinstruction, which computes the average of two registers ๐ธ.-mbased=nโ variables of sizenbytes or smaller get placed in the.basedsection by default ๐ฎ. Based variables use the$tpregister as a base register, and there's a 128-byte limit to the.basedsection.-mbitopsโ enables the bit operation instructions: bit test (btstm), set (bsetm), clear (bclrm), invert (bnotm), and test-and-set (tas) ๐.-mc=nameโ selects which section constant data gets placed in ๐๏ธ.namemay betiny,near, orfar.-mclipโ enables theclipinstruction โ๏ธ. Heads up,-mclipisn't useful unless you also provide-mminmax.-mconfig=nameโ selects one of the built-in core configurations ๐งฉ. Each MeP chip has one or more modules, and each module has a core CPU plus a variety of coprocessors, optional instructions, and peripherals. The "MeP-Integrator" tool, which isn't part of GCC, provides these configurations through this option. Using this option is the same as using all the corresponding command-line options. The default configuration isdefault.-mcopโ enables the coprocessor instructions ๐ค. By default this is a 32-bit coprocessor. The coprocessor is normally enabled through the-mconfig=option.-mcop32โ enables the 32-bit coprocessor's instructions ๐ฉ.-mcop64โ enables the 64-bit coprocessor's instructions ๐.-mivc2โ enables IVC2 scheduling ๐ง . IVC2 is a 64-bit VLIW coprocessor.-mdcโ causes constant variables to be placed in the.nearsection ๐.-mdivโ enables thedivanddivuinstructions โ.-mebโ generates big-endian code ๐ .-melโ generates little-endian code ๐.-mio-volatileโ tells the compiler that any variable marked with theioattribute should be considered volatile ๐.-mlโ causes variables to be assigned to the.farsection by default ๐๏ธ.-mleadzโ enables theleadz(leading zero) instruction 0๏ธโฃ.-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 that-mall-optsenabled ๐ โโ๏ธ.-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 currently generate these itself, 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 the built-in support for reset and exception vectors and tables ๐งน.-mtfโ okay so this one makes every function default to the.farsection ๐ฆ Without it, functions chill in the.nearsection instead โจ-mtiny=nโ variables that arenbytes or smaller get tucked into the.tinysection ๐ They lean on the$gpbase register ๐ The default is4.
Heads up, bestie: the .tiny section has a 65536-byte limit ๐
๐ธ MicroBlaze Options ๐ธ
-msoft-floatโ software emulation for floating point ๐ซถ This is the default.-mhard-floatโ use hardware floating-point instructions ๐ฅ-mmemcpyโ don't optimize block moves, just usememcpy๐-mno-clearbssโ deprecated, so please switch to-fno-zero-initialized-in-bssinstead ๐-mcpu=cpu-typeโ use the features of, and schedule code for, the CPU you pick ๐ Values follow the formatvX.YY.Z, whereXis a major version,YYis the minor version, andZis compatibility code. Example values arev3.00.a,v4.00.b,v5.00.a,v5.00.b, andv6.00.a๐-mxl-soft-mulโ software multiply emulation (default) ๐ง-mxl-soft-divโ software emulation for divides (default) ๐ง-mxl-barrel-shiftโ use the hardware barrel shifter โญ-mxl-pattern-compareโ use pattern compare instructions ๐-msmall-dividesโ table lookup optimization for small signed integer divisions ๐งฎ-mxl-stack-checkโ deprecated, so use-fstack-checkinstead ๐-mxl-gp-optโ use GP-relative.sdataand.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. The valid models are:executableโ normal executable, and the default ๐ It uses the 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๐ It uses the startup filecrt1.oand sets the program's start address to0x800.bootstrapโ for applications loaded by a bootloader ๐ฅพ This model uses the startup filecrt2.o, which does not contain a processor reset vector handler. It's suitable for handing control to the bootloader on a processor reset instead of the application.novectorsโ for applications that don't need any of the MicroBlaze vectors ๐ This can be handy for apps running inside a monitoring application. This model usescrt3.oas its startup file.
-xl-mode-app-modelis a deprecated alias for-mxl-mode-app-model, so it's giving old news ๐ฐ๏ธ
๐ง 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 a generic MIPS ISA name or the name of a particular processor ๐ The ISA names aremips1,mips2,mips3,mips4,mips32,mips32r2,mips32r3,mips32r5,mips32r6,mips64,mips64r2,mips64r3,mips64r5, andmips64r6. The processor names are4kc,4km,4kp,4ksc,4kec,4kem,4kep,4ksd,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,24kec,24kef2_1,24kef1_1,34kc,34kf2_1,34kf1_1,34kn,74kc,74kf2_1,74kf1_1,74kf3_2,1004kc,1004kf2_1,1004kf1_1,i6400,i6500,interaptiv,loongson2e,loongson2f,loongson3a,gs464,gs464e,gs264e,m4k,m14k,m14kc,m14ke,m14kec,m5100,m5101,octeon,octeon+,octeon2,octeon3,orion,p5600,p6600,r2000,r3000,r3900,r4000,r4400,r4600,r4650,r4700,r5900,r6000,r8000,rm7000,rm9000,r10000,r12000,r14000,r16000,sb1,sr71000,vr4100,vr4111,vr4120,vr4130,vr4300,vr5000,vr5400,vr5500,xlr, andxlp๐งโโ๏ธ The special valuefrom-abipicks the most compatible architecture for the selected ABI, which meansmips1for 32-bit ABIs andmips3for 64-bit ABIs.
The native Linux/GNU toolchain also supports the value native, which picks the best architecture option for the host processor ๐ฅ๏ธ -march=native has no effect if GCC doesn't recognize the processor, so no cap, it just does nothing.
In processor names, a final 000 can be abbreviated as k, so for example -march=r2k. Prefixes are optional, and vr may be written r โจ
Names of the form nf2_1 refer to processors with FPUs clocked at half the rate of the core ๐ข Names of the form nf1_1 refer to processors with FPUs clocked at the same rate as the core ๐ Names of the form nf3_2 refer to processors with FPUs clocked at a 3:2 ratio with respect to the core ๐ฏ For compatibility reasons, nf is accepted as a synonym for nf2_1, while nx and bfx are accepted as synonyms for nf1_1 ๐ซถ
GCC defines two macros based on the value of this option. The first is _MIPS_ARCH, which gives the name of the target architecture as a string ๐ฎ The second has the form _MIPS_ARCH_foo, where foo is the capitalized value of _MIPS_ARCH. For example, -march=r2000 sets _MIPS_ARCH to r2000 and defines the macro _MIPS_ARCH_R2000 ๐
Note that the _MIPS_ARCH macro uses the processor names listed above. In other words, it has the full prefix and does not abbreviate 000 as k. In the case of from-abi, the macro names the resolved architecture, which is 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 isn't used, GCC optimizes for the processor specified by -march. By using -march and -mtune together, you can generate code that runs on a family of processors but is optimized for one particular member of that family ๐ฏ
-mtune defines the macros _MIPS_TUNE and _MIPS_TUNE_foo, which work the same way as the -march ones described above ๐
-mips1โ equivalent to-march=mips1โจ-mips2โ equivalent to-march=mips2โจ-mips3โ equivalent to-march=mips3โจ-mips4โ equivalent to-march=mips4โจ-mips32โ equivalent to-march=mips32โจ-mips32r3โ equivalent to-march=mips32r3โจ-mips32r5โ equivalent to-march=mips32r5โจ-mips32r6โ equivalent to-march=mips32r6โจ-mips64โ equivalent to-march=mips64โจ-mips64r2โ equivalent to-march=mips64r2โจ-mips64r3โ equivalent to-march=mips64r3โจ-mips64r5โ equivalent to-march=mips64r5โจ-mips64r6โ equivalent to-march=mips64r6โจ-mips16,-mno-mips16โ generate (or don't generate) MIPS16 code ๐ If GCC is targeting a MIPS32 or MIPS64 architecture, it uses the MIPS16e ASE.
MIPS16 code generation can also be controlled on a per-function basis using the mips16 and nomips16 attributes ๐
-mflip-mips16โ generate MIPS16 code on alternating functions ๐งช This option exists for regression testing of mixed MIPS16/non-MIPS16 code generation. It is not intended for ordinary use when compiling user code, so please don't go using it in your everyday builds ๐-minterlink-compressed,-mno-interlink-compressedโ require (or don't require) that code using the standard, uncompressed MIPS ISA be link-compatible with MIPS16 and microMIPS code, and vice versa ๐
For example, code using the standard ISA encoding cannot jump directly to MIPS16 or microMIPS code. It has to use either a call or an indirect jump. So -minterlink-compressed disables direct jumps unless GCC knows the jump's target isn't compressed ๐ซ
-minterlink-mips16,-mno-interlink-mips16โ aliases of-minterlink-compressedand-mno-interlink-compressed๐ฐ๏ธ These options predate the microMIPS ASE and are kept around for backwards compatibility.-mabi=32,-mabi=o64,-mabi=n32,-mabi=64,-mabi=eabiโ generate code for the given ABI ๐
The EABI comes in a 32-bit and a 64-bit variant. GCC normally generates 64-bit code when you pick a 64-bit architecture, but you can use -mgp32 to get 32-bit code instead ๐
For info about the O64 ABI, check out http://gcc.gnu.org/projects/mipso64-abi.html ๐
GCC supports a variant of the o32 ABI where the floating-point registers are 64 bits wide instead of 32 ๐ฆ You can select this combo with -mabi=32 -mfp64. This ABI relies on the mthc1 and mfhc1 instructions, so it's only supported for MIPS32R2, MIPS32R3, and MIPS32R5 processors.
The register assignments for arguments and return values stay the same, but each scalar value is passed in a single 64-bit register instead of a pair of 32-bit registers. For example, scalar floating-point values are returned in $f0 only, not a $f0/$f1 pair. The set of call-saved registers also stays the same, in that the even-numbered double-precision registers are saved ๐ง
Two more variants of the o32 ABI exist to help with the move from 32-bit to 64-bit registers: FPXX (-mfpxx) and FP64A (-mfp64 -mno-odd-spreg) ๐ The FPXX extension requires that all code run correctly with either 32-bit or 64-bit registers. That code can be interlinked with either FP32 or FP64, but not both. FP64A is similar to the FP64 extension, but it forbids the use of odd-numbered single-precision registers. It can be used together with the FRE mode of FPUs in MIPS32R5 processors, and it lets both FP32 and FP64A code interlink and run in the same process without changing FPU modes ๐ซถ
-mabicalls,-mno-abicallsโ generate (or don't generate) code suitable for SVR4-style dynamic objects ๐-mabicallsis the default for SVR4-based systems.-mshared,-mno-sharedโ okay so these decide whether the code is fully position-independent ๐ฆ, which means it can be linked into shared libraries ๐.-msharedturns that on and-mno-sharedturns it off. Both only affect-mabicalls๐
Quick lore: all -mabicalls code has traditionally been position-independent no matter what -fPIC or -fpic say ๐ธ. BUT the GNU toolchain has a sneaky extension where executables can use absolute accesses for locally-binding symbols, use shorter GP initialization sequences, and generate direct calls to locally-defined functions ๐ฅ. That whole mode is what -mno-shared selects.
-mno-sharedneeds binutils 2.16 or higher and makes objects that only the GNU linker can link ๐. It doesn't change the ABI of the final executable, only the ABI of relocatable objects. Using-mno-sharedgenerally makes executables both smaller and quicker ๐ญ
-mshared is the default ๐
-mplt,-mno-pltโ you can tell GCC to assume (or not assume) that the static and dynamic linkers support PLTs and copy relocations ๐. This only affects-mno-shared-mabicalls. For the n64 ABI, it does nothing without-msym32.
You can make -mplt the default by configuring GCC with --with-mips-plt. Otherwise the default is -mno-plt ๐ง.
-mxgot,-mno-xgotโ lift (or don't lift) the usual limits on how big the global offset table can be ๐.
GCC normally uses a single instruction to load values from the GOT. That's pretty efficient, but it only works if the GOT is smaller than about 64k. Anything bigger and the linker throws an error like this:
relocation truncated to fit: R_MIPS_GOT16 foobar
If that happens, recompile your code with -mxgot โจ. It works with very large GOTs, but the code is a bit less efficient, since it takes three instructions to fetch the value of a global symbol.
Some linkers can create multiple GOTs. If you've got one of those, you should only need -mxgot when a single object file touches more than 64k's worth of GOT entries. Very few linkers do ๐.
These options do nothing unless GCC is generating position-independent code.
-mgp32โ assume general-purpose registers are 32 bits wide ๐.-mgp64โ assume general-purpose registers are 64 bits wide ๐.-mfp32โ assume floating-point registers are 32 bits wide ๐.-mfp64โ assume floating-point registers are 64 bits wide ๐.-mfpxxโ don't assume anything about how wide the floating-point registers are ๐ฆ.-mhard-floatโ use the floating-point coprocessor instructions ๐ฅ.-msoft-floatโ don't use the floating-point coprocessor instructions. Floating-point math gets handled with library calls instead ๐ซถ.-mno-floatโ works like-msoft-float, but also promises that the program never does any floating-point operations ๐ค. This is only supported by some bare-metal MIPS configurations, where it might pick a special set of libraries with zero floating-point support (so no floating-pointprintfformats either, for example).
If code compiled with -mno-float accidentally has floating-point operations in it, it's likely to crash and burn with a link-time or run-time failure ๐.
-msingle-floatโ assume the floating-point coprocessor only does single-precision operations ๐ธ.-mdouble-floatโ assume the floating-point coprocessor does double-precision operations. This is the default ๐ .-modd-spreg,-mno-odd-spregโ turn on (or off) the use of odd-numbered single-precision floating-point registers for the o32 ABI โจ. On is the default for processors known to support these registers. When you're using the o32 FPXX ABI,-mno-odd-spregis set by default.-mabs=2008,-mabs=legacyโ these control how the special not-a-number (NaN) IEEE 754 floating-point data gets treated by theabs.fmtandneg.fmtmachine instructions ๐.
By default, or when you use -mabs=legacy, the legacy treatment kicks in. Here, those instructions count as arithmetic, so they get avoided wherever correct operation matters and the input might be a NaN. Instead, a longer sequence that manipulates the sign bit of the floating-point datum by hand gets used, unless -ffinite-math-only has also been specified.
-mabs=2008 picks the IEEE 754-2008 treatment. Now those instructions count as non-arithmetic, so they work correctly in every case, including when the input operand is a NaN. That means they're always used for the respective operations ๐.
-mnan=2008,-mnan=legacyโ these control how the special not-a-number (NaN) IEEE 754 floating-point data gets encoded ๐ฆ.
-mnan=legacy picks the legacy encoding. Quiet NaNs (qNaNs) are marked by the first bit of their trailing significand field being 0, and signaling NaNs (sNaNs) are marked by that first bit being 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โ use (or don't use) thell,sc, andsyncinstructions to implement the atomic memory built-in functions โก. If you don't specify either one, GCC uses those instructions as long as the target architecture supports them.
-mllsc is handy if the runtime environment can emulate the instructions. -mno-llsc can be useful when you're compiling for nonstandard ISAs. You can make either one the default by configuring GCC with --with-llsc or --without-llsc respectively. --with-llsc is the default for some configurations, so check the installation documentation for the details ๐.
-mdsp,-mno-dspโ use (or don't use) revision 1 of the MIPS DSP ASE ๐ถ. This option defines the preprocessor macro__mips_dsp, and it also sets__mips_dsp_revto 1.-mdspr2,-mno-dspr2โ use (or don't use) revision 2 of the MIPS DSP ASE ๐ถ. This option defines the preprocessor macros__mips_dspand__mips_dspr2, and it also sets__mips_dsp_revto 2.-msmartmips,-mno-smartmipsโ use (or don't use) the MIPS SmartMIPS ASE ๐ง .-mpaired-single,-mno-paired-singleโ use (or don't use) paired-single floating-point instructions ๐ฏ. This one needs hardware floating-point support to be enabled first.-mdmx,-mno-dmxโ wait, correction, it's-mdmx,-mno-mdmxโ use (or don't use) MIPS Digital Media Extension instructions ๐ฌ. This can only be used when generating 64-bit code, and it also needs hardware floating-point support enabled.-mips3d,-mno-mips3dโ use (or don't use) the MIPS-3D ASE ๐. The option-mips3dimplies-mpaired-single.-mmicromips,-mno-micromipsโ generate (or don't generate) microMIPS code ๐ธ.
You can also control microMIPS code generation on a per-function basis with the "micromips" and "nomicromips" attributes ๐
.
-mmt,-mno-mtโ use (or don't use) MT Multithreading instructions ๐งต.-mmcu,-mno-mcuโ use (or don't use) the MIPS MCU ASE instructions ๐.-meva,-mno-evaโ use (or don't use) the MIPS Enhanced Virtual Addressing instructions ๐บ๏ธ.-mvirt,-mno-virtโ use (or don't use) the MIPS Virtualization (VZ) instructions ๐ฅ๏ธ.-mxpa,-mno-xpaโ use (or don't use) the MIPS eXtended Physical Address (XPA) instructions ๐ .-mcrc,-mno-crcโ use (or don't use) the MIPS Cyclic Redundancy Check (CRC) instructions ๐.-mginv,-mno-ginvโ use (or don't use) the MIPS Global INValidate (GINV) instructions ๐งน.-mloongson-mmi,-mno-loongson-mmiโ use (or don't use) the MIPS Loongson MultiMedia extensions Instructions (MMI) ๐๏ธ.-mloongson-ext,-mno-loongson-extโ use (or don't use) the MIPS Loongson EXTensions (EXT) instructions ๐งฉ.-mloongson-ext2,-mno-loongson-ext2โ use (or don't use) the MIPS Loongson EXTensions r2 (EXT2) instructions ๐งฉ.-mlong64โ forcelongtypes to be 64 bits wide ๐. Check out-mlong32for the full story on the default and how the pointer size gets decided.-mlong32โ forcelong,int, and pointer types to be 32 bits wide ๐.
The default sizes of int, long, and pointers depend on the ABI. Every supported ABI uses 32-bit ints. The n64 ABI uses 64-bit longs, and so does the 64-bit EABI. The others use 32-bit longs. Pointers match the size of longs, or the size of integer registers, whichever is smaller ๐ง.
-msym32,-mno-sym32โ assume (or don't assume) that all symbols have 32-bit values, no matter which ABI you picked ๐ฏ. This is super useful with-mabi=64and-mno-abicalls, since it lets GCC generate shorter and faster references to symbolic addresses โก.-G numโ put definitions of externally-visible data into a small data section, as long as that data is no bigger thannumbytes ๐ฆ. GCC can then generate more efficient accesses to the data. Check out-mgpoptfor the details ๐.
The default -G value depends on the configuration.
-mlocal-sdata,-mno-local-sdataโ extend (or don't extend) the-Gbehavior to local data too, like static variables in C ๐ก.-mlocal-sdatais the default for all configurations.
If the linker complains that your app is using too much small data, try rebuilding the less performance-critical parts with-mno-local-sdata๐ญ. You might also want to build big libraries with-mno-local-sdata, so they leave more room for the main program.
-mextern-sdata,-mno-extern-sdataโ assume (or don't assume) that externally-defined data lives in a small data section, as long as its size is within the-Glimit ๐ซถ.-mextern-sdatais the default for all configurations.
okay bestie, listen up ๐โจ if you compile a module Mod with -mextern-sdata -G num -mgpopt, and Mod references a variable Var that's no bigger than num bytes, you have to make sure Var ends up in a small data section. no skipping this ๐
if another module defines Var, you've got two options: compile that module with a high-enough -G setting, or attach a section attribute to Var's definition. and if Var is common? then you need to link the application with a high-enough -G setting ๐ฅ
the easiest way to slay these restrictions is to compile and link every module with the same -G option ๐ but ngl, you might want a library that supports a bunch of different small data limits. the move there is to compile the library with the highest supported -G setting and also use -mno-extern-sdata, which stops the library from making assumptions about externally-defined data ๐ง
-mgpopt,-mno-gpoptโ okay so-mgpoptlets GCC use GP-relative accesses for symbols it knows are in a small data section (see-G,-mlocal-sdataand-mextern-sdata) ๐ธ and-mno-gpoptturns that off.-mgpoptis the default for all configurations ๐-mno-gpoptis useful when the$gpregister might not hold the value of"_gp"๐ like, if the code is part of a library that might get used in a boot monitor, programs that call boot monitor routines pass an unknown value in$gp. (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, otherwise plain data ๐ it's slightly slower code than the default, but it cuts down on the RAM needed while executing, so it might be your fave for some embedded systems โจ-muninit-const-in-rodata,-mno-uninit-const-in-rodataโ put uninitialized"const"variables in the read-only data section. this only means something together with-membedded-data๐ซถ-mcode-readable=settingโ choose whether GCC may generate code that reads from executable sections. there are three possible settings, bestie:-mcode-readable=yesโ instructions can freely access executable sections. this is the default ๐-mcode-readable=pcrelโ MIPS16 PC-relative load instructions can access executable sections, but other instructions must NOT ๐ this one's useful on 4KSc and 4KSd processors when the code TLBs have the Read Inhibit bit set ๐ญ it's also useful on processors that can be configured to have a dual instruction/data SRAM interface and that, like the M4K, automatically redirect PC-relative loads to the instruction RAM.-mcode-readable=noโ instructions must not access executable sections. this can be useful on targets configured with a dual instruction/data SRAM interface that (unlike the M4K) do not automatically redirect PC-relative loads to the instruction RAM ๐ง
-msplit-addresses,-mno-split-addressesโ enable (or disable) use of the%hi()and%lo()assembler relocation operators. this one's been superseded by-mexplicit-relocs๐ฅ but it's kept around for backwards compatibility ๐ฐ๏ธ-mexplicit-relocs,-mno-explicit-relocsโ use (or don't use) assembler relocation operators when dealing with symbolic addresses. the alternative, 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 stopstrapfrom generating the proper signal ("SIGFPE") ๐ฉ so use-mdivide-trapsto allow conditional traps on architectures that support them, and-mdivide-breaksto force the use of breaks.- the default is usually
-mdivide-traps, but it can be overridden at configure time using--with-divide=breaks. divide-by-zero checks can be completely disabled using-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 to enable load/store bonding ๐ it's on by default, but it only takes effect when the selected architecture is known to support bonding.-mmemcpy,-mno-memcpyโ force (or don't force) the use of"memcpy"for non-trivial block moves. the default is-mno-memcpy, which lets GCC inline most constant-sized copies ๐ช-mlong-calls,-mno-long-callsโ-mlong-callsturns off use of thejalinstruction, while-mno-long-callsdoesn't. calling functions withjalis more efficient, but it requires the caller and callee to be in the same 256 megabyte segment ๐บ๏ธ this option has no effect on abicalls code. the default is-mno-long-calls.-mmad,-mno-madโ enable (or disable) use of themad,maduandmulinstructions, as provided by the R4650 ISA ๐ฆ-mimadd,-mno-imaddโ enable (or disable) use of themaddandmsubinteger instructions. the default is-mimaddon architectures that supportmaddandmsub, except for the 74k architecture, where it was found to generate slower code ๐ข-mfused-madd,-mno-fused-maddโ enable (or disable) use of the floating-point multiply-accumulate instructions, when they're available. the default is-mfused-madd.- on the R8000 CPU, when multiply-accumulate instructions are used, the intermediate product is calculated to infinite precision and is not subject to the FCSR Flush to Zero bit. this may be undesirable in some circumstances ๐
- on other processors, the result is numerically identical to the equivalent computation using separate multiply, add, subtract and negate instructions โจ
-nocppโ tells the MIPS assembler to NOT run its preprocessor over user assembler files (with a.ssuffix) when assembling them ๐-mfix-24k,-mno-fix-24kโ work around the 24K E48 (lost data on stores during refill) errata ๐ฉน the workarounds are implemented by the assembler rather than by GCC.-mfix-r4000,-mno-fix-r4000โ work around certain R4000 CPU errata:- a double-word or a variable shift may give an incorrect result if executed immediately after starting an integer division.
- a double-word or a variable shift may give an incorrect result if executed while an integer multiplication is in progress.
- an integer division may give an incorrect result if started in a delay slot of a taken branch or a jump.
-mfix-r4400,-mno-fix-r4400โ work around certain R4400 CPU errata:- a double-word or a variable shift may give an incorrect result if executed immediately after starting an integer division.
-mfix-r10000,-mno-fix-r10000โ work around certain R10000 errata:"ll"/"sc"sequences may not behave atomically on revisions prior to 3.0. they may deadlock on revisions 2.6 and earlier ๐ฌ- this option can only be used if the target architecture supports branch-likely instructions.
-mfix-r10000is the default when-march=r10000is used;-mno-fix-r10000is the default otherwise.
-mfix-r5900,-mno-fix-r5900โ don't try to schedule the preceding instruction into the delay slot of a branch instruction placed at the end of a short loop of six instructions or fewer, and always schedule anopinstruction there instead ๐ซ the short loop bug can, under certain conditions, make loops execute only once or twice, thanks to a hardware bug in the R5900 chip ๐ต the workaround is implemented by the assembler rather than GCC.-mfix-rm7000,-mno-fix-rm7000โ work around the RM7000"dmult"/"dmultu"errata ๐ ๏ธ the workarounds are implemented by the assembler rather than by GCC.-mfix-vr4120,-mno-fix-vr4120โ work around certain VR4120 errata:"dmultu"does not always produce the correct result."div"and"ddiv"do not always produce the correct result if one of the operands is negative.- the workarounds for the division errata rely on special functions in
libgcc.a. at present, these functions are only provided by the"mips64vr*-elf"configurations ๐ง - other VR4120 errata require a NOP to be inserted between certain pairs of instructions. these are handled by the assembler, not by GCC itself.
-mfix-vr4130โ work around the VR4130"mflo"/"mfhi"errata. the workarounds are implemented by the assembler rather than by GCC, although GCC avoids using"mflo"and"mfhi"if the VR4130"macc","macchi","dmacc"and"dmacchi"instructions are available instead ๐ฆ-mfix-sb1,-mno-fix-sb1โ work 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โ specify whether GCC should insert cache barriers to avoid the side effects of speculation on R10K processors ๐ง- in common with many processors, the R10K tries to predict the outcome of a conditional branch and speculatively executes instructions from the
"taken"branch. it later aborts these instructions if the predicted outcome is wrong. however, on the R10K, even aborted instructions can have side effects ๐ฑ - this problem only affects kernel stores and, depending on the system, kernel loads. as an example, a speculatively-executed store may load the target memory into cache and mark the cache line as dirty, even if the store itself is later aborted. if a DMA operation writes to the same area of memory before the
"dirty"line is flushed, the cached data overwrites the DMA-ed data. see the R10K processor manual for a full description, including other potential problems ๐
- in common with many processors, the R10K tries to predict the outcome of a conditional branch and speculatively executes instructions from the
this is the kind of thing that's genuinely sneaky, so read the R10K manual before you trust a cache barrier to be a magic fix ๐
Okay so one workaround is to slap cache barrier instructions in front of every memory access that might get speculatively executed and could have side effects even if it gets aborted ๐. -mr10k-cache-barrier=setting is the knob that controls how GCC does 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 is the kernel's responsibility to make sure speculative accesses to these regions are actually safe ๐ซถ.
If the input program contains a function declaration like this one:
void foo (void);
then the implementation of foo must allow j foo and jal foo to be executed speculatively. GCC honors this restriction for functions it compiles itself ๐. It expects non-GCC functions (such as hand-written assembly code) to do the same.
The option comes in three forms:
-mr10k-cache-barrier=load-storeโ Inserts a cache barrier before a load or store that might be speculatively executed and that might have side effects even if aborted ๐ฅ.-mr10k-cache-barrier=storeโ Inserts a cache barrier before a store that might be speculatively executed and that might have side effects even if aborted โจ.-mr10k-cache-barrier=noneโ Turns off cache barrier insertion entirely. 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 not call any such function ๐ง. If it gets called, the function must take the same arguments as the common_flush_func: the address of the memory range being flushed, the size of that memory range, and the number3(to flush both caches) ๐. The default depends on the target GCC was configured for, but it's commonly either_flush_funcor__cpu_flush.mbranch-cost=numโ Sets the cost of branches to roughlynum"simple" instructions ๐ฆ. This cost is only a heuristic, so it's not guaranteed to give consistent results across releases ๐. A zero cost redundantly selects the default, which is based on the-mtunesetting.-mbranch-likely,-mno-branch-likelyโ Enables or disables Branch Likely instructions, no matter what the default is for the selected architecture ๐ . By default, Branch Likely instructions may be generated if the selected architecture supports them. The exception is the MIPS32 and MIPS64 architectures, plus processors that implement those architectures. For those, Branch Likely instructions are not generated by default, because the MIPS32 and MIPS64 architectures 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 is successfully filled. If the delay slot isn't filled, a compact branch gets picked instead, as long as one is available ๐. This is the default.-mcompact-branches=alwaysโ Makes sure a compact branch instruction gets generated if one is available. If it isn't, a delay slot form of the branch gets used instead ๐.
This option is supported from MIPS Release 6 onwards ๐.
-mfp-exceptions,-mno-fp-exceptionsโ Specifies whether FP exceptions are enabled ๐ซง. This affects how FP instructions get scheduled for some processors. The default is that FP exceptions are enabled.
For instance, on the SB-1, if FP exceptions are disabled and we're emitting 64-bit code, then we can use both FP pipes. Otherwise, we can only use one FP pipe ๐ฅ.
-mvr4130-align,-mno-vr4130-alignโ The VR4130 pipeline is two-way superscalar, but it can only issue two instructions together if the first one is 8-byte aligned ๐. When this option is enabled, GCC aligns pairs of instructions that it thinks should execute in parallel โจ.
This option only has an effect when optimizing for the VR4130. It usually makes code faster, but the tradeoff is that the code gets bigger ๐ฃ. It is enabled by default at optimization level -O3.
-msynci,-mno-synciโ Enables (or disables) generation ofsynciinstructions on architectures that support them ๐ง . Thesynciinstructions (if enabled) get generated when__builtin___clear_cacheis compiled.
This option defaults to -mno-synci, but you can override the default by configuring GCC with --with-synci ๐ธ.
Heads up bestie โ ๏ธ: when compiling for single processor systems, it's generally safe to use synci. However, on many multi-core (SMP) systems, it does not invalidate the instruction caches on all cores and may lead to undefined behavior ๐.
-mrelax-pic-calls,-mno-relax-pic-callsโ Tries to turn PIC calls that are normally dispatched via register$25into direct calls ๐ฆ. This only works if the linker can resolve the destination at link time and the destination is within range for a direct call.
-mrelax-pic-calls is the default if GCC was configured to use an assembler and a linker that support the .reloc assembly directive and -mexplicit-relocs is in effect. With -mno-explicit-relocs, this optimization can be done by the assembler and the linker alone, without any help from the compiler ๐
.
-mmcount-ra-address,-mno-mcount-ra-addressโ Emits (or doesn't emit) code that lets_mcountmodify the calling function's return address ๐ฎ. When enabled, this option extends the usual_mcountinterface with a new ra-address parameter. It has typeintptr_t *and gets passed in register$12._mcountcan then modify the return address by doing both of the following:- Returning the new address in register
$31. - Storing the new address in
*ra-address, if ra-address is nonnull.
- Returning the new address in register
The default is -mno-mcount-ra-address ๐.
-mframe-header-opt,-mno-frame-header-optโ Enables (or disables) frame header optimization in the o32 ABI ๐. When you're using the o32 ABI, calling functions allocate 16 bytes on the stack for the called function to write out register arguments. When this optimization is enabled, it suppresses that frame header allocation if it can be determined that the header is unused.
This optimization is off by default at all optimization levels ๐ค.
-mlxc1-sxc1,-mno-lxc1-sxc1โ When applicable, enables (or disables) generation oflwxc1,swxc1,ldxc1, andsdxc1instructions. Enabled by default ๐ซถ.-mmadd4,-mno-madd4โ When applicable, enables (or disables) generation of 4-operandmadd.s,madd.d, and related instructions. Enabled by default โจ.
๐ MMIX Options ๐
These options are defined for the MMIX ๐ง:
-mlibfuncs,-mno-libfuncsโ Specifies that intrinsic library functions are being compiled, passing all values in registers, no matter the size ๐.-mepsilon,-mno-epsilonโ Generates floating-point comparison instructions that compare with respect to therEepsilon register ๐ฅ.-mabi=mmixware,-mabi=gnuโ Generates code that passes function parameters and return values which (in the called function) are seen as registers$0and up ๐. The GNU ABI, by contrast, uses global registers$231and up.-mzero-extend,-mno-zero-extendโ When reading data from memory in sizes shorter than 64 bits, uses (or doesn't use) zero-extending load instructions by default, instead of sign-extending ones ๐.-mknuthdiv,-mno-knuthdivโ Makes the result of a division that yields a remainder have the same sign as the divisor ๐งฎ. With the default,-mno-knuthdiv, the sign of the remainder follows the sign of the dividend. Both methods are arithmetically valid, though the latter is almost exclusively used.-mtoplevel-symbols,-mno-toplevel-symbolsโ Prepends (or doesn't prepend) a:to all global symbols, so the assembly code can be used with thePREFIXassembly directive ๐ฆ.-melfโ Generates an executable in the ELF format, rather than the default mmo format used by the mmix simulator ๐ธ.-mbranch-predict,-mno-branch-predictโ Uses (or doesn't use) the probable-branch instructions, when static branch prediction indicates a probable branch ๐ฎ.-mbase-addresses,-mno-base-addressesโ Generates (or doesn't generate) code that uses base addresses ๐ซง. Using a base address automatically generates a request, handled by the assembler and the linker, for a constant to be set up in a global register. That register is used for one or more base address requests within the range 0 to 255 from the value held in the register. This generally leads to short and fast code, but the number of different data items that can be addressed is limited. That means a program that uses lots of static data may need-mno-base-addresses๐.-msingle-exit,-mno-single-exitโ Forces (or doesn't force) generated code to have a single exit point in each function ๐ช.
๐ฆ MN10300 Options ๐ฆ
These -m options are defined for Matsushita MN10300 architectures ๐
:
-mmult-bugโ Generates code to avoid bugs in the multiply instructions for the MN10300 processors. This is the default โจ.-mno-mult-bugโ Doesn't generate code to avoid bugs in the multiply instructions for the MN10300 processors ๐.-mam33โ Generates code using features specific to the AM33 processor ๐.-mno-am33โ Doesn't generate code using features specific to the AM33 processor. 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 doesn't change the targeted processor type. The CPU type must be one ofmn10300,am33,am33-2, oram34๐.
-mreturn-pointer-on-d0 ๐
Okay so this one is about functions that hand back a pointer ๐. When GCC generates one of those, it can return the pointer in both "a0" and "d0" ๐ซถ. Otherwise the pointer only goes in "a0", and if you try to call those functions without a prototype, you get errors ๐. Heads up, this option is on by default โจ, and if you want it off, use -mno-return-pointer-on-d0 ๐
.
-mno-crt0โ Skips linking in the C run-time initialization object file ๐ง-mrelaxโ Tells the linker to run a relaxation pass โญ that shortens branches, calls and absolute memory addresses. It only does anything when you pass it on the command line for the final link step ๐ฅ
This option makes symbolic debugging impossible ๐ญ so keep that in mind before you reach for it ๐
-mliwโ Lets the compiler generate Long Instruction Word instructions when the target is AM33 or later ๐ This one is the default ๐. It also defines the preprocessor macro"__LIW__"๐-mno-liwโ Stops the compiler from generating Long Instruction Word instructions ๐ It defines the preprocessor macro"__NO_LIW__"๐ฆ-msetlbโ Lets the compiler generate SETLB and Lcc instructions when the target is AM33 or later ๐ Also the default ๐. It defines the preprocessor macro"__SETLB__"โจ-mno-setlbโ No SETLB or Lcc instructions for you ๐ This one 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โ Skips linking 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 these are signed decimals, but this is handy for testsuite and/or aesthetic purposes ๐ฆ-mmcu=โ Picks the MCU you're targeting ๐ฏ It creates a C preprocessor symbol based on the MCU name, converted to upper case and wrapped in__on both ends โจ Themsp430.hheader then uses that symbol to pick an MCU-specific supplementary header file ๐
The option also sets the ISA. If the MCU is one that only supports the 430 ISA, that's the one you get ๐ Otherwise you get the 430X ISA โญ The generic MCU name msp430 selects the 430 ISA, and the generic msp430x selects the 430X ISA ๐ซถ
An MCU-specific linker script also gets added to the linker command line ๐ฅ Its name is the MCU name with .ld appended. So -mmcu=xxx defines the C preprocessor symbol "__XXX__" and makes the linker search for a script called xxx.ld ๐
The ISA and hardware multiply support for each MCU is hard-coded into GCC ๐ง But you can extend device support with an external devices.csv file ๐ฆ
GCC looks for devices.csv using these methods, in this precedence order: the first method beats the second, and the second beats the third ๐
- Include path specified with
"-I"and"-L"โdevices.csvgets searched for in each directory given by the include paths and linker library search paths ๐ - Path specified by the environment variable
MSP430_GCC_INCLUDE_DIRโ Set the global environment variableMSP430_GCC_INCLUDE_DIRto the full path of the directory holdingdevices.csv, and GCC searches there ๐ If it finds the file, that directory also gets registered as an include path and linker library path ๐ธ Header files and linker scripts in there can be used without typing"-I"and"-L"on the command line ๐ - The
msp430-elf{,bare}/include/devicesdirectory โ GCC also checksmsp430-elf{,bare}/include/devicesfrom the toolchain root directory ๐ This directory doesn't exist in a default installation ๐ญ But if you made it and copieddevices.csvin there, the MCU data gets read ๐ซถ Same deal as above: it's also registered as an include path and linker library path โจ
If none of those methods find devices.csv, the hard-coded MCU data is used ๐
-mwarn-mcu/-mno-warn-mcuโ Turns warnings on or off about conflicts between the MCU name from-mmcuand the ISA from-mcpuand/or the hardware multiply support from-mhwmult๐ฅ It also toggles warnings about unrecognized MCU names ๐ This one is on by default โจ-mcpu=โ Specifies the ISA to use. Accepted values aremsp430,msp430xandmsp430xv2๐ฅบ This option is deprecated, so use-mmcu=to select the ISA instead ๐-msimโ Links to the simulator runtime libraries and linker script ๐งช It overrides any scripts that-mmcu=would have picked ๐-mlargeโ Uses large-model addressing (20-bit pointers, 32-bit"size_t") ๐-msmallโ Uses small-model addressing (16-bit pointers, 16-bit"size_t") ๐ง-mrelaxโ Passed on to the assembler and linker, so the linker can do certain optimizations that can't happen until the final link โญmhwmult=โ Describes the type of hardware multiply the target supports ๐ Accepted values arenonefor no hardware multiply,16bitfor the original 16-bit-only multiply from early MCUs,32bitfor the 16/32-bit multiply in later MCUs, andf5seriesfor the 16/32-bit multiply in F5-series MCUs ๐ฆ You can also giveauto, which tells GCC to figure out the hardware multiply support from the MCU name given with-mmcu๐ซถ If there's no-mmcuor the MCU name isn't recognized, no hardware multiply support is assumed ๐"auto"is the default setting ๐
Hardware multiplies are normally done by calling a library routine, which saves space in the generated code ๐ธ At -O3 or higher, though, the hardware multiplier gets invoked inline ๐ฅ That makes the code bigger but faster โจ
The hardware multiply routines disable interrupts while they run and restore the previous interrupt state when they finish ๐ก๏ธ So they're safe to use inside interrupt handlers as well as in normal code ๐
-minrtโ Turns on a minimum runtime environment with no static initializers or constructors ๐ It's meant for memory-constrained devices ๐ฅน The compiler puts special symbols in some objects that tell the linker and runtime which code fragments are required ๐ง-mtiny-printfโ Enables reduced code size"printf"and"puts"library functions โจ The tiny versions aren't reentrant, so be careful with them in multi-threaded apps ๐ญ
Stream support has been removed, and the string to print always goes to stdout via the "write" syscall ๐ The string isn't buffered before it's sent to write ๐
This option requires Newlib Nano IO, so GCC has to be configured with --enable-newlib-nano-formatted-io ๐
-mcode-region=/-mdata-region=โ These tell the compiler where to place functions and data that don't have a"lower","upper","either"or"section"attribute ๐ The possible values are"lower","upper","either"or"any"๐ฆ The first three behave like the matching attribute ๐ The fourth,"any", is the default, and it leaves placement entirely up to the linker script and how it assigns the standard sections (".text",".data", etc) to memory regions ๐ซถ-msilicon-errata=โ Passes a request to the assembler to enable fixes for the named silicon errata ๐ง-msilicon-errata-warn=โ Passes a request to the assembler to turn on warning messages when a silicon erratum might need to be applied ๐จ-mwarn-devices-csv/-mno-warn-devices-csvโ Warns ifdevices.csvisn't found or there's a problem parsing it (default: on) ๐ธ
โจ 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โ Doesn't generate conditional move instructions ๐-mext-perfโ Generates performance extension instructions โญ-mno-ext-perfโ Doesn't generate performance extension instructions ๐ญ-mext-perf2โ Generates performance extension 2 instructions ๐ฅ-mno-ext-perf2โ Doesn't generate performance extension 2 instructions ๐-mext-stringโ Generates string extension instructions ๐-mno-ext-stringโ Doesn't generate string extension instructions ๐-mv3pushโ Generates v3 push25/pop25 instructions ๐ง-mno-v3pushโ Doesn't generate v3 push25/pop25 instructions ๐-m16-bitโ Generates 16-bit instructions ๐-mno-16-bitโ Doesn't generate 16-bit instructions ๐ฆ-misr-vector-size=numโ Specifies the size of each interrupt vector, which must be4or16๐-mcache-block-size=numโ Specifies the size of each cache block, which must be a power of 2 between4and512๐-march=archโ Specifies the name of the target architecture ๐ธ-mcmodel=code-modelโ Sets the code model to one of the following ๐ซถsmallโ All the data and read-only data segments must be within 512KB of addressing space. The text segment must be within 16MB of addressing space ๐งธmediumโ The data segment must be within 512KB, while the read-only data segment can be within 4GB of addressing space. The text segment should still be within 16MB of addressing space ๐largeโ All the text and data segments can be within 4GB of addressing space ๐
-mctor-dtorโ Enables the constructor/destructor feature ๐ฅ-mrelaxโ Guides the linker to relax instructions โญ
โจ Nios II Options โจ
okay bestie, this next batch is all about the Altera Nios II processor ๐ง these are the options that only matter when you're building for that chip, so let's get into it ๐
-G numโ this one decides which global and static objects get tucked into the small data or BSS sections ๐ธ anything less than or equal to num bytes goes there instead of the normal data or BSS sections. the default value of num is8โจ-mgpopt=option,-mgpopt,-mno-gpoptโ this is how you turn GP-relative accesses on (or off) ๐ฆ these are the option names it recognizes:noneโ no GP-relative accesses at all, bye ๐localโ GP-relative accesses for small data objects that aren't external, weak, or uninitialized common symbols ๐ it also uses GP-relative addressing for objects you've explicitly put in a small data section with a"section"attribute.globalโ same aslocal, but it also does GP-relative accesses for small data objects that are external, weak, or common ๐ญ if you pick this one, you must make sure every part of your program (including libraries) is compiled with the same-Gsetting. no skipping!dataโ GP-relative accesses for all data objects in the program ๐
heads up: if you use this, the entire data and BSS segments of your program have to fit in 64K of memory, and you need an appropriate linker script to allocate them within the addressable range of the global pointer.
allโ GP-relative addresses for function pointers as well as data pointers ๐
same energy here: the entire text, data, and BSS segments of your program must fit in 64K of memory, and you need an appropriate linker script to allocate them within the addressable range of the global pointer.
-mgpopt is the same as -mgpopt=local, and -mno-gpopt is the same as -mgpopt=none ๐ the default is -mgpopt, except when you specify -fpic or -fPIC to make position-independent code. also, the Nios II ABI doesn't allow GP-relative accesses from shared libraries, so don't try it ๐
You might need to specify -mno-gpopt explicitly when you're building programs with a ton of small data, including large GOT data sections ๐ฅบ in that case the 16-bit offset for GP-relative addressing might not be big enough to reach the entire small data section.
-mgprel-sec=regexpโ this adds extra section names that can be reached through GP-relative addressing โจ it's most useful alongside"section"attributes on variable declarations and a custom linker script. the regexp is a POSIX Extended Regular Expression. this option doesn't change how-Gbehaves, and the sections you list are in addition to the standard".sdata"and".sbss"small-data sections that-mgpoptalready recognizes.-mr0rel-sec=regexpโ this one names sections that can be accessed via a 16-bit offset from"r0", so basically the low 32K or high 32K of the 32-bit address space ๐ง it's most useful with"section"attributes on variable declarations and a custom linker script. the regexp is a POSIX Extended Regular Expression. Lowkey different from the GP-relative stuff: 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โ generates little-endian (the default) or big-endian (experimental) code, respectively ๐งช-march=archโ this sets the name of the target Nios II architecture ๐๏ธ GCC uses it to figure out what kinds of instructions it can emit when generating assembly code. the permissible names are:r1,r2. The preprocessor macro"__nios2_arch__"is available to your programs, with the value1or2, which tells you the targeted ISA level ๐-mbypass-cache,-mno-bypass-cacheโ forces all load and store instructions to always bypass the cache by using I/O variants of the instructions ๐โโ๏ธ the default is not to bypass the cache.-mno-cache-volatile,-mcache-volatileโ volatile memory access bypasses the cache using the I/O variants of the load and store instructions โก the default is not to bypass the cache.-mno-fast-sw-div,-mfast-sw-divโ-mno-fast-sw-divmeans don't use table-based fast divide for small numbers ๐ โโ๏ธ the default is to use the fast divide at-O3and above.-mno-hw-mul,-mhw-mul,-mno-hw-mulx,-mhw-mulx,-mno-hw-div,-mhw-divโ these enable or disable the compiler emitting the"mul","mulx", and"div"family of instructions ๐ฅ the default is to emit"mul", and to not emit"div"and"mulx".-mbmx,-mno-bmx,-mcdx,-mno-cdxโ enables or disables generation of Nios II R2 BMX (bit manipulation) and CDX (code density) instructions ๐ enabling these also requires-march=r2. since they're optional extensions to the R2 architecture, the default is not to emit them.-mcustom-insn=N,-mno-custom-insnโ each-mcustom-insn=Noption enables use of a custom instruction with encoding N when generating code that uses insn ๐ฆ for example,-mcustom-fadds=253generates custom instruction 253 for single-precision floating-point add operations, instead of the default behavior of using a library call. 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_lroundf"function when-fno-math-errnois used.floatis,floatus,floatid,floatudโ conversion from signed or unsigned integer types to floating-point types.
- Transfer instructions for internal registers X and Y: you have to provide all of these 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 register
X. the other operand (or the only operand of a unary operation) is given to the custom arithmetic instruction with the least significant half in source 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, so you don't have to do it yourself ๐ซถ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.
- Single-precision floating point:
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 ๐
-mcustom-fpu-cfg=nameโ this enables a predefined, named set of custom instruction encodings (see-mcustom-insnabove) โจ right now, these sets are defined:-mcustom-fpu-cfg=60-1is equivalent to:-mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -fsingle-precision-constant-mcustom-fpu-cfg=60-2is equivalent to:-mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254 -mcustom-fdivs=255 -fsingle-precision-constant-mcustom-fpu-cfg=72-3is 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
Custom instruction assignments given by individual -mcustom-insn= options override those given by -mcustom-fpu-cfg=, regardless of the order of the options on the command line ๐ and you can gain more local control over selection of an FPU configuration by using the target("custom-fpu-cfg=name") function attribute or pragma ๐ธ
These additional -m options are available for the Altera Nios II ELF (bare-metal) target:
-mhalโ ๐ Links with the HAL BSP! This skips the GCC-provided C runtime startup and termination code, and it's usually paired with-msys-crt0=to point at the alternate startup code that comes with the HAL BSP. ๐ฆ-msmallcโ ๐ธ Links with a slimmed-down C library,-lsmallc, instead of Newlib. โจ-msys-crt0=startfileโ ๐ง startfile is the file name of the startfile (crt0) you want to use while linking. This one's only useful together with-mhal. ๐-msys-lib=systemlibโ ๐ซถ systemlib is the library name for 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 provided by 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 specific PTX ISA you pick (e.g.sm_35). ISA strings must be lower-case! Valid ISA strings includesm_30andsm_35, and the default issm_30. ๐-mmainkernelโ Links in code for a__mainkernel. This is for stand-alone execution instead of offloading execution. ๐ฆ-moptimizeโ Applies partitioned execution optimizations. This is the default whenever any level of optimization is selected. โจ-msoft-stackโ Generates code that doesn't use".local"memory directly for stack storage. Instead, a per-warp stack pointer is maintained explicitly. This enables variable-length stack allocation (with variable-length arrays or"alloca"), and when global memory is the underlying storage, it makes it possible to access automatic variables from other threads, or with atomic instructions. This code generation variant is used for OpenMP offloading, but the option is exposed on its own so you can test the compiler. To generate code that's suitable for linking into programs using OpenMP offloading, use option-mgomp. ๐ง ๐-muniform-simtโ Switches to a code generation variant that lets all threads in each warp execute, while keeping memory state and side effects as if only one thread in each warp was active outside OpenMP SIMD regions. All atomic operations and calls to the runtime (malloc,free,vprintf) are conditionally executed (iff current lane index equals the master lane index), and the register being assigned is copied via a shuffle instruction from the master lane. Outside of SIMD regions, lane 0 is the master; inside, each thread sees itself as the master. The shared memory arrayint __nvptx_uni[]stores all-zeros or all-ones bitmasks for each warp, indicating the current mode (0 outside of SIMD regions). Each thread can bitwise-and the bitmask at positiontid.ywith the current lane index to compute the master lane index. ๐-mgompโ Generates code for use in OpenMP offloading: it enables-msoft-stackand-muniform-simt, and selects the corresponding multilib variant. ๐ฅ
โจ OpenRISC Options โจ
These options are defined for OpenRISC: ๐ธ
-mboard=nameโ Configures a board-specific runtime. This gets passed to the linker for newlib board library linking. The default is"or1ksim". ๐-mnewlibโ This option is ignored; it's just here for compatibility purposes. It used to select linker and preprocessor options for use with newlib. ๐-msoft-div,-mhard-divโ Picks software or hardware divide (l.div,l.divu) instructions. The default is hardware divide. โญ-msoft-mul,-mhard-mulโ Picks software or hardware multiply (l.mul,l.muli) instructions. The default is hardware multiply. โญ-msoft-float,-mhard-floatโ Picks software or hardware for floating point operations. The default is software. ๐ง-mdouble-floatโ When-mhard-floatis selected, this enables generation of double-precision floating point instructions. By default, functions from libgcc are used to perform double-precision floating point operations. ๐-munordered-floatโ When-mhard-floatis selected, this enables generation of unordered floating point compare and set flag (lf.sfun*) instructions. By default, functions from libgcc are used to perform unordered floating point compare and set flag operations. ๐-mcmovโ Enables generation of conditional move (l.cmov) instructions. By default, the equivalent is generated using set and branch. ๐ฆ-mrorโ Enables generation of rotate right (l.ror) instructions. By default, functions from libgcc are used to perform rotate right operations. ๐-mroriโ Enables generation of rotate right with immediate (l.rori) instructions. By default, functions from libgcc are used to perform rotate right with immediate operations. ๐-msextโ Enables generation of sign extension (l.ext*) instructions. By default, memory loads are used to perform sign extension. ๐ซถ-msfimmโ Enables generation of compare and set flag with immediate (l.sf*i) instructions. By default, extra instructions are generated to store the immediate to a register first. ๐ญ-mshftimmโ Enables generation of shift with immediate (l.srai,l.srli,l.slli) instructions. By default, extra instructions are generated to store the immediate to a register first. ๐ญ
โจ PDP-11 Options โจ
These options are defined for the PDP-11: ๐น๏ธ
-mfpuโ Uses hardware FPP floating point. This is the default. (FIS floating point on the PDP-11/40 is not supported.) Implies-m45. ๐ฅ-msoft-floatโ Doesn't use hardware floating point. ๐ โโ๏ธ-mac0โ Returns floating-point results in ac0 (fr0in Unix assembler syntax). ๐-mno-ac0โ Returns floating-point results in memory. This is the default. ๐-m40โ Generates code for a PDP-11/40. Implies-msoft-float -mno-split. ๐-m45โ Generates code for a PDP-11/45. This is the default. ๐-m10โ Generates code for a PDP-11/10. Implies-msoft-float -mno-split. ๐-mint16,-mno-int32โ Uses 16-bit"int". This is the default. โจ-mint32,-mno-int16โ Uses 32-bit"int". โจ-msplitโ The target has split instruction and data space. Implies-m45. ๐ฆ-munix-asmโ Uses Unix assembler syntax. ๐ง-mdec-asmโ Uses DEC assembler syntax. ๐ง-mgnu-asmโ Uses GNU assembler syntax. This is the default. ๐-mlraโ Uses the new LRA register allocator. By default, the old"reload"allocator is used. ๐ง
โจ picoChip Options โจ
These -m options are defined for picoChip implementations: ๐ฉต
-mae=ae_typeโ Sets the instruction set, register set, and instruction scheduling parameters for array element typeae_type. Supported values forae_typeareANY,MUL, andMAC. ๐-mae=ANYโ Selects a completely generic AE type. Code generated with this option runs on any of the other AE types. The code isn't as efficient as it would be if 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 directly use a symbol name as an address in a load/store instruction, without first loading it into a register. This usually generates larger programs that run faster than when the option isn't used. However, the results vary from program to program, so it's left as a user option rather than being permanently enabled. ๐ซถ-mno-inefficient-warningsโ Disables warnings about the generation of inefficient code. These warnings can be generated, for example, when compiling code that performs byte-level memory operations on the MAC AE type. The MAC AE has no hardware support for byte-level memory operations, so all byte load/stores must be synthesized from word load/store operations. This is inefficient, and a warning is generated to tell you to rewrite the code to avoid byte operations, or to target an AE type that has the necessary hardware support. This option turns those warnings off. ๐
โจ PowerPC Options โจ
These are listed under
โจ PRU Options โจ
These command-line options are defined for PRU target: ๐ง
-minrtโ Links with a minimum runtime environment, with no support for static initializers and constructors. Using this can significantly reduce the size of the final ELF binary. Beware: the compiler could still generate code with static initializers and constructors, so it's up to the programmer to make sure the source program won't use those features. โ ๏ธ-mmcu=mcuโ Specifies the PRU MCU variant to use. Check Newlib for the exact list of supported MCUs. ๐-mno-relaxโ Makes GCC pass the--no-relaxcommand-line option to the linker instead of the--relaxoption. ๐ฆ-mloopโ Allows (or does not allow) GCC to use the LOOP instruction. ๐ธ-mabi=variantโ Specifies the ABI variant to output code for.-mabi=tiselects the unmodified TI ABI, while-mabi=gnuselects a GNU variant that copes more naturally with certain GCC assumptions. These are the differences: ๐- Function Pointer Size โ TI ABI specifies that function (code) pointers are 16-bit, whereas GNU supports only 32-bit data and code pointers. ๐ง
- Optional Return Value Pointer โ Function return values larger than 64 bits are passed by using a hidden pointer as the first argument of the function. TI ABI, though, mandates that the pointer can be NULL in case the caller is not using the returned value. GNU always passes and expects a valid return value pointer. ๐ง
The current -mabi=ti implementation simply raises a compile error when any of the above code constructs is detected. As a consequence, the standard C library cannot be built, and it is omitted when linking with -mabi=ti. ๐
Relaxation is a GNU feature and, for safety reasons, is disabled when using -mabi=ti. The TI toolchain does not emit relocations for QBBx instructions, so the GNU linker cannot adjust them when shortening adjacent LDI32 pseudo instructions. ๐
โจ RISC-V Options โจ
These command-line options are defined for RISC-V targets: ๐
-mbranch-cost=nโ okay so this one sets the cost of branches to roughlyninstructions ๐ โจ-mplt,-mno-pltโ when you're generating PIC code, this decides whether PLTs are allowed or not ๐ฆ It's ignored for non-PIC, and the default is-mplt๐ธ-mabi=ABI-stringโ this sets the integer and floating-point calling convention, and the vibe is very specific ๐ TheABI-stringhas two parts: the size of integer types, and which registers get used for floating-point types.- For example,
-march=rv64ifd -mabi=lp64dmeanslongand pointers are 64-bit (which implicitly makesint32-bit), and floating-point values up to 64 bits wide get passed in F registers ๐ - Now contrast that with
-march=rv64ifd -mabi=lp64f. The compiler can still generate code that uses the F and D extensions, but only floating-point values up to 32 bits long get passed in registers ๐ฅบ - Or there's
-march=rv64ifd -mabi=lp64, where no floating-point arguments get passed in registers at all ๐
- For example,
The default for this one is system dependent, so if you want a specific calling convention, you should specify one explicitly, bestie ๐ซถ The valid calling conventions are: ilp32, ilp32f, ilp32d, lp64, lp64f, and lp64d. Some of them are literally impossible on some ISAs. For example, -march=rv32if -mabi=ilp32d is invalid, because the ABI needs 64-bit values passed in F registers, but F registers are only 32 bits wide ๐ There's also the ilp32e ABI, which can only be used with the rv32e architecture.
๐ Warning: the ilp32e ABI is not well specified at present, and it is subject to change. Don't get too attached to it yet ๐ญ
-mfdiv,-mno-fdivโ do or don't use hardware floating-point divide and square root instructions ๐ฅ This needs the F or D extensions for floating-point registers. The default is to use them if the specified architecture has these instructions โจ-mdiv,-mno-divโ do or don't use hardware instructions for integer division ๐ง This needs the M extension. The default is to use them if the specified architecture has these instructions ๐-march=ISA-stringโ generates code for the given RISC-V ISA, likerv64im๐ISAstrings must be lower-case, no exceptions, no cap. Examples includerv64i,rv32g,rv32e, andrv32imaf๐-mtune=processor-stringโ optimizes the output for the processor you pick, by microarchitecture name ๐ The permissible values for this option are:rocket,sifive-3-series,sifive-5-series,sifive-7-series, andsize.- When
-mtune=isn't specified, the default isrocketโญ - The
sizechoice is not intended for end-users, honestly. It's used when-Osis specified. It overrides the instruction cost info provided by-mtune=, but it does not override the pipeline info. This helps reduce code size while still giving good performance ๐ฆ
- When
-mpreferred-stack-boundary=numโ attempts to keep the stack boundary aligned to a 2 raised tonumbyte boundary ๐ If-mpreferred-stack-boundaryisn't specified, the default is 4 (16 bytes, or 128-bits).
๐ Warning: if you use this switch, then you must build all modules with the same value, including any libraries. This includes the system libraries and startup modules. No skipping, periodt ๐ญ
-msmall-data-limit=nโ puts global and static data smaller thannbytes into a special section (on some targets) ๐ธ-msave-restore,-mno-save-restoreโ do or don't use smaller but slower prologue and epilogue code that uses library function calls ๐ข The default is to use fast inline prologues and epilogues โก-mstrict-align,-mno-strict-alignโ toggles whether unaligned memory accesses are generated, which is giving "do not" vs "do" energy ๐ The default depends on whether the processor you're optimizing for supports fast unaligned access or not ๐-mcmodel=medlowโ generates code for the medium-low code model ๐ฐ The program and its statically defined symbols must lie within a single 2 GiB address range, and must lie between absolute addresses -2 GiB and +2 GiB. Programs can be statically or dynamically linked. This is the default code model โจ-mcmodel=medanyโ generates code for the medium-any code model ๐ The program and its statically defined symbols must be within any single 2 GiB address range. Programs can be statically or dynamically linked ๐-mexplicit-relocs,-mno-exlicit-relocsโ uses or doesn't use assembler relocation operators when dealing with symbolic addresses ๐งฉ The alternative is to use assembler macros instead, which may limit optimization ๐ฅฒ-mrelax,-mno-relaxโ takes advantage of linker relaxations to reduce the number of instructions required to materialize symbol addresses โก The default is to take advantage of linker relaxations ๐-memit-attribute,-mno-emit-attributeโ emits (or doesn't emit) a RISC-V attribute to record extra information into ELF objects ๐ฆ This feature requires at least binutils 2.32 ๐ซถ-malign-data=typeโ controls how GCC aligns variables and constants of array, structure, or union types ๐ The supported values fortypearexlen, which uses the x register width as the alignment value, andnatural, which uses natural alignment.xlenis the default ๐
๐ธ RL78 Options ๐ธ
-msimโ links in additional target libraries so you can run inside a simulator ๐ฎ-mmul=none,-mmul=g10,-mmul=g13,-mmul=g14,-mmul=rl78โ picks the type of hardware multiplication and division support to use ๐งฎ- The simplest one is
"none", which uses software for both multiplication and division. This is the default ๐ฃ - The
"g13"value is for the hardware multiply/divide peripheral found on the RL78/G13 (S2 core) targets ๐ง - The
"g14"value selects the use of the multiplication and division instructions supported by the RL78/G14 (S3 core) parts โญ - The value
"rl78"is an alias for"g14", and the value"mg10"is an alias for"none"๐ฆ
- The simplest one is
Also, a C preprocessor macro gets defined based on the setting of this option. The possible values are: "__RL78_MUL_NONE__", "__RL78_MUL_G13__", or "__RL78_MUL_G14__" ๐ง
-mcpu=g10,-mcpu=g13,-mcpu=g14,-mcpu=rl78โ specifies the RL78 core to target ๐ฏ The default is the G14 core, also known as an S3 core or just RL78 ๐- The G13 or S2 core doesn't have multiply or divide instructions. Instead, it uses a hardware peripheral for these operations ๐ ๏ธ
- The G10 or S1 core doesn't have register banks, so it uses a different calling convention ๐
If this option is set, it also selects the type of hardware multiply support to use, unless you override that with an explicit -mmul=none option on the command line. So -mcpu=g13 enables the use of the G13 hardware multiply peripheral, and -mcpu=g10 disables hardware multiplications altogether ๐
Note: even though the RL78/G14 core is the default target, specifying -mcpu=g14 or -mcpu=rl78 on the command line does change the behavior of the toolchain, since it also enables G14 hardware multiply support ๐ฅ If these options aren't specified 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 ๐ฅน
And yes, a C preprocessor macro gets defined based on this option too. The possible values are: "__RL78_G10__", "__RL78_G13__", or "__RL78_G14__" ๐
-mg10,-mg13,-mg14,-mrl78โ these are aliases for the corresponding-mcpu=option, kept around for backwards compatibility ๐ฐ๏ธ-mallregsโ lets the compiler use all of the available registers ๐ By default, registersr24..r31are reserved for use in interrupt handlers. With this option enabled, those registers can be used in ordinary functions as well โจ-m64bit-doubles,-m32bit-doublesโ makes the"double"data type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) in size ๐ The default is-m32bit-doubles๐-msave-mduc-in-interrupts,-mno-save-mduc-in-interruptsโ specifies that interrupt handler functions should preserve the MDUC registers ๐ก๏ธ This is only necessary if normal code might use the MDUC registers, for example because it performs multiplication and division operations. The default is to ignore the MDUC registers, because that makes the interrupt handlers faster ๐โโ๏ธ The target option-mg13needs to be passed for this to work, since this feature is only available on the G13 target (S2 core) ๐ซถ The MDUC registers only get saved if the interrupt handler performs a multiplication or division operation, or if it calls another function.
๐ฆ IBM RS/6000 and PowerPC Options ๐ฆ
These -m options are defined for the IBM RS/6000 and PowerPC ๐
-mpowerpc-gpopt,-mno-powerpc-gpoptโ one of the instruction-availability switches ๐-mpowerpc-gfxopt,-mno-powerpc-gfxoptโ one of the instruction-availability switches ๐-mpowerpc64,-mno-powerpc64โ one of the instruction-availability switches ๐-mmfcrf,-mno-mfcrfโ one of the instruction-availability switches ๐-mpopcntb,-mno-popcntbโ one of the instruction-availability switches ๐-mpopcntd,-mno-popcntdโ one of the instruction-availability switches ๐-mfprnd,-mno-fprndโ one of the instruction-availability switches ๐-mcmpb,-mno-cmpbโ one of the instruction-availability switches ๐-mhard-dfp,-mno-hard-dfpโ one of the instruction-availability switches ๐
You use these options to specify which instructions are available on the processor you're using ๐ฅ๏ธ The default value of these options is determined when configuring GCC. Specifying -mcpu=cpu_type overrides the specification of these options. We recommend you use the -mcpu=cpu_type option rather than the options listed above, bestie ๐ซถ
Specifying -mpowerpc-gpopt allows GCC to use the optional PowerPC architecture instructions in the General Purpose group, including floating-point square root โจ Specifying -mpowerpc-gfxopt allows GCC to use the optional PowerPC architecture instructions in the Graphics group, including floating-point select ๐
I'm going to start with the PowerPC ISA flags and the rest of the CPU-tuning goodies, bestie ๐
-mmfcrfโ okay so this one lets GCC generate the move from condition register field instruction ๐ฆ. It's on the POWER4 processor and any other chip that supports the PowerPC V2.01 architecture โจ-mpopcntbโ lets GCC generate the popcount and double-precision FP reciprocal estimate instruction ๐ธ. Lives on the POWER5 processor and other chips with the PowerPC V2.02 architecture ๐-mpopcntdโ lets GCC generate the popcount instruction ๐ซถ. It's on the POWER7 processor and other chips with the PowerPC V2.06 architecture ๐-mfprndโ lets GCC generate the FP round to integer instructions ๐ฅ. Found on the POWER5+ processor and other chips with the PowerPC V2.03 architecture ๐-mcmpbโ lets GCC generate the compare bytes instruction โญ. It's on the POWER6 processor and other chips with the PowerPC V2.05 architecture ๐ง-mhard-dfpโ lets GCC generate the decimal floating-point instructions ๐. These show up on some POWER processors, so not every chip gets them ๐-mpowerpc64โ unlocks the extra 64-bit instructions from the full PowerPC64 architecture ๐ . It also treats GPRs as 64-bit, doubleword quantities. GCC defaults to-mno-powerpc64, so you have to ask for it ๐
๐ -mcpu=cpu_type
This one sets the architecture type, register usage, and instruction scheduling parameters for the machine type cpu_type ๐. The supported values are:
401, 403, 405, 405fp, 440, 440fp, 464, 464fp, 476, 476fp, 505,
601, 602, 603, 603e, 604, 604e, 620, 630, 740, 7400, 7450, 750, 801,
821, 823, 860, 970, 8540, a2, e300c2, e300c3, e500mc, e500mc64,
e5500, e6500, ec603e, G3, G4, G5, titan, power3, power4, power5,
power5+, power6, power6x, power7, power8, power9, power10, powerpc,
powerpc64, powerpc64le, rs64, and native
-mcpu=powerpc, -mcpu=powerpc64, and -mcpu=powerpc64le are the generic ones ๐ธ. They give you pure 32-bit PowerPC (either endian), 64-bit big endian PowerPC, and 64-bit little endian PowerPC machine types. A generic processor model gets assumed for scheduling, so it's not chasing one specific chip โจ
Specifying native as the CPU type is main character energy ๐
. GCC detects the host processor of the system doing the compiling and picks the matching architecture option. -mcpu=native does absolutely nothing if GCC doesn't recognize the processor ๐
The other options point at one specific processor. Code generated for that chip runs its best there, and it may not run at all on others ๐
Heads up bestie: code tuned for one specific chip may not run at all on other chips ๐
The -mcpu options automatically enable or disable the following options ๐ฆ:
-maltivec -mfprnd -mhard-float -mmfcrf -mmultiple -mpopcntb
-mpopcntd -mpowerpc64 -mpowerpc-gpopt -mpowerpc-gfxopt -mmulhw
-mdlmzb -mmfpgpr -mvsx -mcrypto -mhtm -mpower8-fusion
-mpower8-vector -mquad-memory -mquad-memory-atomic -mfloat128
-mfloat128-hardware -mprefixed -mpcrel -mmma
The exact set for each CPU changes between compiler versions ๐. It depends on what GCC thinks makes the best code for that chip, so it doesn't always match what the hardware can actually do ๐คทโโ๏ธ. If you want to set one option by hand, put it after the -mcpu option, like -mcpu=970 -mno-altivec ๐
On AIX, -maltivec and -mpowerpc64 aren't turned on or off by -mcpu right now ๐. That's because AIX doesn't fully support those options yet. You can still enable or disable them one at a time if you're sure it'll work in your environment โจ
-mtune=cpu_typeโ this sets only the instruction scheduling parameters for cpu_type ๐. It doesn't touch the architecture type or register usage the way-mcpu=cpu_typedoes. The same values work for-mtuneas for-mcpu. If you use both, the code keeps the architecture and registers from-mcpu, but the scheduling comes from-mtune๐-mcmodel=smallโ generates PowerPC64 code for the small model ๐ง. The TOC is limited to 64k-mcmodel=mediumโ generates PowerPC64 code for the medium model ๐ธ. The TOC and other static data can total up to 4G in size. This is the default for 64-bit Linux ๐-mcmodel=largeโ generates PowerPC64 code for the large model ๐. The TOC can be up to 4G in size. Other data and code is only limited by the 64-bit address space โญ-maltivec,-mno-altivecโ generates code that uses (or doesn't use) AltiVec instructions ๐ฅ. It also turns on built-in functions that give you more direct access to the AltiVec instruction set ๐. You may also need to set-mabi=altivecto adjust the current ABI with AltiVec ABI enhancements ๐ซถ
When -maltivec is used, the element order for AltiVec intrinsics like vec_splat, vec_extract, and vec_insert matches the array element order for the target's endianness ๐
. Element zero is the leftmost element in a vector register on a big-endian target. On a little-endian target, element zero is the rightmost element in a vector register ๐
-mvrsave,-mno-vrsaveโ generates VRSAVE instructions when generating AltiVec code ๐ฆ-msecure-pltโ generates code that letsldandld.sobuild executables and shared libraries with non-executable.pltand.gotsections ๐. This is a PowerPC 32-bit SYSV ABI option ๐-mbss-pltโ generates code that uses a BSS.pltsection thatld.sofills in ๐ธ. It needs.pltand.gotsections that are both writable and executable ๐. This is also a PowerPC 32-bit SYSV ABI option โจ-misel,-mno-iselโ enables or disables the generation of ISEL instructions ๐ง-mvsx,-mno-vsxโ generates code that uses (or doesn't use) vector/scalar (VSX) instructions ๐. It also enables built-in functions for more direct access to the VSX instruction set ๐-mcrypto,-mno-cryptoโ enables (or disables) the built-in functions for direct access to the cryptographic instructions added in version 2.07 of the PowerPC ISA ๐ฅ-mhtm,-mno-htmโ enables (or disables) the built-in functions for direct access to the Hardware Transactional Memory (HTM) instructions added in version 2.07 of the PowerPC ISA ๐-mpower8-fusion,-mno-power8-fusionโ the first one keeps some integer operations adjacent so they can be fused together on POWER8 and later processors ๐. The second one does not keep them adjacent ๐-mpower8-vector,-mno-power8-vectorโ generates code that uses (or doesn't use) the vector and scalar instructions added in version 2.07 of the PowerPC ISA โญ. It also enables built-in functions for more direct access to the vector instructions ๐-mquad-memory,-mno-quad-memoryโ generates code that uses (or doesn't use) the non-atomic quad word memory instructions ๐ซถ. The-mquad-memoryoption requires 64-bit mode ๐ง-mquad-memory-atomic,-mno-quad-memory-atomicโ generates code that uses (or doesn't use) the atomic quad word memory instructions ๐ธ. The-mquad-memory-atomicoption requires 64-bit mode too ๐-mfloat128,-mno-float128โ enables or disables the__float128keyword for IEEE 128-bit floating point ๐. It also picks whether IEEE 128-bit floating point uses software emulation or hardware instructions โจ
The VSX instruction set (-mvsx) has to be enabled before you can use IEEE 128-bit floating point support ๐ซถ. This support is only available on Linux ๐ง
The default for -mfloat128 is enabled on PowerPC Linux systems that use the VSX instruction set ๐. It's disabled on other systems ๐
If you use the ISA 3.0 instruction set (-mpower9-vector or -mcpu=power9) on a 64-bit system, IEEE 128-bit floating point support also enables the generation of ISA 3.0 IEEE 128-bit floating point instructions ๐ฅ. If you don't ask for ISA 3.0 instructions, or you're targeting a 32-bit big endian system, IEEE 128-bit floating point gets done with software emulation instead ๐ฆ
-mfloat128-hardware,-mno-float128-hardwareโ enables or disables using ISA 3.0 hardware instructions to support the__float128data type ๐
The default for -mfloat128-hardware is enabled on PowerPC Linux systems using the ISA 3.0 instruction set ๐. It's disabled 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 generates code that runs on any PowerPC variant ๐. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits, and generates code for PowerPC64, as for-mpowerpc64๐-mfull-toc,-mno-fp-in-toc,-mno-sum-in-toc,-mminimal-tocโ these change how the TOC (Table Of Contents) gets generated ๐. Every executable file gets one.-mfull-tocis selected by default ๐ . In that case, GCC allocates at least one TOC entry for each unique non-automatic variable reference in your program ๐ซถ. GCC also puts floating-point constants in the TOC ๐ธ. The catch is that only 16,384 entries are available in the TOC ๐ญ
If the linker throws an error saying you've overflowed the available TOC space, you can shrink the TOC usage with -mno-fp-in-toc and -mno-sum-in-toc ๐. -mno-fp-in-toc stops GCC from putting floating-point constants in the TOC ๐ฆ. -mno-sum-in-toc makes GCC generate code that calculates the sum of an address and a constant at run time, instead of stuffing that sum into the TOC โจ. You can use one or both of them. Each one makes the code very slightly slower and larger, but it saves TOC space ๐
If you still run out of TOC space even with both of those options, try -mminimal-toc instead ๐ง. It makes only one TOC entry for every file ๐. The code is slower and larger, but it uses extremely little TOC space ๐. You might only want to use it on files that have less frequently-executed code ๐ฅบ
-maix64,-maix32โ okay so this one flips the 64-bit AIX ABI and calling convention on or off ๐ . You get 64-bit pointers, a 64-bitlongtype, and all the infrastructure needed to make them work ๐ฅ.-maix64implies-mpowerpc64, while-maix32turns the 64-bit ABI off and implies-mno-powerpc64. Also, GCC defaults to-maix32๐ธ-mxl-compat,-mno-xl-compatโ this one is giving IBM XL compiler energy ๐ When you're using the AIX-compatible ABI, it makes the output match XL semantics more closely. That means floating-point args to prototyped functions past the register save area (RSA) go on the stack too, not just in the argument FPRs. It also means GCC won't assume the most significant double in a 128-bitlong doubleis properly rounded when comparing and converting todouble, and it uses XL symbol names for thelong doublesupport routines โจ
The AIX calling convention got extended without any initial docs to handle an obscure K&R C situation: calling a function that takes the address of its arguments with fewer arguments than it declares ๐ IBM XL compilers read floating-point args that don't fit in the RSA from the stack when a subroutine is compiled without optimization. Always storing FP args on the stack is inefficient and rarely needed, so this option is not on by default ๐ You only really need it when calling subroutines compiled by IBM XL compilers without optimization.
-mpeโ main character energy for the IBM RS/6000 SP Parallel Environment (PE) ๐ It links your message-passing app with special startup code so it can actually run. The system needs PE installed in the standard location (/usr/lpp/ppe.poe/), or you need to override the specs file with-specs=to point at the right directory ๐ง Also, PE doesn't do threads, so-mpeand-pthreadare incompatible ๐ญ-malign-natural,-malign-powerโ on AIX, 32-bit Darwin, and 64-bit PowerPC GNU/Linux,-malign-naturaloverrides the ABI's alignment for 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. The default is the standard alignment defined in the ABI ๐
On 64-bit Darwin, natural alignment is already the default, and -malign-power is not supported ๐
โโ๏ธ
-msoft-float,-mhard-floatโ-msoft-floatgenerates code that does not use the floating-point register set, and-mhard-floatgenerates code that does use it ๐ซถ With-msoft-float, software floating-point emulation is provided, but you have to pass the option to GCC when linking too, so don't forget that bestie ๐ฅ-mmultiple,-mno-multipleโ these make the code use (or not use) the load multiple word and store multiple word instructions ๐ They're on by default on POWER systems and off by default on PowerPC systems. Don't use-mmultipleon little-endian PowerPC systems, because those instructions don't work in little-endian mode ๐ The exceptions are PPC740 and PPC750, which allow them in little-endian mode ๐-mupdate,-mno-updateโ these make the code use (or not use) the load and store instructions that update the base register to the address of the calculated memory location โจ They're on by default. Heads up: if you use-mno-update, there's a tiny window between the stack pointer being updated and the previous frame's address being stored. That means code that walks the stack across interrupts or signals might end up with corrupted data ๐ญ-mavoid-indexed-addresses,-mno-avoid-indexed-addressesโ these make the code try to avoid (or not avoid) indexed load and store instructions ๐ง Those can be a performance hit on Power6 processors in certain situations, like stepping through big arrays that cross a 16M boundary. This is enabled by default when targeting Power6 and disabled otherwise ๐-mfused-madd,-mno-fused-maddโ these make the code use (or not use) the floating-point multiply and accumulate instructions ๐ฆ They're generated by default if hardware floating point is in use. Also, 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 make the code use (or not use) the half-word multiply and multiply-accumulate instructions on the IBM 405, 440, 464, and 476 processors ๐ธ They're on by default when you're targeting those processors ๐-mdlmzb,-mno-dlmzbโ these make the code use (or not use) the string-searchdlmzbinstruction on the IBM 405, 440, 464, and 476 processors ๐ฅ It's on by default when targeting those processors ๐ซถ-mno-bit-align,-mbit-alignโ on System V.4 and embedded PowerPC systems,-mno-bit-alignmeans structures and unions containing bit-fields are not forced to align to the base type of the bit-field, and-mbit-alignmeans they are ๐
Okay, example time ๐ By default, a structure with nothing but 8 "unsigned" bit-fields of length 1 gets aligned to a 4-byte boundary and ends up 4 bytes in size. With -mno-bit-align, that same structure is aligned to a 1-byte boundary and is just 1 byte in size. Iconic ๐
-mno-strict-align,-mstrict-alignโ on System V.4 and embedded PowerPC systems,-mno-strict-alignmeans GCC does not assume the system handles unaligned memory references, and-mstrict-alignmeans it does assume that ๐-mrelocatable,-mno-relocatableโ these make the code allow (or 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. That's a table of 32-bit addresses this option generates ๐ง For this to work, every object linked together has to be compiled with-mrelocatableor-mrelocatable-lib. Also,-mrelocatablecode aligns the stack to an 8-byte boundary โจ-mrelocatable-lib,-mno-relocatable-libโ like-mrelocatable, this generates a".fixup"section so static executables can be relocated at run time ๐ฆ The difference is that-mrelocatable-libdoesn't 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,-mno-tocmeans GCC does not assume register 2 holds a pointer to a global area with the addresses the program uses, and-mtocmeans it does ๐ธ-mlittle,-mlittle-endianโ on System V.4 and embedded PowerPC systems, this compiles code for the processor in little-endian mode ๐-mlittle-endianis the same as-mlittle๐-mbig,-mbig-endianโ on System V.4 and embedded PowerPC systems, this compiles code for the processor in big-endian mode ๐ฅ-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 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 that register with an appropriate value before execution begins ๐ง-mprioritize-restricted-insns=priorityโ this controls the priority given to dispatch-slot restricted instructions during the second scheduling pass ๐ Thepriorityargument takes0,1, or2, which assign no priority, the highest priority, or the 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 whose latency is greater than or equal to number is costly โจ
-minsert-sched-nops=schemeโ this controls which NOP insertion scheme is 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 into 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 into a new group ๐
-mcall-sysvโ on System V.4 and embedded PowerPC systems, this compiles code using calling conventions that follow the March 1995 draft of the System V Application Binary Interface, PowerPC processor supplement ๐ This is the default unless you configured GCC usingpowerpc-*-eabiaix๐ซถ-mcall-sysv-eabi,-mcall-eabiโ these are the same as specifying both-mcall-sysvand-meabi๐-mcall-sysv-noeabiโ this is the same as specifying both-mcall-sysvand-mno-eabi๐ฅ-mcall-aixdescโ on System V.4 and embedded PowerPC systems, this compiles code for the AIX operating system โจ-mcall-linuxโ on System V.4 and embedded PowerPC systems, this compiles code for the Linux-based GNU system ๐ง-mcall-freebsdโ on System V.4 and embedded PowerPC systems, this compiles code for the FreeBSD operating system ๐-mcall-netbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the NetBSD operating system ๐ฆ-mcall-openbsdโ on System V.4 and embedded PowerPC systems, this compiles code for the OpenBSD operating system ๐ธ-mtraceback=traceback_typeโ 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 ๐
Okay bestie, -mabi=abi-type is the big one ๐ It lets you extend the current ABI with a particular extension, or remove one. The valid values are altivec, no-altivec, ibmlongdouble, ieeelongdouble, elfv1, and elfv2. For AIX there are also vec-extabi and vec-default ๐ฆ
-mabi=ibmlongdoubleโ switches the ABI to IBM extended-precision long double ๐ง. This is not likely to work if your system defaults to IEEE extended-precision long double ๐. If you change the long double type away from IEEE extended-precision, the compiler issues a warning unless you use-Wno-psabi. You also need-mlong-double-128enabled for this one ๐-mabi=ieeelongdoubleโ switches the ABI to IEEE extended-precision long double ๐. This is not likely to work if your system defaults to IBM extended-precision long double ๐. If you change the long double type away from IBM extended-precision, the compiler issues a warning unless you use-Wno-psabi. This also requires-mlong-double-128to be enabled ๐-mabi=elfv1โ the ELFv1 ABI, which is the default for big-endian PowerPC 64-bit Linux ๐ธ. Overriding the default needs special system support and is likely to fail in spectacular ways ๐ญ-mabi=elfv2โ the ELFv2 ABI, which is the default for little-endian PowerPC 64-bit Linux โจ. Overriding the default needs special system support and is likely to fail in spectacular ways ๐ญ-mgnu-attribute,-mno-gnu-attributeโ emits.gnu_attributeassembly directives that set tag/value pairs in a.gnu.attributessection. These describe ABI variations in function parameters or return values ๐ฆ-mprototype,-mno-prototypeโ on System V.4 and embedded PowerPC systems, this assumes all calls to variable argument functions are properly prototyped ๐. Otherwise, the compiler has to insert an instruction before every non-prototyped call to set or clear bit 6 of the condition code register (CR). That bit says whether floating-point values are passed in the floating-point registers, in case the function takes variable arguments. With-mprototype, only calls to prototyped variable argument functions set or clear the bit ๐-msimโ on embedded PowerPC systems, assumes the startup module issim-crt0.oand the standard C libraries arelibsim.aandlibc.a. This is the default forpowerpc-*-eabisimconfigurations ๐งธ-mmvmeโ on embedded PowerPC systems, assumes the startup module iscrt0.oand the standard C libraries arelibmvme.aandlibc.a๐-madsโ on embedded PowerPC systems, assumes the startup module iscrt0.oand the standard C libraries arelibads.aandlibc.a๐-myellowknifeโ on embedded PowerPC systems, assumes the startup module iscrt0.oand the standard C libraries arelibyk.aandlibc.a๐ผ-mvxworksโ on System V.4 and embedded PowerPC systems, tells the compiler you're building for a VxWorks system ๐ธ-membโ on embedded PowerPC systems, sets thePPC_EMBbit in the ELF flags header. This indicates that eabi extended relocations are used ๐ฆ-meabi,-mno-eabiโ on System V.4 and embedded PowerPC systems, this makes you adhere to (or not adhere to) the Embedded Applications Binary Interface (EABI), a set of modifications to the System V.4 specifications ๐
With -meabi, the stack is aligned to an 8-byte boundary, a function __eabi is called from main to set up the EABI environment, and the -msdata option can use both r2 and r13 to point to two separate small data areas ๐ซถ With -mno-eabi, the stack is aligned to a 16-byte boundary, no EABI initialization function is called from main, and the -msdata option only uses r13 to point to a single small data area ๐ฅน The -meabi option is on by default if you configured GCC using one of the powerpc*-*-eabi* options โจ
-msdata=eabiโ on System V.4 and embedded PowerPC systems, puts small initializedconstglobal and static data in the.sdata2section, whichr2points to ๐ฆ Small initialized non-constglobal and static data goes in the.sdatasection, whichr13points to ๐ง Small uninitialized global and static data goes in the.sbsssection, right next to.sdata๐ Heads up:-msdata=eabiis incompatible with-mrelocatable. It also sets-memb๐ซ-msdata=sysvโ on System V.4 and embedded PowerPC systems, puts small global and static data in the.sdatasection, whichr13points to ๐ท Small uninitialized global and static data goes in the.sbsssection, next to.sdata. This is incompatible with-mrelocatable๐ โโ๏ธ-msdata=default,-msdataโ on System V.4 and embedded PowerPC systems, if-meabiis used, the code compiles the same as-msdata=eabi. Otherwise it compiles the same as-msdata=sysv๐ฎ-msdata=dataโ on System V.4 and embedded PowerPC systems, puts small global data in the.sdatasection and small uninitialized global data in the.sbsssection ๐ซ It does not user13to address small data, though. This is the default behavior unless other-msdataoptions are used ๐ธ-msdata=none,-mno-sdataโ on embedded PowerPC systems, puts all initialized global and static data in the.datasection, and all uninitialized data in the.bsssection ๐ซง-mreadonly-in-sdataโ puts read-only objects in the.sdatasection too. This is the default ๐-mblock-move-inline-limit=numโ inlines all block moves (like calls tomemcpyor structure copies) that are less than or equal to num bytes ๐ The minimum value for num is 32 bytes on 32-bit targets and 64 bytes on 64-bit targets. The default is target-specific ๐ฏ-mblock-compare-inline-limit=numโ generates non-looping inline code for all block compares (like calls tomemcmpor structure compares) that are less than or equal to num bytes โ๏ธ If num is0, all inline expansion (non-loop and loop) of block compare is disabled ๐ The default is target-specific ๐-mblock-compare-inline-loop-limit=numโ generates an inline expansion using loop code for all block compares that are less than or equal to num bytes but greater than the limit for non-loop inline block compare expansion ๐ If the block length isn't constant, at most num bytes get compared beforememcmpis called to compare the rest of the block. The default is target-specific ๐ง-mstring-compare-inline-limit=numโ compares at most num string bytes with inline code ๐งต If the difference or end of string isn't found at the end of the inline compare, a call tostrcmporstrncmptakes care of the rest. The default is 64 bytes ๐-G numโ on embedded PowerPC systems, puts global and static items less than or equal to num bytes into the small data or BSS sections, instead of the normal data or BSS section ๐ฌ By default, num is 8. The-G numswitch is also passed to the linker. All modules should be compiled with the same-G numvalue ๐งฉ-mregnames,-mno-regnamesโ on System V.4 and embedded PowerPC systems, this makes you (or doesn't make you) emit register names in the assembly output using symbolic forms ๐ท๏ธ-mlongcall,-mno-longcallโ by default, the compiler assumes all calls are far away, so a longer and more expensive calling sequence is required ๐ข This is needed for calls farther than 32 megabytes (33,554,432 bytes) from the current location. A short call is generated if the compiler knows the call can't be that far away ๐ 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 is planned to add this feature to the GNU linker for 32-bit PowerPC systems too ๐ ๏ธ
On PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers, GCC can generate long calls using an inline PLT call sequence (see -mpltseq). PowerPC with -mbss-plt and PowerPC64 ELFv1 (big-endian) do not support inline PLT calls ๐
โโ๏ธ
On Darwin/PPC systems, #pragma longcall generates jbsr callee, L42, plus a branch island (glue code) ๐๏ธ The two target addresses represent the callee and the branch island. The Darwin/PPC linker prefers the first address and generates a bl callee if the PPC bl instruction reaches the callee directly. Otherwise, the linker generates bl L42 to call the branch island ๐ช The branch island is appended to the body of the calling function. It computes the full 32-bit address of the callee and jumps to it ๐ฆ
On Mach-O (Darwin) systems, this option directs the compiler to emit the glue for every direct call, and the Darwin linker decides whether to use it or discard it ๐ง
In the future, GCC may ignore all longcall specifications when the linker is known to generate glue ๐ฎ
-mpltseq,-mno-pltseqโ implements (or doesn't implement)-fno-pltand long calls using an inline PLT call sequence. That sequence supports lazy linking and long calls to functions indlopen'd shared libraries ๐งฉ Inline PLT calls are only supported on PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers. They're enabled by default if support is detected when configuring GCC, and, for 32-bit PowerPC, if GCC is configured with--enable-secureplt๐ Heads up:-mpltseqcode and-mbss-plt32-bit PowerPC relocatable objects may not be linked together ๐ซ-mtls-markers,-mno-tls-markersโ marks (or doesn't mark) calls to__tls_get_addrwith a relocation that specifies the function argument ๐ท๏ธ That relocation lets the linker reliably connect the function call with the argument setup instructions for TLS optimization. That in turn lets GCC schedule the sequence better ๐-mrecip,-mno-recipโ okay bestie, this one is a speed boost ๐โจ It turns on the reciprocal estimate and reciprocal square root estimate instructions, plus extra Newton-Raphson steps to win back precision, so you don't have to do a divide or a square root and then a divide for your floating-point arguments ๐งฎ. If you're using-mrecip, you should also use-ffast-math(or at the very least-funsafe-math-optimizations,-ffinite-math-only,-freciprocal-mathand-fno-trapping-math) ๐ . The sequence usually has higher throughput than the non-reciprocal instruction, but for reciprocal square roots the precision can drop by up to 2 ulp (i.e. the inverse of1.0comes out as0.99999994) ๐ญ-mrecip=optโ this lets you pick exactly which reciprocal estimate instructions are allowed ๐ฏoptis a comma-separated list, and you can put a!in front of any option to flip it. Here's the menu:allโ Enable all estimate instructions. ๐defaultโ Enable the default instructions, equivalent to-mrecip.noneโ Disable all estimate instructions, equivalent to-mno-recip. ๐ โโ๏ธdivโ Enable the reciprocal approximation instructions for both single and double precision.divfโ Enable the single-precision reciprocal approximation instructions.divdโ Enable the double-precision reciprocal approximation instructions.rsqrtโ Enable the reciprocal square root approximation instructions for both single and double precision.rsqrtfโ Enable the single-precision reciprocal square root approximation instructions.rsqrtdโ Enable the double-precision reciprocal square root approximation instructions.
So, for example, -mrecip=all,!rsqrtd enables all of the reciprocal estimate instructions, except for the "FRSQRTE", "XSRSQRTEDP", and "XVRSQRTEDP" instructions, which handle the double-precision reciprocal square root calculations ๐ฆ
-mrecip-precision,-mno-recip-precisionโ basically you're telling the compiler to assume (or not assume) that the reciprocal estimate instructions are more precise than the PowerPC ABI requires โจ Picking-mcpu=power6,-mcpu=power7or-mcpu=power8turns-mrecip-precisionon automatically ๐ Also, the double-precision square root estimate instructions aren't generated by default on low-precision machines, because they don't converge after three steps ๐-mveclibabi=typeโ this sets the ABI type for vectorizing intrinsics with an external library ๐ The only type supported right now ismass, which means using IBM's Mathematical Acceleration Subsystem (MASS) libraries ๐ฅ GCC currently emits calls toacosd2,acosf4,acoshd2,acoshf4,asind2,asinf4,asinhd2,asinhf4,atan2d2,atan2f4,atand2,atanf4,atanhd2,atanhf4,cbrtd2,cbrtf4,cosd2,cosf4,coshd2,coshf4,erfcd2,erfcf4,erfd2,erff4,exp2d2,exp2f4,expd2,expf4,expm1d2,expm1f4,hypotd2,hypotf4,lgammad2,lgammaf4,log10d2,log10f4,log1pd2,log1pf4,log2d2,log2f4,logd2,logf4,powd2,powf4,sind2,sinf4,sinhd2,sinhf4,sqrtd2,sqrtf4,tand2,tanf4,tanhd2, andtanhf4when generating code for power7. Both-ftree-vectorizeand-funsafe-math-optimizationsmust also be enabled, and the MASS libraries must be specified at link time ๐-mfriz,-mno-frizโ generate (or don't generate) thefrizinstruction when-funsafe-math-optimizationsis used to optimize rounding of floating-point values to 64-bit integer and back to floating point ๐ง > Thefrizinstruction does not return the same value if the floating-point number is too large to fit in an integer. ๐-mpointers-to-nested-functions,-mno-pointers-to-nested-functionsโ generate (or don't generate) code that loads up the static chain register (r11) when calling through a pointer on AIX and 64-bit Linux systems ๐ง This is where a function pointer points to a 3-word descriptor giving the function address, the TOC value to be loaded in registerr2, and the static chain value to be loaded in registerr11.-mpointers-to-nested-functionsis on by default ๐ > If you use-mno-pointers-to-nested-functions, you cannot call through pointers to nested functions, or through pointers to functions compiled in other languages that use the static chain.-msave-toc-indirect,-mno-save-toc-indirectโ generate (or don't generate) code that saves the TOC value in the reserved stack location in the function prologue, if the function calls through a pointer on AIX and 64-bit Linux systems ๐ธ If the TOC value isn't saved in the prologue, it gets saved just before the call through the pointer.-mno-save-toc-indirectis the default, so that's the main character by default ๐-mcompat-align-parm,-mno-compat-align-parmโ generate (or don't generate) code that passes structure parameters with a maximum alignment of 64 bits, for compatibility with older versions of GCC ๐ฐ๏ธ Older versions (prior to 4.9.0) incorrectly didn't align a structure parameter on a 128-bit boundary when that structure had a member needing 128-bit alignment. Newer versions fixed this, but this option lets you generate code that plays nicely with functions compiled by the older versions ๐ซถ-mno-compat-align-parmis the default.-mstack-protector-guard=guardโ generate stack protection code using a canary atguard๐ก๏ธ The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block (the default with GNU libc version 2.4 or later).-mstack-protector-guard-reg=regโ with thetlschoice, this picks which register to use as the base register for reading the canary ๐งญ The default is whatever the relevant ABI specifies.-mstack-protector-guard-offset=offsetโ with thetlschoice, this sets the offset from that base register where the canary is read ๐ The default is whatever the relevant ABI specifies.-mstack-protector-guard-symbol=symbolโ this overrides the offset with a symbol reference to a canary in the TLS block ๐ช-mpcrel,-mno-pcrelโ generate (or don't generate) pc-relative addressing ๐-mpcrelneeds the medium code model (-mcmodel=medium) and prefixed addressing (-mprefixed) to be enabled too.-mprefixed,-mno-prefixedโ generate (or don't generate) addressing modes using prefixed load and store instructions ๐-mprefixedrequires-mcpu=power10(or later) to be enabled.-mmma,-mno-mmaโ generate (or don't generate) the MMA instructions ๐ฅ The-mmaoption requires-mcpu=power10(or later) to be enabled.
๐ RX Options ๐
These command-line options are defined for RX targets ๐ฆ
-m64bit-doubles,-m32bit-doublesโ this makes thedoubledata type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) in size ๐ The default is-m32bit-doubles, and that's because RX floating-point hardware only works on 32-bit values ๐-fpu,-nofpuโ-fpuenables and-nofpudisables the use of RX floating-point hardware โก It's enabled by default for the RX600 series and disabled for the RX200 series. Floating-point instructions are only generated for 32-bit floating-point values, though, so the FPU hardware isn't used for doubles if-m64bit-doublesis used ๐ซ
If-fpuis enabled, then-funsafe-math-optimizationsis also enabled automatically, because the RX FPU instructions are themselves unsafe. ๐
-mcpu=nameโ this selects the type of RX CPU you're targeting ๐ฅ๏ธ 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. The RX200 series doesn't have a hardware floating-point unit, so-nofpuis enabled by default when this type is selected ๐ โโ๏ธ-mbig-endian-data,-mlittle-endian-dataโ this stores data (but not code) in the big-endian format ๐ The default is-mlittle-endian-data, which means data is stored in the little-endian format.-msmall-data-limit=Nโ this sets the maximum size in bytes of global and static variables that can be placed into the small data area ๐ง The small data area can lead to smaller and faster code, but the area is limited, so 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") is reserved to point to this area, so the compiler can't use it anymore. That could make code slower and/or larger if variables get pushed onto the stack instead of being held in this register ๐ฅฒ
Note, common variables (variables that haven't been initialized) and constants are not placed into the small data area, since they're assigned to other sections in the output executable ๐ง
The default value is zero, which disables this feature ๐ This feature isn't enabled by default with higher optimization levels (-O2 etc) because of the potentially detrimental effects of reserving a register. It's up to you to experiment and see whether it benefits your program. See the description of the -mpid option for how the actual register that holds the small data area pointer is chosen ๐
-msim,-mno-simโ use the simulator runtime ๐ฅ๏ธ The default is to use the libgloss board-specific runtime.-mas100-syntax,-mno-as100-syntaxโ when generating assembler output, this uses a syntax that's compatible with Renesas's AS100 assembler ๐ท The GAS assembler can handle this syntax too, but it has some restrictions, so it isn't generated by default ๐ซถ-mmax-constant-size=Nโ ๐ This sets the biggest a constant can be, in bytes, when it's used as an operand in an RX instruction. RX can technically fit constants up to 4 bytes, but a longer value makes the instruction longer too, so sometimes it's worth shrinking the limit. Constants that are too big get shoved into a constant pool and reached through register indirection instead. The valueNcan be between0and4. A value of0(the default) or4means constants of any size are allowed. ๐ธ-mrelaxโ ๐ฆ Turns on linker relaxation. That's when the linker hunts for shorter versions of various instructions to shrink your program. It's off by default.-mint-register=Nโ โจ Reserves a number of registers for fast interrupt handler functions.Ncan be between0and4. A value of1keeps"r13"reserved for the exclusive use of fast interrupt handlers.2reserves"r13"and"r12".3reserves"r13","r12"and"r11", and4reserves"r13"through"r10". The default,0, doesn't reserve any registers. ๐-msave-acc-in-interruptsโ ๐ฅ Tells interrupt handler functions to preserve the accumulator register. You only need this if normal code might use the accumulator, like if it's doing 64-bit multiplications. By default the accumulator gets ignored, because that makes the interrupt handlers faster. ๐ง-mpid,-mno-pidโ ๐ Turns on the generation of position independent data. When it's on, any access to constant data happens through an offset from a base address held in a register. This lets the location of constant data get figured out at run time without the executable needing to be relocated, which is a big win for embedded apps with tight memory constraints. Data that can be modified isn't affected by this option. ๐ซถ
Heads up, bestie: 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. ๐
The actual register that holds the constant data base address depends on whether -msmall-data-limit and/or -mint-register are turned on. Starting at "r13" and working downwards, registers get allocated first to satisfy -mint-register, then -mpid, and finally -msmall-data-limit. So the small data area register can totally end up being "r8" if both -mint-register=4 and -mpid are on the command line. ๐
By default this feature is not enabled. You can restore the default with the -mno-pid command-line option. ๐
-mno-warn-multiple-fast-interrupts,-mwarn-multiple-fast-interruptsโ ๐ Stops GCC from throwing a warning if it finds more than one fast interrupt handler while compiling a file. By default it warns for each extra fast interrupt handler it finds, since the RX only supports one of those. โญ-mallow-string-insns,-mno-allow-string-insnsโ ๐ Turns the string manipulation instructionsSMOVF,SCMPU,SMOVB,SMOVU,SUNTIL,SWHILEand also theRMPAinstruction on or off. These instructions might prefetch data, which isn't safe if you're accessing an I/O register. (Check section 12.2.7 of the RX62N Group User's Manual for more deets.) ๐ง
The default is to allow these instructions. Sadly GCC can't reliably detect every situation where a string instruction might touch an I/O register, so it can't turn them off on its own. Instead, it's on the programmer to use -mno-allow-string-insns if their program accesses I/O space. ๐
When the instructions are enabled, GCC defines the C preprocessor symbol __RX_ALLOW_STRING_INSNS__. Otherwise it defines __RX_DISALLOW_STRING_INSNS__. ๐ฅ
-mjsr,-mno-jsrโ ๐ฆ Uses only (or not only)JSRinstructions to access functions. This can come in clutch when your code size goes past the range ofBSRinstructions. Note that-mno-jsrdoesn't mean "don't useJSR" ๐. It means any type of branch may be used instead.
Note: The generic GCC command-line option -ffixed-reg has special significance to the RX port when it's used with the interrupt function attribute. That attribute marks a function meant to process fast interrupts. GCC makes sure it only uses the registers "r10", "r11", "r12" and/or "r13", and only when the normal use of those registers has been restricted with -ffixed-reg or -mint-register on the command line. ๐ซถ
โจ S/390 and zSeries Options โจ
These are the -m options defined for the S/390 and zSeries architecture. ๐ง
-mhard-float,-msoft-floatโ ๐ธ Uses (or doesn't use) the hardware floating-point instructions and registers for floating-point operations. With-msoft-float, functions inlibgcc.ado the floating-point work instead. With-mhard-float, the compiler generates IEEE floating-point instructions.-mhard-floatis the default. ๐-mhard-dfp,-mno-hard-dfpโ ๐ Uses (or doesn't use) the hardware decimal-floating-point instructions for decimal-floating-point operations. With-mno-hard-dfp, functions inlibgcc.ahandle 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 the"long double"type. A size of 64 bits makes"long double"the same as"double". This is the default. ๐-mbackchain,-mno-backchainโ ๐ Stores (or doesn't store) the address of the caller's frame as a backchain pointer in the callee's stack frame. A backchain might be needed to debug with tools that don't understand DWARF call frame information. When-mno-packed-stackis in effect, the backchain pointer goes 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. However, 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 want to build a Linux kernel, use -msoft-float. โ ๏ธ
The default is to not maintain the backchain. ๐
-mpacked-stack,-mno-packed-stackโ ๐ฆ Uses (or doesn'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. Unused fields still eat up stack space. With-mpacked-stack, register save slots get densely packed at the top of the register save area, and unused space gets reused for other purposes. That means more efficient use of the stack space. ๐ง
However, when -mbackchain is also in effect, the topmost word of the save area is always used to store 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. And, again, the combination of -mbackchain, -mpacked-stack and -mhard-float is not supported. To build a Linux kernel, use -msoft-float. ๐ซ
The default is to not use the packed stack layout. ๐ซ
-msmall-exec,-mno-small-execโ ๐ Generates (or doesn't generate) code that uses thebrasinstruction for subroutine calls. This only works reliably if the total executable size doesn't go over 64k. By default it uses thebasrinstruction instead, which doesn't have that limit. ๐ง-m64,-m31โ ๐ With-m31, code is generated to comply with the GNU/Linux for S/390 ABI. With-m64, code is generated to comply with the GNU/Linux for zSeries ABI. This lets GCC in particular generate 64-bit instructions. For the s390 targets the default is-m31, while the s390x targets default to-m64. ๐-mzarch,-mesaโ ๐ฆ With-mzarch, code is generated using the instructions available on z/Architecture. With-mesa, code is generated 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. When generating code 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. That facility was introduced with the IBM zEnterprise EC12 machine generation, and the builtins are part of the S/390 System z Built-in Functions.-mhtmis enabled by default when using-march=zEC12. ๐ฅ-mvx,-mno-vxโ ๐ With-mvx, code is generated using the instructions available with the vector extension facility, which was 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 that was used.-mvxis enabled by default when using-march=z13. ๐-mzvector,-mno-zvectorโ Turns on vector language extensions and builtins that use the vector instructions from the z13 era and later. ๐ It makesvectora keyword for declaring vector type variables and arguments, but only with GNU extensions on. With strict standard compliance, like-std=c99,vectorwon't work. โจ On top of the GCC low-level builtins, you also get builtins for AltiVec-style compatibility, the kind you'd see on Power and Cell. To use them, include the headervecintrin.h. ๐ It's off by default.-mmvcle,-mno-mvcleโ Use (or skip) the"mvcle"instruction for block moves. ๐ฆ With-mno-mvcle, you get an"mvc"loop instead. This is the default unless you're optimizing for size.-mdebug,-mno-debugโ Print (or don't print) extra debug info while compiling. ๐ The default is no debug printing.-march=cpu-typeโ Generate code that runs on cpu-type, which is the name of a processor type. ๐ The possible values arez900/arch5,z990/arch6,z9-109,z9-ec/arch7,z10/arch8,z196/arch9,zEC12,z13/arch11,z14/arch12,z15/arch13, andnative. ๐ธ The default is-march=z900.
Picking native tells GCC to choose the best architecture option for the host processor. โญ -march=native does nothing if GCC doesn't recognize your processor.
-mtune=cpu-typeโ Tune everything applicable in the generated code to cpu-type, except for the ABI and the set of available instructions. ๐ง The list of values is the same as for-march. The default is whatever value-marchis using.-mtpf-trace,-mno-tpf-traceโ Add (or don't add) TPF OS specific branches to trace routines in the operating system. ๐ This is off by default, even when you're compiling for TPF OS.-mtpf-trace-skip,-mno-tpf-trace-skipโ Change (or don't change) the default branch targets enabled by-mtpf-traceso they point to specialized trace routines. ๐ These let you selectively skip function trace entries for TPF OS. It's off by default, even when you're compiling for TPF OS and also passing-mtpf-trace.-mfused-madd,-mno-fused-maddโ Use (or don't use) the floating-point multiply and accumulate instructions. ๐ฅ These get generated by default if hardware floating point is in use.-mwarn-framesize=framesizeโ Emit a warning if the current function goes over the given frame size. ๐ซถ This is a compile-time check, so it doesn't have to be a real problem when the program runs. It's meant to flag functions that are likely to cause a stack overflow, which makes it 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. ๐ That's generally a bad idea when the stack size is limited.-mstack-guard=stack-guard,-mstack-size=stack-sizeโ If you pass these, the S/390 back end adds extra instructions to the function prologue. Those instructions trigger a trap if the stack size goes stack-guard bytes above stack-size. (Heads up: on S/390, the stack grows downward. ๐) If you leave outstack-guard, GCC picks the smallest power of 2 that's bigger than the compiled function's frame size. ๐ These are meant for debugging stack overflow problems. The extra code adds only a little overhead, so you can use it on production-like systems without a big performance hit.
The values have to be exact powers of 2, and stack-size has to be bigger than stack-guard without going over 64k. To be efficient, the extra code assumes the stack starts at an address aligned to the value of stack-size. ALSOstack-guardcan only be used together withstack-size. ๐ญ
-mhotpatch=pre-halfwords,post-halfwordsโ If hotpatch is enabled, GCC generates a "hot-patching" function prologue for every function in the compilation unit. ๐ง The function label gets the given number of two-byte NOP instructions stuck in front of it (pre-halfwords, max 1000000). After the label,2 * post-halfwordsbytes get appended, using the largest NOP-like instructions the architecture allows (post-halfwords max 1000000). ๐
If both arguments are zero, hotpatching is disabled. โจ You can override this for individual functions with the "hotpatch" attribute.
๐ Score Options ๐
These options are defined for Score implementations:
-mebโ Compile for big-endian mode. ๐ธ This is the default.-melโ Compile for little-endian mode.-mnhwloopโ Disable generation of"bcnz"instructions. ๐-mulsโ Enable generation of unaligned load and store instructions. ๐ฅ-mmacโ Enable multiply-accumulate instructions. ๐ฆ These are disabled by default.-mscore5โ Set SCORE5 as the target architecture.-mscore5uโ Set SCORE5U as the target architecture.-mscore7โ Set SCORE7 as the target architecture. ๐ This is the default.-mscore7dโ Set SCORE7D as the target architecture.
๐ SH Options ๐
These -m options are defined for the SH implementations:
-m1โ Generate code for the SH1. ๐-m2โ Generate code for the SH2. ๐-m2eโ Generate code for the SH2e.-m2a-nofpuโ Generate code for the SH2a without an FPU, or for an SH2a-FPU in a way that the floating-point unit isn't used. ๐ซถ-m2a-single-onlyโ Generate code for the SH2a-FPU so that no double-precision floating-point operations get used. ๐-m2a-singleโ Generate code for the SH2a-FPU, assuming the floating-point unit is in single-precision mode by default. โจ-m2aโ Generate code for the SH2a-FPU, assuming the floating-point unit is in double-precision mode by default. โจ-m3โ Generate code for the SH3. ๐-m3eโ Generate code for the SH3e.-m4-nofpuโ Generate code for the SH4 without a floating-point unit. ๐ธ-m4-single-onlyโ Generate code for the SH4 with a floating-point unit that only supports single-precision arithmetic. ๐-m4-singleโ Generate code for the SH4, assuming the floating-point unit is in single-precision mode by default. โจ-m4โ Generate code for the SH4. ๐-m4-100โ Generate code for SH4-100. ๐-m4-100-nofpuโ Generate code for SH4-100 in a way that the floating-point unit isn't used. ๐-m4-100-singleโ Generate code for SH4-100, assuming the floating-point unit is in single-precision mode by default. โจ-m4-100-single-onlyโ Generate code for SH4-100 so that no double-precision floating-point operations get used. ๐-m4-200โ Generate code for SH4-200. ๐-m4-200-nofpuโ Generate code for SH4-200 without the floating-point unit being used. ๐-m4-200-singleโ Generate code for SH4-200, assuming the floating-point unit is in single-precision mode by default. โจ-m4-200-single-onlyโ Generate code for SH4-200 so that no double-precision floating-point operations get used. ๐-m4-300โ Generate code for SH4-300. ๐-m4-300-nofpuโ Generate code for SH4-300 without the floating-point unit being used. ๐-m4-300-singleโ Generate code for SH4-300 so that no double-precision floating-point operations get used. ๐-m4-300-single-onlyโ Generate code for SH4-300 so that no double-precision floating-point operations get used. ๐-m4-340โ Generate code for SH4-340 (no MMU, no FPU). ๐ง-m4-500โ Generate code for SH4-500 (no FPU). ๐ It passes-isa=sh4-nofputo the assembler.-m4a-nofpuโ Generate code for the SH4al-dsp, or for an SH4a in a way that the floating-point unit isn't used. ๐ซถ-m4a-single-onlyโ Generate code for the SH4a so that no double-precision floating-point operations get used. ๐-m4a-singleโ Generate code for the SH4a, assuming the floating-point unit is in single-precision mode by default. โจ-m4aโ Generate code for the SH4a. ๐-m4alโ Same as-m4a-nofpu, except it implicitly passes-dspto the assembler. ๐ GCC doesn't generate any DSP instructions at the moment, so don't expect them. ๐-mbโ Compile code for the processor in big-endian mode. ๐ธ-mlโ Compile code for the processor in little-endian mode. ๐ธ-mdalignโ Align doubles on 64-bit boundaries.
This changes the calling conventions, so some functions from the standard C library won't work unless you recompile the library first with -mdalign. ๐ญ
-mrelaxโ When possible, shorten some address references at link time. ๐ฆ This uses the linker option-relax.-mbigtableโ Use 32-bit offsets in"switch"tables. ๐ The default is 16-bit offsets.-mbitopsโ Enable bit manipulation instructions on SH2A. ๐ฅ-mfmovdโ Enable the"fmovd"instruction. ๐ฆ Check-mdalignfor alignment constraints.-mrenesasโ Follow the calling conventions defined by Renesas. ๐-mno-renesasโ Follow the calling conventions GCC used before Renesas conventions existed. ๐ฐ๏ธ This is the default for all targets of the SH toolchain.-mnomacsaveโ Mark the"MAC"register as call-clobbered, even when-mrenesasis given. ๐-mieee,-mno-ieeeโ Control the IEEE compliance of floating-point comparisons, which affects how cases where the comparison result is unordered get handled. ๐ง-mieeeis implicitly enabled by default. If-ffinite-math-onlyis on,-mno-ieeegets implicitly set, which makes floating-point greater-equal and less-equal comparisons faster. โญ You can override either implicit setting by explicitly passing-mieeeor-mno-ieee. ๐-minline-ic_invalidateโ okay bestie, this one inlines code that invalidates instruction cache entries right after it sets up nested function trampolines ๐งโจ. Heads up though: if-musermodeis in effect and your code generation option (like-m4) doesn't allow the"icbi"instruction, this does absolutely nothing ๐. If the"icbi"instruction isn't allowed and-musermodeisn't in effect, the inlined code pokes the instruction cache address array directly with an associative write ๐ซฃ.
โ ๏ธ That associative write requires privileged mode at run time, and it fails if the cache line had been mapped via the TLB and has become unmapped. Lowkey scary stuff, so be careful!
-misizeโ dumps the instruction size and location into the assembly code ๐๐ธ.-mpadstructโ this one is deprecated ๐ โโ๏ธ. It pads structures to a multiple of 4 bytes, which is incompatible with the SH ABI, so it's giving outdated energy ๐.-matomic-model=modelโ sets the model of atomic operations, plus any extra parameters, as a comma separated list ๐ง. For the deets on atomic built-in functions, check out__atomic Builtins. These models and parameters 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 sequences need extra help from the system's interrupt/exception handling code, and they're only suitable for SH3* and SH4* single-core systems. This is enabled by default when the target is"sh*-*-linux*"and 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 can also be used on SH1* and SH2* targets ๐. These sequences need extra help from the interrupt/exception handling code and are only suitable for single-core systems. When using this model, thegbr-offset=parameter has to be specified as well.soft-imaskโ 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. Extra support from the interrupt/exception handling code isn't required. It's enabled by default when the target is"sh*-*-linux*"and SH1* or SH2*.hard-llcsโ generates hardware atomic sequences using only the"movli.l"and"movco.l"instructions ๐ช. This is only available on SH4A and is suitable for multi-core systems. Since the hardware instructions only support 32 bit atomic variable access, 8 or 16 bit variables get emulated with 32 bit accesses. Code compiled with this option is also compatible with other software atomic model interrupt/exception handling systems, if it's executed on an SH4A system. Extra support from the interrupt/exception handling code isn't required for this model.gbr-offset=โ specifies the offset in bytes of the variable in the thread control block structure that the generated atomic sequences should use when thesoft-tcbmodel has been selected ๐งต. For other models this parameter gets ignored. The value must be an integer multiple of four and in the range0-1020.strictโ prevents mixing multiple atomic models, even if they're compatible, and makes the compiler generate atomic sequences of the specified model only ๐ซ.
-mtasโ generates the"tas.b"opcode for__atomic_test_and_set๐งช. Notice that depending on your hardware and software configuration, this can degrade overall performance because of the operand cache line flushes that the"tas.b"instruction implies.
โ ๏ธ On multi-core SH4A processors, the "tas.b" instruction must be used with caution, since it can result in data corruption for certain cache configurations.
-mprefergotโ when generating position-independent code, emits function calls using the Global Offset Table instead of the Procedure Linkage Table ๐.-musermode,-mno-usermodeโ-musermodemeans don't allow the compiler to generate privileged mode code ๐ , while-mno-usermodemeans allow it ๐. Specifying-musermodealso implies-mno-inline-ic_invalidateif the inlined code wouldn't work in user mode.-musermodeis the default when the target is"sh*-*-linux*". If the target is SH1* or SH2*,-musermodehas no effect, since there's no user mode at all ๐ซ .-multcost=numberโ sets the cost to assume for a multiply insn ๐ข.-mdiv=strategyโ sets the division strategy used for integer division operations ๐ฐ.strategycan be one of:call-div1โ calls a library function that uses the single-step division instruction"div1"to do the operation. Division by zero gives an unspecified result and doesn't trap. This is the default except for SH4, SH2A and SHcompact.call-fpโ calls a library function that performs the operation in double precision floating point. Division by zero causes a floating-point exception. This is the default for SHcompact with FPU. Specifying this for targets without a double precision FPU defaults to"call-div1".call-tableโ calls a library function that uses a lookup table for small divisors, and the"div1"instruction with case distinction for larger divisors ๐. Division by zero gives an unspecified result and doesn't trap. This is the default for SH4. Specifying this for targets without dynamic shift instructions defaults to"call-div1".
When a division strategy hasn't been specified, the default strategy gets picked based on the current target. For SH2A, the default strategy is to use the "divs" and "divu" instructions instead of library function calls โจ.
-maccumulate-outgoing-argsโ reserves space once for outgoing arguments in the function prologue, rather than around each call ๐งบ. This is generally beneficial for performance and size. It's also needed for unwinding, so the stack frame doesn't get changed around conditional code.-mdivsi3_libfunc=nameโ sets the name of the library function used for 32-bit signed division toname๐ท๏ธ. This only affects the name used in the call division strategies, and the compiler still expects the same sets of input/output/clobbered registers as if this option weren't present.-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers ๐. A fixed register is one that the register allocator can't use, which is super useful when compiling kernel code ๐. A register range is specified as two registers separated by a dash, and multiple register ranges can be specified separated by a comma.-mbranch-cost=numโ assumesnumis the cost for a branch instruction ๐ฟ. Higher numbers make the compiler try to generate more branch-free code when it's possible. If it isn't specified, the value gets selected based on the processor type being compiled for.-mzdcbranch,-mno-zdcbranchโ assumes (or doesn't assume) that zero displacement conditional branch instructions"bt"and"bf"are fast ๐๏ธ. With-mzdcbranch, the compiler prefers zero displacement branch code sequences. This is enabled by default when generating code for SH4 and SH4A. It can be explicitly disabled by specifying-mno-zdcbranch.-mcbranch-force-delay-slotโ forces the use of delay slots for conditional branches, which stuffs the delay slot with a"nop"if a suitable instruction can't be found ๐ซ. This is disabled by default. Turn it on to work around hardware bugs like the ones found in the original SH7055 ๐ ๏ธ.-mfused-madd,-mno-fused-maddโ generates code that uses (or doesn't use) the floating-point multiply and accumulate instructions ๐งฎ. These are generated by default if hardware floating point is used. The machine-dependent-mfused-maddoption is now mapped to the machine-independent-ffp-contract=fastoption, and-mno-fused-maddis mapped to-ffp-contract=off.-mfsca,-mno-fscaโ allows or disallows the compiler from emitting the"fsca"instruction for sine and cosine approximations ๐. The option-mfscamust be used in combination with-funsafe-math-optimizations. It's enabled by default when generating code for SH4A. Using-mno-fscadisables sine and cosine approximations, even if-funsafe-math-optimizationsis in effect.-mfsrra,-mno-fsrraโ allows or disallows the compiler from emitting the"fsrra"instruction for reciprocal square root approximations ๐. The option-mfsrramust be used in combination with-funsafe-math-optimizationsand-ffinite-math-only. It's enabled by default when generating code for SH4A. Using-mno-fsrradisables reciprocal square root approximations, even if-funsafe-math-optimizationsand-ffinite-math-onlyare in effect.-mpretend-cmoveโ prefers zero-displacement conditional branches for conditional move instruction patterns ๐ซ. This can result in faster code on the SH4 processor.-mfdpicโ generates code using the FDPIC ABI ๐งฉ.
โจ Solaris 2 Options โจ
These -m options are supported on Solaris 2 ๐:
-mclear-hwcapโ tells the compiler to remove the hardware capabilities generated by the Solaris assembler ๐งน. This is only necessary when object files use ISA extensions that aren't supported by the current machine, but check at runtime whether or not to use them.-mimpure-textโ used in addition to-shared, this tells the compiler to not pass-z textto the linker when linking a shared object ๐ฆ. With this option, you can link position-dependent code into a shared object.
Okay so, -mimpure-text is lowkey a trap ๐ชค. It does make the linker stop yelling about "relocations remain against allocatable but non-writable sections" ๐ค, BUT those relocations trigger copy-on-write, so the shared object is not actually shared across processes anymore ๐. Instead, bestie, compile ALL your source code with -fpic or -fPIC โจ๐ซถ.
These switches also work on Solaris 2, on top of everything above ๐:
-pthreadsโ literally just a synonym for-pthread๐ฆ
๐ธ SPARC Options ๐ธ
These -m options work on the SPARC ๐
:
-mno-app-regs,-mapp-regsโ Okay so-mapp-regsmakes the compiler use global registers 2 through 4, which the SPARC SVR4 ABI reserves for applications ๐. Just like global register 1, each of 2 through 4 becomes an allocable register that gets clobbered by function calls. This is the default โจ. If you want to be fully SVR4 ABI-compliant (with a bit of a performance hit ๐ญ), go with-mno-app-regs. Libraries and system software should be compiled with this one ๐.-mflat,-mno-flatโ With-mflat, the compiler skips the save/restore instructions and uses a "flat" or single register window model ๐ง. It's still compatible with the regular register window model, and the local registers and input registers (0--5) are still "call-saved" and get stashed on the stack as needed. With-mno-flat(the default ๐), the compiler makes save/restore instructions, except for leaf functions. That's the normal operating mode, no notes.-mfpu,-mhard-floatโ Generates output with floating-point instructions. This is the default ๐ฅ.-mno-fpu,-msoft-floatโ Generates output with library calls for floating point instead ๐ธ. Here's the tea:
Warning: the requisite libraries are NOT available for every SPARC target ๐. Normally the machine's usual C compiler facilities get used, but that can't happen directly in cross-compilation. You'll have to make your own arrangements to provide suitable library functions for cross-compilation. The embedded targetssparc-*-aoutandsparclite-*-*do come with software floating-point support.
Also, -msoft-float changes the calling convention in the output file, so it's only useful if you compile your WHOLE program with it ๐. Specifically, you need to compile libgcc.a (the library that comes with GCC) with -msoft-float for it to work.
-mhard-quad-floatโ Generates output with quad-word (long double) floating-point instructions ๐.-msoft-quad-floatโ Generates output with library calls for quad-word (long double) floating-point instructions instead โจ. The functions called are the ones 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 what the instruction does. Because of that overhead, it's way slower than calling the ABI library routines, which is why -msoft-quad-float is the default. Iconic behavior, honestly ๐
.
-mno-unaligned-doubles,-munaligned-doublesโ-mno-unaligned-doublesassumes doubles have 8-byte alignment, and it's the default ๐ฆ. With-munaligned-doubles, GCC only assumes 8-byte alignment if the doubles are contained in another type, or if they have an absolute address. Otherwise it assumes 4-byte alignment. This avoids some rare compatibility problems with code from other compilers ๐ซถ. It's not the default because it causes a performance loss, especially for floating-point code ๐ฌ.-muser-mode,-mno-user-modeโ-muser-mode(the default ๐) means the compiler won't generate code that can only run in supervisor mode. This only matters for thecasainstruction emitted for the LEON3 processor ๐ง .-mfaster-structs,-mno-faster-structsโ With-mfaster-structs, the compiler assumes structures should have 8-byte alignment ๐. That lets it use pairs oflddandstdinstructions for copies in structure assignment, instead of twice as manyldandstpairs. BUT, this changed alignment directly violates the SPARC ABI.
Heads up bestie: this is ONLY for targets where the developer knows and accepts that the resulting code isn't in line with the ABI rules ๐.
-mstd-struct-return,-mno-std-struct-returnโ With-mstd-struct-return, the compiler generates checking code in functions that return structures or unions ๐. It catches size mismatches between the two sides of function calls, as per the 32-bit ABI. The default is-mno-std-struct-return๐. This option has no effect in 64-bit mode, so it's not giving anything there ๐.-mlra,-mno-lraโ Enables Local Register Allocation โจ. This has been the default for SPARC since GCC 7, so if you want the old Reload, you need to pass-mno-lra๐ฐ๏ธ.-mcpu=cpu_typeโ Sets the instruction set, register set, and instruction scheduling parameters for the machine typecpu_type๐. The supported values arev7,cypress,v8,supersparc,hypersparc,leon,leon3,leon3v7,leon5,sparclite,f930,f934,sparclite86x,sparclet,tsc701,v9,ultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7andm8๐.
Native Solaris and GNU/Linux toolchains also accept native, which picks the best architecture option for your host processor ๐ง. -mcpu=native does nothing if GCC doesn't recognize the processor ๐คทโโ๏ธ.
Default instruction scheduling parameters are used for the values that pick an architecture instead of an implementation. Those are v7, v8, sparclite, sparclet, and v9 ๐
.
Here's the full lineup of each architecture and its implementations, bestie ๐:
v7โcypress,leon3v7v8โsupersparc,hypersparc,leon,leon3,leon5sparcliteโf930,f934,sparclite86xsparcletโtsc701v9โultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7,m8
By default (unless configured otherwise), GCC generates code for the V7 variant of SPARC ๐ธ. With -mcpu=cypress, it's also optimized for the Cypress CY7C602 chip, the one used in the SPARCStation/SPARCServer 3xx series. That's 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 code is that it emits the integer multiply and integer divide instructions that exist in SPARC-V8 but not SPARC-V7 โจ. With -mcpu=supersparc, it's additionally optimized 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, it's optimized for the Fujitsu MB86930 chip, the original SPARClite, which has no FPU ๐. With -mcpu=f934, it's optimized for the Fujitsu MB86934 chip, the more recent SPARClite that does have 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, it's optimized 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. -mcpu=ultrasparc optimizes for the Sun UltraSPARC I/II/IIi chips. -mcpu=ultrasparc3 optimizes for the Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips ๐ฅ. -mcpu=niagara optimizes for Sun UltraSPARC T1 chips, -mcpu=niagara2 for Sun UltraSPARC T2 chips, -mcpu=niagara3 for Sun UltraSPARC T3 chips, and -mcpu=niagara4 for Sun UltraSPARC T4 chips ๐. -mcpu=niagara7 optimizes for Oracle SPARC M7 chips, and -mcpu=m8 optimizes for Oracle M8 chips ๐
.
-mtune=cpu_typeโ Sets the instruction scheduling parameters forcpu_type, but NOT the instruction set or register set that-mcpu=cpu_typesets ๐. The same values work for-mtune=cpu_type, but only the ones that pick a particular CPU implementation are useful there:cypress,supersparc,hypersparc,leon,leon3,leon3v7,leon5,f930,f934,sparclite86x,tsc701,ultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7andm8๐ง . With native Solaris and GNU/Linux toolchains, you can also usenative๐ซถ.-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. It's enabled by default on Solaris in 32-bit mode for all SPARC-V9 processors ๐.-mvis,-mno-visโ With-mvis, GCC generates code that takes advantage of the UltraSPARC Visual Instruction Set extensions ๐ฆ. The default is-mno-vis๐ธ.-mvis2,-mno-vis2โ With-mvis2, GCC generates code that takes advantage of version 2.0 of the UltraSPARC Visual Instruction Set extensions ๐ฅ. The default is-mvis2when targeting a CPU that supports those instructions, such as UltraSPARC-III and later. Setting-mvis2also sets-mvis๐ซถ.-mvis3,-mno-vis3โ With-mvis3, GCC generates code that takes advantage of version 3.0 of the UltraSPARC Visual Instruction Set extensions ๐. The default is-mvis3when targeting a CPU that supports those instructions, such asniagara-3and later. Setting-mvis3also sets-mvis2and-mvis๐.-mvis4,-mno-vis4โ okay bestie,-mvis4tells GCC to write code that uses version 4.0 of the UltraSPARC Visual Instruction Set extensions ๐ฆ It's the default when you target a cpu that has them, likeniagara-7and later. Turning it on also flips on-mvis3,-mvis2and-mvis๐-mvis4b,-mno-vis4bโ-mvis4bis giving version 4.0 of the UltraSPARC VIS extensions plus the extra VIS instructions added in the Oracle SPARC Architecture 2017 โจ It's the default when targeting a cpu that supports them, likem8and later. Setting it also sets-mvis4,-mvis3,-mvis2and-mvis๐ฅ-mcbcond,-mno-cbcondโ-mcbcondlets GCC use the UltraSPARC Compare-and-Branch-on-Condition instructions ๐ธ It's the default when targeting a CPU that supports them, like Niagara-4 and later.-mfmaf,-mno-fmafโ-mfmafopens the door to the UltraSPARC Fused Multiply-Add Floating-point instructions ๐ง It's the default when targeting a CPU that supports them, like Niagara-3 and later.-mfsmuld,-mno-fsmuldโ-mfsmuldlets GCC use the Floating-point Multiply Single to Double (FsMULd) instruction ๐ It's the default when targeting a CPU supporting the architecture versions V8 or V9 with FPU, except-mcpu=leon.-mpopc,-mno-popcโ-mpopcis for the UltraSPARC Population Count instruction ๐ It's the default when targeting a CPU that supports it, like Niagara-2 and later.-msubxc,-mno-subxcโ-msubxcis the UltraSPARC Subtract-Extended-with-Carry instruction, and GCC will use it when you're aiming for it ๐ It's the default when targeting a CPU that supports it, like Niagara-7 and later.-mfix-at697fโ literal bodyguard energy ๐ก๏ธ Turns on the documented workaround for the single erratum of the Atmel AT697F processor (which corresponds to erratum #13 of the AT697E processor).-mfix-ut699โ turns on the documented workarounds for the floating-point errata and the data cache nullify errata of the UT699 processor ๐ซถ-mfix-ut700โ turns on the documented workaround for the back-to-back store errata of the UT699E/UT700 processor โญ-mfix-gr712rcโ turns on the documented workaround for the back-to-back store errata of the GR712RC processor ๐
These -m options are supported in addition to the above on SPARC-V9 processors in 64-bit environments, and they're giving main character energy ๐
-m32,-m64โ generate 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โ set the code model to one of these, bestie, pick your fighter ๐ฆmedlowโ The Medium/Low code model: 64-bit addresses, programs must be linked in the low 32 bits of memory. Programs can be statically or dynamically linked.medmidโ The Medium/Middle code model: 64-bit addresses, programs must be linked in the low 44 bits of memory, the text and data segments must be less than 2GB in size and the data segment must be located within 2GB of the text segment.medanyโ The Medium/Anywhere code model: 64-bit addresses, programs may be linked anywhere in memory, the text and data segments must be less than 2GB in size and the data segment must be located within 2GB of the text segment.embmedanyโ The Medium/Anywhere code model for embedded systems: 64-bit addresses, the text and data segments must be less than 2GB in size, both starting anywhere in memory (determined at link time). The global register%g4points to the base of the data segment. Programs are statically linked and PIC is not supported ๐ง
-mmemory-model=mem-modelโ set the memory model in force on the processor to one of these vibes ๐defaultโ The default memory model for the processor and operating system.rmoโ Relaxed Memory Orderpsoโ Partial Store Ordertsoโ Total Store Orderscโ Sequential Consistency
These memory models are formally defined in Appendix D of the SPARC-V9 architecture manual, as set in the processor's "PSTATE.MM" field ๐
-mstack-bias,-mno-stack-biasโ with-mstack-bias, GCC assumes the stack pointer, and frame pointer if present, are offset by-2047, which must be added back when making stack frame references ๐ This is the default in 64-bit mode. Otherwise, it assumes no such offset is present.
๐ Options for System V ๐
These additional options are available on System V Release 4 for compatibility with other compilers on those systems, so they're here for the group project energy ๐ซถ
-Gโ create a shared object. It is recommended that-symbolicor-sharedbe used instead ๐-Qyโ identify the versions of each tool used by the compiler, in a.identassembler directive in the output ๐ฅ-Qnโ refrain from adding.identdirectives to the output file (this is the default) ๐ธ-YP,dirsโ search the directoriesdirs, and no others, for libraries specified with-lโจ-Ym,dirโ look 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โ generate 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โ generate code for the large model. There is no limitation on call distance, pc-relative addresses, or absolute addresses ๐-mcpu=nameโ selects the type of CPU to be targeted. Currently the only supported type istilegx๐-m32,-m64โ generate code for a 32-bit or 64-bit environment. The 32-bit environment setsint,long, and pointer to 32 bits. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits ๐-mbig-endian,-mlittle-endianโ generate code in big/little endian mode, respectively ๐
๐ธ TILEPro Options ๐ธ
These -m options are supported on the TILEPro ๐
-mcpu=nameโ selects the type of CPU to be targeted. Currently the only supported type istilepro๐-m32โ generate 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, and this section is lowkey a lot ๐ญ
-mlong-calls,-mno-long-callsโ treat all calls as being far away (near). If calls are assumed to be far away, the compiler always loads the function's address into a register, and calls indirect through the pointer ๐ฆ-mno-ep,-mepโ do not optimize (do optimize) basic blocks that use the same index pointer 4 or more times to copy pointer into the"ep"register, and use the shorter"sld"and"sst"instructions. The-mepoption is on by default if you optimize โจ-mno-prolog-function,-mprolog-functionโ do not use (do use) external functions to save and restore registers at the prologue and epilogue of a function. The external functions are slower, but 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โ try to make the code as small as possible. At present, this just turns on the-mepand-mprolog-functionoptions ๐ซถ-mtda=nโ put static or global variables whose size isnbytes or less into the tiny data area that register"ep"points to. The tiny data area can hold up to 256 bytes in total (128 bytes for byte references) ๐-msda=nโ put static or global variables whose size isnbytes or less into the small data area that register"gp"points to. The small data area can hold up to 64 kilobytes ๐-mzda=nโ put static or global variables whose size isnbytes or less into the first 32 kilobytes of memory ๐ธ-mv850โ specify that the target processor is the V850 ๐-mv850e3v5โ specify that the target processor is the V850E3V5. The preprocessor constant"__v850e3v5__"is defined if this option is used ๐ฅ-mv850e2v4โ specify that the target processor is the V850E3V5. This is an alias for the-mv850e3v5option ๐-mv850e2v3โ specify that the target processor is the V850E2V3. The preprocessor constant"__v850e2v3__"is defined if this option is used ๐-mv850e2โ specify that the target processor is the V850E2. The preprocessor constant"__v850e2__"is defined if this option is used โญ-mv850e1โ specify that the target processor is the V850E1. The preprocessor constants"__v850e1__"and"__v850e__"are defined if this option is used ๐ฆ-mv850esโ specify that the target processor is the V850ES. This is an alias for the-mv850e1option ๐-mv850eโ specify that the target processor is the V850E. The preprocessor constant"__v850e__"is defined if this option is used ๐
If neither -mv850 nor -mv850e nor -mv850e1 nor -mv850e2 nor -mv850e2v3 nor -mv850e3v5 are defined, then a default target processor is chosen and the relevant __v850*__ preprocessor constant is defined ๐
The preprocessor constants "__v850" and "__v851__" are always defined, regardless of which processor variant is the target ๐ซถ
-mdisable-callt,-mno-disable-calltโ this option suppresses generation of the"CALLT"instruction for the v850e, v850e1, v850e2, v850e2v3 and v850e3v5 flavors of the v850 architecture ๐
This option is enabled by default when the RH850 ABI is in use (see -mrh850-abi), and disabled by default when the GCC ABI is in use. If "CALLT" instructions are being generated, then the C preprocessor symbol "__V850_CALLT__" is defined ๐
-mrelax,-mno-relaxโ pass on (or do not pass on) the-mrelaxcommand-line option to the assembler ๐ธ-mlong-jumps,-mno-long-jumpsโ disable (or re-enable) the generation of PC-relative jump instructions ๐-msoft-float,-mhard-floatโ Turn hardware floating point instruction generation off (or back on) ๐ . This only matters when the target is V850E2V3 or higher โจ. When hardware FP is being generated, the__FPU_OK__preprocessor symbol gets defined. Otherwise you get__NO_FPU__๐ธ.-mloopโ Lets you use the e3v5LOOPinstruction ๐. It's not on by default when e3v5 is selected, because it's still experimental ๐.-mrh850-abi,-mghsโ Turns on support for the RH850 version of the V850 ABI ๐. This is the default, and with it these rules apply:- Integer sized structures and unions come back through a memory pointer, not a register.
- Big structures and unions (more than 8 bytes) get passed by value.
- Functions are aligned to 16-bit boundaries.
-m8byte-alignis supported.-mdisable-calltis on by default.-mno-disable-calltis not supported, so don't even try ๐.
When this ABI is active, the __V850_RH850_ABI__ preprocessor symbol gets defined ๐.
-mgcc-abiโ Turns on support for the old GCC version of the V850 ABI ๐ฐ๏ธ. With this one:- Integer sized structures and unions get returned in register
r10. - Big structures and unions (more than 8 bytes) get passed by reference.
- Functions are aligned to 32-bit boundaries, unless you're optimizing for size.
-m8byte-alignis not supported.-mdisable-calltis supported, but not enabled by default.
- Integer sized structures and unions get returned in register
With this ABI on, the __V850_GCC_ABI__ preprocessor symbol is defined ๐ง.
-m8byte-align,-mno-8byte-alignโ Letsdoubleandlong longget aligned on 8-byte boundaries ๐. By default, everything gets capped at 4-byte alignment. When-m8byte-alignis in effect, the__V850_8BYTE_ALIGN__preprocessor symbol gets defined โจ.-mbig-switchโ Generates code that's suitable for big switch tables ๐. Only reach for this if the assembler or linker starts complaining about out of range branches inside a switch table ๐ญ.-mapp-regsโ Makesr2andr5get used in the generated code ๐ซถ. This is the default โจ.-mno-app-regsโ Makesr2andr5get treated as fixed registers ๐.
๐ฆ VAX Options ๐ฆ
These -m options are defined for the VAX ๐:
-munixโ Don't output certain jump instructions (likeaobleqand so on) that the Unix assembler for the VAX can't handle across long ranges ๐ โโ๏ธ.-mgnuโ Do output those jump instructions ๐, on the assumption that you're using the GNU assembler.-mgโ Output code for G-format floating-point numbers instead of D-format ๐ฅ.
๐ธ Visium Options ๐ธ
-mdebugโ If your program does file I/O and is headed for an MCM target, link it with this option ๐ฏ. That causes thelibc.aandlibdebug.alibraries to get linked. Run the program on the target under the control of the GDB remote debugging stub ๐ ๏ธ.-msimโ If your program does file I/O and is headed for the simulator, link it with the option ๐ฅ๏ธ. That causeslibc.aandlibsim.ato get linked.-mfpu,-mhard-floatโ Generate code with floating-point instructions ๐ . This is the default โจ.-mno-fpu,-msoft-floatโ Generate code that uses library calls for floating-point instead ๐.
-msoft-floatchanges the calling convention in the output file, so it's only useful if you compile your entire program with it ๐จ. You also need to compilelibgcc.a(the library that comes with GCC) with-msoft-floatfor this to work ๐ฌ.
-mcpu=cpu_typeโ Sets the instruction set, register set, and instruction scheduling parameters for the machine typecpu_type๐ค. The supported values aremcm,gr5andgr6๐.mcmis a synonym forgr5, kept around for backward compatibility ๐ฐ๏ธ.
By default (unless it was configured otherwise), GCC generates code for the GR5 variant of the Visium architecture ๐.
With -mcpu=gr6, GCC generates code for the GR6 variant. The only difference from GR5 code is that the compiler will generate block move instructions ๐.
-mtune=cpu_typeโ Sets the instruction scheduling parameters for the machine typecpu_type๐ต, but doesn't touch the instruction set or register set the way-mcpu=cpu_typewould.-msv-modeโ Generate code for supervisor mode, where there are no restrictions on access to general registers ๐. This is the default.-muser-modeโ Generate code for user mode, where access to some general registers is forbidden ๐. On the GR5, registersr24tor31can't be accessed in this mode. On the GR6, only registersr29tor31are affected.
๐ VMS Options ๐
These -m options are defined for the VMS implementations ๐ฆ:
-mvms-return-codesโ Return VMS condition codes frommain. The default is POSIX-style condition (like 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 ๐. The possible values forsizeare32orshortfor 32-bit pointers,64orlongfor 64-bit pointers, andnofor supporting only 32-bit pointers ๐ซ . That last 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__RTP__preprocessor macro ๐.-non-staticโ Links an RTP executable against shared libraries instead of static libraries ๐ฆ. The options-staticand-sharedcan also be used for RTPs, and-staticis the default ๐ซถ.-Bstatic,-Bdynamicโ These get passed down to the linker ๐. They're there for compatibility with Diab ๐.-Xbind-lazyโ Enables lazy binding of function calls ๐ด. This is equivalent to-Wl,-z,nowand is there for compatibility with Diab ๐ธ.-Xbind-nowโ Disables lazy binding of function calls โก. This is the default, and it's there for compatibility with Diab ๐ .
๐ x86 Options ๐
These -m options are defined for the x86 family of computers ๐ป.
-march=cpu-typeโ Generates instructions for the machine typecpu-type๐. Unlike-mtune=cpu-type, which only tunes the generated code for the specifiedcpu-type,-march=cpu-typelets GCC generate code that may not run at all on processors other than the one you picked ๐ญ. Specifying-march=cpu-typeimplies-mtune=cpu-type, except where noted otherwise โจ.
The choices for cpu-type are:
nativeโ Picks the CPU to generate code for at compile time by detecting the processor type of the compiling machine ๐. Using-march=nativeenables all instruction subsets the local machine supports, so the result might not run on different machines ๐. Using-mtune=nativeproduces code optimized for the local machine, within the limits of the chosen instruction set ๐ฏ.x86-64โ A generic CPU with 64-bit extensions ๐.x86-64-v2,x86-64-v3,x86-64-v4โ These pick the matching micro-architecture level from the x86-64 psABI ๐ฆ. On ABIs other than the x86-64 psABI, they select the same CPU features the x86-64 psABI documents for that micro-architecture level ๐.
Since these cpu-type values don't have a matching -mtune setting, using -march with them enables generic tuning ๐ต. If you want specific tuning, use -mtune=other-cpu-type with an appropriate other-cpu-type value ๐ซถ.
i386โ The original Intel i386 CPU ๐ฆ.i486โ The Intel i486 CPU ๐. (No scheduling is implemented for this chip ๐.)i586,pentiumโ Intel Pentium CPU with no MMX support ๐ง.lakemontโ Intel Lakemont MCU, based on the Intel Pentium CPU ๐งฉ.pentium-mmxโ Intel Pentium MMX CPU, based on the Pentium core with MMX instruction set support ๐น.pentiumproโ Intel Pentium Pro CPU ๐.i686โ With-march, the Pentium Pro instruction set gets used, so the code runs on all i686 family chips ๐. With-mtune, it means the same thing asgenericโจ.pentium2โ Intel Pentium II CPU, based on the Pentium Pro core with MMX instruction set support ๐.pentium3,pentium3mโ Intel Pentium III CPU, based on the Pentium Pro core with MMX and SSE instruction set support ๐.pentium-mโ Intel Pentium M, a low-power version of the Intel Pentium III CPU with MMX, SSE and SSE2 instruction set support ๐ป. It's used by Centrino notebooks ๐.pentium4,pentium4mโ Intel Pentium 4 CPU with MMX, SSE and SSE2 instruction set support ๐ฅ.prescottโ An improved version of the Intel Pentium 4 CPU with MMX, SSE, SSE2 and SSE3 instruction set support ๐ธ.noconaโ An improved version of the Intel Pentium 4 CPU with 64-bit extensions, MMX, SSE, SSE2 and SSE3 instruction set support ๐ง.core2โ Intel Core 2 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support โ.nehalemโ Intel Nehalem CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and POPCNT instruction set support ๐.westmereโ Intel Westmere CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES and PCLMUL instruction set support ๐โจ.
sandybridge๐ โ Intel Sandy Bridge CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AES and PCLMUL instruction set support.ivybridgeโจ โ Intel Ivy Bridge CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AES, PCLMUL, FSGSBASE, RDRND and F16C instruction set support.haswell๐ โ Intel Haswell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2 and F16C instruction set support.broadwell๐ฆ โ Intel Broadwell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX and PREFETCHW instruction set support.skylake๐ธ โ Intel Skylake CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC and XSAVES instruction set support.bonnell๐ง โ Intel Bonnell CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support.silvermont๐ โ Intel Silvermont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL and RDRND instruction set support.goldmont๐ โ Intel Goldmont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT and FSGSBASE instruction set support.goldmont-plus๐ฅ โ Intel Goldmont Plus CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX and UMIP instruction set support.tremont๐ โ Intel Tremont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AES, PREFETCHW, PCLMUL, RDRND, XSAVE, XSAVEC, XSAVES, XSAVEOPT, FSGSBASE, PTWRITE, RDPID, SGX, UMIP, GFNI-SSE, CLWB, MOVDIRI, MOVDIR64B, CLDEMOTE and WAITPKG instruction set support.knl๐ โ Intel Knight's Landing CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, PREFETCHWT1, AVX512F, AVX512PF, AVX512ER and AVX512CD instruction set support.knmโญ โ Intel Knights Mill CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, PREFETCHWT1, AVX512F, AVX512PF, AVX512ER, AVX512CD, AVX5124VNNIW, AVX5124FMAPS and AVX512VPOPCNTDQ instruction set support.skylake-avx512๐ โ Intel Skylake Server CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ and AVX512CD instruction set support.cannonlake๐ซถ โ Intel Cannonlake Server CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA and UMIP instruction set support.icelake-client๐ธ โ Intel Icelake Client CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ 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.cooperlake๐ โ Intel cooperlake CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, CLWB, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VNNI and AVX512BF16 instruction set support.tigerlake๐ฏ โ Intel Tigerlake CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, POPCNT, PKU, AVX, AVX2, AES, PCLMUL, FSGSBASE, RDRND, FMA, BMI, BMI2, F16C, RDSEED, ADCX, PREFETCHW, CLFLUSHOPT, XSAVEC, XSAVES, AVX512F, AVX512VL, AVX512BW, AVX512DQ, AVX512CD, AVX512VBMI, AVX512IFMA, SHA, CLWB, UMIP, RDPID, GFNI, AVX512VBMI2, AVX512VPOPCNTDQ, AVX512BITALG, AVX512VNNI, VPCLMULQDQ, VAES, PCONFIG, WBNOINVD, MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT and KEYLOCKER instruction set support.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, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)bdver2๐ โ AMD Family 15h core based CPUs with x86-64 instruction set support. (This supersets BMI, TBM, F16C, FMA, FMA4, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)bdver3๐ฆ โ AMD Family 15h core based CPUs with x86-64 instruction set support. (This supersets BMI, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)bdver4๐ธ โ AMD Family 15h core based CPUs with x86-64 instruction set support. (This supersets BMI, BMI2, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, AVX2, XOP, LWP, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)znver1โจ โ AMD Family 17h core based CPUs with x86-64 instruction set support. (This supersets BMI, BMI2, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, and 64-bit instruction set extensions.)znver2๐ซถ โ AMD Family 17h core based CPUs with x86-64 instruction set support. (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, and 64-bit instruction set extensions.)znver3๐ โ AMD Family 19h core based CPUs with x86-64 instruction set support. (This supersets BMI, BMI2, CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, RDPID, WBNOINVD, PKU, VPCLMULQDQ, VAES, and 64-bit instruction set extensions.)btver1๐ โ CPUs based on AMD Family 14h cores with x86-64 instruction set support. (This supersets MMX, SSE, SSE2, SSE3, SSSE3, SSE4A, CX16, ABM and 64-bit instruction set extensions.)btver2๐ โ CPUs based on AMD Family 16h cores with x86-64 instruction set support. This includes MOVBE, F16C, BMI, AVX, PCLMUL, AES, SSE4.2, SSE4.1, CX16, ABM, SSE4A, SSSE3, SSE3, SSE2, SSE, MMX and 64-bit instruction set extensions.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โ the VIA C3 CPU ๐, with MMX and 3DNow! instruction set support. (No scheduling is implemented for this chip ๐.)c3-2โ the VIA C3-2 ๐ธ, also called Nehemiah/C5XL, with MMX and SSE instruction set support. (No scheduling is implemented for this chip.)c7โ the VIA C7 ๐ , also called Esther, with MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.)samuel-2โ the VIA Eden Samuel 2 ๐ฆ, with MMX and 3DNow! instruction set support. (No scheduling is implemented for this chip.)nehemiahโ the VIA Eden Nehemiah ๐, with MMX and SSE instruction set support. (No scheduling is implemented for this chip.)estherโ the VIA Eden Esther ๐ง, with MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.)eden-x2โ the VIA Eden X2 ๐, with x86-64, MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.)eden-x4โ the VIA Eden X4 ๐, with x86-64, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and AVX2 instruction set support. (No scheduling is implemented for this chip.)nanoโ the generic VIA Nano โญ, with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-1000โ the VIA Nano 1xxx ๐, with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-2000โ the VIA Nano 2xxx ๐, with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-3000โ the VIA Nano 3xxx โจ, with 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 ๐ฆ, with 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 ๐ฅ, with 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 ๐ง, with MMX and 3DNow! instruction set support.-mtune=cpu-typeโ okay so this one is lowkey iconic ๐ . It tunes everything applicable in the generated code tocpu-type, except for the ABI and the set of available instructions. Picking a specificcpu-typeschedules 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 use a-march=cpu-typeoption. For example, if GCC is configured fori686-pc-linux-gnu, then-mtune=pentium4generates code tuned for Pentium 4 that still runs on i686 machines ๐ซถ.- The choices for
cpu-typeare the same as for-march. On top of that,-mtunegives you 2 extra choices forcpu-typeโจ: genericโ code optimized for the most common IA32/AMD64/EM64T processors ๐ธ. If you know which 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 use.- As new processors get deployed in the marketplace, the behavior of this option will change. So if you upgrade to a newer GCC, the code generation controlled by this option will shift to reflect whichever processors are most common when that GCC version is released.
- There is no
-march=genericoption, because-marchindicates the instruction set the compiler can use, and there's no generic instruction set that applies to all processors.-mtuneis different: it indicates the processor (or, in this case, the collection of processors) the code is optimized for.
intelโ code optimized for the most current Intel processors, which for this version of GCC are Haswell and Silvermont ๐ง. If you know your CPU, use the corresponding-mtuneor-marchoption instead of-mtune=intel. But if you want your application to perform better on both Haswell and Silvermont, this is the move ๐.- As new Intel processors get deployed in the marketplace, the behavior of this option will change. So if you upgrade to a newer GCC, the code generation controlled by this option will reflect the most current Intel processors at the time that version of GCC is released.
- There is no
-march=inteloption, because-marchindicates the instruction set the compiler can use, and there's no common instruction set that applies to all processors.-mtuneindicates the processor (or collection of processors) the code is optimized for.
- The choices for
-mcpu=cpu-typeโ an old nickname for-mtune. It's deprecated, so please don't reach for it ๐.-mfpmath=unitโ generate floating-point arithmetic for the selectedunit. The choices forunitare ๐งฎ:387โ use the standard 387 floating-point coprocessor that's on most chips, and emulate it 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 your results may differ slightly from most other chips. See-ffloat-storefor a more detailed description.- This is the default choice for non-Darwin x86-32 targets.
sseโ use the scalar floating-point instructions in the SSE instruction set ๐ฅ. This is supported by Pentium III and newer chips, and in the AMD line by Athlon-4, Athlon XP and Athlon MP chips. The earlier version of SSE only supports single-precision arithmetic, so double and extended-precision still get done using 387. A later version, only in Pentium 4 and AMD x86-64 chips, supports double-precision too.- For the x86-32 compiler, you must use
-march=cpu-type,-msseor-msse2to enable the 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. Heads up though: 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 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 amount of available registers, and on chips with separate execution units for 387 and SSE, the execution resources too ๐ฆ. Use this with care! It's still experimental, because the GCC register allocator doesn't model separate functional units well, which can lead to unstable performance.
-masm=dialectโ output assembly instructions using the selected dialect ๐. This also affects which dialect is used for basicasmand extendedasm. The supported choices (in dialect order) areattorintel. The default isatt. Darwin does not supportintel.-mieee-fp,-mno-ieee-fpโ 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,-mhard-floatโ generate output containing 80387 instructions for floating point ๐.-mno-80387,-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 cannot be done directly in cross-compilation. You must make your own arrangements to provide suitable library functions for cross-compilation.
Also, 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 function return values ๐.- The usual calling convention has functions return
floatanddoublevalues in an FPU register, even if there's no FPU. The idea is that the operating system should emulate an FPU. - The option
-mno-fp-ret-in-387causes those values to be returned in ordinary CPU registers instead.
- The usual calling convention has functions return
-mno-fancy-math-387โ some 387 emulators don't support thesin,cosandsqrtinstructions for the 387 ๐ธ. Specify this option to avoid generating those instructions. It gets overridden when-marchsays the target CPU always has an FPU, because then the instruction doesn't need emulating. These instructions aren't generated unless you also use the-funsafe-math-optimizationsswitch.-malign-double,-mno-align-doubleโ control whether GCC alignsdouble,long double, andlong longvariables on a two-word boundary or a one-word boundary ๐. Aligningdoublevariables on a two-word boundary produces code that runs somewhat faster on a Pentium, at the expense of more memory.- On x86-64,
-malign-doubleis enabled by default.
- On x86-64,
Warning: if you use the -malign-double switch, structures containing the above types are aligned differently than the published application binary interface specifications for x86-32, and they are NOT binary compatible with structures in code compiled without that switch ๐.
-m96bit-long-double,-m128bit-long-doubleโ these switches control the size of thelong doubletype โจ. The x86-32 application binary interface specifies the size to be 96 bits, so-m96bit-long-doubleis the default in 32-bit mode.
Okay so modern chips (Pentium and newer) really, really want long double lined up on an 8- or 16-byte boundary ๐ซถ But in arrays and structs that follow the ABI, that's just not possible ๐ญ So -m128bit-long-double pads the long double with an extra 32-bit zero to push it onto a 16-byte boundary โจ
On the x86-64 compiler, -m128bit-long-double is already the default, because its ABI says long double gets aligned on a 16-byte boundary ๐
Notice that neither of these options unlocks any extra precision over the x87 standard of 80 bits for a long double ๐
Warning: bestie, if you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables. It also changes the function calling convention for functions takinglong double. Hence they are not binary-compatible with code compiled without that switch ๐
-mlong-double-64โ giveslong doublea 64-bit size, making it equivalent todouble๐ธ This is the default for the 32-bit Bionic C library.-mlong-double-80โ one of the three size switches forlong double, the 80-bit one ๐ง-mlong-double-128โ giveslong doublea 128-bit size, making it equivalent to__float128๐ This is the default for the 64-bit Bionic C library.
Warning: same energy as before, bestie. Overriding the default value for your target ABI changes the size of structures and arrays containinglong doublevariables, and it also modifies the function calling convention for functions takinglong double. Hence they are not binary-compatible with code compiled without that switch ๐
-malign-data=typeโ controls how GCC aligns variables ๐ The supported values fortypearecompat, which uses an increased alignment value that's compatible with GCC 4.8 and earlier;abi, which uses the alignment value specified by the psABI; andcacheline, which uses an increased alignment value to match the cache line size.compatis the default, so no stress ๐-mlarge-data-threshold=thresholdโ when-mcmodel=mediumis specified, data objects larger thanthresholdget placed in the large data section ๐ฆ This value must be the same across all objects linked into the binary, and it defaults to65535.-mrtdโ switches to a different function-calling convention, where functions that take a fixed number of arguments return with theret numinstruction, which pops their arguments while returning โจ This saves one instruction in the caller, since there's no need to pop the arguments there.
You can give a single function this calling sequence with the function attribute stdcall. You can also override -mrtd for one 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. In addition, seriously incorrect code results if you call a function with too many arguments. (Normally, extra arguments are harmlessly ignored.) ๐
-mregparm=numโ controls how many registers get used to pass integer arguments ๐ง By default, no registers are used 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, then you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules ๐จ
-msseregparmโ uses SSE register passing conventions forfloatanddoublearguments and return values ๐ฅ You can control this for a specific function with the function attributesseregparm.
Warning: if you use this switch, you must build all modules with the same value, including any libraries. That includes the system libraries and startup modules ๐ซ
-mvect8-ret-in-memโ returns 8-byte vectors in memory instead of MMX registers ๐ This is the default on VxWorks, to match the ABI of the Sun Studio compilers until version 12. Only use this option if you need to stay compatible with existing code made by those older compiler versions or older versions of GCC.-mpc32โ sets 80387 floating-point precision to 32 bits ๐ The significands of floating-point operation results get rounded to 24 bits (single precision).-mpc64โ sets 80387 floating-point precision to 64 bits ๐ The significands get rounded to 53 bits (double precision).-mpc80โ sets 80387 floating-point precision to 80 bits ๐ The significands get rounded to 64 bits (extended double precision), and this is the default.
When -mpc32 (or -mpc64, or -mpc80) is used, floating-point operations in higher precisions aren't available to the programmer unless you set the FPU control word explicitly ๐ค
Setting the rounding of floating-point operations to less than the default 80 bits can speed some programs up by 2% or more ๐โโ๏ธ But some math libraries assume extended-precision (80-bit) floating-point operations are on by default. Routines in those libraries could suffer serious accuracy loss, usually through so-called "catastrophic cancellation", if you use this option to drop the precision below extended precision ๐ญ
-mstackrealignโ realigns the stack at entry ๐ช On x86,-mstackrealigngenerates an alternate prologue and epilogue that realigns the run-time stack if necessary. This lets legacy code that keeps 4-byte stack alignment mix with modern code that keeps 16-byte stack alignment for SSE compatibility. See also the attributeforce_align_arg_pointer, which applies to individual functions.-mpreferred-stack-boundary=numโ tries to keep the stack boundary aligned to a 2 raised tonumbyte boundary ๐ If-mpreferred-stack-boundaryisn't specified, the default is4(16 bytes or 128 bits).
Warning: when generating code for the x86-64 architecture with SSE extensions disabled,-mpreferred-stack-boundary=3can keep the stack boundary aligned to an 8-byte boundary. The x86-64 ABI requires 16-byte stack alignment, so this is ABI incompatible and only meant for a controlled environment where stack space is a seriously limited resource ๐งธ This option leads to wrong code when functions compiled with 16-byte stack alignment (like functions from a standard library) get called with a misaligned stack. In that case, SSE instructions may cause misaligned memory access traps. Variable arguments are also handled incorrectly for 16-byte aligned objects (including x87long doubleand__int128), which leads to wrong results. You must build all modules with-mpreferred-stack-boundary=3, including any libraries. That includes the system libraries and startup modules ๐
-mincoming-stack-boundary=numโ assumes the incoming stack is aligned to a 2 raised tonumbyte boundary ๐ฆ If-mincoming-stack-boundaryisn't specified, the one set 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 you'll take significant run-time performance penalties ๐ข On Pentium III, the Streaming SIMD Extension (SSE) data type __m128 may not work properly if it isn't 16-byte aligned.
To keep values properly aligned on the stack, the stack boundary has to be as aligned as the strictest value stored on the stack. 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 using callbacks always use the default setting.
This extra alignment does eat up extra stack space and generally increases code size. Code that is sensitive to stack space usage, like embedded systems and operating system kernels, may want to reduce the preferred alignment to -mpreferred-stack-boundary=2 ๐ธ
These next switches are the ISA extension party ๐ Each one turns on its matching instruction set, and each has a corresponding -mno- option to disable it again. These extensions are also available as built-in functions: see x86 Built-in Functions for details of the functions enabled and disabled by these switches ๐
-mmmxโ enables the MMX instructions ๐-msseโ enables the SSE instructions ๐-msse2โ enables the SSE2 instructions ๐-msse3โ enables the SSE3 instructions ๐-mssse3โ enables the SSSE3 instructions ๐-msse4โ enables the SSE4 instructions ๐-msse4aโ enables the SSE4A instructions ๐-msse4.1โ enables the SSE4.1 instructions ๐-msse4.2โ enables the SSE4.2 instructions ๐-mavxโ enables the AVX instructions ๐ฆ-mavx2โ enables the AVX2 instructions ๐ฆ-mavx512fโ enables the AVX512F instructions ๐ฆ-mavx512pfโ enables the AVX512PF instructions ๐ฆ-mavx512erโ enables the AVX512ER instructions ๐ฆ-mavx512cdโ enables the AVX512CD instructions ๐ฆ-mavx512vlโ enables the AVX512VL instructions ๐ฆ-mavx512bwโ enables the AVX512BW instructions ๐ฆ-mavx512dqโ enables the AVX512DQ instructions ๐ฆ-mavx512ifmaโ enables the AVX512IFMA instructions ๐ฆ-mavx512vbmiโ enables the AVX512VBMI instructions ๐ฆ-mshaโ enables the SHA instructions ๐-maesโ enables the AES instructions ๐-mpclmulโ enables the PCLMUL instructions ๐-mclflushoptโ enables the CLFLUSHOPT instructions ๐งน-mclwbโ enables the CLWB instructions ๐งน-mfsgsbaseโ enables the FSGSBASE instructions ๐-mptwriteโ enables the PTWRITE instructions โ๏ธ-mrdrndโ enables the RDRND instructions ๐ฒ-mf16cโ enables the F16C instructions ๐ฅ-mfmaโ enables the FMA instructions ๐ฅ-mpconfigโ enables the PCONFIG instructions โญ-mwbnoinvdโ enables the WBNOINVD instructions โญ-mfma4โ enables the FMA4 instructions ๐ฅ-mprfchwโ enables the PREFETCHW instructions ๐โโ๏ธ-mrdpidโ enables the RDPID instructions ๐ชช-mprefetchwt1โ enables the PREFETCHWT1 instructions ๐โโ๏ธ-mrdseedโ enables the RDSEED instructions ๐ฒ-msgxโ enables the SGX instructions ๐ฐ-mxopโ enables the XOP instructions ๐ง-mlwpโ enables the LWP instructions ๐ง-m3dnowโ enables the 3DNow! instructions ๐น๏ธ-m3dnowaโ enables the enhanced 3DNow! instructions ๐น๏ธ-mpopcntโ enables the POPCNT instructions ๐ฟ-mabmโ enables the ABM instructions ๐งฎ-madxโ enables the ADX instructions ๐งฎ-mbmiโ enables the BMI instructions ๐งฎ-mbmi2โ enables the BMI2 instructions ๐งฎ-mlzcntโ enables the LZCNT instructions ๐งฎ-mfxsrโ enables the FXSR instructions ๐พ-mxsaveโ enables the XSAVE instructions ๐พ-mxsaveoptโ enables the XSAVEOPT instructions ๐พ-mxsavecโ enables the XSAVEC instructions ๐พ-mxsavesโ enables the XSAVES instructions ๐พ-mrtmโ enables the RTM instructions ๐งต-mhleโ enables the HLE instructions ๐งต-mtbmโ enables the TBM instructions ๐งฎ-mmwaitxโ enables the MWAITX instructions โณ-mclzeroโ enables the CLZERO instructions ๐งฝ-mpkuโ enables the PKU instructions ๐-mavx512vbmi2โ enables the AVX512VBMI2 instructions ๐ฆ-mavx512bf16โ enables the AVX512BF16 instructions ๐ฆ-mgfniโ enables the GFNI instructions ๐ธ-mvaesโ enables the VAES instructions ๐-mwaitpkgโ enables the WAITPKG instructions โณ-mvpclmulqdqโ enables the VPCLMULQDQ instructions ๐-mavx512bitalgโ enables the AVX512BITALG instructions ๐ฆ-mmovdiriโ enables the MOVDIRI instructions ๐-mmovdir64bโ enables the MOVDIR64B instructions ๐-menqcmdโ enables the ENQCMD instructions ๐-mavx512vpopcntdqโ enables the AVX512VPOPCNTDQ instructions ๐ฆ-mavx512vp2intersectโ enables the AVX512VP2INTERSECT instructions ๐ฆ-mavx5124fmapsโ enables the AVX5124FMAPS instructions ๐ฆ-mavx512vnniโ enables the AVX512VNNI instructions ๐ฆ-mavx5124vnniwโ enables the AVX5124VNNIW instructions ๐ฆ-mcldemoteโ enables the CLDEMOTE instructions ๐งน
To generate SSE/SSE2 instructions automatically from floating-point code (instead of 387 instructions), bestie, check out -mfpmath=sse. ๐
โจ
โ ๏ธ Heads up: when -mavx is on, GCC kinda benches the SSEx instructions ๐ญ It swaps in brand new AVX instructions, or AVX equivalents for all the SSEx ones, whenever it needs them. Major glow-up energy ๐ฆ
These options let GCC use those extended instructions in the generated code, even without -mfpmath=sse. ๐ธ If your app does run-time CPU detection, you have to compile separate files for each supported architecture, using the right flags for each one. Lowkey the file with the CPU detection code should be compiled without these options. This is the step people always mess up, so pls be careful ๐ซถ
-mdump-tune-featuresโ tells GCC to dump the names of the x86 performance tuning features and their default settings. You can use those names in-mtune-ctrl=feature-list. ๐ง-mtune-ctrl=feature-listโ fine-grain control over x86 code generation features ๐feature-listis a comma-separated list of feature names (see also-mdump-tune-features). A feature gets turned on if it's not preceded by^, and turned off if it is. This one is really meant for GCC developers, so proceed with care ๐
โ ๏ธ Using -mtune-ctrl=feature-list may lead to code paths that aren't covered by testing, and it can potentially result in compiler ICEs or runtime errors. Not the vibe if you're not ready for that ๐ญ
-mno-defaultโ turns off all tunable features. See also-mtune-ctrl=feature-listand-mdump-tune-features. ๐-mcldโ makes GCC emit acldinstruction in the prologue of functions that use string instructions. Here's the tea โ String instructions depend on the DF flag to pick between autoincrement and autodecrement mode. The ABI says DF should be cleared on function entry, but some operating systems don't clear it in their exception dispatchers ๐ So the exception handler can run with DF set, which gives you the wrong direction mode when string instructions are used. This can be enabled by default on 32-bit x86 targets by configuring GCC with the--enable-cldconfigure option. In that case, you can suppress generation ofcldinstructions with the-mno-cldcompiler option.-mvzeroupperโ makes GCC emit avzeroupperinstruction before control flow leaves the function. This minimizes the AVX to SSE transition penalty and removes unnecessaryzeroupperintrinsics. Clean girl energy ๐งผโจ-mprefer-avx128โ tells GCC to use 128-bit AVX instructions instead of 256-bit AVX instructions in the auto-vectorizer ๐-mprefer-vector-width=optโ tells GCC to use opt-bit vector width in instructions, instead of the default for the selected platform. ๐ฆnoneโ no extra limitations are applied to GCC beyond what the selected platform 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 generateCMPXCHG16Binstructions in 64-bit code to implement compare-and-exchange operations on 16-byte aligned 128-bit objects. This is super useful for atomic updates of data structures bigger than one machine word ๐ The compiler uses this instruction to implement__syncBuiltins. However, for__atomicBuiltins operating on 128-bit integers, a library call is always used.-msahfโ enables generation ofSAHFinstructions in 64-bit code. Okay so, early Intel Pentium 4 CPUs with Intel 64 support (before the Pentium 4 G1 step in December 2005) didn't have theLAHFandSAHFinstructions that AMD64 supports ๐ These are load and store instructions, respectively, for certain status flags. In 64-bit mode, theSAHFinstruction is used to optimize thefmod,drem, andremainderbuilt-in functions; see Other Builtins for details.-mmovbeโ enables use of themovbeinstruction to implement__builtin_bswap32and__builtin_bswap64. โญ-mshstkโ enables shadow stack built-in functions from x86 Control-flow Enforcement Technology (CET). ๐ฅ-mcrc32โ enables the built-in functions__builtin_ia32_crc32qi,__builtin_ia32_crc32hi,__builtin_ia32_crc32siand__builtin_ia32_crc32dito generate thecrc32machine instruction. ๐-mrecipโ enables use ofRCPSSandRSQRTSSinstructions (and their vectorized variantsRCPPSandRSQRTPS) with an extra Newton-Raphson step for better precision. They're used instead ofDIVSSandSQRTSS(and their vectorized variants) for single-precision floating-point arguments. These instructions are generated only 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 non-reciprocal instruction, the precision can drop by up to 2 ulp (i.e. the inverse of 1.0 equals0.99999994). ๐ฅฒ
Also, GCC implements 1.0f/sqrtf(x) in terms of RSQRTSS (or RSQRTPS) already with -ffast-math (or the option combination above), so you don't need -mrecip for that โจ
And GCC emits the sequence with the additional Newton-Raphson step for vectorized single-float division and vectorized sqrtf(x) already with -ffast-math (or the option combination above), so again, no -mrecip needed ๐
-mrecip=optโ controls which reciprocal estimate instructions may be used. opt is a comma-separated list of options, and any of them can be preceded by a!to invert it ๐งallโ enable all estimate instructions.defaultโ enable the default instructions, equivalent to-mrecip.noneโ disable all estimate instructions, equivalent to-mno-recip.divโ enable the approximation for scalar division.vec-divโ enable the approximation for vectorized division.sqrtโ enable the approximation for scalar square root.vec-sqrtโ enable the approximation for vectorized square root.
So, for example, -mrecip=all,!sqrt enables all of the reciprocal approximations except for square root. Main character decision ๐
-mveclibabi=typeโ specifies the ABI type to use when vectorizing intrinsics with an external library. Supported values for type aresvmlfor the Intel short vector math library andacmlfor the AMD math core library. To use this option, you need both-ftree-vectorizeand-funsafe-math-optimizationsenabled, plus an SVML or ACML ABI-compatible library specified at link time ๐ซถ
GCC currently emits calls to these functions for -mveclibabi=svml:
"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"
and these for the corresponding function type when -mveclibabi=acml is used:
"__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"
-mabi=nameโ generates code for the specified calling convention. Permissible values aresysv(the ABI used on GNU/Linux and other systems) andms(the Microsoft ABI). The default is the Microsoft ABI when targeting Microsoft Windows, and the SysV ABI on all other systems. You can control this for specific functions with the function attributesms_abiandsysv_abi๐-mforce-indirect-callโ forces all function calls to be indirect. This is handy with Intel Processor Trace, since it gives more precise timing information for function calls ๐-mmanual-endbrโ inserts an ENDBR instruction at function entry only via thecf_checkfunction attribute. This is useful with-fcf-protection=branchto control ENDBR insertion at function entry ๐ง-mcall-ms2sysv-xloguesโ because of differences in 64-bit ABIs, any Microsoft ABI function that calls a System V ABI function has to treat RSI, RDI and XMM6-15 as clobbered ๐ญ By default, the code that saves and restores these registers is emitted inline, which makes 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 can't be satisfied on all systems โ ๏ธ-mpush-args,-mno-push-argsโ uses PUSH operations to store outgoing parameters. This method is shorter and usually just as fast as the SUB/MOV method, and it's enabled by default. In some cases, disabling it may improve performance because of better scheduling and fewer dependencies ๐-maccumulate-outgoing-argsโ if enabled, the maximum amount of space needed for outgoing arguments is computed in the function prologue. This is faster on most modern CPUs thanks to fewer dependencies, better scheduling, and reduced stack usage when the preferred stack boundary isn't equal to 2. The drawback? 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-mthreads. When compiling,-mthreadsdefines-D_MT. When linking, it pulls in a special thread helper library,-lmingwthrd, which cleans up per-thread exception-handling data ๐งต-mms-bitfields,-mno-ms-bitfieldsโ enables or disables bit-field layout that's compatible with the native Microsoft Windows compiler ๐ฆ
Okay so, if "packed" is used on a structure or bit-fields show up, the Microsoft ABI might lay that structure out differently than GCC normally does ๐ญ. This gets extra messy when you're passing packed data between GCC-compiled functions and the native Microsoft compiler, whether through a function call or as data in a file. You might need to access either format ๐ซถ.
This option is enabled by default for Microsoft Windows targets ๐ธ. You can also control it locally with variable or type attributes โจ. For more info, check out x86 Variable Attributes and x86 Type Attributes ๐ฆ.
The Microsoft structure layout algorithm is pretty simple, except for bit-field packing ๐ . The padding and alignment of structure members, and whether a bit-field can straddle a storage-unit boundary, are determined by these rules:
- Structure members are stored sequentially, in the order they're declared. The first member has the lowest memory address and the last member has the highest ๐.
- Every data object has an alignment requirement. For all data except structures, unions, and arrays, that requirement is either the size of the object or the current packing size (set with the
"aligned"attribute or the"pack"pragma), whichever is less. For structures, unions, and arrays, the alignment requirement is the largest alignment requirement of any of their members. Every object gets an offset so that:
offset % alignment_requirement == 0
- Adjacent bit-fields get packed into the same 1-, 2-, or 4-byte allocation unit if their integral types are the same size, and if the next bit-field fits into the current allocation unit without crossing the boundary set by the common alignment requirements of the bit-fields ๐ฅ.
MSVC interprets zero-length bit-fields in these ways, and it's lowkey wild ๐:
- If a zero-length bit-field is inserted between two bit-fields that would normally be coalesced, the bit-fields are not coalesced ๐.
For example:
struct
{
unsigned long bf_1 : 12;
unsigned long : 0;
unsigned long bf_2 : 12;
} t1;
The size of t1 is 8 bytes with the zero-length bit-field. If you removed the zero-length bit-field, t1's size would be 4 bytes ๐.
- If a zero-length bit-field is inserted after a bit-field called
foo, and the alignment of the zero-length bit-field is greater than that of the member that follows it,bar, thenbargets aligned as the type of the zero-length bit-field ๐ง.
For example:
struct
{
char foo : 4;
short : 0;
char bar;
} t2;
struct
{
char foo : 4;
short : 0;
double bar;
} t3;
For t2, bar is placed at offset 2 instead of offset 1, so the size of t2 is 4. For t3, the zero-length bit-field doesn't affect the alignment of bar or, as a result, the size of the structure ๐ฆ.
Taking this into account, it's important to note the following:
- If a zero-length bit-field follows a normal bit-field, the type of the zero-length bit-field can affect the alignment of the structure as a whole. For example,
t2has a size of 4 bytes, since the zero-length bit-field follows a normal bit-field and is of typeshortโจ. - Even if a zero-length bit-field isn't followed by a normal bit-field, it can still affect the alignment of the structure:
struct
{
char foo : 6;
long : 0;
} t4;
Here, t4 takes up 4 bytes ๐.
- Zero-length bit-fields that follow non-bit-field members are ignored:
struct
{
char foo;
long : 0;
char bar;
} t5;
Here, t5 takes up 2 bytes ๐.
-mno-align-stringopsโ Skip aligning the destination of inlined string operations. This makes the code smaller and can be faster if 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 option inlines more, which bumps up code size but can speed up code that relies on quickmemcpyandmemsetfor short lengths ๐ฅ. It also turns on inline expansion ofstrlenfor all pointer alignments ๐ .-minline-stringops-dynamicallyโ For string operations of unknown size, use run-time checks. Small blocks get inline code, and large blocks get a library call ๐ง.-mstringop-strategy=algโ Override GCC's internal heuristic for picking which algorithm to inline string operations with. The allowed values foralgare: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 heuristic that decides whether__builtin_memcpygets inlined, and which inline algorithm to use, when the expected size of the copy is known ๐. Thestrategyis a comma-separated list ofalg:max_size:dest_aligntriplets.algis one of the values from-mstringop-strategy, andmax_sizeis the max byte size thatalgis allowed to handle. The last triplet must have amax_sizeof-1. Themax_sizevalues in the list have to be in increasing order. The minimum byte size foralgis 0 for the first triplet, andmax_size + 1of the preceding range for every other triplet ๐.-mmemset-strategy=strategyโ Same vibe as-mmemcpy-strategy=, except this one controls__builtin_memsetexpansion ๐ซถ.-momit-leaf-frame-pointerโ Don't keep the frame pointer in a register for leaf functions. This skips the instructions that save, set up, and restore frame pointers, and frees up an extra register in leaf functions ๐ฆ. The option-fomit-leaf-frame-pointerremoves the frame pointer for leaf functions too, but that might make debugging harder ๐.-mtls-direct-seg-refs,-mno-tls-direct-seg-refsโ Controls whether TLS variables can be accessed with offsets from the TLS segment register (%gsfor 32-bit,%fsfor 64-bit), or whether the thread base pointer has to be added. Whether that's valid depends on 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 a VEX prefix. The option-mavxturns this on by default ๐.-mfentry,-mno-fentryโ If profiling is active (-pg), put the profiling counter call before the prologue. Note: on x86 architectures, the attribute"ms_hook_prologue"isn't possible for-mfentryand-pgright now ๐ญ.-mrecord-mcount,-mno-record-mcountโ If profiling is active (-pg), generate a__mcount_locsection that holds pointers to each profiling call. This is handy 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 get 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 that end withret, not sibling calls that end with a jump ๐ฅ. The valid types arenoneto not instrument,callto generate a call to__return__, ornop5to generate a 5-byte NOP ๐ง.-mrecord-return,-mno-record-returnโ Generate a__return_locsection that points to all of the 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 that records-mrecord-mcountcalls (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 skip setting up the RAX register when no variable arguments are passed in vector registers ๐ซถ.
Warning: The RAX register is used to avoid unnecessarily saving vector registers on the stack when passing variable arguments. So the impacts of this option are that callees may waste some stack space, misbehave, or jump to a random location. GCC 4.4 or newer doesn't have those issues, regardless of the RAX register value ๐ญ.
-m8bit-idiv,-mno-8bit-idivโ On some processors, like Intel Atom, 8-bit unsigned integer divide is way faster than 32-bit/64-bit integer divide ๐ฅ. This option generates a run-time check. If both the dividend and 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 loads and stores ๐ฆ.-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ Generate stack protection code using a canary atguard. The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block (the default) ๐. This option only has an effect when-fstack-protectoror-fstack-protector-allis specified ๐.
Okay so, with that latter choice ๐
the options -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset also decide which segment register (%fs or %gs) gets used as the base register for reading the canary, and what offset from that base it starts at. If you don't pick, the defaults come from whatever the relevant ABI says ๐ซถ
-mgeneral-regs-onlyโ Generate code that only uses the general-purpose registers ๐ง. The compiler is NOT allowed to touch floating-point, vector, mask, or bound registers. Strict bestie energy, but iconic.-mindirect-branch=choiceโ Converts indirect calls and jumps based onchoice๐ฆ. The default iskeep, which leaves indirect call and jump totally unmodified. The other options are:thunkconverts indirect call and jump to a call and return thunk.thunk-inlineconverts them to an inlined call and return thunk.thunk-externconverts them to an external call and return thunk that lives in a separate object file.
You can control this for one specific function with the function attribute "indirect_branch" โจ
Note that-mcmodel=largeis incompatible with-mindirect-branch=thunkand-mindirect-branch=thunk-externsince the thunk function may not be reachable in the large code model. ๐
Note that-mindirect-branch=thunk-externis compatible with-fcf-protection=branchsince the external thunk can be made to enable control-flow check. ๐
-mfunction-return=choiceโ Converts function return based onchoice๐ธ. The default iskeep, which keeps function return unmodified. The other options are: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 one specific function with the function attribute "function_return" ๐
Note that-mindirect-return=thunk-externis compatible with-fcf-protection=branchsince the external thunk can be made to enable control-flow check. ๐
Note that-mcmodel=largeis incompatible with-mfunction-return=thunkand-mfunction-return=thunk-externsince the thunk function may not be reachable in the large code model. ๐
-mindirect-branch-registerโ Forces indirect calls and jumps to go through a register ๐-mharden-sls=choiceโ Generates code to mitigate straight line speculation (SLS) withchoice๐ก๏ธ. The default isnone, which disables all SLS hardening.returnturns on SLS hardening for function returns,indirect-jmpturns it on for indirect jumps, andallenables every SLS hardening.-mindirect-branch-cs-prefixโ Adds a CS prefix to call and jmp to an indirect thunk whose branch target is inr8-r15registers โญ. That makes the call and jmp instruction length 6 bytes, so they can be swapped at run-time forlfence; call *%r8-r15orlfence; jmp *%r8-r15.
These -m switches are supported in addition to the above on x86-64 processors in 64-bit environments ๐
-m32,-m64,-mx32,-m16,-miamcuโ Generate code for a 16-bit, 32-bit or 64-bit environment ๐ Here's the breakdown:-m32โ sets"int","long", and pointer types to 32 bits, and generates code that runs in 32-bit mode.-m64โ sets"int"to 32 bits and"long"and 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.-mx32โ sets"int","long", and pointer types to 32 bits, and generates code for the x86-64 architecture.-m16โ 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 ๐ง-miamcuโ generates code that conforms to the Intel MCU psABI. It requires the-m32option to be turned on.
-mno-red-zoneโ Don't use a so-called "red zone" for x86-64 code ๐. The red zone is mandated by the x86-64 ABI. It's a 128-byte area beyond the location of the stack pointer that signal or interrupt handlers don't modify, so it can hold temporary data without adjusting the stack pointer. The flag-mno-red-zonedisables this red zone.-mcmodel=smallโ Generate code for the small code model ๐ธ: the program and its symbols must be linked in the lower 2 GB of the address space. Pointers are 64 bits. Programs can be statically or dynamically linked. This is the default code model.-mcmodel=kernelโ Generate code for the kernel code model. The kernel runs in the negative 2 GB of the address space. This model has to be used for Linux kernel code ๐-mcmodel=mediumโ Generate code for the medium model: the program is linked in the lower 2 GB of the address space, and small symbols are placed there too. Symbols with sizes larger than-mlarge-data-thresholdget put into large data or BSS sections and can be located above 2GB. Programs can be statically or dynamically linked.-mcmodel=largeโ Generate code for the large model. It makes no assumptions about addresses and sizes of sections ๐-maddress-mode=longโ Generate code for long address mode. This is only supported for 64-bit and x32 environments. It's the default address mode for 64-bit environments.-maddress-mode=shortโ Generate code for short address mode. This is only supported for 32-bit and x32 environments. It's the default address mode for 32-bit and x32 environments.
โจ x86 Windows Options โจ
These additional options are available for Microsoft Windows targets ๐ช
-mconsoleโ Generates a console application by instructing the linker to set the PE header subsystem type required for console applications. Available for Cygwin and MinGW targets, and enabled by default on those targets.-mdllโ Available for Cygwin and MinGW targets. Generates a DLL (a dynamic link library), which enables selecting the required runtime startup object and entry point ๐ฆ-mnop-fun-dllimportโ Available for Cygwin and MinGW targets. The"dllimport"attribute should be ignored.-mthreadโ Available for MinGW targets. Uses MinGW-specific thread support ๐งต-municodeโ Available for MinGW-w64 targets. Predefines the"UNICODE"preprocessor macro and chooses Unicode-capable runtime startup code ๐-mwin32โ Available for Cygwin and MinGW targets. Sets the typical Microsoft Windows predefined macros in the pre-processor, but doesn't influence the choice of runtime library/startup code.-mwindowsโ Available for Cygwin and MinGW targets. Generates a GUI application by instructing the linker to set the PE header subsystem type appropriately ๐-fno-set-stack-executableโ Available for MinGW targets. The executable flag for the stack used by nested functions isn't set. This is necessary for binaries running in kernel mode of Microsoft Windows, because the User32 API (which is used to set executable privileges) isn't available there ๐-fwritable-relocated-rdataโ Available for MinGW and Cygwin targets. Relocated data in a read-only section gets put into the".data"section. This is necessary for older runtimes that don't support modifying".rdata"sections for pseudo-relocation ๐-mpe-aligned-commonsโ Available for Cygwin and MinGW targets. Uses the GNU extension to the PE file format that permits correct alignment of COMMON variables when generating code. It's enabled by default if GCC detects that the target assembler found during configuration supports the feature โจ
See also under x86 Options for standard options ๐ซถ
โจ Xstormy16 Options โจ
These options are defined for Xstormy16:
-msimโ Chooses startup files and a linker script suitable for the simulator ๐ง
โจ Xtensa Options โจ
These options are supported for Xtensa targets:
-mconst16,-mno-const16โ Enable or disable use of"CONST16"instructions for loading constant values ๐. The"CONST16"instruction is currently not a standard option from Tensilica. When enabled,"CONST16"instructions are always used in place of the standard"L32R"instructions. The use of"CONST16"is enabled by default only if the"L32R"instruction is not available.-mfused-madd,-mno-fused-maddโ Enable or disable use of fused multiply/add and multiply/subtract instructions in the floating-point option ๐ฅ. This has no effect if the floating-point option is not also enabled. Disabling them forces the compiler to use separate instructions for the multiply and add/subtract operations. That can be desirable when strict IEEE 754-compliant results are required, because the fused multiply add/subtract instructions don't round the intermediate result, so they produce results with more bits of precision than the IEEE standard specifies. Disabling them also ensures the program output isn't sensitive to the compiler's ability to combine multiply and add/subtract operations ๐ธ-mserialize-volatile,-mno-serialize-volatileโ When enabled, GCC insertsMEMWinstructions before"volatile"memory references to guarantee sequential consistency ๐. The default is-mserialize-volatile. Use-mno-serialize-volatileto omit theMEMWinstructions.-mforce-no-picโ For targets like GNU/Linux, where all user-mode Xtensa code must be position-independent code (PIC), this option disables PIC for compiling kernel code ๐
Okay so these four are all about where the literal pools end up ๐ง and they're lowkey very important for code size ๐
-mtext-section-literals,-mno-text-section-literalsโ The default is-mno-text-section-literals, which puts literals in their own separate section of the output file. That lets the literal pool live in data RAM/ROM, and it lets the linker combine literal pools from different object files to get rid of redundant literals and shrink the code ๐ธ With-mtext-section-literals, the literals get interspersed right into the text section so they stay as close as possible to where they're used. This might be necessary for large assembly files ๐ซถ Literals for each function get placed right before that function โจ-mauto-litpools,-mno-auto-litpoolsโ The default is-mno-auto-litpools, which puts literals in a separate section in the output file unless-mtext-section-literalsis used ๐ฆ With-mauto-litpools, the assembler is the one that interleaves literals into the text section. The compiler doesn't produce explicit.literaldirectives and instead loads literals into registers withMOVIinstructions instead ofL32R, so the assembler can do relaxation and place literals wherever they're needed ๐ง This option lets the assembler make several literal pools per function and assemble very big functions, which might not be possible with-mtext-section-literals. Literally main character energy ๐-mtarget-align,-mno-target-alignโ When this is enabled, GCC tells the assembler to automatically align instructions so branch penalties go down, at the cost of a little code density ๐ The assembler tries to widen density instructions so that branch targets and the instructions after call instructions are aligned. If there aren't enough safe density instructions before a target to align it, no widening happens ๐ The default is-mtarget-align. These options don't change how auto-aligned instructions likeLOOPare handled. The assembler always aligns those, either by widening density instructions or by insertingNOPinstructions โจ-mlongcalls,-mno-longcallsโ When this is enabled, GCC tells the assembler to turn direct calls into indirect calls, unless it can tell that the target of a direct call is within the range the call instruction allows ๐ญ This usually happens for calls to functions in other source files. Specifically, the assembler swaps a directCALLinstruction for anL32Rfollowed by aCALLXinstruction ๐ The default is-mno-longcalls. Use this option in programs where the call target could potentially be out of range ๐ This option is implemented in the assembler, not the compiler, so the assembly code GCC generates still shows direct call instructions---so go look at the disassembled object code if you want to see the actual instructions ๐ฅ Also, the assembler uses an indirect call for every cross-file call, not just the ones that really are out of range. Iykyk ๐
zSeries Options ๐
These are listed under
โจ ENVIRONMENT โจ
Okay so bestie, this section is all about the environment variables that tweak how GCC behaves ๐ธ Some of them tell GCC which directories or prefixes to dig through when hunting for files, and others set up the rest of the compilation vibe ๐
Quick tea โ: you can also tell GCC where to search with options like -B, -I and -L. Those beat environment variables, and environment variables beat whatever GCC was configured with. The hierarchy is real ๐
LANG, LC_CTYPE, LC_MESSAGES, LC_ALL ๐
These are how GCC handles different national conventions ๐ฌ๐ง GCC looks at LC_CTYPE and LC_MESSAGES, but only if it was configured to do so. They can be set to any value your installation supports, like en_GB.UTF-8 (English in the United Kingdom, encoded in UTF-8) ๐ซถ
LC_CTYPEโ this one handles character classification ๐. GCC uses it to figure out where characters start and stop in a string. That matters for some multibyte encodings with quote and escape characters that could otherwise be mistaken for the end of a string or an escape ๐LC_MESSAGESโ picks the language for diagnostic messages ๐ฌLC_ALLโ if this one is set, it overridesLC_CTYPEandLC_MESSAGES๐. If it isn't, those two default to whateverLANGsays. And if none of these are set, GCC goes with traditional C English behaviour ๐
TMPDIR ๐
If TMPDIR is set, that's the directory GCC uses for temporary files. GCC stashes the output of one stage of compilation there so the next stage can use it as input. For example, the preprocessor's output is what the compiler proper takes in ๐ง
GCC_COMPARE_DEBUG ๐ฆ
Setting GCC_COMPARE_DEBUG is nearly the same as passing -fcompare-debug to the compiler driver. Check that option's docs for the full scoop ๐
GCC_EXEC_PREFIX ๐
If GCC_EXEC_PREFIX is set, it's a prefix stuck onto the names of the subprograms the compiler runs. No slash gets added when the prefix is combined with a subprogram name, so if you want one, end your prefix with a slash yourself ๐ซถ
If it's not set, GCC tries to work out a sensible prefix based on the pathname it was invoked with ๐
If GCC can't find a subprogram using that prefix, it checks the usual places instead ๐
The default value is prefix/lib/gcc/, where prefix is the prefix of the installed compiler. A lot of the time that's whatever "prefix" was set to when you ran the configure script ๐ ๏ธ
Prefixes given with -B take precedence over this one โญ
This prefix is also used to find files like crt0.o that get used for linking ๐
Now for the weird part ๐คฏ The prefix works differently when GCC is finding header directories. For each standard directory that normally begins with /usr/local/lib/gcc (or, more precisely, the value of GCC_INCLUDE_DIR), GCC swaps that beginning out for the specified prefix to make an alternate directory name. So with -Bfoo/, GCC searches foo/bar just before it searches the standard directory /usr/local/lib/bar. If a standard directory begins with the configured prefix, then the prefix gets replaced by GCC_EXEC_PREFIX when GCC looks for header files ๐
COMPILER_PATH ๐
The value is a colon-separated list of directories, kinda like PATH โจ GCC checks these when searching for subprograms, but only if it can't find them using GCC_EXEC_PREFIX first.
LIBRARY_PATH ๐
Also a colon-separated list of directories, like PATH ๐ When GCC is configured as a native compiler, it checks these for special linker files, again only if GCC_EXEC_PREFIX couldn't find them. Linking with GCC also searches these directories for ordinary libraries used with the -l option, but directories given with -L come first ๐ฅ
LANG ๐ฃ๏ธ
This variable passes locale info to the compiler ๐ One thing that info controls is which character set gets used when character literals, string literals and comments are parsed in C and C++. When the compiler is configured to allow multibyte characters, these values for LANG are recognised:
C-JISโ recognise JIS characters.C-SJISโ recognise SJIS characters.C-EUCJPโ recognise EUCJP characters.
If LANG isn't defined, or it has some other value, the compiler uses mblen and mbtowc as defined by the default locale to recognise and translate multibyte characters ๐ซ
Preprocessor vibes ๐งน
Some additional environment variables affect how the preprocessor behaves ๐
CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH ๐๏ธ
Each of these holds a list of directories, separated by a special character (much like PATH), to look in for header files. That special character is PATH_SEPARATOR. It depends on the target and gets decided when GCC is built ๐ ๏ธ For Microsoft Windows-based targets it's a semicolon, and for almost every other target it's a colon ๐
CPATHโ searched as if the directories were given with-I, but after any-Ipaths on the command line. This one gets used no matter which language is being preprocessed ๐C_INCLUDE_PATH,CPLUS_INCLUDE_PATHandOBJC_INCLUDE_PATHโ these only apply when preprocessing their particular language. Each one is searched as if the directories were given with-isystem, but after any-isystempaths 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 CPATH is ":/special/include", that has the same effect as -I. -I/special/include โจ
DEPENDENCIES_OUTPUT ๐งพ
If this variable is set, its value says how to output Make dependencies based on the non-system header files the compiler processes. System header files are ignored in the dependency output ๐
The value can be just a file name. In that case the Make rules get written to that file, and the target name is guessed from the source file name ๐ฏ Or the value can look like file target, where the rules get written to file and target is used as the target name.
In other words, this variable is equivalent to combining -MM and -MF, with an optional -MT switch too ๐
SUNPRO_DEPENDENCIES ๐
This one's the same as DEPENDENCIES_OUTPUT, except system header files are not ignored, so it implies -M rather than -MM. The dependence on the main input file gets left out, though ๐
SOURCE_DATE_EPOCH โฐ
If this variable is set, its value is a UNIX timestamp used instead of the current date and time in the __DATE__ and __TIME__ macros, so the embedded timestamps come out reproducible ๐
The value has to be a UNIX timestamp, meaning the number of seconds (leap seconds excluded) since 01 Jan 1970 00:00:00, written in ASCII. That's identical to the output of date +%s on GNU/Linux and other systems that support the %s extension in the date command ๐งฎ
It should be a known timestamp, like the last modification time of the source or package, and it should be set by the build process ๐ ๏ธ
๐ BUGS ๐
For instructions on reporting bugs, check out file:///usr/share/doc/gcc-10/README.Bugs ๐
๐ FOOTNOTES ๐
- On some systems,
gcc -sharedneeds to build supplementary stub code for constructors to work. On multi-libbed systems,gcc -sharedmust select the correct support libraries to link against. Failing to supply the correct flags may lead to subtle defects. Supplying them where they aren't necessary is innocuous ๐ซง
๐ SEE ALSO ๐
gpl(7), gfdl(7), fsf-funding(7), cpp(1), gcov(1), as(1), ld(1), gdb(1), dbx(1) and the Info entries for gcc, cpp, as, ld, binutils and gdb ๐
๐ฉโ๐ป AUTHOR ๐ฉโ๐ป
See the Info entry for gcc, or http://gcc.gnu.org/onlinedocs/gcc/Contributors.html, for contributors to GCC ๐
โ๏ธ COPYRIGHT โ๏ธ
Copyright (c) 1988-2020 Free Software Foundation, Inc. ๐ธ
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with the Invariant Sections being "GNU General Public License" and "Funding Free Software", the Front-Cover texts being (a) (see below), and with the Back-Cover Texts being (b) (see below). A copy of the license is included in the gfdl(7) man page ๐
- (a) The FSF's Front-Cover Text is: "A GNU Manual"
- (b) The FSF's Back-Cover Text is: "You have freedom to copy and modify this GNU Manual, like GNU software. Copies published by the Free Software Foundation raise funds for GNU development."
That's the whole page, bestie! ๐ This one came from the gcc-10 source, version stamp 2023-07-07, and it's GCC(1) all the way through ๐ Stay iconic, stay compiling ๐ฆโจ
๐ฆ where this page comes from
- ubuntu noble: g++-10-aarch64-linux-gnu 10.5.0-4ubuntu2.1cross1
- ubuntu noble: g++-10-aarch64-linux-gnu 10.5.0-4ubuntu2cross1
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms