GCC(1)
๐ GCC(1) ๐
Heyyy bestie ๐ซถ this is the manual page for gcc, the GNU project C and C++ compiler, and it is about to be SO good. Let's go ๐
โจ NAME โจ
gcc - GNU project C and C++ compiler ๐ธ
โจ SYNOPSIS โจ
gcc [-c|-S|-E] [-std=standard]
[-g] [-pg] [-Olevel]
[-Wwarn...] [-Wpedantic]
[-Idir...] [-Ldir...]
[-Dmacro[=defn]...] [-Umacro]
[-foption...] [-mmachine-option...]
[-o outfile] [@file] infile...
Okay so this is only the most useful options ๐ง The rest are down below. Also, g++ takes mostly the same options as gcc, so you're not learning two whole different vibes ๐
โจ DESCRIPTION โจ
Okay so when you invoke GCC, it normally does preprocessing, compilation, assembly and linking, all in one go โจ The "overall options" let you stop that whole process at an intermediate stage. For example, the -c option says don't run the linker ๐ฆ Then what you get back is object files spit out by the assembler.
Other options get passed along to one or more stages. Some control the preprocessor, some control the compiler itself, and yet others control the assembler and linker. Most of those last ones aren't documented here, because honestly you almost never need them ๐
Most of the command-line options are useful for C programs. When an option is only useful with another language (usually C++), the explanation will say so explicitly. If an option's description doesn't mention a source language, you can use it with all supported languages ๐
The usual way to run 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, you should invoke GCC as g++ instead ๐
The gcc program takes options and file names as operands. Lots of options have multi-letter names, so multiple single-letter options can't be grouped together. -dv is very different from -d -v ๐
You can mix options and other arguments, and for the most part the order doesn't matter. Order does matter when you use several options of the same kind. For example, if you specify -L more than once, the directories get searched in the order you specified them. Also, where you put the -l option is significant ๐ฅ
Many options have long names starting with -f or with -W---for example, -fmove-loop-invariants, -Wformat and so on. Most of these have both a positive and a negative form, and the negative form of -ffoo is -fno-foo. This manual only documents one of the two forms, whichever one is not the default โจ
Some options take one or more arguments, usually separated from the option name by either a space or an equals sign (=). Unless documented otherwise, an argument can be numeric or a string. Numeric arguments must typically be small unsigned decimal or hexadecimal integers, and hexadecimal arguments must begin with the 0x prefix ๐
Arguments to options that set a size threshold can be arbitrarily large decimal or hexadecimal integers followed by a byte size suffix. That suffix is a multiple of bytes, like "kB" and "KiB" for kilobyte and kibibyte, respectively, "MB" and "MiB" for megabyte and mebibyte, "GB" and "GiB" for gigabyte and gigibyte, and so on. These arguments get called byte-size in the rest of the text. For the full listing 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, so you can get the big picture first ๐ฆ The explanations come in the sections after this.
๐ธ Overall Options
-c -S -E -o file -x language -v -### --help[=class[,...]]
--target-help --version -pass-exit-codes -pipe -specs=file
-wrapper @file -ffile-prefix-map=old=new -fplugin=file
-fplugin-arg-name=arg -fdump-ada-spec[-slim] -fada-spec-parent=unit
-fdump-go-spec=file
๐ C Language Options
-ansi -std=standard -fgnu89-inline
-fpermitted-flt-eval-methods=standard -aux-info filename
-fallow-parameterless-variadic-functions -fno-asm -fno-builtin
-fno-builtin-function -fgimple -fhosted -ffreestanding -fopenacc
-fopenacc-dim=geom -fopenmp -fopenmp-simd -fms-extensions
-fplan9-extensions -fsso-struct=endianness -fallow-single-precision
-fcond-mismatch -flax-vector-conversions -fsigned-bitfields
-fsigned-char -funsigned-bitfields -funsigned-char
๐ฅ C++ Language Options
-fabi-version=n -fno-access-control -faligned-new=n
-fargs-in-order=n -fchar8_t -fcheck-new -fconstexpr-depth=n
-fconstexpr-loop-limit=n -fconstexpr-ops-limit=n
-fno-elide-constructors -fno-enforce-eh-specs -fno-gnu-keywords
-fno-implicit-templates -fno-implicit-inline-templates
-fno-implement-inlines -fms-extensions -fnew-inheriting-ctors
-fnew-ttp-matching -fno-nonansi-builtins -fnothrow-opt
-fno-operator-names -fno-optional-diags -fpermissive
-fno-pretty-templates -frepo -fno-rtti -fsized-deallocation
-ftemplate-backtrace-limit=n -ftemplate-depth=n
-fno-threadsafe-statics -fuse-cxa-atexit -fno-weak -nostdinc++
-fvisibility-inlines-hidden -fvisibility-ms-compat
-fext-numeric-literals -Wabi=n -Wabi-tag -Wconversion-null
-Wctor-dtor-privacy -Wdelete-non-virtual-dtor -Wdeprecated-copy
-Wdeprecated-copy-dtor -Wliteral-suffix -Wmultiple-inheritance
-Wno-init-list-lifetime -Wnamespaces -Wnarrowing -Wpessimizing-move
-Wredundant-move -Wnoexcept -Wnoexcept-type -Wclass-memaccess
-Wnon-virtual-dtor -Wreorder -Wregister -Weffc++
-Wstrict-null-sentinel -Wtemplates -Wno-non-template-friend
-Wold-style-cast -Woverloaded-virtual -Wno-pmf-conversions
-Wno-class-conversion -Wno-terminate -Wsign-promo
-Wvirtual-inheritance
๐ฆ Objective-C and Objective-C++ Language Options
-fconstant-string-class=class-name -fgnu-runtime -fnext-runtime
-fno-nil-receivers -fobjc-abi-version=n -fobjc-call-cxx-cdtors
-fobjc-direct-dispatch -fobjc-exceptions -fobjc-gc -fobjc-nilcheck
-fobjc-std=objc1 -fno-local-ivars
-fivar-visibility=[public|protected|private|package]
-freplace-objc-classes -fzero-link -gen-decls -Wassign-intercept
-Wno-protocol -Wselector -Wstrict-selector-match
-Wundeclared-selector
๐ง Diagnostic Message Formatting Options
-fmessage-length=n -fdiagnostics-show-location=[once|every-line]
-fdiagnostics-color=[auto|never|always]
-fdiagnostics-format=[text|json] -fno-diagnostics-show-option
-fno-diagnostics-show-caret -fno-diagnostics-show-labels
-fno-diagnostics-show-line-numbers
-fdiagnostics-minimum-margin-width=width
-fdiagnostics-parseable-fixits -fdiagnostics-generate-patch
-fdiagnostics-show-template-tree -fno-elide-type -fno-show-column
โ ๏ธ Warning Options โ ๏ธ
Okay bestie, this is the warning squad, and it is THICK ๐ The original just drops these names with no explanations in this part, so I'm lining up the whole crew exactly as written ๐
-fsyntax-only-fmax-errors=n-Wpedantic-pedantic-errors-w-Wextra-Wall-Waddress-Waddress-of-packed-member-Waggregate-return-Waligned-new-Walloc-zero-Walloc-size-larger-than=byte-size-Walloca-Walloca-larger-than=byte-size-Wno-aggressive-loop-optimizations-Warray-bounds-Warray-bounds=n-Wno-attributes-Wattribute-alias=n-Wbool-compare-Wbool-operation-Wno-builtin-declaration-mismatch-Wno-builtin-macro-redefined-Wc90-c99-compat-Wc99-c11-compat-Wc11-c2x-compat-Wc++-compat-Wc++11-compat-Wc++14-compat-Wc++17-compat-Wcast-align-Wcast-align=strict-Wcast-function-type-Wcast-qual-Wchar-subscripts-Wcatch-value-Wcatch-value=n-Wclobbered-Wcomment-Wconditionally-supported-Wconversion-Wcoverage-mismatch-Wno-cpp-Wdangling-else-Wdate-time-Wdelete-incomplete-Wno-attribute-warning-Wno-deprecated-Wno-deprecated-declarations-Wno-designated-init-Wdisabled-optimization-Wno-discarded-qualifiers-Wno-discarded-array-qualifiers-Wno-div-by-zero-Wdouble-promotion-Wduplicated-branches-Wduplicated-cond-Wempty-body-Wenum-compare-Wno-endif-labels-Wexpansion-to-defined-Werror-Werror=*-Wextra-semi-Wfatal-errors-Wfloat-equal-Wformat-Wformat=2-Wno-format-contains-nul-Wno-format-extra-args-Wformat-nonliteral-Wformat-overflow=n-Wformat-security-Wformat-signedness-Wformat-truncation=n-Wformat-y2k-Wframe-address-Wframe-larger-than=byte-size-Wno-free-nonheap-object-Wjump-misses-init-Whsa-Wif-not-aligned-Wignored-qualifiers-Wignored-attributes-Wincompatible-pointer-types-Wimplicit-Wimplicit-fallthrough-Wimplicit-fallthrough=n-Wimplicit-function-declaration-Wimplicit-int-Winit-self-Winline-Wno-int-conversion-Wint-in-bool-context-Wno-int-to-pointer-cast-Winvalid-memory-model-Wno-invalid-offsetof-Winvalid-pch-Wlarger-than=byte-size-Wlogical-op-Wlogical-not-parentheses-Wlong-long-Wmain-Wmaybe-uninitialized-Wmemset-elt-size-Wmemset-transposed-args-Wmisleading-indentation-Wmissing-attributes-Wmissing-braces-Wmissing-field-initializers-Wmissing-format-attribute-Wmissing-include-dirs-Wmissing-noreturn-Wmissing-profile-Wno-multichar-Wmultistatement-macros-Wnonnull-Wnonnull-compare-Wnormalized=[none|id|nfc|nfkc]-Wnull-dereference-Wodr-Wno-overflow-Wopenmp-simd-Woverride-init-side-effects-Woverlength-strings-Wpacked-Wpacked-bitfield-compat-Wpacked-not-aligned-Wpadded-Wparentheses-Wno-pedantic-ms-format-Wplacement-new-Wplacement-new=n-Wpointer-arith-Wpointer-compare-Wno-pointer-to-int-cast-Wno-pragmas-Wno-prio-ctor-dtor-Wredundant-decls-Wrestrict-Wno-return-local-addr-Wreturn-type-Wsequence-point-Wshadow-Wno-shadow-ivar-Wshadow=global,-Wshadow=local,-Wshadow=compatible-local-Wshift-overflow-Wshift-overflow=n-Wshift-count-negative-Wshift-count-overflow-Wshift-negative-value-Wsign-compare-Wsign-conversion-Wfloat-conversion-Wno-scalar-storage-order-Wsizeof-pointer-div-Wsizeof-pointer-memaccess-Wsizeof-array-argument-Wstack-protector-Wstack-usage=byte-size-Wstrict-aliasing-Wstrict-aliasing=n-Wstrict-overflow-Wstrict-overflow=n-Wstringop-overflow=n-Wstringop-truncation-Wsubobject-linkage-Wsuggest-attribute=[pure|const|noreturn|format|malloc]-Wsuggest-final-types-Wsuggest-final-methods-Wsuggest-override-Wswitch-Wswitch-bool-Wswitch-default-Wswitch-enum-Wswitch-unreachable-Wsync-nand-Wsystem-headers-Wtautological-compare-Wtrampolines-Wtrigraphs-Wtype-limits-Wundef-Wuninitialized-Wunknown-pragmas-Wunsuffixed-float-constants-Wunused-Wunused-function-Wunused-label-Wunused-local-typedefs-Wunused-macros-Wunused-parameter-Wno-unused-result-Wunused-value-Wunused-variable-Wunused-const-variable-Wunused-const-variable=n-Wunused-but-set-parameter-Wunused-but-set-variable-Wuseless-cast-Wvariadic-macros-Wvector-operation-performance-Wvla-Wvla-larger-than=byte-size-Wvolatile-register-var-Wwrite-strings-Wzero-as-null-pointer-constant
โจ C and Objective-C-only Warning Options โจ
These ones are the C and Objective-C-only crew ๐ง Same deal, just the names, no cap:
-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 ๐
Debugging era, bestie ๐ฆ Here's the whole glow-up lineup:
-g-glevel-gdwarf-gdwarf-version-ggdb-grecord-gcc-switches-gno-record-gcc-switches-gstabs-gstabs+-gstrict-dwarf-gno-strict-dwarf-gas-loc-support-gno-as-loc-support-gas-locview-support-gno-as-locview-support-gcolumn-info-gno-column-info-gstatement-frontiers-gno-statement-frontiers-gvariable-location-views-gno-variable-location-views-ginternal-reset-location-views-gno-internal-reset-location-views-ginline-points-gno-inline-points-gvms-gxcoff-gxcoff+-gz[=type]-gsplit-dwarf-gdescribe-dies-gno-describe-dies-fdebug-prefix-map=old=new-fdebug-types-section-fno-eliminate-unused-debug-types-femit-struct-debug-baseonly-femit-struct-debug-reduced-femit-struct-debug-detailed[=spec-list]-feliminate-unused-debug-symbols-femit-class-debug-always-fno-merge-debug-strings-fno-dwarf2-cfi-asm-fvar-tracking-fvar-tracking-assignments
๐ Optimization Options ๐
And finally the optimization squad ๐ This list is absolutely massive, so get comfy ๐
-faggressive-loop-optimizations-falign-functions[=n[:m:[n2[:m2]]]]-falign-jumps[=n[:m:[n2[:m2]]]]-falign-labels[=n[:m:[n2[:m2]]]]-falign-loops[=n[:m:[n2[:m2]]]]-fassociative-math-fauto-profile-fauto-profile[=path]-fauto-inc-dec-fbranch-probabilities-fbranch-target-load-optimize-fbranch-target-load-optimize2-fbtr-bb-exclusive-fcaller-saves-fcombine-stack-adjustments-fconserve-stack-fcompare-elim-fcprop-registers-fcrossjumping-fcse-follow-jumps-fcse-skip-blocks-fcx-fortran-rules-fcx-limited-range-fdata-sections-fdce-fdelayed-branch-fdelete-null-pointer-checks-fdevirtualize-fdevirtualize-speculatively-fdevirtualize-at-ltrans-fdse-fearly-inlining-fipa-sra-fexpensive-optimizations-ffat-lto-objects-ffast-math-ffinite-math-only-ffloat-store-fexcess-precision=style-fforward-propagate-ffp-contract=style-ffunction-sections-fgcse-fgcse-after-reload-fgcse-las-fgcse-lm-fgraphite-identity-fgcse-sm-fhoist-adjacent-loads-fif-conversion-fif-conversion2-findirect-inlining-finline-functions-finline-functions-called-once-finline-limit=n-finline-small-functions-fipa-cp-fipa-cp-clone-fipa-bit-cp-fipa-vrp-fipa-pta-fipa-profile-fipa-pure-const-fipa-reference-fipa-reference-addressable-fipa-stack-alignment-fipa-icf-fira-algorithm=algorithm-flive-patching=level-fira-region=region-fira-hoist-pressure-fira-loop-pressure-fno-ira-share-save-slots-fno-ira-share-spill-slots-fisolate-erroneous-paths-dereference-fisolate-erroneous-paths-attribute-fivopts-fkeep-inline-functions-fkeep-static-functions-fkeep-static-consts-flimit-function-alignment-flive-range-shrinkage-floop-block-floop-interchange-floop-strip-mine-floop-unroll-and-jam-floop-nest-optimize-floop-parallelize-all-flra-remat-flto-flto-compression-level-flto-partition=alg-fmerge-all-constants-fmerge-constants-fmodulo-sched-fmodulo-sched-allow-regmoves-fmove-loop-invariants-fno-branch-count-reg-fno-defer-pop-fno-fp-int-builtin-inexact-fno-function-cse-fno-guess-branch-probability-fno-inline-fno-math-errno-fno-peephole-fno-peephole2-fno-printf-return-value-fno-sched-interblock-fno-sched-spec-fno-signed-zeros-fno-toplevel-reorder-fno-trapping-math-fno-zero-initialized-in-bss-fomit-frame-pointer-foptimize-sibling-calls-fpartial-inlining-fpeel-loops-fpredictive-commoning-fprefetch-loop-arrays-fprofile-correction-fprofile-use-fprofile-use=path-fprofile-values-fprofile-reorder-functions-freciprocal-math-free-frename-registers-freorder-blocks-freorder-blocks-algorithm=algorithm-freorder-blocks-and-partition-freorder-functions-frerun-cse-after-loop-freschedule-modulo-scheduled-loops-frounding-math-fsave-optimization-record-fsched2-use-superblocks-fsched-pressure-fsched-spec-load-fsched-spec-load-dangerous-fsched-stalled-insns-dep[=n]-fsched-stalled-insns[=n]-fsched-group-heuristic-fsched-critical-path-heuristic-fsched-spec-insn-heuristic-fsched-rank-heuristic-fsched-last-insn-heuristic-fsched-dep-count-heuristic-fschedule-fusion-fschedule-insns-fschedule-insns2-fsection-anchors-fselective-scheduling-fselective-scheduling2-fsel-sched-pipelining-fsel-sched-pipelining-outer-loops-fsemantic-interposition-fshrink-wrap-fshrink-wrap-separate-fsignaling-nans-fsingle-precision-constant-fsplit-ivs-in-unroller-fsplit-loops-fsplit-paths-fsplit-wide-types-fssa-backprop-fssa-phiopt-fstdarg-opt-fstore-merging-fstrict-aliasing-fthread-jumps-ftracer-ftree-bit-ccp-ftree-builtin-call-dce-ftree-ccp-ftree-ch-ftree-coalesce-vars-ftree-copy-prop-ftree-dce-ftree-dominator-opts-ftree-dse-ftree-forwprop-ftree-fre-fcode-hoisting-ftree-loop-if-convert-ftree-loop-im-ftree-phiprop-ftree-loop-distribution-ftree-loop-distribute-patterns-ftree-loop-ivcanon-ftree-loop-linear-ftree-loop-optimize-ftree-loop-vectorize-ftree-parallelize-loops=n-ftree-pre-ftree-partial-pre-ftree-pta-ftree-reassoc-ftree-scev-cprop-ftree-sink-ftree-slsr-ftree-sra-ftree-switch-conversion-ftree-tail-merge-ftree-ter-ftree-vectorize-ftree-vrp-funconstrained-commons-funit-at-a-time-funroll-all-loops-funroll-loops-funsafe-math-optimizations-funswitch-loops-fipa-ra-fvariable-expansion-in-unroller-fvect-cost-model-fvpt-fweb-fwhole-program-fwpa-fuse-linker-plugin--param name=value-O-O0-O1-O2-O3-Os-Ofast-Og
โจ Program Instrumentation Options โจ
okay bestie, this group is all about profiling, coverage, and sanitizers ๐๐ here's the whole lineup:
-p-pg-fprofile-arcs--coverage-ftest-coverage-fprofile-abs-path-fprofile-dir=path-fprofile-generate-fprofile-generate=path-fprofile-update=method-fprofile-filter-files=regex-fprofile-exclude-files=regex-fsanitize=style-fsanitize-recover-fsanitize-recover=style-fasan-shadow-offset=number-fsanitize-sections=s1,s2,...-fsanitize-undefined-trap-on-error-fbounds-check-fcf-protection=[full|branch|return|none|check]-fstack-protector-fstack-protector-all-fstack-protector-strong-fstack-protector-explicit-fstack-check-fstack-limit-register=reg-fstack-limit-symbol=sym-fno-stack-limit-fsplit-stack-fvtable-verify=[std|preinit|none]-fvtv-counts-fvtv-debug-finstrument-functions-finstrument-functions-exclude-function-list=sym,sym,...-finstrument-functions-exclude-file-list=file,file,...
โจ Preprocessor Options โจ
the preprocessor flags, where macros and headers get sorted out ๐ง๐
-Aquestion=answer-A-question[=answer]-C-CC-Dmacro[=defn]-dD-dI-dM-dN-dU-fdebug-cpp-fdirectives-only-fdollars-in-identifiers-fexec-charset=charset-fextended-identifiers-finput-charset=charset-fmacro-prefix-map=old=new-fno-canonical-system-headers-fpch-deps-fpch-preprocess-fpreprocessed-ftabstop=width-ftrack-macro-expansion-fwide-exec-charset=charset-fworking-directory-H-imacros file-include file-M-MD-MF-MG-MM-MMD-MP-MQ-MT-no-integrated-cpp-P-pthread-remap-traditional-traditional-cpp-trigraphs-Umacro-undef-Wp,option-Xpreprocessor option
โจ Assembler Options โจ
just two, but they're doing the most ๐ฆ
-Wa,option-Xassembler option
โจ Linker Options โจ
the final step where everything gets glued together ๐๐
object-file-name-fuse-ld=linker-llibrary-nostartfiles-nodefaultlibs-nolibc-nostdlib-e entry--entry=entry-pie-pthread-r-rdynamic-s-static-static-pie-static-libgcc-static-libstdc++-static-libasan-static-libtsan-static-liblsan-static-libubsan-shared-shared-libgcc-symbolic-T script-Wl,option-Xlinker option-u symbol-z keyword
โจ Directory Options โจ
where the compiler goes looking for stuff, main character energy ๐บ๏ธ๐ธ
-Bprefix-Idir-I--idirafter dir-imacros file-imultilib dir-iplugindir=dir-iprefix file-iquote dir-isysroot dir-isystem dir-iwithprefix dir-iwithprefixbefore dir-Ldir-no-canonical-prefixes--no-sysroot-suffix-nostdinc-nostdinc++--sysroot=dir
โจ Code Generation Options โจ
this is where the actual machine code gets shaped ๐ฅ๐
-fcall-saved-reg-fcall-used-reg-ffixed-reg-fexceptions-fnon-call-exceptions-fdelete-dead-exceptions-funwind-tables-fasynchronous-unwind-tables-fno-gnu-unique-finhibit-size-directive-fno-common-fno-ident-fpcc-struct-return-fpic-fPIC-fpie-fPIE-fno-plt-fno-jump-tables-frecord-gcc-switches-freg-struct-return-fshort-enums-fshort-wchar-fverbose-asm-fpack-struct[=n]-fleading-underscore-ftls-model=model-fstack-reuse=reuse_level-ftrampolines-ftrapv-fwrapv-fvisibility=[default|internal|hidden|protected]-fstrict-volatile-bitfields-fsync-libcalls
โจ Developer Options โจ
the debugging and diagnostics drawer, for when you're feeling extra ๐ต๏ธโโ๏ธ๐ these are a lot, so grab a snack
-dletters-dumpspecs-dumpmachine-dumpversion-dumpfullversion-fchecking-fchecking=n-fdbg-cnt-list-fdbg-cnt=counter-value-list-fdisable-ipa-pass_name-fdisable-rtl-pass_name-fdisable-rtl-pass-name=range-list-fdisable-tree-pass_name-fdisable-tree-pass-name=range-list-fdump-debug-fdump-earlydebug-fdump-noaddr-fdump-unnumbered-fdump-unnumbered-links-fdump-final-insns[=file]-fdump-ipa-all-fdump-ipa-cgraph-fdump-ipa-inline-fdump-lang-all-fdump-lang-switch-fdump-lang-switch-options-fdump-lang-switch-options=filename-fdump-passes-fdump-rtl-pass-fdump-rtl-pass=filename-fdump-statistics-fdump-tree-all-fdump-tree-switch-fdump-tree-switch-options-fdump-tree-switch-options=filename-fcompare-debug[=opts]-fcompare-debug-second-fenable-kind-pass-fenable-kind-pass=range-list-fira-verbose=n-flto-report-flto-report-wpa-fmem-report-wpa-fmem-report-fpre-ipa-mem-report-fpost-ipa-mem-report-fopt-info-fopt-info-options[=file]-fprofile-report-frandom-seed=string-fsched-verbose=n-fsel-sched-verbose-fsel-sched-dump-cfg-fsel-sched-pipelining-verbose-fstats-fstack-usage-ftime-report-ftime-report-details-fvar-tracking-assignments-toggle-gtoggle-print-file-name=library-print-libgcc-file-name-print-multi-directory-print-multi-lib-print-multi-os-directory-print-prog-name=program-print-search-dirs-Q-print-sysroot-print-sysroot-headers-suffix-save-temps-save-temps=cwd-save-temps=obj-time[=file]
โจ Machine-Dependent Options โจ
every chip has its own vibe, so these are the target-specific flags ๐๐
๐ฆ AArch64 Options
-mabi=name-mbig-endian-mlittle-endian-mgeneral-regs-only-mcmodel=tiny-mcmodel=small-mcmodel=large-mstrict-align-mno-strict-align-momit-leaf-frame-pointer-mtls-dialect=desc-mtls-dialect=traditional-mtls-size=size-mfix-cortex-a53-835769-mfix-cortex-a53-843419-mlow-precision-recip-sqrt-mlow-precision-sqrt-mlow-precision-div-mpc-relative-literal-loads-msign-return-address=scope-mbranch-protection=none|standard|pac-ret[+leaf]|bti-mharden-sls=opts-march=name-mcpu=name-mtune=name-moverride=string-mverbose-cost-dump-mstack-protector-guard=guard-mstack-protector-guard-reg=sysreg-mstack-protector-guard-offset=offset-mtrack-speculation-moutline-atomics
๐ธ Adapteva Epiphany Options
-mhalf-reg-file-mprefer-short-insn-regs-mbranch-cost=num-mcmove-mnops=num-msoft-cmpsf-msplit-lohi-mpost-inc-mpost-modify-mstack-offset=num-mround-nearest-mlong-calls-mshort-calls-msmall16-mfp-mode=mode-mvect-double-max-vect-align=num-msplit-vecmove-early-m1reg-reg
๐ AMD GCN Options
-march=gpu-mtune=gpu-mstack-size=bytes
๐ฅ ARC Options
-mbarrel-shifter-mjli-always-mcpu=cpu-mA6-mARC600-mA7-mARC700-mdpfp-mdpfp-compact-mdpfp-fast-mno-dpfp-lrsr-mea-mno-mpy-mmul32x16-mmul64-matomic-mnorm-mspfp-mspfp-compact-mspfp-fast-msimd-msoft-float-mswap-mcrc-mdsp-packa-mdvbf-mlock-mmac-d16-mmac-24-mrtsc-mswape-mtelephony-mxy-misize-mannotate-align-marclinux-marclinux_prof-mlong-calls-mmedium-calls-msdata-mirq-ctrl-saved-mrgf-banked-regs-mlpc-width=width-G num-mvolatile-cache-mtp-regno=regno-malign-call-mauto-modify-reg-mbbit-peephole-mno-brcc-mcase-vector-pcrel-mcompact-casesi-mno-cond-exec-mearly-cbranchsi-mexpand-adddi-mindexed-loads-mlra-mlra-priority-none-mlra-priority-compactmlra-priority-noncompact-mmillicode-mmixed-code-mq-class-mRcq-mRcw-msize-level=level-mtune=cpu-mmultcost=num-mcode-density-frame-munalign-prob-threshold=probability-mmpy-option=multo-mdiv-rem-mcode-density-mll64-mfpu=fpu-mrf16-mbranch-index
๐ ARM Options
-mapcs-frame-mno-apcs-frame-mabi=name-mapcs-stack-check-mno-apcs-stack-check-mapcs-reentrant-mno-apcs-reentrant-mgeneral-regs-only-msched-prolog-mno-sched-prolog-mlittle-endian-mbig-endian-mbe8-mbe32-mfloat-abi=name-mfp16-format=name-mthumb-interwork-mno-thumb-interwork-mcpu=name-march=name-mfpu=name-mtune=name-mprint-tune-info-mstructure-size-boundary=n-mabort-on-noreturn-mlong-calls-mno-long-calls-msingle-pic-base-mno-single-pic-base-mpic-register=reg-mnop-fun-dllimport-mpoke-function-name-mthumb-marm-mflip-thumb-mtpcs-frame-mtpcs-leaf-frame-mcaller-super-interworking-mcallee-super-interworking-mtp=name-mtls-dialect=dialect-mword-relocations-mfix-cortex-m3-ldrd-munaligned-access-mneon-for-64bits-mslow-flash-data-masm-syntax-unified-mrestrict-it-mverbose-cost-dump-mpure-code-mcmse
๐ง AVR Options
-mmcu=mcu-mabsdata-maccumulate-args-mbranch-cost=cost-mcall-prologues-mgas-isr-prologues-mint8-mn_flash=size-mno-interrupts-mmain-is-OS_task-mrelax-mrmw-mstrict-X-mtiny-stack-mfract-convert-truncate-mshort-calls-nodevicelib-nodevicespecs-Waddr-space-convert-Wmisspelled-isr
๐ Blackfin Options
-mcpu=cpu[-sirevision]-msim-momit-leaf-frame-pointer-mno-omit-leaf-frame-pointer-mspecld-anomaly-mno-specld-anomaly-mcsync-anomaly-mno-csync-anomaly-mlow-64k-mno-low64k-mstack-check-l1-mid-shared-library-mno-id-shared-library-mshared-library-id=n-mleaf-id-shared-library-mno-leaf-id-shared-library-msep-data-mno-sep-data-mlong-calls-mno-long-calls-mfast-fp-minline-plt-mmulticore-mcorea-mcoreb-msdram-micplb
๐ C6X Options
-mbig-endian-mlittle-endian-march=cpu-msim-msdata=sdata-type
๐ CRIS Options
-mcpu=cpu-march=cpu-mtune=cpu-mmax-stack-frame=n-melinux-stacksize=n-metrax4-metrax100-mpdebug-mcc-init-mno-side-effects-mstack-align-mdata-align-mconst-align-m32-bit-m16-bit-m8-bit-mno-prologue-epilogue-mno-gotplt-melf-maout-melinux-mlinux-sim-sim2-mmul-bug-workaround-mno-mul-bug-workaround
๐ซถ CR16 Options
-mmac-mcr16cplus-mcr16c-msim-mint32-mbit-ops-mdata-model=model
๐ฎ C-SKY Options
-march=arch-mcpu=cpu-mbig-endian-EB-mlittle-endian-EL-mhard-float-msoft-float-mfpu=fpu-mdouble-float-mfdivdu-melrw-mistack-mmp-mcp-mcache-msecurity-mtrust-mdsp-medsp-mvdsp-mdiv-msmart-mhigh-registers-manchor-mpushpop-mmultiple-stld-mconstpool-mstack-size-mccrt-mbranch-cost=n-mcse-cc-msched-prolog
๐ Darwin Options ๐
okay bestie, the Darwin ones are up first and there are a LOT of them ๐ญ no descriptions in this part, just the flags themselves, so here they are in full ๐
-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 ๐ง
the Alpha crew next, bestie ๐
-mno-fp-regs-msoft-float-mieee-mieee-with-inexact-mieee-conformant-mfp-trap-mode=mode-mfp-rounding-mode=mode-mtrap-precision=mode-mbuild-constants-mcpu=cpu-type-mtune=cpu-type-mbwx-mmax-mfix-mcix-mfloat-vax-mfloat-ieee-mexplicit-relocs-msmall-data-mlarge-data-msmall-text-mlarge-text-mmemory-latency=time
๐ธ FR30 Options ๐ธ
-msmall-model-mno-lsim
๐ฆ FT32 Options ๐ฆ
-msim-mlra-mnodiv-mft32b-mcompress-mnopm
๐ FRV Options ๐
the FRV set is giving main character energy, no cap ๐ฅ
-mgpr-32-mgpr-64-mfpr-32-mfpr-64-mhard-float-msoft-float-malloc-cc-mfixed-cc-mdword-mno-dword-mdouble-mno-double-mmedia-mno-media-mmuladd-mno-muladd-mfdpic-minline-plt-mgprel-ro-multilib-library-pic-mlinked-fp-mlong-calls-malign-labels-mlibrary-pic-macc-4-macc-8-mpack-mno-pack-mno-eflags-mcond-move-mno-cond-move-moptimize-membar-mno-optimize-membar-mscc-mno-scc-mcond-exec-mno-cond-exec-mvliw-branch-mno-vliw-branch-mmulti-cond-exec-mno-multi-cond-exec-mnested-cond-exec-mno-nested-cond-exec-mtomcat-stats-mTLS-mtls-mcpu=cpu
๐ง GNU/Linux Options ๐ง
-mglibc-muclibc-mmusl-mbionic-mandroid-tno-android-cc-tno-android-ld
๐ H8/300 Options ๐
-mrelax-mh-ms-mn-mexr-mno-exr-mint32-malign-300
๐ HPPA Options ๐
-march=architecture-type-mcaller-copies-mdisable-fpregs-mdisable-indexing-mfast-indirect-calls-mgas-mgnu-ld-mhp-ld-mfixed-range=register-range-mjump-in-delay-mlinker-opt-mlong-calls-mlong-load-store-mno-disable-fpregs-mno-disable-indexing-mno-fast-indirect-calls-mno-gas-mno-jump-in-delay-mno-long-load-store-mno-portable-runtime-mno-soft-float-mno-space-regs-msoft-float-mpa-risc-1-0-mpa-risc-1-1-mpa-risc-2-0-mportable-runtime-mschedule=cpu-type-mspace-regs-msio-mwsio-munix=unix-std-nolibdld-static-threads
๐ง IA-64 Options ๐ง
this list is LONG, bestie, pace yourself ๐ญ
-mbig-endian-mlittle-endian-mgnu-as-mgnu-ld-mno-pic-mvolatile-asm-stop-mregister-names-msdata-mno-sdata-mconstant-gp-mauto-pic-mfused-madd-minline-float-divide-min-latency-minline-float-divide-max-throughput-mno-inline-float-divide-minline-int-divide-min-latency-minline-int-divide-max-throughput-mno-inline-int-divide-minline-sqrt-min-latency-minline-sqrt-max-throughput-mno-inline-sqrt-mdwarf2-asm-mearly-stop-bits-mfixed-range=register-range-mtls-size=tls-size-mtune=cpu-type-milp32-mlp64-msched-br-data-spec-msched-ar-data-spec-msched-control-spec-msched-br-in-data-spec-msched-ar-in-data-spec-msched-in-control-spec-msched-spec-ldc-msched-spec-control-ldc-msched-prefer-non-data-spec-insns-msched-prefer-non-control-spec-insns-msched-stop-bits-after-every-cycle-msched-count-spec-in-critical-path-msel-sched-dont-check-control-spec-msched-fp-mem-deps-zero-cost-msched-max-memory-insns-hard-limit-msched-max-memory-insns=max-insns
๐ LM32 Options ๐
-mbarrel-shift-enabled-mdivide-enabled-mmultiply-enabled-msign-extend-enabled-muser-enabled
๐ M32R/D Options ๐
-m32r2-m32rx-m32r-mdebug-malign-loops-mno-align-loops-missue-rate=number-mbranch-cost=number-mmodel=code-size-model-type-msdata=sdata-type-mno-flush-func-mflush-func=name-mno-flush-trap-mflush-trap=number-G num
โญ M32C Options โญ
-mcpu=cpu-msim-memregs=number
๐ซถ M680x0 Options ๐ซถ
-march=arch-mcpu=cpu-mtune=tune-m68000-m68020-m68020-40-m68020-60-m68030-m68040-m68060-mcpu32-m5200-m5206e-m528x-m5307-m5407-mcfv4e-mbitfield-mno-bitfield-mc68000-mc68020-mnobitfield-mrtd-mno-rtd-mdiv-mno-div-mshort-mno-short-mhard-float-m68881-msoft-float-mpcrel-malign-int-mstrict-align-msep-data-mno-sep-data-mshared-library-id=n-mid-shared-library-mno-id-shared-library-mxgot-mno-xgot-mlong-jump-table-offsets
๐ฅ MCore Options ๐ฅ
-mhardlit-mno-hardlit-mdiv-mno-div-mrelax-immediates-mno-relax-immediates-mwide-bitfields-mno-wide-bitfields-m4byte-functions-mno-4byte-functions-mcallgraph-data-mno-callgraph-data-mslow-bytes-mno-slow-bytes-mno-lsim-mlittle-endian-mbig-endian-m210-m340-mstack-increment
๐ท MeP Options ๐ท
-mabsdiff-mall-opts-maverage-mbased=n-mbitops-mc=n-mclip-mconfig=name-mcop-mcop32-mcop64-mivc2-mdc-mdiv-meb-mel-mio-volatile-ml-mleadz-mm-mminmax-mmult-mno-opts-mrepeat-ms-msatur-msdram-msim-msimnovec-mtf-mtiny=n
๐ฆ MicroBlaze Options ๐ฆ
-msoft-float-mhard-float-msmall-divides-mcpu=cpu-mmemcpy-mxl-soft-mul-mxl-soft-div-mxl-barrel-shift-mxl-pattern-compare-mxl-stack-check-mxl-gp-opt-mno-clearbss-mxl-multiply-high-mxl-float-convert-mxl-float-sqrt-mbig-endian-mlittle-endian-mxl-reorder-mxl-mode-app-model-mpic-data-is-text-relative
๐พ MIPS Options ๐พ
okay this is the BIGGEST one, bestie, it's giving "I have too many flags" energy ๐
-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 ๐งฉ
-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
๐ซง 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-mcmov-mror-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 ๐ฎ
See RS/6000 and PowerPC Options.
๐ฆ 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
๐ 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 ๐
Okay this one is LONG, bestie. Grab a snack. ๐
-mcpu=cpu-type -mtune=cpu-type
-mcmodel=code-model -mpowerpc64 -maltivec -mno-altivec
-mpowerpc-gpopt -mno-powerpc-gpopt -mpowerpc-gfxopt
-mno-powerpc-gfxopt -mmfcrf -mno-mfcrf -mpopcntb -mno-popcntb
-mpopcntd -mno-popcntd -mfprnd -mno-fprnd -mcmpb -mno-cmpb
-mmfpgpr -mno-mfpgpr -mhard-dfp -mno-hard-dfp -mfull-toc
-mminimal-toc -mno-fp-in-toc -mno-sum-in-toc -m64 -m32
-mxl-compat -mno-xl-compat -mpe -malign-power -malign-natural
-msoft-float -mhard-float -mmultiple -mno-multiple -mupdate
-mno-update -mavoid-indexed-addresses -mno-avoid-indexed-addresses
-mfused-madd -mno-fused-madd -mbit-align -mno-bit-align
-mstrict-align -mno-strict-align -mrelocatable -mno-relocatable
-mrelocatable-lib -mno-relocatable-lib -mtoc -mno-toc -mlittle
-mlittle-endian -mbig -mbig-endian -mdynamic-no-pic -mswdiv
-msingle-pic-base -mprioritize-restricted-insns=priority
-msched-costly-dep=dependence_type -minsert-sched-nops=scheme
-mcall-aixdesc -mcall-eabi -mcall-freebsd -mcall-linux
-mcall-netbsd -mcall-openbsd -mcall-sysv -mcall-sysv-eabi
-mcall-sysv-noeabi -mtraceback=traceback_type -maix-struct-return
-msvr4-struct-return -mabi=abi-type -msecure-plt -mbss-plt
-mlongcall -mno-longcall -mpltseq -mno-pltseq
-mblock-move-inline-limit=num -mblock-compare-inline-limit=num
-mblock-compare-inline-loop-limit=num
-mstring-compare-inline-limit=num -misel -mno-isel -mvrsave
-mno-vrsave -mmulhw -mno-mulhw -mdlmzb -mno-dlmzb -mprototype
-mno-prototype -msim -mmvme -mads -myellowknife -memb -msdata
-msdata=opt -mreadonly-in-sdata -mvxworks -G num -mrecip
-mrecip=opt -mno-recip -mrecip-precision -mno-recip-precision
-mveclibabi=type -mfriz -mno-friz -mpointers-to-nested-functions
-mno-pointers-to-nested-functions -msave-toc-indirect
-mno-save-toc-indirect -mpower8-fusion -mno-mpower8-fusion
-mpower8-vector -mno-power8-vector -mcrypto -mno-crypto -mhtm
-mno-htm -mquad-memory -mno-quad-memory -mquad-memory-atomic
-mno-quad-memory-atomic -mcompat-align-parm -mno-compat-align-parm
-mfloat128 -mno-float128 -mfloat128-hardware
-mno-float128-hardware -mgnu-attribute -mno-gnu-attribute
-mstack-protector-guard=guard -mstack-protector-guard-reg=reg
-mstack-protector-guard-offset=offset
๐ RX Options ๐
-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 -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
๐ฆ SPU Options ๐ฆ
-mwarn-reloc -merror-reloc -msafe-dma -munsafe-dma
-mbranch-hints -msmall-mem -mlarge-mem -mstdmain
-mfixed-range=register-range -mea32 -mea64
-maddress-space-conversion -mno-address-space-conversion
-mcache-size=cache-size -matomic-updates -mno-atomic-updates
๐ System V Options ๐
-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 ๐ซง
-mdebug -msim -mfpu -mno-fpu -mhard-float
-msoft-float -mcpu=cpu-type -mtune=cpu-type -msv-mode -muser-mode
๐บ VMS Options ๐บ
-mvms-return-codes -mdebug-main=prefix -mmalloc64
-mpointer-size=size
๐ฆ VxWorks Options ๐ฆ
-mrtp -non-static -Bstatic -Bdynamic -Xbind-lazy
-Xbind-now
๐ x86 Options ๐
This is the biggest list in the whole page, 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 -mvpclmulqdq -mavx512bitalg -mmovdiri -mmovdir64b
-mavx512vpopcntdq -mavx5124fmaps -mavx512vnni -mavx5124vnniw
-mprfchw -mrdpid -mrdseed -msgx -mcldemote -mms-bitfields
-mno-align-stringops -minline-all-stringops
-minline-stringops-dynamically -mstringop-strategy=alg
-mmemcpy-strategy=strategy -mmemset-strategy=strategy -mpush-args
-maccumulate-outgoing-args -m128bit-long-double -m96bit-long-double
-mlong-double-64 -mlong-double-80 -mlong-double-128 -mregparm=num
-msseregparm -mveclibabi=type -mvect8-ret-in-mem -mpc32 -mpc64
-mpc80 -mstackrealign -momit-leaf-frame-pointer -mno-red-zone
-mno-tls-direct-seg-refs -mcmodel=code-model -mabi=name
-maddress-mode=mode -m32 -m64 -mx32 -m16 -miamcu
-mlarge-data-threshold=num -msse2avx -mfentry -mrecord-mcount
-mnop-mcount -m8bit-idiv -minstrument-return=type
-mfentry-name=name -mfentry-section=name
-mavx256-split-unaligned-load -mavx256-split-unaligned-store
-malign-data=type -mstack-protector-guard=guard
-mstack-protector-guard-reg=reg
-mstack-protector-guard-offset=offset
-mstack-protector-guard-symbol=symbol -mgeneral-regs-only
-mcall-ms2sysv-xlogues -mindirect-branch=choice
-mfunction-return=choice -mindirect-branch-register
๐ช x86 Windows Options ๐ช
-mconsole -mcygwin -mno-cygwin -mdll
-mnop-fun-dllimport -mthread -municode -mwin32 -mwindows
-fno-set-stack-executable
๐ Xstormy16 Options ๐
-msim
๐ง Xtensa Options ๐ง
-mconst16 -mno-const16 -mfused-madd -mno-fused-madd
-mforce-no-pic -mserialize-volatile -mno-serialize-volatile
-mtext-section-literals -mno-text-section-literals -mauto-litpools
-mno-auto-litpools -mtarget-align -mno-target-align -mlongcalls
-mno-longcalls
zSeries Options โ 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. They always happen in that order, no exceptions, bestie.
GCC can preprocess and compile several files into several assembler input files, or squish them all into one assembler input file. Then each assembler input file makes an object file, and linking combines all the object files (the ones just compiled AND the ones you handed it as input) into an executable file. Iconic pipeline. ๐
For any given input file, the file name suffix decides what kind of compilation happens. Here's the vibe check:
file.cโ C source code that must be preprocessed first. ๐งfile.iโ C source code that should not be preprocessed. ๐file.iiโ C++ source code that should not be preprocessed. ๐file.mโ Objective-C source code. Heads up, bestie: you MUST link with thelibobjclibrary or your Objective-C program won't work. ๐ญfile.miโ Objective-C source code that should not be preprocessed. ๐ฆfile.mm,file.Mโ ๐ Objective-C++ source code! Bestie, you have to link with thelibobjclibrary or your Objective-C++ program won't work ๐. Also,.Mmeans a literal capital M, not a typo.file.miiโ Objective-C++ source that should not get preprocessed ๐.file.hโ A C, C++, Objective-C or Objective-C++ header that gets turned into a precompiled header by default โจ. Or, if it's a C or C++ header, it can become an Ada spec instead, using the-fdump-ada-specswitch ๐ฆ.file.cc,file.cp,file.cxx,file.cpp,file.CPP,file.c++,file.Cโ C++ source that must be preprocessed ๐ธ. In.cxx, the last two letters have to be literallyx, and.Cmeans a literal capital C.file.mm,file.Mโ Objective-C++ source that must be preprocessed ๐ .file.miiโ Objective-C++ source that should not be preprocessed (yep, same as above ๐).file.hh,file.H,file.hp,file.hxx,file.hpp,file.HPP,file.h++,file.tccโ C++ headers that get turned into a precompiled header or an Ada spec ๐ง.file.f,file.for,file.ftnโ Fixed form Fortran source that should not be preprocessed ๐.file.F,file.FOR,file.fpp,file.FPP,file.FTNโ Fixed form Fortran source that must be preprocessed, using the traditional preprocessor ๐ฅ.file.f90,file.f95,file.f03,file.f08โ Free form Fortran source that should not be preprocessed ๐.file.F90,file.F95,file.F03,file.F08โ Free form Fortran source that must be preprocessed, using the traditional preprocessor ๐.file.goโ Go source code ๐ฉต.file.brigโ BRIG files, which are the binary representation of HSAIL ๐ค.file.dโ D source code ๐.file.diโ A D interface file ๐.file.ddโ D documentation code, aka Ddoc ๐.file.adsโ An Ada source file with a library unit declaration (a declaration of a package, subprogram, or generic, or a generic instantiation), or a library unit renaming declaration (a package, generic, or subprogram renaming declaration). These are also called specs ๐ก๏ธ.file.adbโ An Ada source file containing a library unit body (a subprogram or package body). These are also called bodies ๐ช.file.sโ Assembler code โญ.file.S,file.sxโ Assembler code that must be preprocessed ๐ซถ.otherโ An object file that gets fed straight into linking. Any file name with no recognized suffix gets treated this way ๐ง.
You can also be super explicit about the input language with the -x option, instead of letting the compiler guess from the file name suffix ๐ต๏ธโโ๏ธ.
-x languageโ Tells gcc the language for the input files that come after it, instead of picking one from the suffix. It applies to every following input file until the next-xoption. The possible values forlanguageare:
c c-header cpp-output
c++ c++-header c++-cpp-output
objective-c objective-c-header objective-c-cpp-output
objective-c++ objective-c++-header objective-c++-cpp-output
assembler assembler-with-cpp
ada
d
f77 f77-cpp-input f95 f95-cpp-input
go
brig
-x noneโ Turns off any language specification, so the files after it get handled by their suffixes, just like they would if-xhad never been used at all ๐งน.
If you only want some stages of compilation, you can use -x (or filename suffixes) to tell gcc where to start, then pick one of -c, -S, or -E to say where it should stop ๐. Heads up: some combos (like -x cpp-output -E) make gcc do absolutely nothing ๐.
-cโ Compiles or assembles the source files but does not link. The linking stage just doesn't happen ๐ โโ๏ธ. You get an object file for each source file.
By default, the object file name for a source file is made by swapping the suffix .c, .i, .s, etc. for .o ๐ท.
Unrecognized input files that don't need compiling or assembling are ignored ๐ซ .
-Sโ Stops after the actual compilation stage and does not assemble ๐จ. You get an assembler code file for each non-assembler input file.
By default, the assembler file name is made by swapping the suffix .c, .i, etc. for .s ๐ญ.
Input files that don't need compiling are ignored ๐.
-Eโ Stops after the preprocessing stage and does not run the compiler proper ๐งผ. The output is preprocessed source code, which gets sent to standard output.
Input files that don't need preprocessing are ignored ๐ค.
-o fileโ Puts the output infile. This works for whatever you're making, whether that's an executable, an object file, an assembler file, or preprocessed C code ๐.
If you don't use -o, the defaults are: an executable goes in a.out, the object file for source.suffix goes in source.o, its assembler file goes in source.s, a precompiled header file goes in source.suffix.gch, and all the preprocessed C source goes to standard output ๐ค.
-vโ Prints (on standard error output) the commands that get run for each stage of compilation ๐. It also prints the version number of the compiler driver program, the preprocessor, and the compiler proper ๐ท๏ธ.-###โ Basically-v, but the commands don't actually run ๐ . Arguments get quoted unless they only contain alphanumeric characters or"./-_". This is super useful for shell scripts that want to capture the driver-generated command lines ๐.--helpโ Prints (on standard output) a description of the command-line options gcc understands ๐. If-vis also specified,--helpgets passed along to the various processes gcc invokes, so they can show the options they accept ๐ช. If-Wextrawas specified before--help, command-line options with no documentation get displayed too ๐ต๏ธ.--target-helpโ Prints (on standard output) the target-specific command-line options for each tool ๐ฏ. For some targets, extra target-specific info might get printed too โจ.--help={class|[^]qualifier}[,...]โ Prints (on standard output) the command-line options the compiler understands that fit all of the classes and qualifiers you specify ๐. These are the supported classes:optimizersโ Shows all the optimization options the compiler supports ๐.warningsโ Shows all the options that control warning messages ๐จ.targetโ Shows target-specific options ๐ฏ. Unlike--target-help, target-specific options of the linker and assembler are not shown, because those tools don't support the extended--help=syntax yet ๐.paramsโ Shows the values the--paramoption recognizes ๐งฎ.languageโ Shows the options supported forlanguage, wherelanguageis the name of one of the languages this version of GCC supports ๐.commonโ Shows the options that are common to all languages ๐ค.
These are the supported qualifiers:
undocumentedโ Shows only the options that are undocumented ๐ซฃ.joinedโ Shows options that take an argument appearing after an equal sign in the same continuous piece of text, like--help=target๐.separateโ Shows options that take an argument appearing as a separate word right after the original option, like-o output-fileโ๏ธ.
So if you want every undocumented target-specific switch the compiler supports, use:
--help=target,undocumented
You can flip a qualifier by putting a ^ in front of it ๐. For example, to see 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 be made up solely of inverted qualifiers ๐
โโ๏ธ.
You can combine several classes, but that usually narrows things down so much there's nothing to show ๐. One case where it actually works is when one of the classes is target. For example, to show all the target-specific optimization options, use:
--help=target,optimizers
You can repeat the --help= option on the command line ๐. Each one shows its requested class of options, skipping anything already displayed. If --help is also anywhere on the command line, it takes precedence over any --help= option ๐.
If -Q appears on the command line before --help=, the descriptive text changes ๐ช. Instead of describing the options, it tells you whether each option is enabled, disabled, or set to a specific value (assuming the compiler knows that at the point where --help= is used).
Here's a truncated example from the ARM port of gcc ๐ฆพ:
% gcc -Q -mabi=2 --help=target -c
The following options are target specific:
-mabi= 2
-mabort-on-noreturn [disabled]
-mapcs [disabled]
The output is sensitive to previous command-line options, so you can find out which optimizations are enabled at -O2 by using:
-Q -O2 --help=optimizers
Or, if you want to see which binary optimizations -O3 enables, you can compare the two levels like this ๐ง:
gcc -c -Q -O3 --help=optimizers > /tmp/O3-opts
gcc -c -Q -O2 --help=optimizers > /tmp/O2-opts
diff /tmp/O2-opts /tmp/O3-opts | grep enabled
--versionโ Displays the version number and copyrights of the GCC you invoked ๐.-pass-exit-codesโ okay so normallygccjust exits with1if any phase of the compiler comes back with a non-success return code ๐ฅฑ. But if you add-pass-exit-codes, it instead returns the numerically highest error that any phase reported. And the C, C++, and Fortran front ends return4if they hit an internal compiler error ๐.-pipeโ use pipes instead of temporary files to pass stuff between the stages of compilation ๐ง. Heads up though, this breaks on some systems where the assembler can't read from a pipe. The GNU assembler has zero trouble with it tho โจ.-specs=fileโ processfileafter the compiler reads in the standard specs file, so you can override the defaults thegccdriver uses to decide which switches get passed tocc1,cc1plus,as,ld, etc. ๐ You can stack more than one-specs=file, and they get processed in order, left to right.-wrapperโ invoke all subcommands under a wrapper program ๐ฆ. The wrapper's name and its parameters go in one comma separated list. Here's the vibe:
gcc -c t.c -wrapper gdb,--args
That runs every gcc subprogram under gdb --args, so the cc1 call turns into gdb --args cc1 .... ๐
-ffile-prefix-map=old=newโ when compiling files that live in directoryold, record any references to them in the compilation result as if they lived in directorynewinstead ๐. Using this is the same as specifying all the individual-f*-prefix-mapoptions. It's a total slay for reproducible builds that don't care about location. See also-fmacro-prefix-mapand-fdebug-prefix-map.-fplugin=name.soโ load the plugin code inname.so, which is assumed to be a shared object the compiler willdlopen. The base name of the shared object is used to identify the plugin when parsing arguments (see-fplugin-arg-name-key=valuebelow). Each plugin should define the callback functions specified in the Plugins API ๐.-fplugin-arg-name-key=valueโ defines an argument calledkeywith a value ofvaluefor the plugin callednameโจ.-fdump-ada-spec[-slim]โ for C and C++ source and include files, generate corresponding Ada specs ๐ธ.-fada-spec-parent=unitโ used together with-fdump-ada-spec[-slim]above, this generates Ada specs as child units of the parentunit๐งธ.-fdump-go-spec=fileโ for input files in any language, generate corresponding Go declarations infile. You getconst,type,var, andfuncdeclarations, which is a super useful starting point if you want to write a Go interface to code written in some other language ๐.@fileโ read command-line options fromfile, and the options read get inserted right where the original@fileoption was ๐ซถ. Iffiledoesn't exist or can't be read, then the option gets treated literally and isn't removed. Options infileare separated by whitespace. You can put a whitespace character inside an option by surrounding the entire option in single or double quotes. Any character (backslash included) can be included by prefixing it with a backslash. The file can even contain more@fileoptions of its own, and those get processed recursively ๐.
๐ Compiling C++ Programs ๐
C++ source files usually 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 does not 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 with the name c++ ๐.
When you compile C++ programs, you can use many of the same command-line options you'd use for programs in any language, or command-line options meaningful for C and related languages, or options that only mean something 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 equivalent to-std=c90, and in C++ mode it's equivalent to-std=c++98๐. It turns off certain GCC features that are incompatible with ISO C90 (when compiling C code) or standard C++ (when compiling C++ code), such as theasmandtypeofkeywords, plus predefined macros likeunixandvaxthat identify the type of system you're using. It also enables the undesirable and rarely used ISO trigraph feature. For the C compiler, it disables recognition of C++ style//comments as well as theinlinekeyword ๐.- The alternate keywords
__asm__,__extension__,__inline__and__typeof__keep working despite-ansi. You wouldn't want to use them in an ISO C program, of course, but it's useful to put them 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
-ansioption does not cause non-ISO programs to be rejected gratuitously. For that,-Wpedanticis required in addition to-ansi๐ซ . - The macro
__STRICT_ANSI__is predefined when the-ansioption is used. Some header files may notice this macro and refrain from declaring certain functions or defining certain macros that the ISO standard doesn't call for. This avoids interfering with any programs that might use these names for other things ๐คซ. - Functions that are normally built in but don't have semantics defined by ISO C (such as
allocaandffs) are not built-in functions when-ansiis used ๐ซ.
- The alternate keywords
-std=โ determine the language standard. This option is currently only supported when compiling C or C++ ๐.- The compiler can accept several base standards, like
c90orc++98, plus GNU dialects of those standards, likegnu90orgnu++98. When a base standard is specified, the compiler accepts all programs following that standard, plus those using GNU extensions that don't contradict it. For example,-std=c90turns off certain GCC features that are incompatible with ISO C90, such as theasmandtypeofkeywords, but not other GNU extensions that have no meaning in ISO C90, like omitting the middle term of a?:expression ๐ฐ. - On the other hand, when a GNU dialect of a standard is specified, every feature the compiler supports is enabled, even when those features change the meaning of the base standard. As a result, some strict-conforming programs may get rejected ๐ฌ.
- The particular standard is used by
-Wpedanticto identify which features are GNU extensions for that version of the standard. For example,-std=gnu90 -Wpedanticwarns about C++ style//comments, while-std=gnu99 -Wpedanticdoes not โญ.
- The compiler can accept several base standards, like
A value for this option must be provided. Possible values are:
c90,c89,iso9899:1990โ supports all ISO C90 programs (certain GNU extensions that conflict with ISO C90 are disabled). Same as-ansifor C code ๐ธ.iso9899:199409โ ISO C90 as modified in amendment 1.c99,c9x,iso9899:1999,iso9899:199xโ ISO C99. This standard is substantially completely supported, modulo bugs and floating-point issues (mainly but not entirely relating to optional C99 features from Annexes F and G). Seehttp://gcc.gnu.org/c99status.htmlfor more information. The namesc9xandiso9899:199xare deprecated ๐ฅ.c11,c1x,iso9899:2011โ ISO C11, the 2011 revision of the ISO C standard. This standard is substantially completely supported, modulo bugs, floating-point issues (mainly but not entirely relating to optional C11 features from Annexes F and G) and the optional Annexes K (Bounds-checking interfaces) and L (Analyzability). The namec1xis deprecated ๐ท.c17,c18,iso9899:2017,iso9899:2018โ ISO C17, the 2017 revision of the ISO C standard (published in 2018). This standard is the same as C11 except for corrections of defects (all of which are also applied with-std=c11) and a new value of__STDC_VERSION__, so it's supported to the same extent as C11 ๐.c2xโ the next version of the ISO C standard, still under development. Support for this version is experimental and incomplete ๐งช.gnu90,gnu89โ GNU dialect of ISO C90 (including some C99 features) ๐.gnu99,gnu9xโ GNU dialect of ISO C99. The namegnu9xis deprecated ๐ฅ.gnu11,gnu1xโ GNU dialect of ISO C11. The namegnu1xis deprecated ๐ฅ.gnu17,gnu18โ GNU dialect of ISO C17. This is the default for C code ๐.gnu2xโ the next version of the ISO C standard, still under development, plus GNU extensions. Support for this version is experimental and incomplete ๐งช.c++98,c++03โ the 1998 ISO C++ standard plus the 2003 technical corrigendum and some additional defect reports. Same as-ansifor C++ code ๐ฆ.gnu++98,gnu++03โ GNU dialect of-std=c++98๐.c++11,c++0xโ the 2011 ISO C++ standard plus amendments. The namec++0xis deprecated ๐ฅ.gnu++11,gnu++0xโ GNU dialect of-std=c++11. The namegnu++0xis deprecated ๐ฅ.c++14,c++1yโ the 2014 ISO C++ standard plus amendments. The namec++1yis deprecated ๐ฅ.gnu++14,gnu++1yโ GNU dialect of-std=c++14. This is the default for C++ code. The namegnu++1yis deprecated ๐.c++17,c++1zโ the 2017 ISO C++ standard plus amendments. The namec++1zis deprecated ๐ฅ.
gnu++17,gnu++1z: okay so this is the GNU flavour of-std=c++17๐. Heads up, the namegnu++1zis deprecated โ ๏ธ.c++2a: the next revision of the ISO C++ standard, tentatively planned for 2020 โจ. Support is highly experimental ๐งช and will almost certainly change in incompatible ways in future releases ๐.gnu++2a: the GNU dialect of-std=c++2a๐. Same energy: highly experimental, and almost certainly going to change in incompatible ways in future releases ๐ญ.-fgnu89-inlineโ this tells GCC to use the traditional GNU semantics forinlinefunctions when you're in C99 mode ๐ .- Using it is roughly the same as adding the
gnu_inlinefunction attribute to every inline function ๐ฆ.
- Using it is roughly the same as adding the
-fno-gnu89-inlineโ the opposite move ๐ โโ๏ธ. It tells GCC to use the C99 semantics forinlinewhen you're in C99 orgnu99mode, which is the default behaviour anyway ๐ธ. This option is not supported in-std=c90or-std=gnu90mode.- The macros
__GNUC_GNU_INLINE__and__GNUC_STDC_INLINE__can be used to check which semantics are in effect forinlinefunctions ๐.
- The macros
-fpermitted-flt-eval-methods=styleโ bestie, this one is a whole mood ๐ง . ISO/IEC TS 18661-3 adds new permissible values forFLT_EVAL_METHOD, which 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 ๐. These new values are a superset of what C99/C11 allows, and C99/C11 doesn't specify what other positive values mean, so C11 code might not have been written with them in mind ๐คทโโ๏ธ.- This option decides whether the compiler allows only the
FLT_EVAL_METHODvalues from C99/C11, or the extended set from ISO/IEC TS 18661-3 โจ. styleis eitherc11orts-18661-3, as appropriate ๐.- The default in a standards-compliant mode (
-std=c11or similar) is-fpermitted-flt-eval-methods=c11๐. - The default in a GNU dialect (
-std=gnu11or similar) is-fpermitted-flt-eval-methods=ts-18661-3๐.
- This option decides whether the compiler allows only the
-aux-info filenameโ output to the given filename a list of prototyped declarations for all functions declared and/or defined in a translation unit, including the ones in header files ๐. This option is silently ignored in any language other than C ๐.- Besides the declarations, the file has comments showing where each one came from (source file and line) ๐บ๏ธ.
- The first character after the line number and the colon tells you whether the declaration was implicit, prototyped or unprototyped:
I,Nfor new, orOfor old, respectively ๐ค. - The character right after that tells you whether it came from a declaration or a definition:
CorF, respectively ๐งพ. - For function definitions, there's also a K&R-style list of arguments, followed by their declarations, inside comments after the declaration ๐.
-fallow-parameterless-variadic-functionsโ accepts variadic functions without named parameters ๐.- You can define one of these, but it's not super useful, because you can't read the arguments ๐ฅฒ.
- This is only supported for C, since C++ allows this construct too ๐ .
-fno-asmโ stopsasm,inlineortypeoffrom being recognized as keywords, so your code can use those words as identifiers ๐. You can use__asm__,__inline__and__typeof__instead ๐.-ansiimplies-fno-asmโจ.- In C++, this switch only affects the
typeofkeyword, sinceasmandinlineare standard keywords ๐ง. You may want to use-fno-gnu-keywordsinstead, which has the same effect ๐. - In C99 mode (
-std=c99or-std=gnu99), this switch only affects theasmandtypeofkeywords, sinceinlineis a standard keyword in ISO C99 ๐ฆ.
- In C++, this switch only affects the
-fno-builtin,-fno-builtin-functionโ stops GCC from recognizing built-in functions that don't begin with__builtin_as a prefix ๐ซ.- Normally GCC generates special code for certain built-in functions so they run more efficiently ๐. For instance, calls to
allocamay turn into single instructions that adjust the stack directly, and calls tomemcpymay become inline copy loops ๐. The result is often smaller and faster, but because the function calls no longer show up as calls, you can't set a breakpoint on them, and you can't change how they behave by linking against a different library ๐ค. - When a function is recognized as built-in, GCC can also use what it knows about that function to warn you about problems with calls to it, or to generate more efficient code, even if the result still contains calls to that function ๐. For example, you get warnings with
-Wformatfor bad calls toprintfwhenprintfis built in andstrlenis known not to modify global memory ๐. - With
-fno-builtin-function, only that one built-in function gets disabled. The function name must not begin with__builtin_. If you name a function that isn't built-in in this version of GCC, the option is ignored ๐คทโโ๏ธ. - There's no matching
-fbuiltin-functionoption. If you want to pick built-in functions selectively when using-fno-builtinor-ffreestanding, you can define macros like these ๐ง :
- Normally GCC generates special code for certain built-in functions so they run more efficiently ๐. For instance, calls to
#define abs(n) __builtin_abs ((n))
#define strcpy(d, s) __builtin_strcpy ((d), (s))
-fgimpleโ enables parsing of function definitions marked with__GIMPLE๐งช. This is an experimental feature that lets you unit test GIMPLE passes ๐ซถ.-fhostedโ asserts that compilation targets a hosted environment ๐ . This implies-fbuiltin๐. A hosted environment is one where the entire standard library is available, and wheremainhas a return type ofint๐. Examples are nearly everything except a kernel. This is equivalent to-fno-freestanding๐.-ffreestandingโ asserts that compilation targets a freestanding environment ๐ธ. This implies-fno-builtin๐ซ. A freestanding environment is one where the standard library may not exist, and program startup may not necessarily be atmain๐คฏ. The most obvious example is an OS kernel ๐ฅ๏ธ. This is equivalent to-fno-hosted๐.-fopenaccโ enables handling of OpenACC directives#pragma accin C/C++ and!$accin Fortran ๐ธ. When you specify-fopenacc, the compiler generates accelerated code according to the OpenACC Application Programming Interface v2.0<https://www.openacc.org>โจ. This option implies-pthread, so it's only supported on targets that support-pthread๐งต.-fopenacc-dim=geomโ sets default compute dimensions for parallel offload regions that don't explicitly specify their own ๐. The geom value is a triple of:-separated sizes, in the ordergang,workerandvector๐ข. A size can be left out, so the target-specific default gets used instead ๐ .-fopenmpโ enables handling of OpenMP directives#pragma ompin C/C++ and!$ompin Fortran ๐. When you specify-fopenmp, the compiler generates parallel code according to the OpenMP Application Program Interface v4.5<https://www.openmp.org>๐งต. This option implies-pthread, so it's only supported on targets that support-pthread๐ซถ.-fopenmpalso implies-fopenmp-simd๐.-fopenmp-simdโ enables handling of OpenMP's SIMD directives written as#pragma ompin C/C++ and!$ompin Fortran ๐ฆ. Other OpenMP directives are ignored ๐.-fgnu-tmโ when you specify-fgnu-tm, the compiler generates code for the Linux variant of Intel's current Transactional Memory ABI specification document (Revision 1.1, May 6 2009) ๐. This is an experimental feature, and its interface may change in future versions of GCC as the official specification changes ๐งช. Not all architectures are supported for this feature, so please check first ๐ซถ.- For more information on GCC's support for transactional memory, (the sentence just kind of stops there in the original ๐)
- Heads up: transactional memory isn't supported with non-call exceptions (
-fnon-call-exceptions) โ ๏ธ.
-fms-extensionsโ accepts some non-standard constructs that show up in Microsoft header files ๐ช.- In C++ code, this lets member names in structures be similar to earlier type declarations ๐คญ. Like this:
typedef int UOW;
struct ABC {
UOW UOW;
};
- Some cases of unnamed fields in structures and unions are only accepted with this option ๐ซฃ.
- This option is off for all targets except x86 targets using
ms-abi๐ .
-fplan9-extensionsโ accepts some non-standard constructs used in Plan 9 code ๐.- This enables
-fms-extensions๐. It also permits passing pointers to structures with anonymous fields to functions that expect pointers to elements of the type of that field ๐, and it permits referring to anonymous fields declared using atypedef๐งฉ. - This is only supported for C, not C++ ๐ โโ๏ธ.
- This enables
-fcond-mismatchโ allows conditional expressions with mismatched types in the second and third arguments ๐คธ. The value of such an expression isvoid๐ซฅ. This option is not supported for C++ ๐.-flax-vector-conversionsโ allows implicit conversions between vectors with differing numbers of elements and/or incompatible element types ๐. This option should not be used for new code ๐ซ.-funsigned-charโ lets the typecharbe unsigned, likeunsigned char๐.- Each kind of machine has a default for what
charshould be. It's either likeunsigned charby default, or likesigned charby default ๐ฅ๏ธ. - Ideally, a portable program should always use
signed charorunsigned charwhen it depends on the signedness of an object ๐ง . But lots of programs were written to use plaincharand expect it to be signed, or expect it to be unsigned, depending on the machines they were written for ๐ฉ. This option, and its inverse, lets you make those programs work with the opposite default ๐. - The type
charis always a distinct type from each ofsigned charandunsigned char, even though its behaviour is always just like one of those two ๐งฌ.
- Each kind of machine has a default for what
-fsigned-charโ lets the typecharbe signed, likesigned charโ๏ธ.- This is equivalent to
-fno-unsigned-char, which is the negative form of-funsigned-char๐. Likewise,-fno-signed-charis equivalent to-funsigned-charโจ.
- This is equivalent to
-fsigned-bitfields,-funsigned-bitfields,-fno-signed-bitfields,-fno-unsigned-bitfieldsโ okay so these decide whether a bit-field is signed or unsigned ๐ when the declaration doesn't already saysignedorunsigned. By default it's signed, and honestly that makes sense bestie, because basic integer types likeintare signed too ๐ซถ-fsso-struct=endiannessโ set the default scalar storage order of structs and unions to whatever endianness you pick ๐ฆ The options arebig-endian,little-endian, andnative(the target's own endianness, which is the default). Heads up, this one isn't supported for C++ ๐
โ ๏ธ Warning: using -fsso-struct makes GCC generate code that is not binary compatible with code built without it, if the endianness you picked isn't the target's native one. Be careful with that one, bestie ๐ญ
โจ Options Controlling C++ Dialect โจ
This section is all about the command-line options that only matter for C++ programs ๐
Also, most GNU compiler options work no matter what language your program is in. For example, you could compile a file called firstClass.C like this:
g++ -g -fstrict-enums -O -c firstClass.C
In that example only -fstrict-enums is meant just for C++ programs ๐ You can use the other options with any language GCC supports. Some options for compiling C programs, like -std, are also relevant for C++ programs too, so don't sleep on those ๐
Here's the list of options that are only for compiling C++ programs ๐
-fabi-version=nโ use versionnof the C++ ABI ๐ The default is version0.- Version
0refers to the version that conforms most closely to the C++ ABI specification. Because of that, the ABI you get with version0will change between versions of G++ as ABI bugs get fixed ๐ง - Version
1is the version of the C++ ABI that first showed up in G++ 3.2 โจ - Version
2is the version of the C++ ABI that first showed up in G++ 3.4, and it was the default all the way through G++ 4.9 ๐ - Version
3fixes an error in mangling a constant address used as a template argument ๐ธ - Version
4, which first appeared in G++ 4.5, adds a standard mangling for vector types ๐ - Version
5, which first appeared in G++ 4.6, fixes the mangling of attribute const/volatile on function pointer types,decltypeof a plain decl, and using a function parameter in the declaration of another parameter ๐ฆ - Version
6, which first appeared in G++ 4.7, fixes 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, treatsnullptr_tas a builtin type and fixes the mangling of lambdas in default argument scope ๐ - Version
8, which first appeared in G++ 4.9, fixes the substitution behavior of function types with function-cv-qualifiers ๐ง - Version
9, which first appeared in G++ 5.2, fixes the alignment ofnullptr_tโญ - Version
10, which first appeared in G++ 6.1, adds mangling of attributes that affect type identity, like ia32 calling convention attributes (e.g.stdcall) ๐ - Version
11, which first appeared in G++ 7, fixes the mangling ofsizeof...expressions and operator names. For multiple entities with the same name inside a function that are declared in different scopes, the mangling now changes starting with the twelfth occurrence. It also implies-fnew-inheriting-ctors๐ซถ - Version
12, which first appeared in G++ 8, fixes 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 that accidental change from version12โ - See also
-Wabi. ๐
- Version
-fabi-compat-version=nโ on targets that support strong aliases, G++ works around mangling changes by making an alias with the correct mangled name whenever it defines a symbol with an incorrect one ๐ช This switch picks which ABI version to use for that alias.- With
-fabi-version=0(the default), this defaults to11(GCC 7 compatibility). If another ABI version is explicitly selected, this defaults to0. For compatibility with GCC versions 3.2 through 4.9, use-fabi-compat-version=2๐ - If this option isn't provided but
-Wabi=nis, that version is used for the compatibility aliases. If this option is provided along with-Wabi(without a version), the version from this option gets used for the warning ๐ง
- With
-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 band-aid than a lifestyle ๐ฉน-faligned-newโ enables support for C++17newof types that need more alignment thanvoid* ::operator new(std::size_t)provides ๐ You can pass a number like-faligned-new=32to say how much alignment (in bytes) that function gives you, but honestly few users will ever need to change the default ofalignof(std::max_align_t).- This flag is enabled by default for
-std=c++17๐
- This flag is enabled by default for
-fchar8_t,-fno-char8_tโ enables support forchar8_tas adopted for C++2a ๐ That includes a brand-newchar8_tfundamental type, changes to the types of UTF-8 string and character literals, new signatures for user-defined literals, associated standard library updates, and new__cpp_char8_tand__cpp_lib_char8_tfeature test macros.
This option lets you overload functions for ordinary and UTF-8 strings, like this:
int f(const char *); // #1
int f(const char8_t *); // #2
int v1 = f("text"); // Calls #1
int v2 = f(u8"text"); // Calls #2
It also introduces new signatures for user-defined literals:
int operator""_udl1(char8_t);
int v3 = u8'x'_udl1;
int operator""_udl2(const char8_t*, std::size_t);
int v4 = u8"text"_udl2;
template<typename T, T...> int operator""_udl3();
int v5 = u8"text"_udl3;
โ ๏ธ Heads up: the change to the types of UTF-8 string and character literals breaks compatibility with ISO C++11 and later standards. For example, this code is fine under ISO C++11, but it's ill-formed when -fchar8_t is specified ๐
char ca[] = u8"xx"; // error: char-array initialized from wide
// string
const char *cp = u8"xx";// error: invalid conversion from
// `const char8_t*' to `const char*'
int f(const char*);
auto v = f(u8"xx"); // error: invalid conversion from
// `const char8_t*' to `const char*'
std::string s{u8"xx"}; // error: no matching function for call to
// `std::basic_string<char>::basic_string()'
using namespace std::literals;
s = u8"xx"s; // error: conversion from
// `basic_string<char8_t>' to non-scalar
// type `basic_string<char>' requested
-fcheck-newโ checks that the pointer returned byoperator newis non-null before trying to modify the storage it allocated ๐ This check is normally unnecessary, because the C++ standard saysoperator newonly returns 0 if it's declaredthrow(). In that case the compiler always checks the return value even without this option. In every other case, whenoperator newhas a non-empty exception specification, memory exhaustion is signalled by throwingstd::bad_alloc. See alsonew (nothrow)๐ง-fconceptsโ enables support for the C++ Extensions for Concepts Technical Specification, ISO 19217 (2015), which lets you write code like this ๐งฉ
template <class T> concept bool Addable = requires (T t) { t + t; };
template <Addable T> T add (T a, T b) { return a + b; }
-fconstexpr-depth=nโ sets the maximum nested evaluation depth for C++11constexprfunctions ton๐ A limit is needed to catch endless recursion during constant expression evaluation. The minimum the standard specifies is512.-fconstexpr-loop-limit=nโ sets the maximum number of iterations for a loop in C++14constexprfunctions ton๐ A limit is needed to catch infinite loops during constant expression evaluation. The default is262144(1<<18).-fconstexpr-ops-limit=nโ sets the maximum number of operations during a singleconstexprevaluation ๐งฎ Even when the iterations of a single loop are capped by the limit above, you can still run into trouble. If there are several nested loops that each have lots of iterations (but are still under that limit), or if a loop body or even code outside a loop needs too many expressions evaluated, theconstexprevaluation might take way too long. The default is33554432(1<<25).-fdeduce-init-listโ enables deducing a template type parameter asstd::initializer_listfrom a brace-enclosed initializer list ๐ Like this:
template <class T> auto forward(T t) -> decltype (realfn (t))
{
return realfn (t);
}
void f()
{
forward({1,2}); // call forward<std::initializer_list<int>>
}
This deduction was implemented as a possible extension to the originally proposed C++11 semantics, but it didn't make it into the final standard, so it's disabled by default. > โ ๏ธ This option is deprecated, and it may be removed in a future version of G++ ๐
-fno-elide-constructorsโ the C++ standard lets an implementation skip creating a temporary that's only used to initialize another object of the same type ๐ซ Specifying this option turns that optimization off and forces G++ to call the copy constructor in all cases. It also makes G++ call trivial member functions that would otherwise be expanded inline.
In C++17 the compiler is required to omit those temporaries, but this option still affects trivial member functions ๐ธ
-fno-enforce-eh-specsโ okay so this one tells the compiler to skip the run-time checks for exception specifications ๐ It technically breaks the C++ standard, but it can shrink code size in production builds, kinda like definingNDEBUG๐
๐ bestie, read this part: this does NOT give your code permission to throw exceptions that break the exception specifications. The compiler still optimizes based on those specs, so throwing an unexpected exception is undefined behavior at run time.
-fextern-tls-init,-fno-extern-tls-initโ โจ the C++11 and OpenMP standards letthread_localandthreadprivatevariables have dynamic (runtime) initialization. To make that work, every use of one of these variables goes through a wrapper function that does the setup. When the use and the definition live 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 lot of overhead even if the variable doesn't actually need dynamic init ๐ญ If you can be 100% sure no use in a non-defining TU needs to trigger dynamic initialization (because the variable is statically initialized, or a use in the defining TU always runs before any use elsewhere), you can skip that overhead with-fno-extern-tls-init๐ซถ- Default: on targets that support symbol aliases, the default is
-fextern-tls-init. On targets that do not support symbol aliases, the default is-fno-extern-tls-init.
- Default: on targets that support symbol aliases, the default is
-fno-gnu-keywordsโ no moretypeofas a keyword, so you can use it as a normal identifier ๐ง You can use__typeof__instead. This is already implied by the strict ISO C++ dialects like-ansi,-std=c++98,-std=c++11, etc.-fno-implicit-templatesโ the compiler won't emit code for non-inline templates that get instantiated implicitly (aka just by using them) ๐ฆ Only explicit instantiations get code. If you go this route, you need to structure your code so you include every necessary explicit instantiation, or you'll get undefined symbols at link time ๐ฌ-fno-implicit-inline-templatesโ same vibe, but for inline templates. No code for implicit instantiations of those either ๐ By default, inlines get handled differently so that compiles with and without optimization need the same set of explicit instantiations.-fno-implement-inlinesโ to save space, out-of-line copies of inline functions controlled by#pragma implementationdon't get emitted ๐ธ Heads up: this causes linker errors if those functions aren't inlined everywhere they're called.-fms-extensionsโ disablesWpedanticwarnings about constructs used in MFC, like implicitintand getting a pointer to a member function via non-standard syntax ๐-fnew-inheriting-ctorsโ enables the P0136 adjustment to the semantics of C++11 constructor inheritance ๐ This is part of C++17, but it's also considered a Defect Report against C++11 and C++14. It's enabled 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 โจ This lets a template with default template arguments be used as an argument for a template template parameter that has fewer template parameters. It's enabled by default for-std=c++17.-fno-nonansi-builtinsโ disables built-in declarations of functions that aren't mandated by ANSI/ISO C ๐ That includesffs,alloca,_exit,index,bzero,conjf, and other related functions.-fnothrow-optโ treats athrow()exception specification as if it were anoexceptspecification ๐ฅ This shrinks or even eliminates the text size overhead compared to a function with no exception specification. If the function has local variables with non-trivial destructors, the exception specification actually makes the function smaller, because the EH cleanups for those variables can be optimized away. The semantic effect: an exception thrown out of a function with that specification results in a call toterminateinstead ofunexpected.-fno-operator-namesโ the operator name keywordsand,bitand,bitor,compl,not,or, andxorare NOT treated as keyword synonyms anymore ๐-fno-optional-diagsโ disables diagnostics the standard says a compiler doesn't need to issue ๐ง Right now the only one G++ issues like this is the one for a name having multiple meanings within a class.-fpermissiveโ downgrades some diagnostics about nonconformant code from errors to warnings ๐ฆ So-fpermissivelets some nonconforming code compile. Chaotic, but sometimes you need it.-fno-pretty-templatesโ when an error message refers to a specialization of a function template, the compiler normally prints the template signature, followed by the template arguments and any typedefs or typenames in the signature. So you getvoid f(T) [with T = int]instead ofvoid f(int), which makes it clear which template is involved ๐ When an error message refers to a specialization of a class template, the compiler leaves out any template arguments that match that template's default arguments. If either of these behaviors makes errors harder to read instead of easier, use-fno-pretty-templatesto turn them off ๐
-frepoโ enables automatic template instantiation at link time ๐ This option also implies-fno-implicit-templates.-fno-rttiโ disables generating the info about every class with virtual functions that the C++ run-time type identification features need (dynamic_castandtypeid) ๐ If you don't use those parts of the language, you can save some space with this flag. Exception handling uses the same information, but G++ generates it only as needed. Thedynamic_castoperator still works for casts that don't require run-time type information, i.e. casts tovoid *or to unambiguous base classes.- > โ ๏ธ Mixing code compiled with
-frttiand code compiled with-fno-rttimay not work. For example, programs may fail to link if a class compiled with-fno-rttiis used as a base for a class compiled with-frtti.
- > โ ๏ธ Mixing code compiled with
-fsized-deallocationโ enables the built-in global declarations below, which were introduced in C++14 ๐ง
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
This is super useful for user-defined replacement deallocation functions that, for example, use the object's size to make deallocation faster โก It's enabled by default under -std=c++14 and above. The flag -Wsized-deallocation warns about places that might want to add a definition.
-fstrict-enumsโ lets the compiler optimize assuming that a value of an enumerated type can only be one of the enumeration's values ๐ธ (As defined in the C++ standard. Basically, that's a value that fits in the minimum number of bits needed to represent all the enumerators.) This assumption may not hold if the program uses a cast to turn an arbitrary integer into the enumerated type, so be careful ๐-fstrong-eval-orderโ evaluates member access, array subscripting, and shift expressions in left-to-right order, and assignment in right-to-left order, as adopted for C++17 ๐ It's enabled by default with-std=c++17.-fstrong-eval-order=someenables just the ordering of member access and shift expressions, and it's the default without-std=c++17.-ftemplate-backtrace-limit=nโ sets the maximum number of template instantiation notes shown for a single warning or error ton๐ The default value is10.-ftemplate-depth=nโ sets the maximum instantiation depth for template classes ton๐ A limit is needed to catch endless recursion during template class instantiation. ANSI/ISO C++ conforming programs must not rely on a maximum depth greater than17(which was changed to1024in C++11). The default value is900, because the compiler can run out of stack space before hitting1024in some situations ๐-fno-threadsafe-staticsโ doesn't emit the extra code that uses the routines from the C++ ABI for thread-safe initialization of local statics ๐งต You can use this to shave a little code size off code that doesn't need to be thread-safe.-fuse-cxa-atexitโ registers destructors for objects with static storage duration with the__cxa_atexitfunction instead of theatexitfunction ๐ This option is required for fully standards-compliant handling of static destructors, but it only works if your C library supports__cxa_atexit.-fno-use-cxa-get-exception-ptrโ doesn't use the__cxa_get_exception_ptrruntime routine ๐ This makesstd::uncaught_exceptionincorrect, but it's necessary if that runtime routine isn't available.-fvisibility-inlines-hiddenโ this switch tells the compiler that you won't try to compare pointers to inline functions or methods where the addresses of the two functions are taken in different shared objects ๐ฆ
GCC may then, effectively, mark inline methods with __attribute__ ((visibility ("hidden"))), so they don't show up in the export table of a DSO and don't need a PLT indirection when used inside that DSO. Turning this on can have a dramatic effect on the load and link times of a DSO, because it massively shrinks the dynamic export table when the library uses lots of templates ๐
The behavior isn't quite the same as marking the methods hidden directly. It doesn't affect static variables local to the function, and it doesn't make the compiler deduce that the function is defined in only one shared object.
You can give a method an explicit visibility to cancel the effect of the switch for that method. For example, if you do want to compare pointers to a particular inline method, mark it with default visibility. Marking the enclosing class with explicit visibility has no effect.
Explicitly instantiated inline methods are unaffected by this option, since their linkage might otherwise cross a shared library boundary ๐ซถ
-fvisibility-ms-compat ๐
Okay so this flag is giving main character energy ๐ฆ It tries to use visibility settings to make GCC's C++ linkage model match Microsoft Visual Studio's, so your code can play nice with MSVC stuff โจ
Turning it on makes these changes to GCC's linkage model:
- It sets the default visibility to "hidden", same as
-fvisibility=hidden. - Types, but not their members, are not hidden by default.
- The One Definition Rule gets relaxed for types without explicit visibility specifications that are defined in more than one shared object. Those declarations are allowed if they'd be allowed without this option ๐ซถ
In new code, it's better to use -fvisibility=hidden and only export the classes you actually want visible to the outside world ๐ธ Unfortunately, code might rely on the Visual Studio behavior, maybe even by accident ๐ญ
Some of the consequences: 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 also may not compare equal.
๐จ When this flag is given, it's a violation of the ODR to define types with the same name differently. Don't do it, bestie ๐
-fno-weak ๐ฅ
This one tells G++ to not use weak symbol support, even if the linker provides it. By default, G++ uses weak symbols when they're available. It only exists for testing and should not be used by end-users, because it gives inferior code and has no benefits. It may get removed in a future release of G++ ๐ค
-nostdinc++ ๐ง
Don't search for header files in the standard directories specific to C++, but do still search the other standard directories. (This is the option used when building the C++ library ๐ ๏ธ)
In addition, these optimization, warning, and code generation options only have meanings for C++ programs ๐
-Wabi (C, Objective-C, C++ and Objective-C++ only) ๐
Okay this one warns when G++ generates code that's probably not compatible with the vendor-neutral C++ ABI. G++ now defaults to updating the ABI with each major release, so normally -Wabi only warns if there's a check added later in a release series for an ABI issue that was found after the initial release. It'll warn about way more things if you select an older ABI version with -fabi-version=n.
You can also give -Wabi an explicit version number to warn about compatibility with a particular -fabi-version level, like -Wabi=2 to warn about changes relative to -fabi-version=2.
If an explicit version number is provided and -fabi-compat-version isn't specified, the version number from this option is used for compatibility aliases. If there's no explicit version number with this option, but -fabi-compat-version is specified, that version number gets used for ABI warnings.
Although an effort has been made to warn about all such cases, there are probably some cases that don't get warned about, even though G++ is generating incompatible code. There may also be cases where warnings get emitted even though the generated code is compatible ๐
โ ๏ธ You should rewrite your code to avoid these warnings if you're worried that code generated by G++ might not be binary compatible with code generated by other compilers.
Known incompatibilities in -fabi-version=2 (which was the default from GCC 3.4 to 4.9) include:
- A template with a non-type template parameter of reference type was mangled incorrectly:
extern int N;
template <int &> struct S {};
void n (S<N>) {2}
This was fixed in -fabi-version=3.
- SIMD vector types declared using
__attribute ((vector_size))were mangled in a non-standard way that doesn't allow for overloading of functions taking vectors of different sizes.
The mangling was changed in -fabi-version=4.
__attribute ((const))andnoreturnwere mangled as type qualifiers, anddecltypeof a plain declaration was folded away.
These mangling issues were fixed in -fabi-version=5.
- Scoped enumerators passed as arguments to a variadic function are promoted like unscoped enumerators, causing
va_argto complain. On most targets this doesn't actually affect the parameter passing ABI, 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. This led to name collisions when function pointers were used as template arguments.
This was fixed in -fabi-version=10, the default for GCC 6.1.
It also warns about psABI-related changes ๐ง The known psABI changes at this point include:
- For SysV/x86-64, unions with
long doublemembers are passed in memory as specified in psABI. For example:
union U {
long double ld;
int i;
};
union U is always passed in memory.
-Wabi-tag (C++ and Objective-C++ only) ๐
Warn when a type with an ABI tag is used in a context that doesn't have that ABI tag. For more on ABI tags, see C++ Attributes ๐
-Wctor-dtor-privacy (C++ and Objective-C++ only) ๐
Warn 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) ๐ซ
Warn when delete is 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) ๐ซ
Warn 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 of std::initializer_list that are likely to result in dangling pointers. The underlying array for an initializer_list is handled like a normal C++ temporary object, so it's super easy to accidentally keep a pointer to the array past the end of its lifetime. 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.
// 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.
-Wliteral-suffix (C++ and Objective-C++ only) ๐
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. This keeps things backwards compatible 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);
}
In this case, PRId64 is treated as a separate preprocessing token.
Also, it warns when a user-defined literal operator is declared with a literal suffix identifier that doesn't begin with an underscore. Literal suffix identifiers that don't begin with an underscore are reserved for future standardization, so hands off ๐ โโ๏ธ
This warning is enabled by default โจ
-Wlto-type-mismatch ๐งฉ
During link-time optimization, warn about type mismatches in global declarations from different compilation units. Requires -flto to be enabled. Enabled by default ๐
-Wno-narrowing(C++ and Objective-C++ only) โ okay so, for C++11 and later, narrowing conversions get flagged by default because the standard literally requires it ๐ A narrowing conversion from a constant slaps you with an error, and one from a non-constant gives a warning.-Wno-narrowingmutes that diagnostic ๐ It doesn't change what well-formed code means, though. Narrowing conversions are still ill-formed in SFINAE contexts, so don't get cocky ๐
Over in C++98, -Wnarrowing 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) โ this one is giving "the compiler knows things" energy ๐ง It warns when anoexcept-expression evaluates tofalsebecause of a call to a function that doesn't have a non-throwing exception specification (throw()ornoexcept), even though the compiler knows that function never actually throws โจ-Wnoexcept-type(C++ and Objective-C++ only) โ the C++17 glow-up wherenoexceptbecomes part of a function type. This warns if that feature changes the mangled name of a symbol compared to C++14 ๐ฆ It's enabled by-Wabiand-Wc++17-compat.
Here's the example, bestie:
template <class T> void f(T t) { t(); };
void g() noexcept;
void h() { f(g); }
In C++14, f calls f<void(*)()>, but in C++17 it calls f<void(*)()noexcept> ๐
-Wclass-memaccess(C++ and Objective-C++ only) โ main character warning, no cap ๐ It fires when the destination of a call to a raw memory function likememsetormemcpyis an object of class type, and when writing into that object might skip the class's non-trivial or deleted constructor or copy assignment, break const-correctness or encapsulation, or corrupt virtual table pointers. Messing with the raw bytes of these objects can violate invariants that the member functions are supposed to keep ๐ญ
Check out this one:
std::string str = "abc";
memset (&str, 0, sizeof str);
That memset call is undefined, because it modifies a non-trivial class object, so the compiler flags it ๐
The safe way to initialize or clear the storage of these objects is to use the appropriate constructor or assignment operator, if one is available ๐ซถ
-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 gets suppressed ๐
-Wnon-virtual-dtor(C++ and Objective-C++ only) โ warns when a class has virtual functions but an accessible non-virtual destructor, either on itself or on an accessible polymorphic base class ๐ฆ That means deleting a derived-class instance through a pointer to the class or base class is possible, but unsafe. 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 got deprecated in C++11 and removed in C++17. It's enabled by default with-std=c++17๐-Wreorder(C++ and Objective-C++ only) โ warns when the order of member initializers in your code doesn't match the order they actually have to run in ๐ง Like this:
struct A {
int i;
int j;
A(): j (0), i (1) { }
};
The compiler rearranges the member initializers for i and j to match the declaration order, and emits a warning about it. This warning is enabled by -Wall ๐
-Wno-pessimizing-move(C++ and Objective-C++ only) โ this warning is about a call tostd::movepreventing copy elision ๐ A typical copy elision scenario is returning from a function with a class return type, where the expression being returned is the name of a non-volatile automatic object, is not a function parameter, and has the same type as the function return type.
Here's the tea:
struct T {
...
};
T fn()
{
T t;
...
return std::move (t);
}
In this example, the std::move call prevents copy elision ๐ญ This warning is enabled by -Wall ๐ฅ
-Wno-redundant-move(C++ and Objective-C++ only) โ warns about redundant calls tostd::move. That's when a move would have happened even without thestd::movecall ๐ It happens because the compiler is forced to treat the object as an rvalue in certain situations, like returning a local variable where copy elision isn't applicable. Consider:
struct T {
...
};
T fn(T t)
{
...
return std::move (t);
}
Here, the std::move call is redundant ๐ Because G++ implements Core Issue 1579, here's another one:
struct T { // convertible to U
...
};
struct U {
...
};
U fn()
{
T t;
...
return std::move (t);
}
In this example, copy elision isn't applicable because the type of the returned expression and the function return type differ. Still, G++ treats the return value as if it were designated by an rvalue ๐ This warning is enabled by -Wextra โจ
-fext-numeric-literals(C++ and Objective-C++ only) โ okay, this one's about literal suffixes ๐ฆ It accepts imaginary, fixed-point, or machine-defined literal number suffixes as GNU extensions. When it's turned off, those suffixes get treated as C++11 user-defined literal numeric suffixes instead.
It's on by default for all pre-C++11 dialects and all GNU dialects: -std=c++98, -std=gnu++98, -std=gnu++11, -std=gnu++14. It's off by default for ISO C++11 onwards (-std=c++11, ...) ๐
The following -W... options are not affected by -Wall. Main character behavior: they need to be turned on on their own ๐
-Weffc++(C++ and Objective-C++ only) โ warns about violations of these style guidelines from Scott Meyers' Effective C++ series of books ๐- Define a copy constructor and an assignment operator for classes with dynamically-allocated memory.
- Prefer initialization to assignment in constructors.
- Have
operator=return a reference to*this. - Don't try to return a reference when you must return an object.
- Distinguish between prefix and postfix forms of increment and decrement operators.
- Never overload
&&,||, or,.
This option also enables -Wnon-virtual-dtor, which is also one of the Effective C++ recommendations. However, the check is extended to warn about the lack of a virtual destructor in accessible non-polymorphic base classes too ๐ซถ
When you select this option, be aware that the standard library headers don't obey all of these guidelines. Use grep -v to filter out those warnings ๐
-Wstrict-null-sentinel(C++ and Objective-C++ only) โ warns about using an uncastedNULLas a sentinel ๐ When you compile only with GCC, this is a valid sentinel, becauseNULLis defined to__null. It's a null pointer constant rather than a null pointer, but it's guaranteed to be the same size as a pointer. Still, this use isn't portable across different compilers ๐-Wno-non-template-friend(C++ and Objective-C++ only) โ disables warnings when non-template friend functions are declared within a template ๐ธ In very old versions of GCC that predate the ISO standard's 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. This warning exists to diagnose those compatibility problems, and it's enabled by default โจ-Wold-style-cast(C++ and Objective-C++ only) โ warns if an old-style (C-style) cast to a non-void type is used in a C++ program ๐ฆ The new-style casts (dynamic_cast,static_cast,reinterpret_cast, andconst_cast) are less vulnerable to unintended effects and much easier to search for, so this one is kinda a vibe check ๐-Woverloaded-virtual(C++ and Objective-C++ only) โ warns when a function declaration hides virtual functions from a base class ๐ For example:
struct A {
virtual void f();
};
struct B: public A {
void f(int);
};
The A class version of f is hidden in B, so code like this:
B* b;
b->f();
fails to compile ๐
-Wno-pmf-conversions(C++ and Objective-C++ only) โ disables the diagnostic for converting a bound pointer to member function to a plain pointer ๐-Wsign-promo(C++ and Objective-C++ only) โ warns when overload resolution chooses a promotion from an unsigned or enumerated type to a signed type, over a conversion to an unsigned type of the same size. Older versions of G++ tried to preserve unsignedness, but the standard mandates the current behavior ๐ง-Wtemplates(C++ and Objective-C++ only) โ warns when a primary template declaration is encountered ๐ Some coding rules disallow templates, so this can be used to enforce that rule. The warning is inactive inside a system header file, like the STL, so you can still use the STL ๐ You can also instantiate or specialize templates.-Wmultiple-inheritance(C++ and Objective-C++ only) โ warns when a class is defined with multiple direct base classes ๐ Some coding rules disallow multiple inheritance, so this can be used to enforce that rule. It's inactive inside a system header file, 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, and this can be used to enforce that rule. It's inactive inside a system header file, like the STL, so you can still use the STL ๐ธ You can also define classes that indirectly use virtual inheritance.-Wnamespacesโ okay so this one warns you whenever a namespace definition gets opened ๐ โโ๏ธ. Some coding rules straight up ban namespaces, and this flag helps enforce that rule ๐. It stays quiet inside system header files like the STL, so you can still use the STL ๐. You're also still allowed to use using directives and qualified names โจ.-Wno-terminate(C++ and Objective-C++ only) โ turns off the warning for a throw-expression that's going to immediately result in a call toterminate๐-Wno-class-conversion(C++ and Objective-C++ only) โ silences the warning for when a conversion function converts an object to the same type, to a base class of that type, or tovoid. That kind of conversion function will never get called ๐
โจ Options Controlling Objective-C and Objective-C++ Dialects โจ
๐ NOTE: This manual does not describe the Objective-C and Objective-C++ languages themselves. This section is only about the command-line options ๐ซถ
This section covers the command-line options that only mean something for Objective-C and Objective-C++ programs. You can also use most of the language-independent GNU compiler options too ๐ For example, you might compile a file some_class.m like this:
gcc -g -fgnu-runtime -O -c some_class.m
In this example, -fgnu-runtime is an option meant only for Objective-C and Objective-C++ programs. You can use the other options with any language GCC supports ๐
Note that since Objective-C is an extension of the C language, Objective-C compilations can also use options specific to the C front-end (e.g., -Wtraditional). Similarly, Objective-C++ compilations can use C++-specific options (e.g., -Wabi) ๐ฆ
Here is a list of options that are only for compiling Objective-C and Objective-C++ programs ๐
-fconstant-string-class=class-nameโ tells GCC to use class-name as the class to instantiate for each literal string written with the@"..."syntax ๐ง The default class name isNXConstantStringif the GNU runtime is being used, andNSConstantStringif the NeXT runtime is being used (see below). If-fconstant-cfstringsis also present, it overrides the-fconstant-string-classsetting and causes@"..."literals to be laid out as constant CoreFoundation strings ๐-fgnu-runtimeโ generates object code compatible with the standard GNU Objective-C runtime. This is the default for most types of systems โจ-fnext-runtimeโ generates output compatible with the NeXT runtime. This is the default for NeXT-based systems, including Darwin and Mac OS X ๐ The macro__NEXT_RUNTIME__is predefined if (and only if) this option is used ๐ธ-fno-nil-receiversโ assumes that every Objective-C message dispatch ([receiver message:arg]) in this translation unit makes sure the receiver is notnil. That lets the runtime use more efficient entry points ๐ This option is only available together with the NeXT runtime and ABI version 0 or 1 ๐-fobjc-abi-version=nโ uses version n of the Objective-C ABI for the selected runtime. Right now this is only supported for the NeXT runtime ๐ In that case, version 0 is the traditional (32-bit) ABI without support for properties or other Objective-C 2.0 additions. Version 1 is the traditional (32-bit) ABI with properties and other Objective-C 2.0 additions. Version 2 is the modern (64-bit) ABI ๐ If you don't specify anything, the default is version 0 on 32-bit target machines, and version 2 on 64-bit target machines ๐-fobjc-call-cxx-cdtorsโ for each Objective-C class, checks whether any of its instance variables is a C++ object with a non-trivial default constructor. If so, it synthesizes a special- (id) .cxx_constructinstance method, which runs those non-trivial default constructors on any such instance variables, in order, and then returnsself. It also checks whether any instance variable is a C++ object with a non-trivial destructor, and if so, synthesizes a special- (void) .cxx_destructmethod that runs all of those default destructors, in reverse order ๐ฅ
The - (id) .cxx_construct and - (void) .cxx_destruct methods generated this way only operate on instance variables declared in the current Objective-C class, not the ones inherited from superclasses. It's the Objective-C runtime's job to invoke all such methods across an object's inheritance hierarchy ๐ซถ The - (id) .cxx_construct methods are invoked by the runtime immediately after a new object instance is allocated. 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โ turns on syntactic support for structured exception handling in Objective-C, similar to what C++ offers ๐ This option is required 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 together 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. Currently 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 used with the Objective-C or Objective-C++ compiler, any Objective-C syntax that GCC 4.0 doesn't recognize gets rejected. This is super useful if you need to make sure your Objective-C code can still be compiled with older versions of GCC ๐ฐ๏ธ-freplace-objc-classesโ emits a special marker that tellsld(1)not to statically link the resulting object file, and letsdyld(1)load it in at run time instead ๐ฆ This is used together with the Fix-and-Continue debugging mode, where the object file in question may be recompiled and dynamically reloaded during program execution, without needing to restart the program itself. Currently, 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 replaces calls toobjc_getClass("...")(when the class name is known at compile time) with static class references that get initialized at load time, which improves run-time performance โญ Specifying-fzero-linksuppresses this behavior and causes calls toobjc_getClass("...")to be retained. That's useful in Zero-Link debugging mode, since it lets you modify individual class implementations during program execution ๐งช The GNU runtime currently always retains calls toobjc_get_class("..."), regardless of command-line options ๐คทโโ๏ธ-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 lead to shadowing between instance variables and other variables declared either locally inside a class method or globally with the same name. Specifying-fno-local-ivarsturns that behavior off, so you avoid variable shadowing issues ๐-fivar-visibility=[public|protected|private|package]โ sets the default instance variable visibility to the option you specify, so that instance variables declared outside the scope of any access modifier directives default to that visibility ๐-gen-declsโ dumps interface declarations for all classes seen in the source file to a file namedsourcename.decl๐-Wassign-intercept(Objective-C and Objective-C++ only) โ warns whenever an Objective-C assignment is being intercepted by the garbage collector ๐จ-Wno-protocol(Objective-C and Objective-C++ only) โ if a class is declared to implement a protocol, a warning is issued for every method in the protocol that the class doesn't implement. The default behavior is to warn about every method not explicitly implemented in the class, even if the implementation is inherited from the superclass. If you use-Wno-protocol, methods inherited from the superclass are considered implemented, and 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 has been found during compilation. Because these checks only scan the method table at the very end of compilation, these warnings aren't produced if the final stage of compilation isn't reached. That happens, for example, if an error is found during compilation, or if the-fsyntax-onlyoption is being used ๐ญ-Wstrict-selector-match(Objective-C and Objective-C++ only) โ warns if multiple methods with differing argument and/or return types are found for a given selector when you try to send a message using that selector to a receiver of typeidorClass๐ When this flag is off (which is the default), the compiler omits 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 lowkey a lifesaver ๐ซถ It warns you when a@selector(...)expression points at a selector that was never declared. A selector counts as undeclared if no method with that name was declared before the@selector(...)expression, either explicitly in an@interfaceor@protocoldeclaration, or implicitly in an@implementationsection. This option runs its checks the moment it spots a@selector(...)expression, while-Wselectoronly checks in the final stage of compilation ๐ It also enforces the coding style convention that methods and selectors must be declared before being used. Main character energy for clean code ๐-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 ๐
Back in the day, diagnostic messages were formatted without any regard for the output device's aspect (e.g. its width, ...) ๐ But you can use the options below to control the formatting algorithm, like how many characters go on a line and how often source location info gets reported. Heads up though: some language front ends may not honor these options ๐
-fmessage-length=nโ tries to format error messages so they fit on lines of aboutncharacters ๐ Ifnis zero, no line-wrapping happens and each error message lands on a single line. This is the default for all front ends.
Note: this option also affects the display of the#errorand#warningpre-processor directives, and the deprecated function/type/variable attribute. It does not, however, affect thepragma GCC warningandpragma GCC errorpragmas.
-fdiagnostics-show-location=onceโ only matters in line-wrapping mode ๐ธ This tells the reporter to emit source location info just once. If a message is too long and has to be wrapped, the location prefix won't get slapped on again and again in the continuation lines. This is the default behavior โจ-fdiagnostics-show-location=every-lineโ also only matters in line-wrapping mode ๐ฆ This one tells the reporter to emit the same source location info (as prefix) for every physical line that comes out of breaking up a message that's too long to fit on one line.-fdiagnostics-color[=WHEN],-fno-diagnostics-colorโ uses color in diagnostics ๐WHENisnever,always, orauto. The default depends on how the compiler was configured. It can be any of the aboveWHENoptions, or alsoneverif theGCC_COLORSenvironment variable isn't present in the environment, andautootherwise.automeans color only gets used when standard error is a terminal. The forms-fdiagnostics-colorand-fno-diagnostics-colorare aliases for-fdiagnostics-color=alwaysand-fdiagnostics-color=never, respectively.- The colors are defined by the environment variable
GCC_COLORS. Its value is a colon-separated list of capabilities and Select Graphic Rendition (SGR) substrings. SGR commands are interpreted by the terminal or terminal emulator (check the section in your text terminal's documentation for permitted values and what they mean as character attributes). These substring values are integers in decimal representation and can be concatenated with semicolons. Common values to concatenate include:1for bold4for underline5for blink7for inverse39for default foreground color30to37for foreground colors90to97for 16-color mode foreground colors38;5;0to38;5;255for 88-color and 256-color modes foreground colors49for default background color40to47for background colors100to107for 16-color mode background colors48;5;0to48;5;255for 88-color and 256-color modes background colors
- The colors are defined by the environment variable
The default GCC_COLORS is:
error=01;31:warning=01;35:note=01;36:range1=32:range2=34:locus=01:\
quote=01:fixit-insert=32:fixit-delete=31:\
diff-filename=01:diff-hunk=32:diff-delete=31:diff-insert=32:\
type-diff=01;32
Here 01;31 is bold red, 01;35 is bold magenta, 01;36 is bold cyan, 32 is green, 34 is blue, 01 is bold, and 31 is red. Setting GCC_COLORS to the empty string disables colors ๐ซ The supported capabilities are as follows:
error=โ SGR substring forerror:markers.warning=โ SGR substring forwarning:markers.note=โ SGR substring fornote:markers.range1=โ SGR substring for first additional range.range2=โ SGR substring for second additional range.locus=โ SGR substring for location information, likefile:lineorfile:line:columnetc.quote=โ SGR substring for information printed within quotes.fixit-insert=โ SGR substring for fix-it hints suggesting text to be inserted or replaced.fixit-delete=โ SGR substring for fix-it hints suggesting text to be deleted.diff-filename=โ SGR substring for filename headers within generated patches.diff-hunk=โ SGR substring for the starts of hunks within generated patches.diff-delete=โ SGR substring for deleted lines within generated patches.diff-insert=โ SGR substring for inserted lines within generated patches.type-diff=โ SGR substring for highlighting mismatching types within template arguments in the C++ frontend.-fno-diagnostics-show-optionโ by default, every diagnostic includes text naming the command-line option that directly controls it (if the diagnostic machinery knows one). Passing this flag shuts that behavior down ๐-fno-diagnostics-show-caretโ by default, each diagnostic shows the original source line plus a caret^pointing at the column. This option hides that info. The source line gets truncated toncharacters if-fmessage-length=nis given. When the output goes to the terminal, the width is capped at the width given by theCOLUMNSenvironment variable or, if that isn't set, the terminal width ๐-fno-diagnostics-show-labelsโ by default, when source code is printed (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 the printing of these labels (in the example above, the vertical bars and the "char *" and "long int" text).
-fno-diagnostics-show-line-numbersโ by default, when source code is printed (via-fdiagnostics-show-caret), a left margin gets printed showing line numbers. This option suppresses that left margin.-fdiagnostics-minimum-margin-width=widthโ controls the minimum width of the left margin printed by-fdiagnostics-show-line-numbers. It defaults to6๐-fdiagnostics-parseable-fixitsโ emits fix-it hints in a machine-parseable format, perfect for IDEs ๐ค For each fix-it, a line gets printed after the relevant diagnostic, starting with the stringfix-it:. For example:
fix-it:"test.c":{45:3-45:21}:"gtk_widget_show_all"
The location is expressed as a half-open range, counted in bytes, starting at byte 1 for the initial column. In the example above, bytes 3 through 20 of line 45 of "test.c" are to be replaced with the given string:
00000000011111111112222222222
12345678901234567890123456789
gtk_widget_showall (dlg);
^^^^^^^^^^^^^^^^^^
gtk_widget_show_all
The filename and replacement string escape backslash as "\\", tab as "\t", newline as "\n", double quotes as "\"", and non-printable characters as octal (e.g. vertical tab as "\013"). An empty replacement string means the given range is to be removed. An empty range (e.g. "45:3-45:3") means the string is to be inserted at the given position.
-fdiagnostics-generate-patchโ prints fix-it hints to stderr in unified diff format, after any diagnostics are printed ๐ฉน For example:
--- test.c
+++ test.c
@ -42,5 +42,5 @
void show_cb(GtkDialog *dlg)
{
- gtk_widget_showall(dlg);
+ gtk_widget_show_all(dlg);
}
The diff may or may not be colorized, following the same rules as for diagnostics (see -fdiagnostics-color).
-fdiagnostics-show-template-treeโ in the C++ frontend, when printing diagnostics showing mismatching template types, this flag turns on a tree-like structure that shows the common and differing parts of the types ๐ณ Here's the original mess first:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
And here's the tree version:
map<
[...],
vector<
[double != float]>>
The parts that differ are highlighted with color ("double" and "float" in this case).
-fno-elide-typeโ by default, when the C++ frontend prints diagnostics showing mismatching template types, the common parts of the types get printed as[...]to simplify the error message ๐ For example:
could not convert 'std::map<int, std::vector<double> >()'
from 'map<[...],vector<double>>' to 'map<[...],vector<float>>
Specifying -fno-elide-type suppresses that behavior. This flag also affects the output of the -fdiagnostics-show-template-tree flag.
-fno-show-columnโ do not print column numbers in diagnostics. This may be necessary if diagnostics are being scanned by a program that doesn't understand column numbers, such as dejagnu ๐-fdiagnostics-format=FORMATโ selects a different format for printing diagnostics ๐งพFORMATistextorjson. The default istext.
The json format is a top-level JSON array full of JSON objects, and each object is one diagnostic ๐ It gets emitted as one line with no formatting ๐, so the examples below have been prettied up so we can actually read them โจ
Diagnostics can have child diagnostics ๐ธ Like, this error and note:
misleading-indentation.c:15:3: warning: this 'if' clause does not
guard... [-Wmisleading-indentation]
15 | if (flag)
| ^~
misleading-indentation.c:17:5: note: ...this statement, but the latter
is misleadingly indented as if it were guarded by the 'if'
17 | y = 2;
| ^
might be printed in JSON form (after formatting) like this:
[
{
"kind": "warning",
"locations": [
{
"caret": {
"column": 3,
"file": "misleading-indentation.c",
"line": 15
},
"finish": {
"column": 4,
"file": "misleading-indentation.c",
"line": 15
}
}
],
"message": "this \u2018if\u2019 clause does not guard...",
"option": "-Wmisleading-indentation",
"children": [
{
"kind": "note",
"locations": [
{
"caret": {
"column": 5,
"file": "misleading-indentation.c",
"line": 17
}
}
],
"message": "...this statement, but the latter is ..."
}
]
},
...
]
where the "note" is a child of the "warning" ๐ซถ
A diagnostic has a "kind" ๐
If it's "warning", then there's an "option" key that tells you which command-line option is controlling that warning ๐ฅ
A diagnostic can have zero or more locations ๐ Each location has up to three positions: a "caret" position and optional "start" and "finish" positions ๐ฆ A location can also have an optional "label" string ๐ท๏ธ For example, this error:
bad-binary-ops.c:64:23: error: invalid operands to binary + (have 'S' {aka
'struct s'} and 'T' {aka 'struct t'})
64 | return callee_4a () + callee_4b ();
| ~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
| | |
| | T {aka struct t}
| S {aka struct s}
has three locations ๐ Its primary location is at the "+" token at column 23. It also has two secondary locations, describing the left and right-hand sides of the expression, and those have labels. It might be printed in JSON form as:
{
"children": [],
"kind": "error",
"locations": [
{
"caret": {
"column": 23, "file": "bad-binary-ops.c", "line": 64
}
},
{
"caret": {
"column": 10, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 21, "file": "bad-binary-ops.c", "line": 64
},
"label": "S {aka struct s}"
},
{
"caret": {
"column": 25, "file": "bad-binary-ops.c", "line": 64
},
"finish": {
"column": 36, "file": "bad-binary-ops.c", "line": 64
},
"label": "T {aka struct t}"
}
],
"message": "invalid operands to binary + ..."
}
If a diagnostic has fix-it hints, it gets a "fixits" array made of half-open intervals, kind of like the output of -fdiagnostics-parseable-fixits ๐ง For example, this diagnostic with a replacement fix-it hint:
demo.c:8:15: error: 'struct s' has no member named 'colour'; did you
mean 'color'?
8 | return ptr->colour;
| ^~~~~~
| color
might be printed in JSON form as:
{
"children": [],
"fixits": [
{
"next": {
"column": 21,
"file": "demo.c",
"line": 8
},
"start": {
"column": 15,
"file": "demo.c",
"line": 8
},
"string": "color"
}
],
"kind": "error",
"locations": [
{
"caret": {
"column": 15,
"file": "demo.c",
"line": 8
},
"finish": {
"column": 20,
"file": "demo.c",
"line": 8
}
}
],
"message": "\u2018struct s\u2019 has no member named ..."
}
where the fix-it hint suggests replacing the text from "start" up to but not including "next" with the value of "string" ๐ Deletions are shown with an empty value for "string", and insertions are shown by having "start" equal "next" ๐
๐ Options to Request or Suppress Warnings ๐
Okay so warnings are diagnostic messages about stuff that isn't flat-out wrong, but is risky or might mean there was a mistake somewhere ๐
These language-independent options don't turn on specific warnings ๐ Instead, they control what kinds of diagnostics GCC produces ๐
-fsyntax-onlyโ Checks the code for syntax errors and then stops there, no extra work ๐ฆ-fmax-errors=nโ Caps the number of error messages at n, and once it hits that, GCC bails instead of trying to keep going through the source code ๐ If n is0(the default), there's no limit on how many error messages get produced. If-Wfatal-errorsis also specified, then-Wfatal-errorstakes precedence over this option โจ-wโ Silences all warning messages ๐คซ-Werrorโ Turns every warning into an error ๐-Werror=โ Turns one specific warning into an error ๐ฅ You append the warning's specifier, so for example-Werror=switchturns the warnings controlled by-Wswitchinto errors. This one also has a negative form, which undoes-Werrorfor specific warnings. For example,-Wno-error=switchmakes-Wswitchwarnings not errors, even when-Werroris in effect ๐ โโ๏ธ
Okay, more on -Werror= ๐
The warning message for every controllable warning includes the option that controls it, and you can plug that option into -Werror= and -Wno-error= like we just talked about. (Want to hide that option from the message? Use the -fno-diagnostics-show-option flag ๐)
Also, specifying -Werror=foo automatically implies -Wfoo ๐ซถ But -Wno-error=foo doesn't imply anything at all ๐คทโโ๏ธ
-Wfatal-errorsโ Makes the compiler abort on the first error it hits, instead of pushing on and printing more error messages ๐ญ
You can request lots of specific warnings with options that start with -W. For example, -Wimplicit requests warnings about implicit declarations โจ Each of these specific warning options also has a -Wno- negative form to turn the warning off, like -Wno-implicit. This manual only lists one of the two forms, whichever one isn't the default ๐ For more language-specific options, also check out C++ Dialect Options and Objective-C and Objective-C++ Dialect Options ๐ธ
Some options, 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 act as if they showed up at the end of the command-line ๐
When you request an unrecognized warning option (e.g., -Wunknown-warning), GCC tells you it doesn't recognize that option ๐ค But if you use the -Wno- form, it's a little different: no diagnostic gets produced for -Wno-unknown-warning unless other diagnostics are being produced too. This lets you use new -Wno- options with old compilers, but if something goes wrong, the compiler warns you that an unrecognized option is present ๐
The effectiveness of some warnings depends on optimizations also being enabled ๐ฅ For example, -Wsuggest-final-types works better with link-time optimization, and -Wmaybe-uninitialized won't warn at all unless optimization is enabled ๐
-Wpedantic,-pedanticโ Issues all the warnings demanded by strict ISO C and ISO C++, and rejects all programs that use forbidden extensions, plus some other programs that don't follow ISO C and ISO C++ ๐ง For ISO C, it follows the version of the ISO C standard specified by any-stdoption used ๐
Okay so, valid ISO C and ISO C++ programs should compile just fine whether or not you use this flag ๐
(though a rare few need -ansi or a -std option naming the ISO C version they want ๐ค). Without this option, GCC still lets in certain GNU extensions plus traditional C and C++ features. With it on? Those get rejected ๐
โโ๏ธ.
-Wpedantic won't warn about the alternate keywords whose names begin and end with __ โจ. Pedantic warnings are also switched off inside the expression that follows __extension__ ๐ฆ. Real talk though: only system header files should use these escape hatches, so your app code should stay away from them ๐ซถ.
Some people use -Wpedantic to check their code for strict ISO C conformance, and they're kinda shocked when it doesn't do exactly what they want ๐ญ. It catches some non-ISO practices, but not all of them. It only flags the stuff ISO C says must get a diagnostic, plus a few others where diagnostics were added ๐.
A feature that reports any failure to conform to ISO C could be useful sometimes, but it would take a ton of extra work and would be totally different from -Wpedantic ๐ฉ. There are no plans to support that in the near future, sorry bestie ๐ฅฒ.
Where the standard named with -std is a GNU extended dialect of C, like gnu90 or gnu99, there's a matching base standard: the version of ISO C that the GNU dialect is built on ๐. -Wpedantic gives warnings wherever the base standard requires them. (It wouldn't make sense to warn only about features outside the GNU dialect you picked, because by definition the GNU dialects include everything the compiler supports with that option, so there'd be nothing to warn about ๐.)
๐จ -pedantic-errors
Gives an error (not just a warning) whenever the base standard, see -Wpedantic, requires a diagnostic. That includes some cases with undefined behavior at compile time, and some other cases that don't stop a program from compiling even though it's valid under the standard ๐
. Heads up: this is not the same as -Werror=pedantic, because each one turns on some errors the other doesn't, and the other way around too ๐คฏ.
๐ฆ -Wall
This turns on all the warnings about constructions that some users consider questionable and that are easy to avoid (or tweak to dodge the warning), even when macros are involved โจ. It also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options ๐.
-Wall turns on the following warning flags:
-Waddress-Warray-bounds=1(only with-O2)-Wbool-compare-Wbool-operation-Wc++11-compat-Wc++14-compat-Wcatch-value(C++ and Objective-C++ only)-Wchar-subscripts-Wcomment-Wduplicate-decl-specifier(C and Objective-C only)-Wenum-compare(in C/ObjC; this is on by default in C++)-Wformat-Wint-in-bool-context-Wimplicit(C and Objective-C only)-Wimplicit-int(C and Objective-C only)-Wimplicit-function-declaration(C and Objective-C only)-Winit-self(only for C++)-Wlogical-not-parentheses-Wmain(only for C/ObjC and unless-ffreestanding)-Wmaybe-uninitialized-Wmemset-elt-size-Wmemset-transposed-args-Wmisleading-indentation(only for C/C++)-Wmissing-attributes-Wmissing-braces(only for C/ObjC)-Wmultistatement-macros-Wnarrowing(only for C++)-Wnonnull-Wnonnull-compare-Wopenmp-simd-Wparentheses-Wpessimizing-move(only for C++)-Wpointer-sign-Wreorder-Wrestrict-Wreturn-type-Wsequence-point-Wsign-compare(only in C++)-Wsizeof-pointer-div-Wsizeof-pointer-memaccess-Wstrict-aliasing-Wstrict-overflow=1-Wswitch-Wtautological-compare-Wtrigraphs-Wuninitialized-Wunknown-pragmas-Wunused-function-Wunused-label-Wunused-value-Wunused-variable-Wvolatile-register-var
Note that some warning flags are not implied by -Wall ๐. Some of them warn about stuff users generally don't think is sketchy but that you might occasionally want to check for. Others warn about constructions that are necessary or hard to avoid in some cases, with no simple way to rewrite the code to shut the warning up ๐ค. Some of them are enabled by -Wextra, but many of them have to be turned on one by one.
๐ธ -Wextra
This enables some extra warning flags that aren't enabled by -Wall ๐. (This option used to be called -W. The older name still works, but the newer name is way more descriptive ๐.)
-Wextra turns on these flags:
-Wclobbered-Wcast-function-type-Wdeprecated-copy(C++ only)-Wempty-body-Wignored-qualifiers-Wimplicit-fallthrough=3-Wmissing-field-initializers-Wmissing-parameter-type(C only)-Wold-style-declaration(C only)-Woverride-init-Wsign-compare(C only)-Wredundant-move(only for C++)-Wtype-limits-Wuninitialized-Wshift-negative-value(in C++11 to C++17 and in C99 and newer)-Wunused-parameter(only with-Wunusedor-Wall)-Wunused-but-set-parameter(only with-Wunusedor-Wall)
The option -Wextra also prints warning messages for these cases:
- A pointer is compared against integer zero with
<,<=,>, or>=. - (C++ only) An enumerator and a non-enumerator both appear in a conditional expression.
- (C++ only) Ambiguous virtual bases.
- (C++ only) Subscripting an array that has been declared
register. - (C++ only) Taking the address of a variable that has been declared
register. - (C++ only) A base class is not initialized in the copy constructor of a derived class.
๐ง -Wchar-subscripts
Warns if an array subscript has type char ๐. This is a super common source of bugs, because programmers often forget that char is signed on some machines ๐ญ. This warning is enabled by -Wall โจ.
๐ -Wno-coverage-mismatch
Warns if feedback profiles don't match when you use the -fprofile-use option ๐. If a source file changes between compiling with -fprofile-generate and compiling 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.
Turning off the error for this warning can result in poorly optimized code, and it's only useful for very minor changes, like bug fixes to an existing code base. Completely disabling the warning is not recommended ๐ซ.
๐ซง -Wno-cpp
(C, Objective-C, C++, Objective-C++ and Fortran only)
Suppresses the warning messages emitted by #warning directives ๐คซ.
๐ฆฉ -Wdouble-promotion (C, C++, Objective-C and Objective-C++ only)
Gives a warning when a value of type float is implicitly promoted to double ๐. CPUs with a 32-bit single-precision floating-point unit implement float in hardware but emulate double in software ๐ค. On a machine like that, doing computations with double values is way more expensive because of the overhead required for software emulation ๐ฉ.
It's super easy to accidentally do computations with double, because floating-point literals are implicitly of type double ๐. For example, in:
float area(float radius)
{
return 3.14159 * radius * radius;
}
the compiler performs the entire computation with double, because the floating-point literal is a double ๐.
๐ -Wduplicate-decl-specifier (C and Objective-C only)
Warns if a declaration has a duplicate const, volatile, restrict or _Atomic specifier ๐ง. This warning is enabled by -Wall โจ.
๐ -Wformat and -Wformat=n
Checks calls to printf and scanf, etc., to make sure the arguments supplied have types that fit the format string, and that the conversions in the format string actually make sense ๐. This covers standard functions plus others specified by format attributes, in the printf, scanf, strftime and strfmon families (strfmon is an X/Open extension, not part of the C standard), or other target-specific families ๐ฆ. Which functions get checked without format attributes depends on the standard version you selected, and those checks are disabled by -ffreestanding or -fno-builtin ๐
โโ๏ธ.
The formats are checked against the format features supported by GNU libc version 2.2. These include all ISO C90 and C99 features, plus features from the Single Unix Specification and some BSD and GNU extensions ๐. Other library implementations might not support all of these, and GCC doesn't warn about features that go beyond a particular library's limits ๐ซ . However, if you use -Wpedantic with -Wformat, you get warnings about format features that aren't in the selected standard version (but not for strfmon formats, since those aren't in any version of the C standard ๐
).
๐ -Wformat=1 and -Wformat
-Wformat is equivalent to -Wformat=1, and -Wno-format is equivalent to -Wformat=0 โจ. Since -Wformat also checks for null format arguments for several functions, it also implies -Wnonnull ๐ซถ. Some parts of this level of format checking can be turned off with -Wno-format-contains-nul, -Wno-format-extra-args, and -Wno-format-zero-length. -Wformat is enabled by -Wall ๐.
๐ซง -Wno-format-contains-nul
If -Wformat is specified, don't warn about format strings that contain NUL bytes ๐.
๐ฆ -Wno-format-extra-args
If -Wformat is specified, don't warn about excess arguments to a printf or scanf format function. The C standard says those arguments are ignored, so it's chill ๐.
Where the unused arguments sit between used arguments that are specified with $ operand number specifications, warnings still normally show up. That's because the implementation couldn't know what type to pass to va_arg to skip the unused arguments ๐คทโโ๏ธ. However, for scanf formats, this option suppresses the warning if the unused arguments are all pointers, since the Single Unix Specification says those unused arguments are allowed ๐.
-Wformat-overflow,-Wformat-overflow=levelโ okay so this one is all about calls likesprintfandvsprintfthat might spill past the destination buffer ๐ฅ When GCC can't pin down the exact number of bytes a format directive writes at compile time, it estimates using heuristics that depend on the level argument and on optimization. Turning optimization on usually makes the warning more accurate, but it can also cause false positives ๐
โจ -Wformat-overflow=1 ๐งธ
Level 1 is turned on by -Wformat and it's super conservative ๐ง It only warns about calls that will 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 whatever value in that range gives the most bytes of output.
In the example below, the sprintf call gets diagnosed because even with a and b both equal to zero, the terminating NUL character ('\0') that the function appends to the destination buffer gets written past its end ๐ญ
void f (int a, int b)
{
char buf [13];
sprintf (buf, "a = %i, b = %i\n", a, b);
}
Bumping the buffer up by a single byte is enough to dodge the warning โจ though it might not be enough to dodge the actual overflow ๐
โจ -Wformat-overflow=2 ๐ฅ
Level 2 warns about calls that might overflow the destination buffer given an argument of sufficient length or magnitude. At level 2, unknown numeric arguments are assumed to have the minimum representable value for signed types with a precision greater than 1, and the maximum representable value otherwise. Unknown string arguments whose length can't be assumed bounded, either by the directive's precision, by a finite set of string literals they may evaluate to, or by the character array they may point to, are assumed to be 1 character long.
At level 2, the call in the example above gets diagnosed again ๐ this time because with a equal to a 32-bit INT_MIN, the first %i directive writes some of its digits beyond the end of the destination buffer. To make the call safe regardless of the values of the two variables, the destination buffer must be increased to at least 34 bytes. GCC includes the minimum size of the buffer in an informational note following the warning ๐
An alternative to making the buffer bigger is to constrain the range of formatted values ๐ง The maximum length of string arguments can be bounded by specifying the precision in the format directive. When numeric arguments of format directives can be assumed to be bounded by less than the precision of their type, choosing an appropriate length modifier for the format specifier will reduce the required buffer size. For example, if a and b in the example above can be assumed to be within the precision of the short int type, then using either the %hi format directive or casting the argument to short reduces the maximum required size of the buffer to 24 bytes.
void f (int a, int b)
{
char buf [23];
sprintf (buf, "a = %hi, b = %i\n", a, (short)b);
}
-Wno-format-zero-lengthโ if-Wformatis on, this tells GCC to stop warning about zero-length formats ๐ซถ The C standard says zero-length formats are totally allowed, so no drama needed.-Wformat=2โ turns on-Wformatplus extra format checks ๐ฅ Right now that's the same as-Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k.-Wformat-nonliteralโ if-Wformatis on, this also warns when the format string isn't a string literal, since GCC can't check it ๐คทโโ๏ธ It won't warn if the format function takes its format arguments as ava_list.-Wformat-securityโ if-Wformatis on, this also warns about format function uses that could be security problems ๐จ Right now it warns about calls toprintfandscanfwhere the format string isn't a string literal and there are no format arguments, likeprintf (foo);.
This one matters! If the format string came from untrusted input and contains%n, it can be a security hole ๐ฑ Right now this is a subset of what-Wformat-nonliteralwarns about, but future warnings may be added to-Wformat-securitythat aren't in-Wformat-nonliteral.
-Wformat-signednessโ if-Wformatis on, this warns when the format string wants an unsigned argument but you pass a signed one, and vice versa ๐งฎ-Wformat-truncation,-Wformat-truncation=levelโ warns about calls to formatted I/O functions likesnprintfandvsnprintfthat might end up truncating the output โ๏ธ Same deal as before: when the exact byte count can't be known at compile time, GCC estimates with heuristics that depend on the level argument and on optimization. Optimization usually helps accuracy but can cause false positives. Except where noted, this option uses the same logic as-Wformat-overflow.-Wformat-truncation,-Wformat-truncation=1โ level 1 is turned on by-Wformatand is conservative ๐งธ It only warns about calls to bounded functions whose return value is unused and that will most likely result in output truncation.-Wformat-truncation=2โ level 2 also warns about calls to bounded functions whose return value is used and that might truncate given an argument of sufficient length or magnitude ๐
-Wformat-y2kโ if-Wformatis on, this also warns aboutstrftimeformats that may only yield a two-digit year ๐ Y2K vibes, but make it a warning ๐-Wnonnullโ warns about passing a null pointer for arguments that thenonnullfunction attribute says must be non-null ๐ซ It's included in-Walland-Wformat, and you can turn it off with-Wno-nonnull.-Wnonnull-compareโ warns when you compare an argument marked with thenonnullfunction attribute against null inside the function ๐ It's included in-Walland can be disabled with-Wno-nonnull-compare.-Wnull-dereferenceโ warns if the compiler finds paths that trigger erroneous or undefined behavior because of dereferencing a null pointer ๐ This only works when-fdelete-null-pointer-checksis active, which optimizations turn on for most targets. How precise the warnings are depends on the optimization options you use.-Winit-self(C, C++, Objective-C and Objective-C++ only) โ warns about uninitialized variables that get initialized with themselves ๐ Heads up, this one only works together with-Wuninitialized.
For example, GCC warns about i being uninitialized in the following snippet only when -Winit-self is specified ๐ง
int f()
{
int i = i;
return i;
}
This warning is enabled by -Wall in C++ ๐ธ
-Wimplicit-int(C and Objective-C only) โ warns when a declaration doesn't specify a type ๐ It's enabled by-Wall.-Wimplicit-function-declaration(C and Objective-C only) โ gives a warning whenever a function is used before it's declared ๐ฃ In C99 mode (-std=c99or-std=gnu99), this is enabled by default, and-pedantic-errorsturns it into an error ๐จ It's also enabled by-Wall.-Wimplicit(C and Objective-C only) โ same as-Wimplicit-intand-Wimplicit-function-declarationcombined ๐ซง It's enabled by-Wall.-Wimplicit-fallthroughโ same as-Wimplicit-fallthrough=3, and-Wno-implicit-fallthroughis the same as-Wimplicit-fallthrough=0๐ฆ-Wimplicit-fallthrough=nโ warns when aswitchcase falls through to the next one ๐ For example:
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, like when there's a return statement or a call to a function declared with the noreturn attribute ๐ It also takes control flow statements like ifs into account, so it only warns when it's actually appropriate. For example:
switch (cond)
{
case 1:
if (i > 3) {
bar (5);
break;
} else if (i < 1) {
bar (0);
} else
return;
default:
...
}
Sometimes a case falling through is exactly what you want ๐ง so GCC gives you an attribute, __attribute__ ((fallthrough)), to use along with a null statement to suppress this warning that would normally happen โจ
switch (cond)
{
case 1:
bar (0);
__attribute__ ((fallthrough));
default:
...
}
Okay so C++17 gives us a standard way to silence -Wimplicit-fallthrough โจ with [[fallthrough]]; instead of the GNU attribute ๐ฆ. If you're stuck on C++11 or C++14, you can use [[gnu::fallthrough]]; instead, which is a GNU extension (slightly less official, but it still slays ๐
). You can also skip the attributes entirely and drop a fallthrough comment in to shush the warning ๐ซถ. The whole body of the C or C++ style comment has to match one of the regular expressions below, and the option argument n decides which kinds of comments count:
-Wimplicit-fallthrough=0โ disables the warning altogether ๐-Wimplicit-fallthrough=1โ matches the".*"regular expression, so any comment at all counts as a fallthrough comment ๐-Wimplicit-fallthrough=2โ case insensitively matches the".*falls?[ \t-]*thr(ough|u).*"regular expression ๐-Wimplicit-fallthrough=3โ case sensitively matches one of these regular expressions:"-fallthrough""@fallthrough@""lint -fallthrough[ \t]*""[ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?FALL(S | |-)?THR(OUGH|U)[ \t.!]*(-[^\n\r]*)?""[ \t.!]*(Else,? |Intentional(ly)? )?Fall((s | |-)[Tt]|t)hr(ough|u)[ \t.!]*(-[^\n\r]*)?""[ \t.!]*([Ee]lse,? |[Ii]ntentional(ly)? )?fall(s | |-)?thr(ough|u)[ \t.!]*(-[^\n\r]*)?"
-Wimplicit-fallthrough=4โ case sensitively matches one of these regular expressions:"-fallthrough""@fallthrough@""lint -fallthrough[ \t]*""[ \t]*FALLTHR(OUGH|U)[ \t]*"
-Wimplicit-fallthrough=5โ doesn't recognize any comments as fallthrough comments, so only attributes disable the warning ๐ฅ
The comment needs to be followed, after optional whitespace and other comments, by a case or default keyword, or by a user label that comes right before some case or default label. Like this:
switch (cond)
{
case 1:
bar (0);
/* FALLTHRU */
default:
...
}
The -Wimplicit-fallthrough=3 warning is enabled by -Wextra โจ.
๐ -Wif-not-aligned (C, C++, Objective-C and Objective-C++ only)
Controls whether the warning triggered by the warn_if_not_aligned attribute gets issued. It's on by default ๐, and you can turn it off with -Wno-if-not-aligned.
๐ -Wignored-qualifiers (C and C++ only)
Warns if a function's return type has a type qualifier like const. In ISO C, a qualifier like that has no effect, since the value a function returns isn't an lvalue ๐. In C++, the warning only shows up for scalar types or void. ISO C also bans qualified void return types on function definitions, so those always get a warning, even without this option ๐.
This warning is also enabled by -Wextra.
๐ -Wignored-attributes (C and C++ only)
Warns when an attribute gets ignored. This is different from -Wattributes, which is about an attribute being unknown or in the wrong place. This one fires whenever the compiler decides to drop an attribute ๐. It's enabled by default.
๐ -Wmain
Warns if the type of main looks sketchy ๐. main should be a function with external linkage that returns int and takes either zero arguments, two, or three arguments of the right types. This warning is enabled by default in C++, and it's enabled by either -Wall or -Wpedantic.
๐ -Wmisleading-indentation (C and C++ only)
Warns when the indentation of your code doesn't match the block structure ๐. Specifically, it fires for if, else, while, and for clauses with a guarded statement that has no braces, followed by an unguarded statement with the same indentation.
In this example, the call to bar is misleadingly indented like it's guarded by the if:
if (some_condition ())
foo ();
bar (); /* Gotcha: this is not guarded by the "if". */
If you mix tabs and spaces, the warning uses the -ftabstop= option to decide whether the statements line up (it defaults to 8) ๐.
The warning is not issued for multiline preprocessor logic like this:
if (flagA)
foo (0);
#if SOME_CONDITION_THAT_DOES_NOT_HOLD
if (flagB)
#endif
foo (1);
It also won't fire after a #line directive, since that usually means autogenerated code, and no assumptions can be made about the layout of the file that the directive points to ๐ค.
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 where that absence could hurt the correctness or efficiency of the generated code ๐ง. For example, it fires for declarations of aliases that use attributes to set less restrictive requirements than their targets. That's usually a potential optimization opportunity. By contrast, -Wattribute-alias=2 controls warnings for when the alias is more restrictive than the target, which could lead to incorrect code generation.
The attributes considered are alloc_align, alloc_size, cold, const, hot, leaf, malloc, nonnull, noreturn, nothrow, pure, returns_nonnull, and returns_twice.
In C++, the warning fires when an explicit specialization of a primary template declared with alloc_align, alloc_size, assume_aligned, format, format_arg, malloc, or nonnull is declared without it. The attributes deprecated, error, and warning suppress the warning ๐ธ.
You can use the copy attribute to apply the same set of attributes to a declaration as another declaration has, without listing them all out. This attribute works on declarations of functions, variables, or types.
-Wmissing-attributes is enabled by -Wall.
For example, the declaration of the primary function template below uses both malloc and alloc_size, so the explicit specialization of the template gets flagged for missing one of them:
template <class T>
T* __attribute__ ((malloc, alloc_size (1)))
allocate (size_t);
template <>
void* __attribute__ ((malloc)) // missing alloc_size
allocate<void> (size_t);
๐ -Wmissing-braces
Warns if an aggregate or union initializer isn't fully bracketed ๐. In the example below, the initializer for a isn't fully bracketed, but the one for b is.
int a[2][2] = { 0, 1, 2, 3 };
int b[2][2] = { { 0, 1 }, { 2, 3 } };
This warning is enabled by -Wall in C.
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 ๐.
๐ -Wmissing-profile
Warns if feedback profiles are missing when you use the -fprofile-use option โจ. This catches the cases where a new function or a new file was added to your code between compiling with -fprofile-generate and compiling with -fprofile-use, without regenerating the profiles. In those cases, the profile feedback data files don't have any profile feedback information for the newly added function or file. Also, if profile count data (.gcda) files get removed, GCC can't use any profile feedback information at all. In all of these cases, you get warnings telling you a profile generation step is due ๐ฆ. You can use -Wno-missing-profile to disable the warning.
๐ Ignoring this warning can result in poorly optimized code. Completely disabling it is not recommended, and you should only do it when non-existent profile data is justified.
๐ -Wmultistatement-macros
Warns about unsafe multiple-statement macros that look like they're guarded by a clause such as if, else, for, switch, or while, where only the first statement is actually guarded once the macro is expanded ๐ญ.
For example:
#define DOIT x++; y++
if (c)
DOIT;
This will increment y unconditionally, not just when c holds. This can usually be fixed by wrapping the macro in a do-while loop:
#define DOIT do { x++; y++; } while (0)
if (c)
DOIT;
This warning is enabled by -Wall in C and C++.
๐ -Wparentheses
Warns if parentheses are left out in certain spots, like when there's an assignment where a truth value is expected, or when operators are nested in a way people often get confused about ๐ง.
It also warns if you write a comparison like x<=y<=z. That's equivalent to (x<=y ? 1 : 0) <= z, which is a different reading from ordinary mathematical notation ๐
.
It warns for dangerous uses of the GNU extension to ?: with the middle operand omitted. When the condition in the ?: operator is a boolean expression, the omitted value is always 1. Programmers often expect it to be a value computed inside the conditional expression instead ๐.
For C++, this also warns about some cases of unnecessary parentheses in declarations, which can mean you meant a function call instead of a declaration:
{
// Declares a local variable called mymutex.
std::unique_lock<std::mutex> (mymutex);
// User meant std::unique_lock<std::mutex> lock (mymutex);
}
This warning is enabled by -Wall.
๐ -Wsequence-point
Warns about code that may have undefined semantics because it breaks the sequence point rules in the C and C++ standards ๐.
โ ๏ธ Undefined semantics means you can't count on what the code will do, so take this one seriously, bestie ๐ซถ.
okay so the C and C++ standards have this whole idea of sequence points ๐ซถ. They're basically checkpoints that split up the order your program runs stuff in. Everything before a checkpoint has to happen before everything after it, but the stuff in between is kinda up for grabs. Sequence points show up after a full expression (one that isn't stuck inside a bigger expression) โจ, after the first operand of &&, ||, ? : or , (comma) operator gets evaluated ๐
, right before a function gets called (but after its arguments and the expression naming the function are evaluated ๐ง), and in a few other spots too. Outside those checkpoints, the order that subexpressions get evaluated in is not specified at all ๐. It's only a partial order, not a total one. So if two functions get called in the same 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 ๐.
Also, it's not specified when changes to object values take effect between sequence points ๐ญ. If your program depends on that, it has undefined behavior ๐. The standards say: "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.". Break those rules and 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 trickier cases won't get caught by this option, and it might give an occasional false positive, but overall it's been found pretty effective at catching this sort of problem ๐.
The C++17 standard is going to define the evaluation order of operands in more cases ๐ธ. In particular, it requires that the right-hand side of an assignment gets evaluated before the left-hand side, so the examples above are no longer undefined. But this warning will still warn about them, to help people avoid writing code that's undefined in C and earlier revisions of C++ ๐ซถ.
The standard is worded confusingly, so there's some debate over the precise meaning of the sequence point rules in subtle cases ๐ตโ๐ซ. Links to discussions of the problem, including proposed formal definitions, may 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โ Chill, don't warn about returning a pointer (or, in C++, a reference) to a variable that goes out of scope after the function returns ๐ฆ.-Wreturn-typeโ Warn whenever a function is defined with a return type that defaults toint๐. Also warn about anyreturnstatement with no return value in a function whose return type is notvoid(falling off the end of the function body counts as returning without a value).- For C only, warn about a
returnstatement with an expression in a function whose return type isvoid, unless the expression type is alsovoid. As a GNU extension, the latter case is accepted without a warning unless-Wpedanticis used. Attempting to use the return value of a non-voidfunction other thanmainthat flows off the end by reaching the closing curly brace that terminates the function is undefined. - Unlike in C, in C++, flowing off the end of a non-
voidfunction other thanmainresults in undefined behavior even when the value of the function is not used ๐ญ. - Enabled by default in C++ and by
-Wallotherwise.
- For C only, warn about a
-Wshift-count-negativeโ Yell if the shift count is negative ๐ . Enabled by default.-Wshift-count-overflowโ Warn if the shift count is>=the width of the type ๐ . Enabled by default.-Wshift-negative-valueโ Warn if you're left shifting a negative value. Enabled by-Wextrain C99 (and newer) and C++11 to C++17 modes.-Wshift-overflow,-Wshift-overflow=nโ Warn about left shift overflows ๐ฅ. Enabled by default in C99 and C++11 modes (and newer).-Wshift-overflow=1โ This is the warning level of-Wshift-overflowand is enabled by default in C99 and C++11 modes (and newer). This level does not warn about left-shifting1into the sign bit. (However, in C, such an overflow is still rejected in contexts where an integer constant expression is required.) No warning is emitted in C++2A mode (and newer), as signed left shifts always wrap.-Wshift-overflow=2โ This level also warns about left-shifting1into the sign bit, unless C++14 mode (or newer) is active.
-Wswitchโ Warn whenever aswitchstatement has an index of enumerated type and lacks acasefor one or more of the named codes of that enumeration. (The presence of adefaultlabel prevents this warning.)caselabels outside the enumeration range also provoke warnings when this option is used, even if there is adefaultlabel ๐. Enabled by-Wall.-Wswitch-defaultโ Warn whenever aswitchstatement does not have adefaultcase ๐งธ.-Wswitch-enumโ Warn 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 provoke warnings when this option is used. The only difference between-Wswitchand this option is that this one warns about an omitted enumeration code even if there is adefaultlabel ๐ง.-Wswitch-boolโ Warn whenever 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 ๐.
-Wswitch-unreachableโ Warn whenever aswitchstatement contains statements between the controlling expression and the firstcaselabel, which 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) โ Warn when the__sync_fetch_and_nandand__sync_nand_and_fetchbuilt-in functions are used. These functions changed semantics in GCC 4.4 โ ๏ธ.-Wunused-but-set-parameterโ Warn whenever a function parameter is assigned to but otherwise unused (aside from its declaration) ๐ซ .- To suppress this warning, use the
unusedattribute. - This warning is also enabled by
-Wunusedtogether with-Wextra.
- To suppress this warning, use the
-Wunused-but-set-variableโ Warn whenever a local variable is assigned to but otherwise unused (aside from its declaration). Enabled by-Wall.- To suppress this warning, use the
unusedattribute. - This warning is also enabled by
-Wunused, which is enabled by-Wall.
- To suppress this warning, use the
-Wunused-functionโ Warn whenever a static function is declared but not defined, or a non-inline static function is unused. Enabled by-Wall๐งน.-Wunused-labelโ Warn whenever a label is declared but not used. Enabled by-Wall.- To suppress this warning, use the
unusedattribute.
- To suppress this warning, use the
-Wunused-local-typedefs(C, Objective-C, C++ and Objective-C++ only) โ Warn when a typedef locally defined in a function is not used. Enabled by-Wall.-Wunused-parameterโ Warn whenever a function parameter is unused aside from its declaration.- To suppress this warning, use the
unusedattribute.
- To suppress this warning, use the
-Wno-unused-resultโ Don't warn if a caller of a function marked with the attributewarn_unused_resultdoesn't use its return value. The default is-Wunused-result.-Wunused-variableโ Warn whenever a local or static variable is unused aside from its declaration. This option implies-Wunused-const-variable=1for C, but not for C++. Enabled by-Wall.- To suppress this warning, use the
unusedattribute.
- To suppress this warning, use the
-Wunused-const-variable,-Wunused-const-variable=nโ Warn whenever a constant static variable is unused aside from its declaration.-Wunused-const-variable=1is enabled by-Wunused-variablefor C, but not for C++. In C this declares variable storage, but in C++ this is not an error, since const variables take the place of#defines ๐.- To suppress this warning, use the
unusedattribute. -Wunused-const-variable=1โ This is the warning level that is enabled by-Wunused-variablefor C. It warns only about unused static const variables defined in the main compilation unit, but not about static const variables declared in any header included.-Wunused-const-variable=2โ This warning level also warns for unused constant static variables in headers (excluding system headers). This is the warning level of-Wunused-const-variableand must be explicitly requested, since in C++ this isn't an error and in C it might be harder to clean up all the headers included.
- To suppress this warning, use the
-Wunused-valueโ Warn whenever a statement computes a result that is explicitly not used. To suppress this warning, 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. Enabled by-Wall.-Wunusedโ All the above-Wunusedoptions combined ๐.
Okay so if you want GCC to yell at you about an unused function parameter ๐ฃ, you've gotta either pass -Wextra -Wunused (and fyi -Wall already implies -Wunused, so you're kinda covered ๐
), or just throw -Wunused-parameter on its own โจ
-Wuninitialized
This one's giving vigilant ๐ It warns if an automatic variable gets used before it's been initialized, or if a variable might get clobbered by a setjmp call. In C++, it also warns if a non-static reference or a non-static const member shows up in a class without any constructors ๐ซถ
If you want a warning for code that uses a variable's uninitialized value inside its own initializer, that's what the -Winit-self option is for ๐
These warnings pop up for individual uninitialized or clobbered elements of structure, union, or array variables, as well as for variables that are uninitialized or clobbered as a whole ๐งฉ They do not show up for variables or elements declared volatile ๐
And since they depend on optimization, the exact variables or elements that get flagged depends on the precise optimization options and the version of GCC you're using ๐
Heads up: you might not get a warning about a variable that's only used to compute a value that's never actually used ๐ Those computations can get deleted by data flow analysis before the warnings are printed.
-Winvalid-memory-model
Okay this one's serious ๐
It warns for invocations of __atomic builtins, __sync builtins, and the C11 atomic generic functions whose memory consistency argument is either invalid for the operation or outside the range of values in the memory_order enumeration. For example, __atomic_store and __atomic_store_n are only defined for the relaxed, release, and sequentially consistent memory orders, so this code gets diagnosed:
void store (int *i)
{
__atomic_store_n (i, 0, memory_order_consume);
}
-Winvalid-memory-model is enabled by default โจ
-Wmaybe-uninitialized
This one's a lil more drama ๐ญ For an automatic (aka local) variable, if there's a path from the function entry to a use of the variable where it is initialized, but other paths exist where it isn't, GCC emits a warning if it can't prove those uninitialized paths never get executed at run time ๐
These warnings are only possible in optimizing compilation, because otherwise GCC doesn't keep track of the state of variables ๐คท
They're optional because GCC sometimes can't tell when code is actually correct even though it looks like an error ๐ญ Here's one example of how that happens:
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
foo (x);
}
If the value of y is always 1, 2 or 3, then x is always initialized, but GCC doesn't know that ๐ฅฒ To suppress the warning, you need to provide a default case with assert(0) or similar code ๐คซ
This option also warns when a non-volatile automatic variable might be changed by a call to longjmp. The compiler only sees the calls to setjmp. It can't know where longjmp will be called, and in fact a signal handler could call it at any point in the code ๐ฑ So you might get a warning even when there's really no problem, because longjmp can't actually be called at the place that would cause one.
Some spurious warnings can be avoided if you declare all the functions you use that never return as noreturn ๐งน
This warning is enabled by -Wall or -Wextra โ
-Wunknown-pragmas
This one warns when a #pragma directive shows up that GCC doesn't understand ๐ง If you use this command-line option, you'll even get warnings for unknown pragmas in system header files. That's not the case if the warnings are only enabled by the -Wall command-line option ๐
-Wno-pragmas
Don't warn about misuses of pragmas, like incorrect parameters, invalid syntax, or conflicts between pragmas ๐ซ See also -Wunknown-pragmas ๐
-Wno-prio-ctor-dtor
Don't warn if a priority from 0 to 100 gets used for a constructor or destructor ๐
The constructor and destructor attributes let you assign a priority to control the order of execution before main is called or after it returns ๐ The priority values must be greater than 100, because the compiler reserves priority values between 0--100 for the implementation ๐
-Wstrict-aliasing
This one's only active when -fstrict-aliasing is active ๐ฏ It warns about code that might break the strict aliasing rules the compiler uses for optimization. It doesn't catch every case, but it does try to catch the more common pitfalls ๐ชค It's included in -Wall, and it's equivalent to -Wstrict-aliasing=3
-Wstrict-aliasing=n
Same deal: only active when -fstrict-aliasing is active, and it warns about code that might break the strict aliasing rules. Higher levels mean higher accuracy (fewer false positives), and they also take more effort, kinda like how -O works ๐ช -Wstrict-aliasing is equivalent to -Wstrict-aliasing=3.
- Level 1 โ Most aggressive, quick, and least accurate ๐ฌ It's possibly useful when higher levels don't warn but
-fstrict-aliasingstill breaks the code, since it has very few false negatives. However, it has many false positives. It warns for all pointer conversions between possibly incompatible types, even if never dereferenced. It runs in the front end only. - Level 2 โ Aggressive, quick, and not too precise. It may still have many false positives (not as many as level 1 though), and few false negatives (but possibly more than level 1). Unlike level 1, it only warns when an address is taken. It warns about incomplete types and runs in the front end only.
- Level 3 (default for
-Wstrict-aliasing) โ Should have very few false positives and few false negatives ๐ฅ It's slightly slower than levels 1 or 2 when optimization is enabled. It takes care of the common pun+dereference pattern in the front end, like*(int*)&some_float. If optimization is enabled, it also runs in the back end, where it deals with multiple statement cases using flow-sensitive points-to information. It only warns when the converted pointer is dereferenced, and it does not warn about incomplete types.
-Wstrict-overflow and -Wstrict-overflow=n
This one's only active when signed overflow is undefined ๐ It warns about cases where the compiler optimizes based on the assumption that signed overflow doesn't occur. It doesn't warn about all the places code might overflow, only where the compiler actually implements some optimization, so it depends on your optimization level ๐๏ธ
An optimization that assumes no signed overflow is perfectly safe if the values involved never actually overflow ๐ฅฐ So this warning can easily give a false positive, which is a warning about code that isn't actually a problem. To help you focus on the important stuff, several warning levels are defined. No warnings are issued for the use of undefined signed overflow when estimating how many iterations a loop requires, in particular when determining whether a loop will be executed at all ๐
-Wstrict-overflow=1โ Warns about cases that are both questionable and easy to avoid. For example, the compiler simplifiesx + 1 > xto1. This level of-Wstrict-overflowis enabled by-Wall. Higher levels aren't, and must be explicitly requested.-Wstrict-overflow=2โ Also warns about other cases where a comparison is simplified to a constant. For example:abs (x) >= 0. This can only be simplified when signed integer overflow is undefined, becauseabs (INT_MIN)overflows toINT_MIN, which is less than zero.-Wstrict-overflow(with no level) is the same as-Wstrict-overflow=2.-Wstrict-overflow=3โ Also warns about other cases where a comparison is simplified. For example:x + 1 > 1is simplified tox > 0.-Wstrict-overflow=4โ Also warns about other simplifications not covered by the above cases. For example:(x * 10) / 5is simplified tox * 2.-Wstrict-overflow=5โ Also warns about cases where the compiler reduces the magnitude of a constant involved in a comparison. For example:x + 2 > yis simplified tox + 1 >= y. This is reported only at the highest warning level, because this simplification applies to many comparisons, so this level gives a very large number of false positives ๐๐
-Wstringop-overflow and -Wstringop-overflow=type
This warns for calls to string manipulation functions like memcpy and strcpy that are determined to overflow the destination buffer ๐งต The optional argument is one greater than the type of Object Size Checking to perform to determine the size of the destination. The argument only matters for functions that operate on character arrays, not for raw memory functions like memcpy, which always make use of Object Size type-0.
It also warns for calls that specify a size in excess of the largest possible object, or at most SIZE_MAX / 2 bytes ๐ The option gives the best results with optimization enabled, but it can detect a small subset of simple buffer overflows even without optimization, in calls to GCC built-in functions like __builtin_memcpy that correspond to the standard functions ๐ In any case, it only warns about a subset of the buffer overflows detected by the corresponding overflow checking built-ins ๐
For example, the option will issue a warning for 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
}
Okay so bestie, look at that strcpy at the bottom ๐ that's the spot where the warning shows up. Also, heads up ๐
-Wstringop-overflow=2 is enabled by default, so you don't have to do anything to get it.
-Wstringop-overflow,-Wstringop-overflow=1โ This is the type-zero Object Size Checking setting, and it's the default for this option ๐ธ At this level, GCC won't yell about writes past the end of subobjects inside bigger objects that you reach through pointers, unless it knows the size of the largest object around them. If the destination could be one of several objects, GCC just assumes it's the biggest one. On Linux, when optimization is turned on at this level, you get the same warnings you'd get with_FORTIFY_SOURCEdefined to a non-zero value ๐ฆ-Wstringop-overflow=2โ This one uses type-one Object Size Checking โจ It warns about overflows when you write into members of the largest complete objects whose exact size is known. It won't flag excessive writes to the same members of unknown objects reached by pointers, since those might point at arrays with an unknown number of elements ๐ง-Wstringop-overflow=3โ Now we're getting picky ๐ This is type-two Object Size Checking, and it warns about overflowing the smallest object or data member. It's the most restrictive setting that can still warn about code that's actually safe, so it's a little extra ๐-Wstringop-overflow=4โ The type-three Object Size Checking setting is the most dramatic one ๐ฅ It warns about overflowing any data members, and when the destination could be one of several objects, it uses the size of the largest one to decide whether to warn. Like=3, this can give you warnings for code that's totally benign ๐
-Wstringop-truncationโ Warns about calls to bounded string functions likestrncat,strncpy, andstpncpythat might either truncate the copied string or leave the destination unchanged ๐
Here's the strncat situation. The bound is smaller than the length of the source string, so the copy gets truncated and the call gets diagnosed ๐ญ To dodge the warning, use bufsize - strlen (buf) - 1) as the bound.
void append (char *buf, size_t bufsize)
{
strncat (buf, ".txt", 3);
}
Now the strncpy one is a very common trap ๐ซถ This call only copies the characters before the terminating NUL, so the NUL never gets appended to the end. Assuming the result is always NUL-terminated is a super common mistake, so GCC diagnoses it. If you're not expecting a NUL-terminated result, call memcpy instead to avoid the warning โจ
void copy (char *d, const char *s)
{
strncpy (d, s, strlen (s));
}
And here, the bound is the size of the destination buffer ๐ If the source is equal to or longer than that size, the copy won't be NUL-terminated, so this call gets flagged too. To fix it, use sizeof buf - 1 as the bound and set the last element of the buffer to NUL ๐
void copy (const char *s)
{
char buf[80];
strncpy (buf, s, sizeof buf);
...
}
Sometimes a character array is meant to hold bytes with no terminating NUL, and that's valid ๐ฆ You can annotate that array with the nonstring attribute so the warning goes away. Just know these arrays aren't suitable for functions that expect NUL-terminated strings. To help catch accidental misuse, GCC still warns unless it can prove the use is safe ๐ฅ
-Wsuggest-attribute=[pure|const|noreturn|format|cold|malloc]โ Warns when adding an attribute might be a good idea ๐ง The attributes supported right now are listed below.-Wsuggest-attribute=pure,-Wsuggest-attribute=const,-Wsuggest-attribute=noreturn,-Wmissing-noreturn,-Wsuggest-attribute=mallocโ These warn about functions that might be candidates for thepure,const,noreturn, ormallocattributes ๐ GCC only warns for functions that are visible in other compilation units, or (forpureandconst) when it can't prove the function returns normally. A function returns normally if it doesn't contain an infinite loop and doesn't return abnormally by throwing, callingabort, or trapping. This analysis needs-fipa-pure-const, which is enabled by default at-Oand higher. Higher optimization levels make the analysis more accurate ๐-Wsuggest-attribute=format,-Wmissing-format-attributeโ These warn about function pointers that might be candidates forformatattributes ๐ธ They're only possible candidates, not guaranteed ones. GCC guesses that function pointers withformatattributes that get used in assignment, initialization, parameter passing, or return statements should have a matchingformatattribute in the resulting type. So the left-hand side of an assignment or initialization, the type of the parameter variable, or the return type of the containing function should also have aformatattribute to avoid the warning โจ
GCC also warns about function definitions that might be candidates for format attributes, again only as possibilities ๐ GCC guesses a format attribute might fit any function that calls something like vprintf or vscanf, but that's not always true, and some functions that do need format attributes might not get detected.
-Wsuggest-attribute=coldโ 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 of C++throwor fatal error reporting functions that lead toabort๐
-Wsuggest-final-typesโ Warns about types with virtual methods where the code would be better 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 works better with link time optimization, where the class hierarchy graph info is more complete ๐ฆ-Wsuggest-final-methodsโ Warns about virtual methods that would be improved by the C++11finalspecifier, or, if possible, by having their type declared in an anonymous namespace or with thefinalspecifier ๐ This one also works better with link-time optimization. It's recommended to look at-Wsuggest-final-typessuggestions first, then rebuild with the new annotations ๐ซถ-Wsuggest-overrideโ Warns about overriding virtual functions that aren't marked with theoverridekeyword ๐
-Walloc-zeroโ Warns about calls to allocation functions decorated with thealloc_sizeattribute that specify zero bytes. That includes the built-in forms ofaligned_alloc,alloca,calloc,malloc, andrealloc๐
Heads up ๐ญ How these functions behave with a zero size differs between implementations (and realloc has been deprecated for this). Relying on that can cause subtle portability bugs, so it should be avoided.
-Walloc-size-larger-than=byte-sizeโ Warns about calls to functions decorated with thealloc_sizeattribute that try to allocate objects larger than the number of bytes you specify ๐ฅ It also warns when the result of the size computation, done in an integer type with infinite precision, would be bigger thanPTRDIFF_MAXon the target.-Walloc-size-larger-than=PTRDIFF_MAXis enabled by default. You can disable these warnings by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-alloc-size-larger-than๐ธ-Wno-alloc-size-larger-thanโ Disables the-Walloc-size-larger-than=warnings ๐ It's the same as-Walloc-size-larger-than=SIZE_MAXor larger โจ-Wallocaโ Warns on all uses ofallocain the source code ๐ง-Walloca-larger-than=byte-sizeโ Warns on calls toallocawhose integer argument is either zero, or isn't bounded by a controlling predicate that limits its value to at most byte-size. It also warns on calls toallocawhere the bound is unknown ๐ Arguments of non-integer types count as unbounded, even if they look like they're constrained to the expected range ๐ฆ
Here's a bounded alloca example, bestie ๐
void func (size_t n)
{
void *p;
if (n <= 1000)
p = alloca (n);
else
p = malloc (n);
f (p);
}
In this example, passing -Walloca-larger-than=1000 won't warn, because the alloca call is known to be at most 1000 bytes ๐ But if you pass -Walloca-larger-than=500, the compiler will emit a warning ๐
Okay so bestie, now we're getting into unbounded alloca uses ๐. These are the ones with no controlling predicate putting a leash on the integer argument, like this:
void func ()
{
void *p = alloca (n);
f (p);
}
๐ If -Walloca-larger-than=500 were passed, the above would absolutely trigger a warning, but this time it's because there's zero bounds checking. Not a vibe ๐
โโ๏ธ.
Also, even code that looks totally correct with signed integers can set off a warning ๐. Major "I thought I was safe" energy:
void func (signed int n)
{
if (n < 500)
{
p = alloca (n);
f (p);
}
}
In that example, n could be negative, which means a way-larger-than-expected argument gets implicitly cast into the alloca call. Iykyk ๐ญ.
This option also warns when alloca is used in a loop ๐.
-Walloca-larger-than=PTRDIFF_MAX is enabled by default, but it's usually only really effective when -ftree-vrp is active (which is the default for -O2 and above) โจ.
See also -Wvla-larger-than=byte-size ๐ฆ.
-Wno-alloca-larger-thanโ Turns off the-Walloca-larger-than=warnings ๐ โโ๏ธ. It's the same as-Walloca-larger-than=SIZE_MAXor larger ๐ .-Warray-bounds,-Warray-bounds=nโ This one only works when-ftree-vrpis active (default for-O2and above) ๐ธ. It warns about subscripts to arrays that are always out of bounds, and it's enabled by-Wall๐.-Warray-bounds=1โ This is the warning level you get from-Warray-bounds, and-Wallturns it on for you. Higher levels aren't on by default, so you have to ask for them explicitly ๐.-Warray-bounds=2โ This level also catches out-of-bounds access for arrays at the end of a struct and for arrays accessed through pointers ๐. Heads up: it can give way more false positives, so it's deactivated by default ๐.
-Wattribute-alias=n,-Wno-attribute-aliasโ Warns about declarations that use thealiasand similar attributes when the target is incompatible with the alias's type ๐ฆ.-Wattribute-alias=1โ This is the default level. It flags incompatibilities between the type of the alias declaration and the type of its target. These are usually a sign of bugs ๐.-Wattribute-alias=2โ At this level, it also flags cases where the alias declaration has more restrictive attributes than its target ๐ซ . Those mismatches can lead to incorrect code generation โ ๏ธ. Sometimes they're harmless, and you can fix them just by adding the missing attribute to the target ๐ฉน. For comparison, check out-Wmissing-attributes, which handles the opposite situation, where the alias is less restrictive than the target ๐ง .
The attributes it considers are "alloc_align", "alloc_size", "cold", "const", "hot", "leaf", "malloc", "nonnull", "noreturn", "nothrow", "pure", "returns_nonnull", and "returns_twice" โจ.
-Wattribute-alias is the same as -Wattribute-alias=1, and that's the default ๐
. If you want these warnings gone, use either -Wno-attribute-alias or -Wattribute-alias=0 ๐.
-Wbool-compareโ Warns when a boolean expression gets compared to an integer value that isn't"true"/"false"๐ง. Like, this one is always false:
int n = 5;
...
if ((n > 1) == 2) { ... }
It's enabled by -Wall ๐.
-Wbool-operationโ Flags suspicious operations on boolean expressions ๐ฉ. For example, bitwise negation of a boolean is very likely a bug ๐ญ. In C, it also warns about incrementing or decrementing a boolean, which almost never makes sense ๐คจ. (In C++, decrementing a boolean is always invalid, and incrementing one is invalid in C++17 and deprecated before that ๐.) It's enabled by-Wallโจ.-Wduplicated-branchesโ Warns when an if-else has identical branches ๐ฏ. It catches stuff like this:
if (p != NULL)
return 0;
else
return 0;
It won't warn if both branches contain just a null statement ๐ซถ. This one also warns about conditional operators:
int i = x ? *p : *p;
-Wduplicated-condโ Warns about duplicated conditions in an if-else-if chain ๐. For instance, it'll warn about this:
if (p->q != NULL) { ... }
else if (p->q != NULL) { ... }
-Wframe-addressโ Warns when__builtin_frame_addressor__builtin_return_addressgets called with an argument greater than 0 ๐จ. Those calls can return indeterminate values or crash the program ๐ฅ. It's included in-Wall๐.-Wno-discarded-qualifiers(C and Objective-C only) โ Stops the compiler from warning when type qualifiers on pointers get dropped ๐ โโ๏ธ. The usual case is passing a"const char *"variable to a function that wants a"char *"parameter, and this option lets you silence that ๐คซ.-Wno-discarded-array-qualifiers(C and Objective-C only) โ Stops the warning when type qualifiers on arrays that are pointer targets get dropped ๐. The usual case is passing a"const int (*)[]"variable to a function that takes an"int (*)[]"parameter, and this option can shush that warning too ๐.-Wno-incompatible-pointer-types(C and Objective-C only) โ No warning when pointers with incompatible types get converted between each other ๐. This one covers cases that-Wno-pointer-signdoesn't, since that one handles pointer argument passing or assignment with different signedness ๐งฉ.-Wno-int-conversion(C and Objective-C only) โ No warnings about incompatible integer-to-pointer and pointer-to-integer conversions ๐ซ . This one is about implicit conversions. For explicit ones, you can use-Wno-int-to-pointer-castand-Wno-pointer-to-int-castinstead ๐ง.-Wno-div-by-zeroโ Stops the warning about compile-time integer division by zero ๐. Floating-point division by zero doesn't get warned about anyway, because it can be a legit way to get infinities and NaNs ๐.-Wsystem-headersโ Prints warning messages for constructs found in system header files ๐๏ธ. Normally those warnings are suppressed, on the assumption that they usually aren't real problems and would just make the compiler output harder to read ๐. This option tells GCC to emit them as if they came from user code ๐ฃ. Be aware that using-Walltogether with this option does not warn about unknown pragmas in system headers---for that,-Wunknown-pragmasalso has to be used ๐ง.-Wtautological-compareโ Warns if a self-comparison always evaluates to true or false ๐ช. It catches mistakes like this:
int i = 1;
...
if (i > i) { ... }
It also warns about bitwise comparisons that always come out true or false. For example, this one will always be false:
if ((a & 16) == 10) { ... }
It's enabled by -Wall ๐
.
-Wtrampolinesโ Warns about trampolines generated for pointers to nested functions ๐ช. A trampoline is a small chunk of data or code created at run time on the stack when the address of a nested function is taken, and it's used to call that nested function indirectly ๐งฉ. Some targets only use data for this, so they don't need any special treatment ๐ท. But most targets use code, which means the stack has to be made executable for the program to work properly ๐ฌ.-Wfloat-equalโ Warns if floating-point values get used in equality comparisons ๐ข. The reasoning is that sometimes it's handy to treat floats as approximations of infinitely precise real numbers. If you're doing that, you need to figure out (by analyzing the code or some other way) the maximum or likely maximum error the computation introduces, and account for it when you compare values (and when you produce output, but that's a whole different problem ๐). So instead of testing for equality, check whether the two values have ranges that overlap ๐ซง. That's done with the relational operators, so equality comparisons are probably a mistake ๐ โโ๏ธ.-Wtraditional(C and Objective-C only) โ Warns about certain constructs that behave differently in traditional C and ISO C ๐ฐ๏ธ. It also warns about ISO C constructs that have no traditional C equivalent, and about problematic constructs you should avoid ๐ซ. Here's the tea:- Macro parameters that show up inside string literals in the macro body ๐งต. In traditional C, macro replacement happens inside string literals, but in ISO C it doesn't ๐คฏ.
- In traditional C, some preprocessor directives didn't exist. Traditional preprocessors only treated a line as a directive if the
#was in column 1 ๐งฑ. So-Wtraditionalwarns about directives that traditional C understands but ignores, because the#isn't the first character on the line ๐. It also suggests hiding directives like#pragma, which traditional C doesn't understand, by indenting them ๐ซฃ. Some traditional implementations don't recognize#elif, so this option suggests avoiding it altogether ๐ซ. - A function-like macro that appears without arguments ๐.
- The unary plus operator โ.
- The
Uinteger constant suffix, or theForLfloating-point constant suffixes ๐ค. (Traditional C does support theLsuffix on integer constants ๐โโ๏ธ.) Heads up, these suffixes show up in macros defined in the system headers of most modern systems, like the_MIN/_MAXmacros in"<limits.h>"๐. Using those macros in user code would normally cause spurious warnings, but GCC's integrated preprocessor has enough context to avoid warning in these cases ๐ง โจ. - A function declared external in one block and then used after the end of that block ๐งญ.
- A
switchstatement with an operand of type"long"๐.
- โจ okay so a non-
"static"function declaration that shows up after a"static"one is giving chaos ๐ some traditional C compilers straight-up refuse this construct, so watch out, bestie ๐ซถ - ๐ข the ISO type of an integer constant can end up with a different width or signedness than its traditional type ๐ this only gets flagged when the base is ten ๐ so hexadecimal or octal values (the bit-pattern ones) are totally safe, no cap
- ๐งต usage of ISO string concatenation gets detected here ๐
- ๐ฆ initialization of automatic aggregates ๐
- ๐ท๏ธ identifier conflicts with labels ๐ฆ traditional C doesn't have a separate namespace for labels, so that's the whole drama
- ๐ช initialization of unions ๐ if the initializer is zero, the warning gets skipped ๐ that's because a zero initializer in user code is usually conditioned on something like
"__STDC__"to dodge missing-initializer warnings, and it relies on default zero-initialization in the traditional C case - ๐ conversions by prototypes between fixed and floating-point values, and vice versa โ ๏ธ if those prototypes are missing when you compile with traditional C, things get seriously messy ๐ญ this is only a subset of the possible conversion warnings, so for the full set use
-Wtraditional-conversion - ๐ use of ISO C style function definitions ๐
this one is intentionally not issued for prototype declarations or variadic functions, since those ISO features show up in your code when you're using libiberty's traditional C compatibility macros,
"PARAMS"and"VPARAMS"๐ธ it's also skipped for nested functions, because that's already a GCC extension and totally irrelevant to traditional C compatibility ๐ง
-Wtraditional-conversion(C and Objective-C only) โ okay this one is giving prototype drama ๐ซ it warns if a prototype causes a type conversion that's different from what would happen to the same argument with no prototype ๐ฅ that includes fixed-point to floating and vice versa, plus conversions that change the width or signedness of a fixed-point argument, except when it matches the default promotion โจ-Wdeclaration-after-statement(C and Objective-C only) โ warns when a declaration shows up after a statement in a block ๐ this one is borrowed from C++ and was introduced with ISO C99, and GCC lets it slide by default ๐ it is not supported by ISO C90, so ngl, be careful there ๐-Wshadowโ this is the main character warning ๐ it 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++ it warns if a local variable shadows an explicit typedef, but not if it shadows astruct,class, orenum๐ซ this is the same as-Wshadow=global-Wno-shadow-ivar(Objective-C only) โ turns off the warning for when a local variable shadows an instance variable inside an Objective-C method ๐-Wshadow=globalโ the default for-Wshadow๐ warns for any (global) shadowing, no exceptions bestie-Wshadow=localโ warns when a local variable shadows another local variable or a parameter ๐ฏ this one gets turned on by-Wshadow=global-Wshadow=compatible-localโ same vibe as-Wshadow=local, but it only warns when the shadowed variable's type is compatible with the shadowing one ๐ง in C++, "compatible" means the shadowing variable's type can be converted to the shadowed variable's type ๐ this flag exists because when a local variable shadows one of an incompatible type, it's most likely on purpose and not a bug or a typo ๐ฆ like in this example:
for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i)
{
for (int i = 0; i < N; ++i)
{
...
}
...
}
okay so the two i variables in that example have incompatible types, which means enabling only -Wshadow=compatible-local won't emit a warning ๐ and that's fine, because if a programmer accidentally uses one in place of the other, type checking will catch it and emit an error or warning ๐ซถ so skipping the shadowing warning here won't lead to any undetected bugs ๐ธ using this flag instead of -Wshadow=local can possibly cut down on the number of warnings triggered by intentional shadowing โจ
This warning gets enabled by -Wshadow=local ๐
-Wlarger-than=byte-sizeโ warns whenever an object is defined whose size goes over byte-size ๐-Wlarger-than=PTRDIFF_MAXis turned on by default ๐ you can disable these warnings either by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-larger-than๐ซถ-Wno-larger-thanโ disables the-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 goes over byte-size ๐ผ๏ธ heads up, the math used to figure out the stack frame size is approximate and not conservative ๐ฌ the actual requirements might be somewhat greater than byte-size even if you never get a warning ๐ also, any space allocated viaalloca, variable-length arrays, or related constructs is not counted by the compiler when it decides whether to warn ๐-Wframe-larger-than=PTRDIFF_MAXis on by default ๐ธ you can disable these warnings by specifying a byte-size ofSIZE_MAXor more, or by using-Wno-frame-larger-thanโจ-Wno-frame-larger-thanโ disables the-Wframe-larger-than=warnings ๐ it's equivalent to-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โ warns if the stack usage of a function might go over byte-size ๐ the math here is conservative, and any space allocated viaalloca, variable-length arrays, or related constructs is included when deciding whether to warn ๐ซถ the message matches the output of-fstack-usage๐- if the stack usage is fully static but goes over the amount, it's:
warning: stack usage is 1120 bytes - if the stack usage is (partly) dynamic but bounded, it's:
warning: stack usage might be 1648 bytes - if the stack usage is (partly) dynamic and not bounded, it's:
warning: stack usage might be unbounded
- if the stack usage is fully static but goes over the amount, it's:
-Wstack-usage=PTRDIFF_MAX is enabled by default ๐ you can disable these warnings by specifying a byte-size of SIZE_MAX or more, or by using -Wno-stack-usage ๐ซ
-Wno-stack-usageโ disables the-Wstack-usage=warnings ๐ it's equivalent to-Wstack-usage=SIZE_MAXor larger โจ-Wunsafe-loop-optimizationsโ warns if a loop can't be optimized because the compiler can't assume anything about the bounds of the loop indices ๐ with-funsafe-loop-optimizations, it warns if the compiler makes those assumptions instead ๐-Wno-pedantic-ms-format(MinGW targets only) โ when you use it together with-Wformatand-pedanticwithout GNU extensions, this turns off the warnings about non-ISO"printf"/"scanf"format width specifiers"I32","I64", and"I"used on Windows targets ๐ช those depend on the MS runtime, so they're not exactly a crime ๐ฅน-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 one is enabled by-Wall๐ธ normally it only warns about global allocation functions, but-Waligned-new=allalso warns about class member allocation functions ๐-Wplacement-new,-Wplacement-new=nโ warns about placement new expressions with undefined behavior, like constructing an object in a buffer that's smaller than the object's type ๐ฑ for example, this placement new gets diagnosed because it tries to construct an array of 64 integers in a buffer that's only 64 bytes large:
char buf [64];
new (buf) int[64];
this warning is enabled by default ๐ซถ
-Wplacement-new=1โ this is the default warning level for-Wplacement-new๐ at this level, the warning is not issued for some strictly undefined constructs that GCC allows as extensions for compatibility with legacy code ๐ง for example, thisnewexpression isn't diagnosed at this level, 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, in addition to diagnosing everything level 1 catches, it also issues a diagnostic for placement new expressions that construct an object in the last member of a structure whose type is an array of a single element and whose 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 avoid the warning at level 2 ๐
struct S { int n, a[]; };
S *s = (S *)malloc (sizeof *s + 32 * sizeof s->a[0]);
new (s->a)int [32]();
-Wpointer-arithโ warns about anything that depends on the "size of" a function type or ofvoid๐งฎ GNU C gives these types a size of 1, for convenience when doing math withvoid *pointers and pointers to functions ๐ฆ in C++, it also warns when an arithmetic operation involvesNULLโ ๏ธ this warning is also enabled by-Wpedanticโจ-Wpointer-compareโ warns if a pointer is compared with a zero character constant ๐ this usually means the pointer was meant to be dereferenced ๐ for example:
const char *p = foo ();
if (p == '\0')
return 42;
the code above is invalid in C++11, bestie ๐ this warning is enabled by default ๐ซถ
-Wtype-limitsโ okay so this one is a total vibe check ๐ It warns if a comparison is always true or always false just because the data type has a limited range, like an unsigned variable compared against zero with<or>=๐ It won't bother you about constant expressions though. This one also comes along for the ride with-Wextraโจ-Wabsolute-value(C and Objective-C only) โ warns when you call a standard absolute-value function on something it doesn't fit, when there's a more appropriate standard function to use ๐ฅ For example,abs(3.14)gets flagged because a double should usefabs. It also warns when the argument to one of these calls has an unsigned type ๐ซถ You can shut the warning up with an explicit type cast, and it's enabled by-Wextratoo ๐-Wcomment,-Wcommentsโ flags a/*showing up inside a/*comment, or a backslash-newline showing up inside a//comment ๐ธ This one is enabled by-Wall๐-Wtrigraphsโ warns about any trigraphs that could change what your program means ๐ฆ Trigraphs sitting inside comments are left alone, except the ones that would form escaped newlines.
This option is implied by -Wall. If -Wall isn't given, it's still switched on unless trigraphs are enabled. If you want trigraph conversion without the warnings, but still want the other -Wall warnings, use -trigraphs -Wall -Wno-trigraphs ๐
-Wundefโ warns if an undefined identifier gets evaluated in an#ifdirective ๐ง Those identifiers get replaced with zero, so keep an eye out ๐-Wexpansion-to-definedโ warns wheneverdefinedshows up in the expansion of a macro, including when the macro gets expanded by an#ifdirective ๐ญ That kind of usage isn't portable, so it's a no-go. This warning is also enabled by-Wpedanticand-Wextraโจ-Wunused-macrosโ warns about macros that are defined in the main file but never used ๐ A macro counts as used if it 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 never warned about ๐
Note: If a macro is actually used, but only used in skipped conditional blocks, then the preprocessor reports it as unused. To dodge the warning in that situation, you might improve the scope of the macro's definition by, for example, moving it into the first skipped block. Or you could give it a dummy use with something like this:
#if defined the_macro_causing_the_warning
#endif
-Wno-endif-labelsโ don't warn when an#elseor an#endifhas text following it ๐ This happens sometimes 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, honestly ๐ This warning is on by default.
-Wbad-function-cast(C and Objective-C only) โ warns when a function call gets cast to a type that doesn't match ๐ For example, it warns if a call to a function returning an integer type gets cast to a pointer type.-Wc90-c99-compat(C and Objective-C only) โ warns about features that aren't in ISO C90 but are in ISO C99 โจ Think variable length arrays, thelong longtype, thebooltype, compound literals, designated initializers, and so on. This option doesn't care what standards mode you're in. Warnings are turned off in the expression that follows__extension__๐-Wc99-c11-compat(C and Objective-C only) โ warns about features that aren't in ISO C99 but are in ISO C11 ๐ฆ Stuff like anonymous structures and unions, the_Atomictype qualifier, the_Thread_localstorage-class specifier, the_Alignasspecifier, theAlignofoperator, the_Generickeyword, and so on. Again, it doesn't matter which standards mode you're in, and warnings are disabled in the expression that follows__extension__๐ธ-Wc11-c2x-compat(C and Objective-C only) โ warns about features that aren't in ISO C11 but are in ISO C2X ๐ง For instance, it warns about leaving out the string in_Static_assert. It's independent of the standards mode, and warnings are disabled in the expression that follows__extension__๐-Wc++-compat(C and Objective-C only) โ warns about ISO C constructs that live outside the common subset of ISO C and ISO C++ ๐ A classic example is asking for an implicit conversion fromvoid *to a pointer to a non-voidtype.-Wc++11-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning 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 warning turns on-Wnarrowingand is enabled by-Wallโจ-Wc++14-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning differs between ISO C++ 2011 and ISO C++ 2014 ๐ It's enabled by-Wall.-Wc++17-compat(C++ and Objective-C++ only) โ warns about C++ constructs whose meaning differs between ISO C++ 2014 and ISO C++ 2017 ๐ It's enabled by-Walltoo.-Wcast-qualโ warns whenever a pointer gets cast in a way that removes a type qualifier from the target type ๐ For example, it warns if aconst char *gets cast to a plainchar *.
It also warns when you make a cast that adds a type qualifier in an unsafe way ๐ Casting char ** to const char ** is unsafe, as in this example:
/* p is char ** value. */
const char **q = (const char **) p;
/* Assignment of readonly string to const char * is OK. */
*q = "string";
/* Now char** pointer points to read-only memory. */
**p = 'b';
-Wcast-alignโ warns whenever a pointer gets cast so the required alignment of the target goes up ๐ฆ For example, it warns if achar *gets cast to anint *on machines where integers can only be accessed at two- or four-byte boundaries.-Wcast-align=strictโ same deal as-Wcast-align, but stricter ๐ค It warns whenever a pointer gets cast so the required alignment of the target goes up, regardless of the target machine. For example, it warns if achar *gets cast to anint *no matter what machine you're on.-Wcast-function-typeโ warns when a function pointer gets cast to an incompatible function pointer ๐ For a cast involving function types with a variable argument list, only the types of the initial arguments that are actually provided get considered. Any parameter of pointer type matches any other pointer type. Harmless differences in integral types get ignored, likeintvs.longon ILP32 targets, and type qualifiers are ignored too. The function typevoid (*) (void)is special and matches everything, so you can use it to suppress this warning ๐ง For a cast involving pointer to member types, this warning fires whenever the cast changes the pointer to member type. It's enabled by-Wextraโจ-Wwrite-stringsโ when you're compiling C, string constants get the typeconst char[length], so copying the address of one into a non-constchar *pointer produces a warning ๐ These warnings help you find code at compile time that could try to write into a string constant, but only if you've been super careful about usingconstin declarations and prototypes. Otherwise, honestly, it's just a nuisance. That's why-Walldoesn't ask for these warnings.
When you're compiling C++, it warns about the deprecated conversion from string literals to char *. This warning is enabled by default for C++ programs ๐
-Wcatch-value,-Wcatch-value=n(C++ and Objective-C++ only) โ warns about catch handlers that don't catch via reference ๐ With-Wcatch-value=1(or-Wcatch-valuefor short), it warns about polymorphic class types that are caught by value. With-Wcatch-value=2, it warns about all class types that are caught by value. With-Wcatch-value=3, it warns about all types that aren't caught by reference.-Wcatch-valueis enabled by-Wall๐ฅ-Wclobberedโ warns for variables that might be changed bylongjmporvfork๐ธ This warning is also enabled by-Wextra.-Wconditionally-supported(C++ and Objective-C++ only) โ warns for conditionally-supported constructs (C++11[intro.defs]) โจ-Wconversionโ warns for implicit conversions that might alter a value ๐ซถ That includes conversions between real and integer types, likeabs (x)whenxis adouble. It also covers conversions between signed and unsigned, likeunsigned ui = -1, and conversions to smaller types, likesqrtf (M_PI). It does not warn for explicit casts likeabs ((int) x)andui = (unsigned) -1, or if the value doesn't actually change because of the conversion, likeabs (2.0). Warnings about conversions between signed and unsigned integers can be turned off with-Wno-sign-conversion๐ฆ
For C++, it also warns about confusing overload resolution for user-defined conversions, and about conversions that never use a type conversion operator: conversions to void, to the same type, to a base class, or to a reference to them ๐ Warnings about conversions between signed and unsigned integers are disabled by default in C++ unless -Wsign-conversion is explicitly enabled.
-Wno-conversion-null(C++ and Objective-C++ only) โ don't warn about conversions betweenNULLand non-pointer types ๐ Heads up,-Wconversion-nullis enabled by default.-Wzero-as-null-pointer-constant(C++ and Objective-C++ only) โ warns when a literal0is used as a null pointer constant ๐ง This can be super useful for making the jump tonullptrin C++11 ๐-Wsubobject-linkage(C++ and Objective-C++ only) โ warns if a class type has a base or a field whose type uses the anonymous namespace or depends on a type with no linkage ๐ญ If a typeAdepends on a typeBwith no or internal linkage, defining it in multiple translation units would be an ODR violation, because the meaning ofBis different in each translation unit. IfAonly shows up in a single translation unit, the best way to silence the warning is to give it internal linkage by putting it in an anonymous namespace as well โจ The compiler doesn't give this warning for types defined in the main.Cfile, since those are unlikely to have multiple definitions.-Wsubobject-linkageis enabled by default ๐-Wdangling-elseโ okay so this one is about the sneaky dangling else ๐ It warns when it's unclear whichifanelsebelongs to. In C/C++, everyelseattaches to the innermost possibleif, which in this example isif (b), even though the indentation makes it look like it's withif (a). Not what the programmer expected, bestie ๐ When that confusion is possible, GCC warns if you turn this on. To shut it up, add explicit braces around the innermostifso theelsecan't possibly belong to the outer one. Like this:
{
if (a)
if (b)
foo ();
else
bar ();
}
{
if (a)
{
if (b)
foo ();
else
bar ();
}
}
This warning is enabled by -Wparentheses โจ
-Wdate-timeโ โฐ warns when the macros__TIME__,__DATE__or__TIMESTAMP__show up, since they can stop your compilations from being bit-wise-identical reproducible ๐-Wdelete-incomplete(C++ and Objective-C++ only) โ warns when you delete a pointer to an incomplete type, which can cause undefined behavior at runtime ๐ This one is enabled by default, so you get it for free ๐ซถ-Wuseless-cast(C++ and Objective-C++ only) โ warns when an expression gets cast to its own type. Iconic, but pointless ๐-Wempty-bodyโ warns if there's an empty body in anif,elseordo whilestatement ๐ง This one also comes along for the ride with-Wextra-Wenum-compareโ warns about comparisons between values of different enumerated types ๐ In C++, enum mismatches in conditional expressions get flagged too, and that one is enabled by default. In C, this warning is turned on by-Wall๐-Wextra-semi(C++, Objective-C++ only) โ warns about a redundant semicolon after an in-class function definition ๐ extra semicolon, who dis ๐-Wjump-misses-init(C, Objective-C only) โ ๐ฆ warns if agotoor aswitchstatement jumps forward across the initialization of a variable, or jumps backward to a label after that variable has already been initialized. It only cares about variables that get initialized when they're declared. This is only supported for C and Objective-C, because in C++ this sort of branch is an error anyway ๐-Wjump-misses-initis included in-Wc++-compat, and you can turn it off with the-Wno-jump-misses-initoption.-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 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 real to integer, and higher precision real to lower precision real. This option is also enabled by-Wconversion.-Wno-scalar-storage-orderโ tells GCC to chill and not warn about suspicious constructs involving reverse scalar storage order ๐-Wsized-deallocation(C++ and Objective-C++ only) โ warns about an unsized deallocation function definition, like these:
void operator delete (void *) noexcept;
void operator delete[] (void *) noexcept;
when the matching sized deallocation function is missing, like these:
void operator delete (void *, std::size_t) noexcept;
void operator delete[] (void *, std::size_t) noexcept;
Or vice versa, so you can't just have one half of the pair ๐งฉ This is enabled by -Wextra along with -fsized-deallocation.
-Wsizeof-pointer-divโ ๐ warns about suspicious divisions of twosizeofexpressions that divide the pointer size by the element size. That's the usual way people compute array size, but it won't work right with pointers. For example, this warns aboutsizeof (ptr) / sizeof (ptr[0])ifptris a pointer and not an array. This warning is enabled by-Wall.-Wsizeof-pointer-memaccessโ warns about suspicious length parameters passed to certain string and memory built-in functions when the argument usessizeof๐ It triggers for things likememset (ptr, 0, sizeof (ptr));ifptris a pointer and not an array (and suggests a possible fix), ormemcpy (&foo, ptr, sizeof (&foo));. It also warns about bounded string copy functions likestrncatorstrncpythat use asizeofexpression of the source array as the bound. In the example below, thestrncatcall uses the size of the source string as its bound. That's almost certainly a mistake, so the call gets flagged ๐ฉ
void make_file (const char *name)
{
char path[PATH_MAX];
strncpy (path, name, sizeof path - 1);
strncat (path, ".text", sizeof ".text");
...
}
The -Wsizeof-pointer-memaccess option is enabled by -Wall.
-Wsizeof-array-argumentโ warns when thesizeofoperator is applied to a parameter that's declared as an array in a function definition ๐ This one is enabled by default for C and C++ programs.-Wmemset-elt-sizeโ warns about suspicious calls to thememsetbuilt-in function, when the first argument references an array and the third argument is a number equal to the number of elements, but not equal to the size of the array in memory. That's a sign you forgot to multiply by the element size ๐ซ This warning is enabled by-Wall.-Wmemset-transposed-argsโ warns about suspiciousmemsetcalls where the second argument isn't zero and the third argument is zero ๐ For example,memset (buf, sizeof buf, 0)gets diagnosed, becausememset (buf, 0, sizeof buf)was what you meant. The diagnostic only fires if the third argument is a literal zero. If it's an expression that folds to zero, or a cast of zero to some type, the arguments are far less likely to have been mixed up by accident, so no warning is emitted. This warning is enabled by-Wall.-Waddressโ warns about suspicious uses of memory addresses ๐ป That includes using the address of a function in a conditional expression, likevoid func(void); if (func), and comparing against the memory address of a string literal, likeif (x == "abc"). The first one is a classic programmer error, since a function's address always evaluates to true, so you probably forgot the parentheses in a function call. The second one leads to unspecified behavior and isn't portable in C, so you probably meant to usestrcmp. This warning is enabled by-Wall.-Waddress-of-packed-memberโ warns when the address of a packed member of a struct or union is taken, which usually results in an unaligned pointer value ๐ฆ This one is enabled by default.-Wlogical-opโ warns about suspicious uses of logical operators in expressions ๐ง That includes using logical operators in places where a bit-wise operator is probably what you wanted. It also warns when both operands of a logical operator are the same, like this:
extern int a;
if (a < 0 && a < 0) { ... }
-Wlogical-not-parenthesesโ warns about a logical not used on the left hand side of a comparison ๐ This option won't warn if the right operand is considered a boolean expression. It's there to catch code like this:
int a;
...
if (!a > 1) { ... }
You can suppress the warning by wrapping the left hand side in parentheses:
if ((!a) > 1) { ... }
This warning is enabled by -Wall โจ
-Waggregate-returnโ warns if any functions that return structures or unions are defined or called ๐งฑ In languages where you can return an array, this also triggers a warning.-Wno-aggressive-loop-optimizationsโ warns if, in a loop with a constant number of iterations, the compiler detects undefined behavior in some statement during one or more of the iterations ๐-Wno-attributesโ don't warn if an unexpected__attribute__is used, like unrecognized attributes, function attributes applied to variables, and so on ๐คทโโ๏ธ This doesn't stop errors for incorrect use of supported attributes, so those still show up.-Wno-builtin-declaration-mismatchโ warns if a built-in function is declared with an incompatible signature or as a non-function ๐ซ It also warns when a built-in function that's declared with a type lacking a prototype gets called with arguments whose promoted types don't match what the function expects. When-Wextrais specified, it also warns when a built-in function that takes arguments gets declared without a prototype. This-Wno-builtin-declaration-mismatchwarning is enabled by default. To avoid it, include the appropriate header so the prototypes of built-in functions are in scope ๐
For example, the memset call below gets diagnosed, because the function expects a value of type size_t as its argument but the type of 32 is int. With -Wextra, the declaration of the function gets diagnosed too.
extern void* memset ();
void f (void *d)
{
memset (d, '\0', 32);
}
-Wno-builtin-macro-redefinedโ don't warn if certain built-in macros get redefined ๐ท This suppresses warnings for redefinitions of__TIMESTAMP__,__TIME__,__DATE__,__FILE__, and__BASE_FILE__.-Wstrict-prototypes(C and Objective-C only) โ warns if a function is declared or defined without specifying its argument types ๐ An old-style function definition is allowed without a warning if it's preceded by a declaration that specifies the argument types.-Wold-style-declaration(C and Objective-C only) โ ๐ง Okay bestie, this one is for old-school declaration vibes. It warns about obsolescent usages in a declaration, according to the C Standard. For example, it warns if storage-class specifiers likestaticaren't the very first thing in a declaration. This warning is also enabled by-Wextraโจ-Wold-style-definition(C and Objective-C only) โ ๐ Warns if you use an old-style function definition, and it does this even if there's already a previous prototype. Ngl, that's a lot of side-eye for a prototype that already exists ๐-Wmissing-parameter-type(C and Objective-C only) โ ๐ Flags a function parameter that's declared without a type specifier in K&R-style functions. Like this:
void foo(bar) { }
This warning is also enabled by -Wextra ๐
-Wmissing-prototypes(C and Objective-C only) โ ๐ Warns if a global function is defined without a previous prototype declaration. This still fires even when the definition itself provides a prototype. Use it to catch global functions that don't have a matching prototype in a header file. Not valid for C++, though, because every function declaration there already provides a prototype, and a non-matching declaration just makes an overload instead of conflicting with an earlier one. For missing declarations in C++, use-Wmissing-declarationsinstead ๐ฆ-Wmissing-declarationsโ ๐๏ธ Warns if a global function is defined without a previous declaration, even if the definition itself provides a prototype. Use it to find global functions that aren't declared in header files. In C, no warnings are issued for functions with previous non-prototype declarations, so use-Wmissing-prototypesto catch missing prototypes there. In C++, no warnings are issued for function templates, inline functions, or functions in anonymous namespaces ๐ธ-Wmissing-field-initializersโ ๐ Warns if a structure's initializer is missing some fields. In the example below, that causes a warning, becausex.his implicitly zero:
struct s { int f, g, h; };
struct s x = { 3, 4 };
This option doesn't warn about designated initializers, so this version doesn't trigger a warning:
struct s { int f, g, h; };
struct s x = { .f = 3, .g = 4 };
In C, this option also doesn't warn about the universal zero initializer { 0 }:
struct s { int f, g, h; };
struct s x = { 0 };
Likewise, in C++, this option doesn't warn about the empty { } initializer:
struct s { int f, g, h; };
s x = { };
This warning is included in -Wextra. If you want the other -Wextra warnings without this one, use -Wextra -Wno-missing-field-initializers ๐ซถ
-Wno-multicharโ ๐ Stops the warning for multicharacter constants like'FOOF'. Those usually mean there's a typo in your code, since they have implementation-defined values, so they shouldn't be used in portable code ๐-Wnormalized=[none|id|nfc|nfkc]โ ๐ค Okay, this one is giving Unicode drama. 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. To stop that confusion, the ISO 10646 standard has normalization rules that turn look-alike sequences into the same sequence. GCC can warn you if your identifiers haven't been normalized, and this option controls that warning โจ
There are four warning 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 catch: some characters that ISO C and ISO C++ allow in identifiers stop being allowed once they're turned into NFC. So there's no way to use those symbols in portable ISO C or C++ and still have all your identifiers in NFC. -Wnormalized=id suppresses the warning for those characters. The hope is that future versions of the standards will fix this, which is why this isn't the default ๐ฅบ
You can switch the warning off for all characters with -Wnormalized=none or -Wno-normalized. Only do this if you're using some other normalization scheme, like "D", because otherwise you can easily create bugs that are literally impossible to see ๐ญ
Some characters in ISO 10646 have distinct meanings but look identical in some fonts or display methods, especially once formatting is applied. For instance, "\u207F", "SUPERSCRIPT LATIN SMALL LETTER N", displays just like a regular "n" placed in a superscript. ISO 10646 defines the NFKC normalization scheme to convert all of these into a standard form too, and GCC warns if your code isn't in NFKC when you use -Wnormalized=nfkc. This is kind of like warning about every identifier that contains the letter O because it might be confused with the digit 0, so it isn't the default. But it can be a useful local coding convention if your programming environment can't be fixed to display these characters distinctly ๐ง
-Wno-attribute-warningโ ๐ Stops warnings about using functions declared with the "warning" attribute. This warning is enabled by default. You can use-Wno-attribute-warningto disable the warning, or-Wno-error=attribute-warningto disable the error when you compile with the-Werrorflag ๐-Wno-deprecatedโ ๐ซฅ Doesn't warn about usage of deprecated features.-Wno-deprecated-declarationsโ ๐ชฆ Doesn't warn about uses of functions, variables, and types marked as deprecated with the "deprecated" attribute.-Wno-overflowโ ๐ Doesn't warn about compile-time overflow in constant expressions.-Wno-odrโ โ๏ธ Warns about One Definition Rule violations during link-time optimization. It requires-flto-odr-type-mergingto be enabled, and it's enabled by default โ-Wopenmp-simdโ ๐๏ธ Warns if the vectorizer cost model overrides the OpenMP simd directive that the user set. You can use-fsimd-cost-model=unlimitedto relax the cost model ๐-Woverride-init(C and Objective-C only) โ ๐ Warns if an initialized field without side effects gets overridden when you use designated initializers.
This warning is included in -Wextra. If you want the other -Wextra warnings without this one, use -Wextra -Wno-override-init ๐
-Woverride-init-side-effects(C and Objective-C only) โ โ ๏ธ Warns if an initialized field with side effects gets overridden when you use designated initializers. This warning is enabled by default ๐ฅ-Wpackedโ ๐ฆ Warns if a structure has the packed attribute, but that attribute doesn't actually change the layout or size of the structure. Those structures can end up misaligned for basically no benefit. For instance, in this code, the variablef.xinstruct baris misaligned, even thoughstruct bardoesn't have the packed attribute itself:
struct foo {
int x;
char a, b, c, d;
} __attribute__((packed));
struct bar {
char z;
struct foo f;
};
-Wpacked-bitfield-compatโ ๐งฉ The 4.1, 4.2, and 4.3 series of GCC ignored the "packed" attribute on bit-fields of type "char." That got fixed in GCC 4.4, but the change can lead to differences in structure layout. GCC tells you when the offset of such a field has changed in GCC 4.4. For example, there's no longer a 4-bit padding between field "a" and "b" in this structure:
struct foo
{
char a:4;
char b:8;
} __attribute__ ((packed));
This warning is enabled by default. Use -Wno-packed-bitfield-compat to disable it ๐
-Wpacked-not-aligned(C, C++, Objective-C and Objective-C++ only) โ ๐ Warns if a structure field with explicitly specified alignment in a packed struct or union is misaligned. For example, a warning gets issued on "struct S", something like "warning: alignment 1 of 'struct S' is less than 8", in this code:
struct __attribute__ ((aligned (8))) S8 { char a[8]; };
struct __attribute__ ((packed)) S {
struct S8 s8;
};
This warning is enabled by -Wall ๐
-Wpaddedโ ๐ง 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 reduce the padding and make the structure smaller ๐ฐ-Wredundant-declsโ ๐ฏ Warns if anything is declared more than once in the same scope, even when multiple declarations are valid and change nothing ๐-Wno-restrictโ ๐ซ Warns when an object referenced by a "restrict"-qualified parameter (or, in C++, a "__restrict"-qualified parameter) is aliased by another argument, or when copies between those objects overlap. In the example below, the call to thestrcpyfunction 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) โ ๐ช Warns if anexterndeclaration shows up inside a function.-Wno-inherited-variadic-ctorโ ๐คซ Suppresses warnings about using C++11 inheriting constructors when the inherited base class has a C variadic constructor. The warning is on by default, because the ellipsis isn't inherited ๐ง-Winlineโ ๐ช Warns if a function declared as inline can't be inlined. Even with this option, the compiler doesn't warn about failures to inline functions declared in system headers ๐
Okay so the compiler is basically doing a vibe check ๐ฎ before it decides whether to inline a function โจ. It looks at how big the function is and how much inlining has already happened in the current function ๐
. That means tiny edits to your source can make -Winline warnings pop up or vanish ๐ซ
-Wno-invalid-offsetof(C++ and Objective-C++ only) โ Shuts up warnings about using the "offsetof" macro on a non-POD type ๐. According to the 2014 ISO C++ standard, using "offsetof" on a non-standard-layout type is undefined ๐. Existing C++ implementations usually still give meaningful results, though โจ. This flag is for people who know their code is nonportable and have deliberately chosen to ignore the warning ๐ .
The restrictions on "offsetof" may be relaxed in a future version of the C++ standard ๐ฆ.
-Wint-in-bool-contextโ Warns about sketchy integer stuff sneaking into boolean spots ๐ง. That includes conditional expressions (?:) using non-boolean integer constants in a boolean context, likeif (a <= b ? 2 : 3). It also covers left shifting signed integers in a boolean context, likefor (a = 0; 1 << a; a++);. And it's the same deal for all kinds of multiplications, no matter the data type โ๏ธ. This warning is enabled by-Wall๐ธ.-Wno-int-to-pointer-castโ Silences warnings about casting an integer of a different size to a pointer type ๐. In C++, casting to a pointer type of smaller size is an error ๐ซ.Wint-to-pointer-castis enabled by default ๐.-Wno-pointer-to-int-cast(C and Objective-C only) โ Silences warnings about casting from a pointer to an integer type of a different size ๐ง.-Winvalid-pchโ Warns if a precompiled header is found in the search path but can't actually be used ๐ฅฒ.-Wlong-longโ Warns whenever the "long long" type is used ๐. It's turned on by either-Wpedanticor-Wtraditionalin ISO C90 and C++98 modes. To inhibit the warning messages, use-Wno-long-long๐คซ.-Wvariadic-macrosโ Warns if variadic macros are used in ISO C90 mode, or if the GNU alternate syntax is used in ISO C99 mode ๐. It's enabled by either-Wpedanticor-Wtraditional. To inhibit the warning messages, use-Wno-variadic-macros๐.-Wvarargsโ Warns about questionable usage of the macros that handle variable arguments, like "va_start" ๐ง. This one is the default. To inhibit the warning messages, use-Wno-varargs๐ .-Wvector-operation-performanceโ Warns if a vector operation isn't implemented using the SIMD capabilities of the architecture ๐. It's mainly useful for performance tuning โก. There are three ways a vector operation can get implemented:- "piecewise" means the scalar operation runs on every vector element ๐งฉ.
- "in parallel" means the vector operation is implemented using scalars of a wider type, which is normally more performance efficient ๐๏ธ.
- "as a single scalar" means the vector fits into a scalar type ๐ฏ.
-Wno-virtual-move-assignโ Suppresses warnings about inheriting from a virtual base with a non-trivial C++11 move assignment operator ๐.
This 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 the move assignment operator is written to avoid moving from a moved-from object, this warning can be disabled ๐ซถ.
-Wvlaโ Warns if a variable-length array is used in the code ๐.-Wno-vlaprevents the-Wpedanticwarning of the variable-length array ๐.-Wvla-larger-than=byte-sizeโ If you use this, the compiler will warn about declarations of variable-length arrays whose size is either unbounded, or bounded by an argument that lets the array size exceed byte-size bytes ๐ฐ. It's kinda like how-Walloca-larger-than=byte-sizeworks, just for variable-length arrays.
Note that GCC may optimize small variable-length arrays of a known value into plain arrays, so this warning may not get triggered for those ๐ค.
-Wvla-larger-than=PTRDIFF_MAX is enabled by default, but it's typically only effective when -ftree-vrp is active, which is the default for -O2 and above ๐.
See also -Walloca-larger-than=byte-size ๐.
-Wno-vla-larger-thanโ Disables-Wvla-larger-than=warnings ๐ซ. It's equivalent to-Wvla-larger-than=SIZE_MAXor larger ๐ง .-Wvolatile-register-varโ Warns if a register variable is declared volatile ๐ง. The volatile modifier doesn't stop every optimization that might eliminate reads and/or writes to register variables. This warning is enabled by-Wall๐.-Wdisabled-optimizationโ Warns if a requested optimization pass gets disabled ๐ฅบ. This doesn't usually mean anything's wrong with your code. It just means GCC's optimizers can't handle it effectively ๐คทโโ๏ธ. Often the problem is that your code is too big or too complex, since GCC refuses to optimize programs when the optimization would likely take inordinate amounts of time โณ.-Wpointer-sign(C and Objective-C only) โ Warns for pointer argument passing or assignment with different signedness ๐งถ. This option is only supported for C and Objective-C. It's implied by-Walland by-Wpedantic, and it can be disabled with-Wno-pointer-sign๐ โโ๏ธ.-Wstack-protectorโ This one only works 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 from the C standard ๐. Modern compilers are pretty chill and allow string constants way longer than that minimum, but very portable programs should avoid longer strings ๐.
The limit applies after string constant concatenation, and it doesn't count the trailing NUL ๐งฎ. In C90 the limit was 509 characters, and in C99 it got raised to 4095 ๐. C++98 doesn't specify a normative minimum maximum, so we don't diagnose overlength strings in C++ ๐.
This option is implied by -Wpedantic, and it can be disabled with -Wno-overlength-strings ๐
.
-Wunsuffixed-float-constants(C and Objective-C only) โ Issues a warning for any floating constant that doesn't have a suffix ๐ข. When you use it together with-Wsystem-headers, it also warns about those constants in system header files ๐๏ธ. This can be super useful when you're prepping code to use with the "FLOAT_CONST_DECIMAL64" pragma from the decimal floating-point extension to C99 ๐.-Wno-designated-init(C and Objective-C only) โ Suppresses warnings when a positional initializer is used to initialize a structure that's been marked with the "designated_init" attribute ๐.-Whsaโ Issues a warning when HSAIL can't be emitted for the compiled function or OpenMP construct โ ๏ธ.
๐ Options for Debugging Your Program
Okay so if you want GCC to emit extra info for a debugger, you almost always just need to add -g to your other options ๐ง. That's it, that's the tea ๐ซ.
GCC lets you use -g with -O too โจ. The shortcuts optimized code takes can be a little surprising, ngl ๐ญ. Some variables you declared might not exist at all ๐ป. Flow of control might briefly jump somewhere you didn't expect ๐. Some statements might not run because they compute constant results or their values are already at hand ๐งฎ. And some statements might execute in different places because they got moved out of loops ๐. Nevertheless, it's totally possible to debug optimized output ๐ช, which makes it reasonable to use the optimizer for programs that might have bugs ๐ซถ.
If you aren't using some other optimization option, consider using -Og with -g ๐ฆ. With no -O option at all, some compiler passes that collect debugging info don't run at all, so -Og may give you a better debugging experience ๐.
-gโ Produces debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF) ๐. GDB can work with this debugging information ๐.
On most systems that use stabs format, -g enables extra debugging info that only GDB can use ๐. That makes debugging work better in GDB, but it probably makes other debuggers crash or refuse to read the program ๐. If you want to control for certain whether to generate the extra info, use -gstabs+, -gstabs, -gxcoff+, -gxcoff, or -gvms (see below) ๐ฏ.
-ggdbโ Produces debugging information for GDB ๐ธ. It uses the most expressive format available (DWARF, stabs, or the native format if neither of those are supported), including GDB extensions if at all possible ๐.-gdwarf,-gdwarf-versionโ Produces debugging information in DWARF format (if that's supported) ๐งโโ๏ธ. The value of version may be 2, 3, 4 or 5 ๐ข. The default version for most targets is 4 โ . DWARF Version 5 is only experimental ๐งช.
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 than 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โ Produces debugging information in stabs format (if that's supported), without GDB extensions ๐งพ. This is the format DBX uses on most BSD systems ๐ก. On MIPS, Alpha and System V Release 4 systems, this option produces stabs debugging output that DBX doesn't understand ๐ต. On System V Release 4 systems, this option requires the GNU assembler ๐ ๏ธ.-gstabs+โ Produces debugging information in stabs format (if that's supported), using GNU extensions that only the GNU debugger (GDB) understands โจ. Using these extensions will likely make other debuggers crash or refuse to read the program ๐.-gxcoffโ Produces debugging information in XCOFF format (if that's supported) ๐ฅ๏ธ. This is the format the DBX debugger uses on IBM RS/6000 systems ๐งก.-gxcoff+โ okay bestie, this one spits out debug info in XCOFF format ๐ง (if your setup even supports it). It uses GNU extensions that only GDB (the GNU debugger) understands, so other debuggers might crash or straight up refuse to read your program ๐. Other assemblers besides GAS (the GNU assembler) might also throw an error on it.-gvmsโ Alpha/VMS debug format ๐ฆ (again, only if it's supported). This is the format DEBUG uses on Alpha/VMS systems, so if that's your world, slay.-glevel,-ggdblevel,-gstabslevel,-gxcofflevel,-gvmslevelโ you ask for debug info AND pick how much with a level ๐ธ. The default is2, obviously iconic.- Level 0 โ zero debug info at all ๐
โโ๏ธ. So
-g0cancels out-g, periodt. - Level 1 โ minimal vibes, just enough for backtraces in the parts you don't plan to debug. You get descriptions of functions and external variables plus line number tables, but no info about local variables.
- Level 3 โ the extra-extra stuff, like all the macro definitions in the program ๐ฅ. Some debuggers can do macro expansion when you use
-g3. - If you stack multiple
-goptions, with or without level numbers, the last one is the one that counts ๐. -gdwarfdoesn't accept a concatenated debug level, so it won't get mixed up with-gdwarf-level. Use an additional-gleveloption to change the debug level for DWARF instead ๐.
- Level 0 โ zero debug info at all ๐
โโ๏ธ. So
-feliminate-unused-debug-symbolsโ produces debug info in stabs format (if supported), but only for symbols that are actually used ๐งน. Lean and mean.-femit-class-debug-alwaysโ instead of dropping a C++ class's debug info into just one object file, it goes into every object file that uses the class ๐. Only use this with debuggers that can't handle GCC's normal way of emitting class debug info.
โ ๏ธ Warning, bestie: this can make your debug info up to a factor of two bigger ๐ญ.
-fno-merge-debug-stringsโ tells the linker to NOT merge together strings in the debug info that are identical across different object files ๐งต. Merging isn't supported by every assembler or linker. It shrinks the debug info in your output file, but costs more link time. Merging is enabled by default โจ.-fdebug-prefix-map=old=newโ when compiling files living in directory old, the debug info describes them as if they lived in directory new instead ๐บ๏ธ. It's great 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 you more reproducible, location-independent builds ๐, but you may 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 works out where variables are stored at each position in the code. That gives you better debug info, as long as the debug info format supports it. It's on by default when you compile with optimization (-Os,-O,-O2, ...), with debug info (-g), and 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 ๐ง . The goal is better debug info while optimizing. Using-gdwarf-4alongside it is recommended ๐ . It can be enabled even if var-tracking is disabled. In that case the annotations are still 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 your build system avoid linking files that have debug info. To be useful, you 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 suitable for conversion into a GDB index ๐งฉ. This is only useful with a linker that can produce GDB index version 7.-fdebug-types-sectionโ when you're using DWARF Version 4 or higher, type DIEs can get their own".debug_types"section instead of living in".debug_info"๐งฉ. Putting them in a separate comdat section is more efficient, since the linker can then remove duplicates โ๏ธ. But not all DWARF consumers support".debug_types"sections yet, and on some objects it makes the debug info bigger instead of smaller ๐ฌ.-grecord-gcc-switches,-gno-record-gcc-switchesโ this one tacks the command-line options that may affect code generation onto theDW_AT_producerattribute in DWARF debug info ๐. The options are joined with spaces, separating them from each other and from the compiler version. It's enabled by default. See also-frecord-gcc-switchesfor another way to store compiler options in the object file.-gstrict-dwarfโ disallows extensions from a later DWARF standard version than the one selected with-gdwarf-version๐ซ. On most targets, though, using non-conflicting DWARF extensions from later standard versions is allowed.-gno-strict-dwarfโ allows extensions from a later DWARF standard version than the one selected with-gdwarf-version๐.-gas-loc-supportโ tells the compiler that the assembler supports.locdirectives ๐, so it can use them to generate DWARF2+ line number tables. This is generally desirable, because assembler-generated line number tables are a lot more compact than the ones the compiler can make itself. It's enabled by default if the assembler was found to support these directives at GCC configure time.-gno-as-loc-supportโ forces GCC to generate DWARF2+ line number tables internally, if DWARF2+ line number tables are going to be generated at all ๐ ๏ธ.gas-locview-supportโ tells the compiler that the assembler supports"view"assignment and reset assertion checking in.locdirectives ๐. It's enabled by default if the assembler was found to support them at GCC configure time.gno-as-locview-supportโ forces GCC to assign view numbers internally, if-gvariable-location-viewsis explicitly requested ๐ .-gcolumn-info,-gno-column-infoโ emits location column information into DWARF debug info, not just file and line ๐. It's enabled by default.-gstatement-frontiers,-gno-statement-frontiersโ makes GCC create markers in its 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 in the program, even if no instructions associated with the corresponding source locations are present there. If the assembler lacks support for view numbers in line number tables, the compiler will emit the line number table, which generally makes them somewhat less compact. The augmented line number tables and location lists are fully backward-compatible, so consumers that aren't aware of these augmentations can still read them, but they won't get any benefit from them either ๐คท.
This is enabled by default when outputting DWARF 2 debug info at the normal level, as long as there's assembler support, -fvar-tracking-assignments is enabled, and -gstrict-dwarf is not. When assembler support isn't available, it may still be enabled, but it forces GCC to output internal line number tables. And if -ginternal-reset-location-views is not 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. Debug info consumers aren't expected to support this extended format, and they would be unable to decode location lists using it.
-ginternal-reset-location-views,-gno-internal-reset-location-viewsโ attempts to determine which location views can be omitted from location view lists ๐ง. This requires the compiler to have very accurate instruction length estimates, which isn't always the case. It may cause incorrect view lists to be generated silently when using an assembler that doesn't support location view lists. The GNU assembler will flag any such error as a"view number mismatch". This is only enabled on ports that define a reliable estimation function.-ginline-points,-gno-inline-pointsโ generates extended debug info for inlined functions ๐ช. Location view tracking markers are inserted at inlined entry points, so address and view numbers can be computed and output in the debug info. This can be enabled independently of location views, in which case the view numbers won't be output. It can only be enabled along with statement frontiers, and it's only enabled by default if location views are enabled ๐.-gz[=type]. Okay so this one makes compressed debug sections in DWARF format ๐๏ธ, but only if that's supported, bestie! If you don't give a type, the default depends on what your assembler and linker can do. type can benone(don't compress the debug sections ๐ ),zlib(zlib compression in ELF gABI format), orzlib-gnu(zlib compression in the traditional GNU format). If the linker can't write compressed debug sections, the option gets rejected ๐. If the assembler can't handle them,-gzis silently ignored when producing object files ๐ซฅ.-femit-struct-debug-baseonly. This one is giving minimalism ๐ฆ. Debug info for struct-like types only gets emitted when the base name of the compilation source file matches the base name of the file where the struct is defined. It substantially reduces the size of the debug info, but there's a big potential loss in type info for the debugger, so be careful ๐ . If you want something less aggressive, check out-femit-struct-debug-reduced, and for more detailed control, look at-femit-struct-debug-detailed. This option only works with DWARF debug output.-femit-struct-debug-reduced. A slightly chiller version of the baseonly one ๐ธ. Debug info for struct-like types only gets emitted when the base name of the compilation source file matches the base name of the file where the type is defined, unless the struct is a template or defined in a system header. It significantly reduces the debug info size, with some potential loss in type info for the debugger. For a more aggressive option, see-femit-struct-debug-baseonly, and for more detailed control, see-femit-struct-debug-detailed. This option only works with DWARF debug output.-femit-struct-debug-detailed[=spec-list]. This is the detailed boss-level version ๐ of-femit-struct-debug-reducedand-femit-struct-debug-baseonly, and it handles most needs. The whole point is to reduce duplicate struct debug info across different object files in the same program. It's where you say which struct-like types get debug info.
A specification looks like this:
[dir:|ind:][ord:|gen:](any|sys|base|none)
The optional first word limits the spec to structs that are used directly (dir:) or used indirectly (ind:). A struct type is used directly when it's the type of a variable or member. Indirect uses come through pointers to structs. So when using an incomplete struct is valid, the use is indirect. For example: struct one direct; is direct, and struct two * indirect; is indirect.
The optional second word limits the spec to ordinary structs (ord:) or generic structs (gen:). Generic structs are a bit complicated to explain ๐. For C++, these are non-explicit specializations of template classes, or non-template classes within the above. Other programming languages have generics, but -femit-struct-debug-detailed doesn't implement them yet.
The third word specifies the source files for those structs that should get debug info. The values none and any have their normal meaning. The value base means the base of the name of the file where the type declaration appears must match the base of the name of the main compilation file. In practice, when compiling foo.c, debug info is generated for types declared in that file and foo.h, but not other header files. The value sys means those types that satisfy base or are declared in system or compiler headers.
You may need to experiment to find the best settings for your app ๐งช.
The default is -femit-struct-debug-detailed=all.
This option only works with DWARF debug output.
-fno-dwarf2-cfi-asm. Instead of using GAS.cfi_*directives, this one emits DWARF unwind info as a compiler-generated.eh_framesection ๐ง.-fno-eliminate-unused-debug-types. Normally, when producing DWARF output, GCC skips debug symbol output for types that are nowhere used in the source file being compiled. Sometimes you actually want debug info for every type declared in a compilation unit, even unused ones. For example, if you want to cast a value to a type in the debugger that your program doesn't actually use (but does declare). Honestly though, this usually just wastes a ton of space ๐ญ.
โจ Options That Control Optimization โจ
These options control various sorts of optimizations ๐.
Without any optimization option, the compiler's goal is to reduce compilation cost and make debugging give the results you expect ๐. Statements are independent: if you stop the program at a breakpoint between statements, you can assign a new value to any variable or change the program counter to any other statement in the function and get exactly the results you expect from the source code.
Turning on optimization flags makes the compiler try to improve performance and/or code size, at the expense of compilation time and possibly the ability to debug the program ๐ฅ.
The compiler optimizes based on what it knows about the program. Compiling multiple files at once into a single output file lets the compiler use info from all the files when compiling each of them ๐ซถ.
Not all optimizations get their own flag. Only optimizations that have a flag are listed in this section ๐.
Most optimizations are completely disabled at -O0, or when no -O level is set on the command line, even if you specify individual optimization flags. Similarly, -Og suppresses many optimization passes.
Depending on the target and how GCC was configured, a slightly different set of optimizations might be enabled at each -O level than what's listed here. To find the exact set enabled at each level, run -Q --help=optimizers โจ.
-O,-O1. Optimize! Optimizing compilation takes somewhat more time, and a lot more memory for a large function ๐ง .
With -O, the compiler tries to reduce code size and execution time, without 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 one 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:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fcaller-saves -fcode-hoisting -fcrossjumping -fcse-follow-jumps
-fcse-skip-blocks -fdelete-null-pointer-checks -fdevirtualize
-fdevirtualize-speculatively -fexpensive-optimizations -fgcse
-fgcse-lm -fhoist-adjacent-loads -finline-small-functions
-findirect-inlining -fipa-bit-cp -fipa-cp -fipa-icf -fipa-ra
-fipa-sra -fipa-vrp -fisolate-erroneous-paths-dereference
-flra-remat -foptimize-sibling-calls -foptimize-strlen
-fpartial-inlining -fpeephole2 -freorder-blocks-algorithm=stc
-freorder-blocks-and-partition -freorder-functions
-frerun-cse-after-loop -fschedule-insns -fschedule-insns2
-fsched-interblock -fsched-spec -fstore-merging -fstrict-aliasing
-fthread-jumps -ftree-builtin-call-dce -ftree-pre
-ftree-switch-conversion -ftree-tail-merge -ftree-vrp
Heads up ๐: please note the warning under-fgcseabout invoking-O2on programs that use computed gotos.
NOTE: In Ubuntu 8.10 and later versions,-D_FORTIFY_SOURCE=2is set by default, and it's activated when-Ois set to 2 or higher. This enables additional compile-time and run-time checks for several libc functions. To disable it, specify either-U_FORTIFY_SOURCEor-D_FORTIFY_SOURCE=0.
-O3. Optimize yet more ๐ฅ๐ฅ.-O3turns on all optimizations specified by-O2, and also turns on the following:
-fgcse-after-reload -finline-functions -fipa-cp-clone
-floop-interchange -floop-unroll-and-jam -fpeel-loops
-fpredictive-commoning -fsplit-paths -ftree-loop-distribute-patterns
-ftree-loop-distribution -ftree-loop-vectorize -ftree-partial-pre
-ftree-slp-vectorize -funswitch-loops -fvect-cost-model
-fversion-loops-for-strides
-O0. The chill default ๐ง. It reduces compilation time and makes debugging give the expected results. This is the default.-Os. Optimize for size ๐.-Osenables all-O2optimizations except the ones that often increase code size:
-falign-functions -falign-jumps -falign-labels -falign-loops
-fprefetch-loop-arrays -freorder-blocks-algorithm=stc
It also enables -finline-functions, makes the compiler tune for code size rather than execution speed, and performs further optimizations designed to shrink the code.
-Ofast. Disregard strict standards compliance ๐ค.-Ofastenables all-O3optimizations. It also enables optimizations that aren't valid for every standard-compliant program. It turns on-ffast-mathand the Fortran-specific-fstack-arrays(unless-fmax-stack-var-sizeis specified), and-fno-protect-parens.-Og. Optimize the debugging experience ๐ฆ.-Ogshould be your go-to optimization level for the standard edit-compile-debug cycle. It offers a reasonable level of optimization while keeping compilation fast and the debugging experience good. It's a better choice than-O0for producing debuggable code, because some compiler passes that collect debug info are disabled at-O0๐.
Like -O0, -Og totally switches off a bunch of optimization passes, so the individual options that control those passes won't do anything ๐ Otherwise, -Og turns on all the -O1 optimization flags, except the ones that might get in the way of debugging ๐ Here's the skip list:
-fbranch-count-reg -fdelayed-branch -fif-conversion
-fif-conversion2 -finline-functions-called-once
-fmove-loop-invariants -fssa-phiopt -ftree-bit-ccp -ftree-pta
-ftree-sra
If you use multiple -O options, with or without level numbers, the last one you write is the one that counts โจ
Options that look like -fflag are the machine-independent flags ๐
Most of them come in two flavours, a positive and a negative. The negative version of -ffoo is -fno-foo. The list below only shows the one you'll usually reach for, so if you need the other one, just add or remove the no- bit ๐ฆ
The following options control specific optimizations ๐ They're either switched on by -O options or they're related to ones that are. Use these in the rare cases when you want to do some "fine-tuning" of which optimizations get performed ๐ง
-fno-defer-popโ On machines that have to pop arguments after a function call, this makes the compiler pop them right away, as soon as each function returns. At-O1and higher,-fdefer-popis the default, which lets arguments pile up on the stack across several function calls and then get popped all at once ๐งน-fforward-propagateโ Runs a forward propagation pass on RTL ๐ฅ The pass tries to combine two instructions and then checks whether the result can be simplified. If loop unrolling is active, two passes get performed, and the second one is scheduled after loop unrolling. This is enabled by default at optimization levels-O,-O2,-O3,-Os.-ffp-contract=styleโ Controls floating-point expression contraction ๐งฎ-ffp-contract=offturns it off.-ffp-contract=fastturns it on, forming things like fused multiply-add operations if the target has native support for them.-ffp-contract=onturns it on only if the language standard allows it. Right now this one isn't actually implemented, so it gets treated the same as-ffp-contract=off๐ญ The default is-ffp-contract=fast.-fomit-frame-pointerโ Omits the frame pointer in functions that don't need one ๐ฆ This skips the instructions 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 and it can't be left out. Also,-fno-omit-frame-pointerdoesn't promise the frame pointer gets used in every function, since several targets always omit it in leaf functions. Enabled by default at-Oand higher.-foptimize-sibling-callsโ Optimizes sibling and tail recursive calls ๐ Enabled at levels-O2,-O3,-Os.-foptimize-strlenโ Upgrades various standard C string functions (like"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 the"always_inline"attribute ๐ โโ๏ธ This is the default when you're not optimizing. Single functions can get exempted from inlining by marking them with the"noinline"attribute.-finline-small-functionsโ Integrates functions into their callers when their body is smaller than the code for the function call itself, so the overall program gets smaller ๐ The compiler heuristically decides which functions are simple enough to be worth it. This applies to all functions, even ones not declared inline. Enabled at levels-O2,-O3,-Os.-findirect-inliningโ Also inlines indirect calls that are discovered to be known at compile time, thanks to previous inlining โจ This option only has an effect when inlining itself is turned on by-finline-functionsor-finline-small-functions. Enabled at levels-O2,-O3,-Os.-finline-functionsโ Considers all functions for inlining, even if they aren't declared inline ๐ The compiler heuristically decides which ones are worth integrating this way. If every call to a given function gets integrated, and the function is declared"static", then it's normally not output as assembler code in its own right. Enabled at levels-O3,-Os. Also enabled by-fprofile-useand-fauto-profile.-finline-functions-called-onceโ Considers all"static"functions that get called once for inlining into their caller, even if they aren't marked"inline"๐ฏ If a call to a given function is integrated, then the function isn't output as assembler code on its own. Enabled at levels-O1,-O2,-O3and-Os, but not-Og.-fearly-inliningโ Inlines functions marked"always_inline", plus functions whose body seems smaller than the function call overhead, early on. This happens before the-fprofile-generateinstrumentation and the real inlining pass ๐โโ๏ธ Doing it this way makes profiling significantly cheaper and usually makes inlining faster on programs with large chains of nested wrapper functions. Enabled by default.-fipa-sraโ Performs interprocedural scalar replacement of aggregates, removes unused parameters, and swaps parameters passed by reference for parameters passed by value ๐งฉ Enabled at levels-O2,-O3and-Os.-finline-limit=nโ By default GCC limits the size of functions that can be inlined ๐ This flag gives you coarse control over that limit.nis the size of functions that can be inlined, measured in pseudo instructions. Inlining is actually controlled by a bunch of parameters, which you can set one at a time with--param name=value. The-finline-limit=noption sets some of those parameters like this:max-inline-insns-singleis set ton/2.max-inline-insns-autois set ton/2.
See below for documentation on the individual parameters that control inlining, plus their defaults ๐ Heads up: there may be no value of -finline-limit that gives you default behaviour ๐คทโโ๏ธ Also, a "pseudo instruction" here is just an abstract measure of a function's size. It is in no way a count of assembly instructions, so what it means might change from one release to another.
-fno-keep-inline-dllexportโ A more fine-grained version of-fkeep-inline-functions, which only applies to functions declared with the"dllexport"attribute or declspec ๐-fkeep-inline-functionsโ In C, emits"static"functions declared"inline"into the object file, even if they've been inlined into all of their callers ๐ซถ This switch doesn't affect functions using the"extern inline"extension in GNU C90. In C++, it emits any and all inline functions into the object file.-fkeep-static-functionsโ Emits"static"functions into the object file, even if they're never used ๐ธ-fkeep-static-constsโ Emits variables declared"static const"when optimization isn't turned on, even if the variables aren't referenced ๐ GCC enables this option by default. If you want the compiler to check whether a variable is referenced, regardless of 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 from happening. 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 even constant initialized arrays, or initialized constant variables with integral or floating-point types. C and C++ require each variable, including multiple instances of the same variable in recursive calls, to have distinct locations, so using this option results in non-conforming behavior.
๐ Bestie, seriously, this one is non-conforming! C and C++ need every variable to have its own distinct location, so -fmerge-all-constants can break that rule. Use it with your eyes open ๐
-fmodulo-schedโ Performs swing modulo scheduling right before the first scheduling pass ๐ This pass looks at innermost loops and reorders their instructions by overlapping different iterations.-fmodulo-sched-allow-regmovesโ Performs more aggressive SMS-based modulo scheduling, with register moves allowed ๐ Setting this flag deletes certain anti-dependences edges, which triggers the generation of reg-moves based on life-range analysis. This option is only effective when-fmodulo-schedis enabled.-fno-branch-count-regโ Disables the optimization pass that scans for chances to use "decrement and branch" instructions on a count register, instead of instruction sequences that decrement a register, compare it against zero, and then branch based on the result ๐ This option is only meaningful on architectures that support such instructions, which include x86, PowerPC, IA-64 and S/390. Note that-fno-branch-count-regdoesn't remove the decrement and branch instructions that other optimization passes put into the generated instruction stream. The default is-fbranch-count-regat-O1and higher, except for-Og.-fno-function-cseโ Doesn't put function addresses in registers. Instead, every instruction that calls a constant function contains the function's address explicitly ๐ง This gives you less efficient code, but some strange hacks that alter the assembler output may get confused by the optimizations performed when this option isn't used. The default is-ffunction-cse-fno-zero-initialized-in-bssโ If the target supports a BSS section, GCC by default puts variables that are initialized to zero into BSS, which can save space in the resulting code ๐พ This option turns that behaviour off, because some programs explicitly rely on variables living in the data section, e.g. so the resulting executable can find the beginning of that section and/or make assumptions based on it. The default is-fzero-initialized-in-bss.-fthread-jumpsโ okay so this one checks if a jump lands somewhere a comparison the first branch already covers shows up again ๐. If it does, 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 you use a type that takes up multiple registers, likelong longon a 32-bit system, this splits those registers apart and allocates each one on its own ๐ฆ. It usually makes the code better for those types, but ngl it can make debugging harder ๐. Enabled at levels-O,-O2,-O3,-Os.-fcse-follow-jumpsโ during common subexpression elimination (CSE), it scans through jump instructions when no other path reaches the jump's target ๐ง. Like, when CSE hits anifwith anelseclause, it follows the jump when the tested condition is false. Enabled at levels-O2,-O3,-Os.-fcse-skip-blocksโ basically the cousin of-fcse-follow-jumps, but this one makes CSE follow jumps that conditionally skip over blocks ๐. For a simpleifwith noelseclause, CSE follows the jump around the body of theif. Enabled at levels-O2,-O3,-Os.-frerun-cse-after-loopโ runs CSE again after the loop optimizations are done ๐. Enabled at levels-O2,-O3,-Os.-fgcseโ a global common subexpression elimination pass that also does global constant and copy propagation โจ. Enabled at levels-O2,-O3,-Os.
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. ๐
-fgcse-lmโ when this is on, global CSE tries to move loads that only get killed by stores into themselves ๐ซถ. That lets a loop with a load/store sequence become a load outside the loop and a copy/store inside it. Enabled by default when-fgcseis enabled.-fgcse-smโ after global CSE, a store motion pass runs that 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 it. Not enabled at any optimization level.-fgcse-lasโ eliminates redundant loads that come after stores to the same memory location, covering both partial and full redundancies ๐. Not enabled at any optimization level.-fgcse-after-reloadโ a redundant load elimination pass after reload, whose whole job is cleaning up redundant spilling ๐งน. Enabled by-fprofile-useand-fauto-profile.-faggressive-loop-optimizationsโ tells the loop optimizer to use language constraints to figure out bounds on how many times a loop iterates ๐ง . It assumes your loop code doesn't invoke undefined behavior, for example by causing signed integer overflows or out-of-bound array accesses. Those bounds guide loop unrolling, loop peeling, and loop exit test optimizations. This option is enabled by default.-funconstrained-commonsโ tells the compiler that variables declared in common blocks (e.g. Fortran) may later be overridden with longer trailing arrays ๐. This stops certain optimizations that depend on knowing the array bounds.-fcrossjumpingโ performs the cross-jumping transformation, which 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 it. Enabled by default at-Oand higher on architectures that support this.-fdceโ performs dead code elimination (DCE) on RTL ๐๏ธ. Enabled by default at-Oand higher.-fdseโ performs dead store elimination (DSE) on RTL ๐. Enabled by default at-Oand 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โ 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 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. Other GCC optimization passes use this flag to control global dataflow analyses that eliminate useless null pointer checks. Those analyses assume a memory access to address zero always results in a trap, so if a pointer gets checked after it's already been dereferenced, it can't be null.
Note however that in some environments this assumption is not true. 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โ tries to convert calls to virtual functions into direct calls ๐ฏ. This happens both within a procedure and interprocedurally, as part of indirect inlining (-findirect-inlining) and interprocedural constant propagation (-fipa-cp). Enabled at levels-O2,-O3,-Os.-fdevirtualize-speculativelyโ tries to convert calls to virtual functions into speculative direct calls ๐ฎ. Based on analysis of the type inheritance graph, it figures out the set of likely targets for a given call. If that set is small, ideally size 1, the call becomes a conditional that decides between a direct and an indirect call. The speculative calls enable more optimizations, such as inlining. If they seem useless after further optimization, they get converted back into their original form.-fdevirtualize-at-ltransโ streams extra information needed for aggressive devirtualization when running the link-time optimizer in local transformation mode ๐ฆ. This option enables more devirtualization but 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, use this flag to disable the optimization. To keep stores made before the constructor starts (e.g. because youroperator newclears 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=0is equivalent to-fno-lifetime-dse.-flive-range-shrinkageโ tries 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โ uses the specified coloring algorithm for the integrated register allocator ๐จ. Thealgorithmargument can bepriority, which specifies Chow's priority coloring, orCB, which specifies Chaitin-Briggs coloring. Chaitin-Briggs coloring isn't implemented for all architectures, but for the targets that do support it, it's the default because it generates better code.-fira-region=regionโ uses the specified regions for the integrated register allocator ๐บ๏ธ. Theregionargument should be one of the following:allโ uses all loops as register allocation regions. This can give the best results for machines with a small and/or irregular register set.mixedโ uses all loops except for loops with small register pressure as the regions. This value usually gives the best results in most cases and for most architectures, and it's enabled by default when compiling with optimization for speed (-O,-O2, ...).oneโ uses all functions as a single region. This typically results in the smallest code size, and it's enabled by default for-Osor-O0.
-fira-hoist-pressure: okay so this one tells IRA to look at register pressure during the code hoisting pass when it decides which expressions to hoist ๐ง It usually gives you smaller code, but it can slow the compiler down ๐ข Enabled at level-Osfor all targets ๐-fira-loop-pressure: IRA checks register pressure inside loops before deciding whether to move loop invariants ๐ On machines with large register files (>= 32 registers) this usually means faster and smaller code ๐ฅ The compiler might be slower though. Enabled at level-O3for some targets โจ-fno-ira-share-save-slots: turns off sharing of stack slots used to save call-used hard registers that stay alive through a call. Every hard register gets its own slot, so your stack frames get bigger ๐ฆ-fno-ira-share-spill-slots: turns off sharing of stack slots for pseudo-registers. Each pseudo-register that doesn't get a hard register gets its own slot, which means bigger stack frames ๐ฅฒ-flra-remat: enables CFG-sensitive rematerialization in LRA ๐งฎ Instead of loading spilled pseudos back in, LRA tries to recalculate the values if that's actually worth it. Enabled at levels-O2,-O3,-Os.-fdelayed-branch: if the target machine supports it, GCC tries to reorder instructions so they fill the slots available after delayed branch instructions ๐ Enabled at levels-O,-O2,-O3,-Os, but not at-Og๐ โโ๏ธ-fschedule-insns: if the target supports it, GCC reorders instructions to get rid of 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 float op is still cooking. Enabled at levels-O2,-O3.-fschedule-insns2: basically-fschedule-insns, but it also runs an extra round of instruction scheduling after register allocation ๐ This is especially iconic on machines with a small number of registers where memory loads take more than one cycle. Enabled at levels-O2,-O3,-Os.-fno-sched-interblock: disables instruction scheduling across basic blocks ๐ซ This is normally on when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher.-fno-sched-spec: disables speculative motion of non-load instructions ๐ โโ๏ธ This is normally enabled when scheduling happens before register allocation, i.e. with-fschedule-insnsor at-O2or higher.-fsched-pressure: enables register pressure sensitive instruction scheduling before register allocation ๐ This only makes sense when scheduling before register allocation is turned on, i.e. with-fschedule-insnsor at-O2or higher. It can improve the generated code and shrink it too, by stopping register pressure from climbing above the number of available hard registers (which would lead to spills later in register allocation).-fsched-spec-load: allows speculative motion of some load instructions ๐ฅ This only makes sense when scheduling before register allocation, i.e. with-fschedule-insnsor at-O2or higher.-fsched-spec-load-dangerous: allows speculative motion of more load instructions ๐ถ๏ธ The name is a little spicy, and it only makes sense when scheduling before register allocation, i.e. with-fschedule-insnsor at-O2or higher.-fsched-stalled-insns,-fsched-stalled-insns=n: sets how many insns (if any) can get moved early from the queue of stalled insns into the ready list during the second scheduling pass ๐ฏ-fno-sched-stalled-insnsmeans no insns get moved early.-fsched-stalled-insns=0means there's no limit on how many queued insns can be moved early. Plain-fsched-stalled-insnswith no value is the same as-fsched-stalled-insns=1.-fsched-stalled-insns-dep,-fsched-stalled-insns-dep=n: sets how many insn groups (cycles) get checked for a dependency on a stalled insn that's a candidate for early removal from the stalled queue ๐ This only has an effect during the second scheduling pass, and only if-fsched-stalled-insnsis being used.-fno-sched-stalled-insns-depis equivalent to-fsched-stalled-insns-dep=0.-fsched-stalled-insns-depwithout a value is equivalent to-fsched-stalled-insns-dep=1.-fsched2-use-superblocks: when scheduling after register allocation, this uses superblock scheduling, which lets instructions move across basic block boundaries for faster schedules ๐ This only makes sense when scheduling after register allocation, i.e. with-fschedule-insns2or at-O2or higher.
Heads up, bestie: this option is experimental! Not every machine description GCC uses models the CPU closely enough to avoid unreliable results from the algorithm ๐
-fsched-group-heuristic: enables the group heuristic in the scheduler, which favors the instruction that belongs to a schedule group ๐ฏ It's enabled by default when scheduling is on, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-fsched-critical-path-heuristic: enables the critical-path heuristic, which favors instructions on the critical path ๐ค๏ธ Also enabled by default when scheduling is on, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-fsched-spec-insn-heuristic: enables the speculative instruction heuristic, which favors speculative instructions with greater dependency weakness ๐ง Enabled by default when scheduling is on, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-fsched-rank-heuristic: enables the rank heuristic, which favors instructions in a basic block with greater size or frequency ๐ Enabled by default when scheduling is on, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-fsched-last-insn-heuristic: enables the last-instruction heuristic, which favors instructions that depend less on the last instruction scheduled ๐ซง Enabled by default when scheduling is on, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-fsched-dep-count-heuristic: enables the dependent-count heuristic, which favors instructions that have more instructions depending on them ๐ Enabled by default when scheduling is on, i.e. with-fschedule-insnsor-fschedule-insns2or at-O2or higher.-freschedule-modulo-scheduled-loops: modulo scheduling happens before the traditional scheduling, and if a loop gets modulo scheduled, later scheduling passes might change its schedule ๐ Use this one to control that behavior.-fselective-scheduling: schedules instructions with the selective scheduling algorithm ๐๏ธ It runs instead of the first scheduler pass.-fselective-scheduling2: schedules instructions with the selective scheduling algorithm too, but this time it runs instead of the second scheduler pass ๐ช-fsel-sched-pipelining: enables software pipelining of the innermost loops during selective scheduling ๐ฅ This does nothing unless-fselective-schedulingor-fselective-scheduling2is turned on.-fsel-sched-pipelining-outer-loops: when pipelining loops during selective scheduling, this also pipelines the outer loops too ๐ช It does nothing unless-fsel-sched-pipeliningis turned on.-fsemantic-interposition: some object formats, like ELF, let the dynamic linker interpose symbols ๐งฉ That means for symbols exported from the DSO, the compiler can't do interprocedural propagation, inlining, or other optimizations, because the function or variable might get swapped out for something else. This is useful, for example, if you want to rewrite memory allocation functions with a debugging implementation, but it's expensive in terms of code quality ๐ญ With-fno-semantic-interposition, the compiler assumes that if interposition happens for functions, the overwriting function will have precisely the same semantics (and side effects). Similarly, if interposition happens for variables, the constructor of the variable will be the same. This flag has no effect on functions explicitly declaredinline(where interposition is never allowed to change semantics), or on symbols explicitly declared weak.-fshrink-wrap: emits function prologues only before the parts of the function that actually need them, instead of at the very top ๐ Enabled by default at-Oand higher.-fshrink-wrap-separate: shrink-wraps the separate parts of the prologue and epilogue separately, so each part only runs when it's needed โจ This is on by default, but it has no effect unless-fshrink-wrapis also turned on and the target supports it.-fcaller-saves: enables allocation of values to registers that get clobbered by function calls ๐พ It does this by emitting extra instructions to save and restore those registers around such calls. This allocation only happens when it seems to result in better code. It's always enabled by default on certain machines, usually the ones with no call-preserved registers to use instead. Enabled at levels-O2,-O3,-Os.-fcombine-stack-adjustments: tracks stack adjustments (pushes and pops) and stack memory references, then tries to find ways to combine them ๐งน Enabled by default at-O1and higher.-fipa-ra: uses caller-save registers for allocation if none of the called functions use those registers ๐ช That means there's no need to save and restore them around calls. This is only possible if the called functions are part of the same compilation unit as the current function and they get compiled before it. Enabled at levels-O2,-O3,-Os. However, the option is disabled if the generated code will be instrumented for profiling (-p, or-pg), or if the callee's register usage can't be known exactly (which happens on targets that don't expose prologues and epilogues in RTL) ๐
-fconserve-stack Attempt to minimize stack usage ๐ง okay so the compiler tries really hard to use less stack space, even if your program ends up a little slower because of it ๐ฅบ This option also sets the large-stack-frame parameter to 100 and the large-stack-frame-growth parameter to 400 ๐
-ftree-reassoc Perform reassociation on trees ๐ธ This flag is turned on by default at -O and higher โจ
-fcode-hoisting Perform code hoisting ๐ฆ Code hoisting tries to move the evaluation of expressions that run on all paths to the function exit as early as possible ๐
This is especially useful as a code size optimization, but it often helps code speed too ๐ฅ This flag is enabled by default at -O2 and higher ๐
-ftree-pre Perform partial redundancy elimination (PRE) on trees ๐ This flag is enabled by default at -O2 and -O3 ๐ซถ
-ftree-partial-pre Make partial redundancy elimination (PRE) more aggressive ๐ This flag is enabled by default at -O3 ๐ญ
-ftree-forwprop Perform forward propagation on trees ๐ This flag is enabled by default at -O and higher ๐
-ftree-fre Perform full redundancy elimination (FRE) on trees ๐ The difference between FRE and PRE is that FRE only considers expressions that are computed on all paths leading to the redundant computation โจ This analysis is faster than PRE, though it exposes fewer redundancies ๐ง This flag is enabled by default at -O and higher ๐
-ftree-phiprop Perform hoisting of loads from conditional pointers on trees ๐ฆ This pass is enabled by default at -O and higher ๐ธ
-fhoist-adjacent-loads Speculatively hoist loads from both branches of an if-then-else if the loads are 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 Perform copy propagation on trees ๐
This pass gets rid of unnecessary copy operations ๐ This flag is enabled by default at -O and higher โจ
-fipa-pure-const Discover which functions are pure or constant ๐ฎ Enabled by default at -O and higher ๐
-fipa-reference Discover which static variables do not escape the compilation unit ๐ซถ Enabled by default at -O and higher ๐
-fipa-reference-addressable Discover read-only, write-only and non-addressable static variables ๐ Enabled by default at -O and higher ๐
-fipa-stack-alignment Reduce stack alignment on call sites if possible ๐ธ Enabled by default ๐
-fipa-pta Perform interprocedural pointer analysis and interprocedural modification and reference analysis ๐ง > Heads up, bestie: this option can cause excessive memory and compile-time usage on large compilation units ๐ It is not enabled by default at any optimization level ๐ โโ๏ธ
-fipa-profile Perform interprocedural profile propagation ๐ฆ The functions called only from cold functions are 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 Perform interprocedural constant propagation ๐ฅ This optimization analyzes the program to figure out when values passed to functions are constants, and then optimizes accordingly ๐ It can substantially boost performance if your app passes constants 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 Perform function cloning to make interprocedural constant propagation stronger ๐ When enabled, interprocedural constant propagation performs function cloning when an externally visible function can be called with constant arguments ๐ฆ > Heads up: because this can create multiple copies of functions, it may significantly increase code size (see --param ipcp-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, perform interprocedural bitwise constant propagation ๐ง This flag is enabled by default at -O2 and by -fprofile-use and -fauto-profile ๐
It requires that -fipa-cp is enabled ๐ซถ
-fipa-vrp When enabled, perform interprocedural propagation of value ranges ๐ธ This flag is enabled by default at -O2 ๐ It requires that -fipa-cp is enabled ๐
-fipa-icf Perform Identical Code Folding for functions and read-only variables ๐ฅ The optimization reduces code size and may disturb unwind stacks by replacing a function with an equivalent one that has a different name ๐ It works more effectively with link-time optimization enabled โจ
Although the behavior is similar to the Gold Linker's ICF optimization, GCC ICF works on different levels, so the optimizations are not the same ๐ค There are equivalences that only GCC finds and equivalences that only Gold finds ๐ซถ
This flag is enabled by default at -O2 and -Os ๐
-flive-patching=level Control GCC's optimizations so they produce output suitable for live-patching ๐ฆ
If the compiler's optimization uses a function's body, or information extracted from its body, to optimize or change another function, that latter function is called an impacted function of the former ๐ If a function is 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 inlining a function into its caller, cloning a function and changing its caller to call the new clone, or extracting a function's pureness or constness information to optimize its direct or indirect callers, and so on ๐
Usually, the more IPA optimizations enabled, the larger the number of impacted functions for each function ๐ To control the number of impacted functions and more easily compute the list of them, IPA optimizations can be partially enabled at two different levels ๐
The level argument should be one of the following:
inline-cloneOnly enable inlining and cloning optimizations, which include inlining, cloning, interprocedural scalar replacement of aggregates and partial inlining ๐ As a result, when patching a function, all its callers and its clones' callers are impacted, so they need to be patched as well ๐ซถ
-flive-patching=inline-clone disables the following optimization flags: -fwhole-program -fipa-pta -fipa-reference -fipa-ra -fipa-icf -fipa-icf-functions -fipa-icf-variables -fipa-bit-cp -fipa-vrp -fipa-pure-const -fipa-reference-addressable -fipa-stack-alignment ๐
โโ๏ธ
inline-only-staticOnly enable inlining of static functions ๐ธ As a result, when patching a static function, all its callers are impacted and so they need to be patched as well ๐
In addition to all the flags that -flive-patching=inline-clone disables, -flive-patching=inline-only-static disables the following additional optimization flags: -fipa-cp-clone -fipa-sra -fpartial-inlining -fipa-cp ๐ซ
When -flive-patching is specified without any value, the default value is inline-clone โจ
This flag is disabled by default ๐ โโ๏ธ
Note that -flive-patching is not supported with link-time optimization (-flto) ๐
-fisolate-erroneous-paths-dereference Detect paths that trigger erroneous or undefined behavior due to dereferencing a null pointer ๐จ Isolate those paths from the main control flow and turn the statement with erroneous or undefined behavior into a trap ๐ชค This flag is enabled by default at -O2 and higher and depends on -fdelete-null-pointer-checks also being enabled ๐
-fisolate-erroneous-paths-attribute Detect paths that trigger erroneous or undefined behavior due to a null value being used in a way forbidden by a "returns_nonnull" or "nonnull" attribute ๐ซฃ Isolate those paths from the main control flow and turn the statement with erroneous or undefined behavior into a trap ๐ชค This is not currently enabled, but it may be enabled by -O2 in the future ๐ฎ
-ftree-sink Perform forward store motion on trees ๐ง This flag is enabled by default at -O and higher ๐
-ftree-bit-ccp Perform sparse conditional bit constant propagation on trees and propagate pointer alignment information ๐ฆ This pass only operates on local scalar variables and is enabled by default at -O1 and higher, except for -Og ๐ธ It requires that -ftree-ccp is enabled ๐
-ftree-ccp Perform sparse conditional constant propagation (CCP) on trees ๐ This pass only operates on local scalar variables and is enabled by default at -O and higher ๐ซถ
-fssa-backprop Propagate information about uses of a value up the definition chain in order to simplify the definitions ๐ง For example, this pass strips sign operations if the sign of a value never matters ๐ The flag is enabled by default at -O and higher โจ
-fssa-phiopt Perform pattern matching on SSA PHI nodes to optimize conditional code ๐ This pass is enabled by default at -O1 and higher, except for -Og ๐
-ftree-switch-conversion Perform conversion of simple initializations in a switch to initializations from a scalar array ๐ This flag is enabled by default at -O2 and higher ๐
-ftree-tail-merge Look for identical code sequences ๐ When found, replace one with a jump to the other ๐ฆ This optimization is known as tail merging or cross jumping ๐ธ This flag is enabled by default at -O2 and higher ๐ The compilation time in this pass can be limited using the max-tail-merge-comparisons parameter and the max-tail-merge-iterations parameter ๐ง
-ftree-dce Perform dead code elimination (DCE) on trees ๐งน This flag is enabled by default at -O and higher ๐
-ftree-builtin-call-dce Perform conditional dead code elimination (DCE) for calls to built-in functions that may set "errno" but are otherwise free of side effects ๐ This flag is enabled by default at -O2 and higher if -Os is not also specified ๐
-ftree-dominator-opts: okay so this one runs a bunch of little scalar cleanups ๐งน (constant/copy propagation, redundancy elimination, range propagation and expression simplification) by walking a dominator tree โจ. It also does jump threading, which cuts down on jumps that just lead to other jumps ๐ฆ. Enabled by default at-Oand higher ๐.-ftree-dse: dead store elimination (DSE) on trees ๐. A dead store is a write to a memory location that gets overwritten by a later write with no intervening loads, so the first write can be deleted ๐๏ธ. Enabled by default at-Oand higher ๐ซถ.-ftree-ch: loop header copying on trees ๐ธ. It's super beneficial because it boosts the code motion optimizations, and it also saves one jump ๐ฆ. Enabled by default at-Oand higher.
๐ It is not enabled for -Os, since it usually increases code size.
-ftree-loop-optimize: loop optimizations on trees ๐. Enabled by default at-Oand higher โจ.-ftree-loop-linear,-floop-strip-mine,-floop-block: these are loop nest optimizations ๐งฉ, same as-floop-nest-optimize. To use this code transformation, GCC has to be configured with--with-islso the Graphite loop transformation infrastructure is enabled ๐ ๏ธ.-fgraphite-identity: turns on the identity transformation for graphite ๐ช. For every SCoP, GCC generates the polyhedral representation and transforms it back to gimple ๐. With this one you can check the costs or benefits of theGIMPLE -> GRAPHITE -> GIMPLEround trip ๐ . Some minimal optimizations also happen in the code generator isl, like index splitting and dead code elimination in loops ๐ง.-floop-nest-optimize: enables the isl based loop nest optimizer ๐. It's a generic one based on the Pluto optimization algorithms, and it calculates a loop structure that's optimized for data-locality and parallelism ๐.
โ ๏ธ bestie, this option is experimental.
-floop-parallelize-all: uses the Graphite data dependence analysis to figure out which loops can be parallelized ๐งต. It parallelizes every loop that can be analyzed as not containing loop carried dependences, without checking whether parallelizing is actually profitable ๐ฌ.-ftree-coalesce-vars: when GCC transforms the program out of the SSA representation, it tries to cut down on copying by merging versions of different user-defined variables, not just compiler temporaries ๐งฉ. Heads up, this may severely limit your ability to debug an optimized program compiled with-fno-var-tracking-assignments๐ญ. In the negated form, this flag stops SSA coalescing of user variables ๐ โโ๏ธ. It's enabled by default if optimization is on, and it does very little otherwise.-ftree-loop-if-convert: tries to transform conditional jumps in the innermost loops into branch-less equivalents ๐. The vibe is to remove control-flow from those innermost loops so the vectorization pass can handle them better ๐ซ. Enabled by default if vectorization is enabled.-ftree-loop-distribution: loop distribution ๐ฐ. This can improve cache performance on big loop bodies and lets other loop optimizations, like parallelization or vectorization, take place ๐. For example, the loop:
DO I = 1, N
A(I) = B(I) + C
D(I) = E(I) * F
ENDDO
is transformed to:
DO I = 1, N
A(I) = B(I) + C
ENDDO
DO I = 1, N
D(I) = E(I) * F
ENDDO
Enabled by default at -O3. It's also enabled by -fprofile-use and -fauto-profile ๐.
-ftree-loop-distribute-patterns: loop distribution of patterns that can be code generated with calls to a library ๐. Enabled by default at-O3, and by-fprofile-useand-fauto-profileโจ.
This pass distributes the initialization loops and generates a call to memset zero ๐งธ. For example, 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: loop interchange outside of graphite ๐. This can improve cache performance on loop nests and let further loop optimizations, like vectorization, take place ๐ธ. For example, the loop:
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
for (int k = 0; k < N; k++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
is transformed to:
for (int i = 0; i < N; i++)
for (int k = 0; k < N; k++)
for (int j = 0; j < N; j++)
c[i][j] = c[i][j] + a[i][k]*b[k][j];
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 ๐งถ. Enabled by default at-O3, and also by-fprofile-useand-fauto-profile๐.-ftree-loop-im: loop invariant motion on trees ๐. This pass only moves the invariants that are hard to handle at the RTL level, 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 loop unswitching can get away with just trivial invariantness analysis ๐ช. The pass also includes store motion ๐พ.-ftree-loop-ivcanon: creates a canonical counter for the number of iterations in loops where figuring out that number takes complicated analysis ๐ข. Later optimizations can then figure out the number easily ๐. It's especially useful alongside unrolling ๐.-ftree-scev-cprop: performs final value replacement ๐ฏ. If a variable changes inside a loop in such a way that its value on exit can be worked out from only its initial value and the number of loop iterations, uses of the final value get replaced with that computation, as long as it's sufficiently cheap ๐ธ. This reduces data dependencies and may allow further simplifications โจ. Enabled by default at-Oand higher.-fivopts: performs induction variable optimizations (strength reduction, induction variable merging and induction variable elimination) on trees ๐.-ftree-parallelize-loops=n: parallelizes loops, which means splitting their iteration space to run innthreads ๐งต. This is only possible for loops whose iterations are independent and can be arbitrarily reordered ๐ซถ. The optimization is only profitable on multiprocessor machines, and only for CPU-intensive loops rather than loops constrained by things like memory bandwidth ๐ฅ๏ธ. This option implies-pthread, so it's only supported on targets that have support for-pthread๐ .-ftree-pta: performs function-local points-to analysis on trees ๐ต๏ธโโ๏ธ. Enabled by default at-O1and higher, except for-Og๐.-ftree-sra: performs scalar replacement of aggregates ๐ง. This pass swaps structure references for scalars so structures don't get committed to memory too early ๐ง . Enabled by default at-O1and higher, except for-Ogโจ.-fstore-merging: merges narrow stores to consecutive memory addresses ๐ฆ. This pass combines contiguous stores of immediate values that are narrower than a word into fewer, wider stores, which cuts down on the number of instructions ๐. Enabled by default at-O2and higher, as well as-Os๐ธ.-ftree-ter: performs temporary expression replacement during the SSA->normal phase ๐. Single use/single def temporaries get replaced at their use location with their defining expression ๐งฉ. This results in non-GIMPLE code, but it gives the expanders much more complex trees to work on, which leads to better RTL generation ๐ซ. Enabled by default at-Oand higher.-ftree-slsr: performs straight-line strength reduction on trees ๐. It spots related expressions involving multiplications and swaps them for cheaper calculations when possible ๐ธ. Enabled by default at-Oand higher ๐ฆ.-ftree-vectorize: performs vectorization on trees ๐. This flag enables-ftree-loop-vectorizeand-ftree-slp-vectorizeif they aren't explicitly specified ๐ซถ.-ftree-loop-vectorize: performs loop vectorization on trees ๐. Enabled by default at-O3, and by-ftree-vectorize,-fprofile-use, and-fauto-profile๐.-ftree-slp-vectorize: performs basic block vectorization on trees ๐ง. Enabled by default at-O3, and by-ftree-vectorize,-fprofile-use, and-fauto-profileโจ.
-fvect-cost-model=model: changes the cost model used for vectorization ๐ฐ. Themodelargument should be one ofunlimited,dynamicorcheap. With theunlimitedmodel, the vectorized code path is assumed to be profitable ๐ค. With thedynamicmodel, a runtime check guards the vectorized code path so it only runs for iteration counts that will likely execute faster than the original scalar loop ๐โโ๏ธ. Thecheapmodel turns off vectorization of loops where it would be cost prohibitive, for example because of required runtime checks for data dependence or alignment, but otherwise it's the same as thedynamicmodel ๐ โโ๏ธ. The default cost model depends on other optimization flags and is eitherdynamicorcheap๐.-fsimd-cost-model=model: changes the cost model used for vectorization of loops marked with the OpenMP simd directive ๐ถ. All values ofmodelhave the same meaning as described in-fvect-cost-model, and by default, a cost model defined with-fvect-cost-modelis used ๐. Themodelargument should be one ofunlimited,dynamic,cheapโจ.-ftree-vrpโ okay so this one runs Value Range Propagation on trees ๐ณ It's basically the cousin of constant propagation, except instead of tracking single values it tracks whole ranges of values โจ That lets the optimizers ditch unnecessary range checks like array bound checks and null pointer checks ๐ It's on by default at-O2and higher. Heads up though: null pointer check elimination only happens if-fdelete-null-pointer-checksis enabled ๐-fsplit-pathsโ splits paths that lead to loop backedges ๐ค๏ธ This can glow up dead code elimination and common subexpression elimination ๐ฅ It's enabled by default at-O3and above.-fsplit-ivs-in-unrollerโ this lets the unroller express the values of induction variables in later iterations of the unrolled loop by using the value from the first iteration ๐ฆ It breaks up long dependency chains, which makes the scheduling passes way more efficient ๐ซถ
A combo of -fweb and CSE is often enough to get the same effect ๐ But that's not reliable when the loop body is more complicated than a single basic block ๐ญ It also doesn't work at all on some architectures because of restrictions in the CSE pass ๐
This optimization is enabled by default โจ
-fvariable-expansion-in-unrollerโ when unrolling a loop, the compiler creates multiple copies of some local variables ๐ which can result in superior code ๐-fpartial-inliningโ inlines parts of functions ๐งฉ This only has an effect when inlining itself is turned on by-finline-functionsor-finline-small-functions๐ธ
Enabled at levels -O2, -O3, -Os.
-fpredictive-commoningโ performs predictive commoning, aka reusing computations (especially memory loads and stores) from previous loop iterations ๐
This option is enabled at level -O3. It's also enabled by -fprofile-use and -fauto-profile ๐
-fprefetch-loop-arraysโ if the target machine supports it, this generates instructions to prefetch memory so loops that access large arrays run better ๐โโ๏ธ
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โ do not substitute constants for the known return value of formatted output functions like"sprintf","snprintf","vsprintf", and"vsnprintf"(but not"printf"or"fprintf") ๐ This transformation lets GCC optimize or even eliminate branches based on the known return value of these functions, as long as the arguments are either constant or known to be in a range that makes the exact return value possible to figure out ๐ง For example, when-fprintf-return-valueis in effect, both the branch and the body of theifstatement (but not the call tosnprint) can be optimized away wheniis a 32-bit or smaller integer, because the return value is guaranteed to be at most 8 ๐
char buf[9];
if (snprintf (buf, "%08x", i) >= sizeof buf)
...
The -fprintf-return-value option relies on other optimizations and yields the best results with -O2 and above โจ It works in tandem with the -Wformat-overflow and -Wformat-truncation options. The -fprintf-return-value option is enabled by default.
-fno-peephole,-fno-peephole2โ disables any machine-specific peephole optimizations ๐งผ The difference between 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โ do not guess branch probabilities using heuristics ๐ซ๐ฒ
GCC uses heuristics to guess branch probabilities when they aren't provided by profiling feedback (-fprofile-arcs) ๐ These heuristics are based on the control flow graph. If some branch probabilities are specified by "__builtin_expect", the heuristics guess the rest of the control flow graph while taking that "__builtin_expect" info into account. The interactions between the heuristics and "__builtin_expect" can get pretty complex, so sometimes it's useful to turn the heuristics off so the effects of "__builtin_expect" are easier to understand ๐ง
You can also specify the expected probability of an expression with the "__builtin_expect_with_probability" built-in function ๐
The default is -fguess-branch-probability at levels -O, -O2, -O3, -Os.
-freorder-blocksโ reorders basic blocks in the compiled function to reduce the number of taken branches and improve code locality ๐ฆ
Enabled at levels -O, -O2, -O3, -Os.
-freorder-blocks-algorithm=algorithmโ picks the algorithm used for basic block reordering ๐งญ Thealgorithmargument can besimple, which doesn't increase code size (except sometimes due to secondary effects like alignment), orstc, the "software trace cache" algorithm, which puts all the often-executed code together and minimizes the number of branches executed by making extra copies of code ๐ง
The default is simple at levels -O, -Os, and stc at levels -O2, -O3.
-freorder-blocks-and-partitionโ in addition to reordering basic blocks to reduce taken branches, this partitions hot and cold basic blocks into separate sections of the assembly and.ofiles, for better paging and cache locality performance ๐ฅ
This optimization is automatically turned off in the presence of exception handling or unwind tables (on targets using setjump/longjump or a target-specific scheme), for linkonce sections, for functions with a user-defined section attribute, and on any architecture that doesn't support named sections. When -fsplit-stack is used, this option is not enabled by default (to avoid linker errors), but it can be enabled explicitly (if you're using a working linker) ๐ค
Enabled for x86 at levels -O2, -O3, -Os.
-freorder-functionsโ reorders functions in the object file to improve code locality ๐บ๏ธ This is done using the special subsections".text.hot"for most frequently executed functions and".text.unlikely"for unlikely executed functions. The linker does the reordering, so the object file format has to support named sections and the linker has to place them in a reasonable way ๐
This option isn't effective unless you either provide profile feedback (see -fprofile-arcs for details) or manually annotate functions with "hot" or "cold" attributes ๐ญ
Enabled at levels -O2, -O3, -Os.
-fstrict-aliasingโ allows the compiler to assume the strictest aliasing rules that apply to the language being compiled ๐งท For C (and C++), this activates optimizations based on the type of expressions. In particular, an object of one type is assumed never to 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;
}
Reading from a different union member than the one most recently written to (called "type-punning") is super common ๐ฅด Even with -fstrict-aliasing, type-punning is allowed, provided the memory is accessed through the union type. So, the code above works as expected. However, this code might not:
int f() {
union a_union t;
int* ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}
Similarly, accessing by taking the address, casting the resulting pointer, and dereferencing the result has undefined behavior, even if the cast uses a union type, e.g.:
int f() {
double d = 3.0;
return ((union a_union *) &d)->i;
}
Bestie, that last one is undefined behavior ๐ Even with a union type in the cast, it's not safe, so don't write it ๐
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 greater thann, skipping up tom-1bytes โจ This makes sure at least the firstmbytes of the function can be fetched by the CPU without crossing ann-byte alignment boundary ๐น
If m is not specified, it defaults to n.
Examples, because you know I love a good example ๐
-falign-functions=32aligns functions to the next 32-byte boundary-falign-functions=24aligns to the next 32-byte boundary only if this can be done by skipping 23 bytes or less-falign-functions=32:7aligns to the next 32-byte boundary only if this can be done by skipping 6 bytes or less
The second pair of n2:m2 values lets you set a secondary alignment ๐ For example, -falign-functions=64:7:32:3 aligns to the next 64-byte boundary if this can be done by skipping 6 bytes or less, otherwise it aligns to the next 32-byte boundary if this can be done by skipping 2 bytes or less. If m2 is not specified, it defaults to n2.
Some assemblers only support this flag when n is a power of two; in that case, it gets rounded up.
-fno-align-functions and -falign-functions=1 are equivalent and mean that functions are not aligned.
If n is not specified or is zero, a machine-dependent default is used. The maximum allowed n value is 65536.
Enabled at levels -O2, -O3.
-flimit-function-alignmentโ if this is enabled, the compiler tries to avoid overaligning functions when it doesn't need to ๐ It attempts to tell the assembler to align by the amount specified by-falign-functions, but not to skip more bytes than the size of the function ๐-falign-labels,-falign-labels=n,-falign-labels=n:m,-falign-labels=n:m:n2,-falign-labels=n:m:n2:m2โ aligns all branch targets to a power-of-two boundary ๐ฏ
The parameters of this option work the same way as they do for -falign-functions. -fno-align-labels and -falign-labels=1 are equivalent and mean that labels are not aligned.
So if -falign-loops or -falign-jumps apply and their values are bigger than this one, their values win instead ๐
โจ
If n isn't specified or is zero, GCC uses a machine-dependent default that's very likely to be 1, which means no alignment at all ๐. The biggest n you can pass is 65536 ๐
Enabled at levels -O2, -O3 ๐
-falign-loops,-falign-loops=n,-falign-loops=n:m,-falign-loops=n:m:n2,-falign-loops=n:m:n2:m2โ bestie, this one lines your loops up on a power-of-two boundary ๐ฆ If the loops run a bajillion times, the padding ends up being worth it, because it makes up for the time spent running those dummy padding instructions ๐ญ- The parameters work the same way as they do for
-falign-functions.-fno-align-loopsand-falign-loops=1are equivalent, and both mean the loops are not aligned ๐ซถ The max n is65536. - If n isn't specified or is zero, you get a machine-dependent default.
- Enabled at levels
-O2,-O3๐ธ
- The parameters work the same way as they do for
-falign-jumps,-falign-jumps=n,-falign-jumps=n:m,-falign-jumps=n:m:n2,-falign-jumps=n:m:n2:m2โ this one aligns branch targets to a power-of-two boundary ๐ง It's for targets that can only be reached by jumping, so no dummy operations need to run at all, which is iconic โจ- The parameters are analogous to
-falign-functions.-fno-align-jumpsand-falign-jumps=1are equivalent and mean that loops are not aligned ๐ - If n isn't specified or is zero, you get a machine-dependent default. The max n is
65536. - Enabled at levels
-O2,-O3๐
- The parameters are analogous to
-funit-at-a-timeโ this one's only hanging around for compatibility reasons ๐ It has no effect on its own, but-fno-unit-at-a-timeimplies-fno-toplevel-reorderand-fno-section-anchors.- Enabled by default ๐
-fno-toplevel-reorderโ tells GCC to leave top-level functions, variables, and"asm"statements alone, outputting them in the exact same order they appear in your input file ๐ With this on, unreferenced static variables are not removed. It's basically there for existing code that depends on a specific ordering. For new code, attributes are the better move when possible ๐-ftoplevel-reorderis the default at-O1and higher, and also at-O0if-fsection-anchorsis explicitly requested.-fno-toplevel-reorderimplies-fno-section-anchorstoo ๐
-fwebโ this builds webs, which are commonly used for register allocation, and gives each web its own pseudo register ๐ง The register allocation pass can now work on pseudos directly, and it also strengthens a bunch of other passes like CSE, the loop optimizer, and the trivial dead code remover. The catch? It can make debugging impossible, since variables no longer stay in a "home register" ๐ฉ- Enabled by default with
-funroll-loops๐
- Enabled by default with
-fwhole-programโ this tells the compiler to treat the current compilation unit as the whole program being compiled ๐ All public functions and variables, exceptmainand anything merged by the attribute"externally_visible", become static functions. That means the interprocedural optimizers can go wild on them.- > Don't use this together with
-flto. Relying on a linker plugin gives safer and more precise information, so that's the better vibe ๐ซถ
- > Don't use this together with
โจ -flto[=n] โจ
This option runs the standard link-time optimizer, and it's literally the main character of this whole section ๐ฅ 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 out of those ELF sections and instantiated as if they were part of the same translation unit ๐ง
To use the link-time optimizer, -flto and your optimization options should be specified at compile time and during the final link. It's recommended that you compile all the files in the same link with the same options, and also specify those options at link time. For example:
gcc -c -O2 -flto foo.c
gcc -c -O2 -flto bar.c
gcc -o myprog -flto -O2 foo.o bar.o
The first two invocations save a bytecode representation of GIMPLE into special ELF sections inside foo.o and bar.o. The final invocation reads the GIMPLE bytecode from foo.o and bar.o, merges the two files into a single internal image, and compiles the result as usual ๐ Since both files get merged into one image, all the interprocedural analyses and optimizations work across the two files as if they were a single one. So, for example, the inliner can inline functions in bar.o into functions in foo.o and vice-versa. Iconic behaviour ๐ญ
Another (simpler) way to turn on link-time optimization is:
gcc -o myprog -flto -O2 foo.c bar.c
That generates bytecode for foo.c and bar.c, merges them together into a single GIMPLE representation, and optimizes them as usual to produce myprog ๐ธ
The important thing to keep in mind is that, to enable link-time optimizations, you need to use the GCC driver to 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 effective, you have to make certain whole program assumptions. The compiler needs to know what functions and variables can be accessed by libraries and runtime outside of the link-time optimized unit. When the linker supports it, the linker plugin (see -fuse-linker-plugin) passes 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 larger than a regular one, because it contains GIMPLE bytecodes and the usual final code (see -ffat-lto-objects). This means object files with LTO information can still be linked as normal object files. But if -fno-lto is passed to the linker, no interprocedural optimizations get applied ๐ฌ Also, if you use -fno-fat-lto-objects, the compile stage is faster, but you can't 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. That means 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 get linked without any further processing.
Generally, options specified at link time override the ones specified at compile time, although sometimes GCC tries to infer link-time options from the settings used to compile the input files ๐ฎ
If you don't specify an optimization level option -O at link time, GCC uses the highest optimization level that was 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 information needed for effective optimization at link time. Second, some early optimization passes can only be performed at compile time, not at link time.
There are some code generation flags that GCC preserves when generating bytecodes, since they need to be used during the final link. Right now, the following options and their settings are taken from the first object file that explicitly specifies them: -fPIC, -fpic, -fpie, -fcommon, -fexceptions, -fnon-call-exceptions, -fgnu-tm and all the -m target flags ๐
Certain ABI-changing flags have to match across all compilation units. Trying to override them at link time with a conflicting value gets ignored ๐ซ This includes options like -freg-struct-return and -fpcc-struct-return.
Other options, such as -ffp-contract, -fno-strict-overflow, -fwrapv, -fno-trapv or -fno-strict-aliasing, are passed through to the link stage and merged conservatively for conflicting translation units. Specifically, -fno-strict-overflow, -fwrapv and -fno-trapv take precedence, and for example -ffp-contract=off takes precedence over -ffp-contract=fast. You can override them at link time ๐
When you need to pass options to the assembler via -Wa or -Xassembler, make sure to either compile those translation units with -fno-lto, or consistently use the same assembler options on all translation units.
You can alternatively also specify assembler options at LTO link time, which is a nice escape hatch ๐ซฃ
To enable debug info generation, you need to supply -g at compile time. If any of the input files at link time were built with debug info generation enabled, the link will enable debug info generation as well ๐ Any elaborate debug info settings, like the dwarf level -gdwarf-5, need to be explicitly repeated on the linker command line, and mixing different settings across translation units is discouraged ๐
โโ๏ธ
If LTO runs into objects with C linkage declared with incompatible types in separate translation units that get linked together (which is undefined behavior according to ISO C99 6.2.7), a non-fatal diagnostic may be issued. The behavior is still undefined at run time ๐ Similar diagnostics may be raised for other languages too.
Another feature of LTO is that you can apply interprocedural optimizations to files written in different languages ๐
gcc -c -flto foo.c
g++ -c -flto bar.cc
gfortran -c -flto baz.f90
g++ -o myprog -flto -O3 foo.o bar.o baz.o -lgfortran
Notice that the final link is done with g++ to get the C++ runtime libraries, and -lgfortran is added to get the Fortran runtime libraries ๐งโโ๏ธ In general, when mixing languages in LTO mode, you should use the same link command options as you would when mixing languages in a regular (non-LTO) compilation ๐
Okay bestie, so say you've got GIMPLE bytecode object files stuck inside a library archive, like libfoo.a ๐ฆโจ. You can totally pull them out for an LTO link, but only if your linker has plugin support ๐. To make static libraries that vibe with LTO, use gcc-ar and gcc-ranlib instead of ar and ranlib ๐. To peek at the symbols in object files that hold GIMPLE bytecode, use gcc-nm ๐. Heads up, those commands need ar, ranlib and nm to have been compiled with plugin support, no cap. At link time, add -fuse-linker-plugin so the library actually joins the LTO optimization party ๐ฅณ:
gcc -o myprog -O2 -flto -fuse-linker-plugin a.o b.o -lfoo
With the plugin on, the linker pulls the needed GIMPLE files out of libfoo.a and hands them to the running GCC, so they become part of the big aggregated GIMPLE image that gets optimized ๐
.
If you aren't using a linker with plugin support, and/or you don't turn the linker plugin on, the objects inside libfoo.a still get extracted and linked as usual, but they sit out the LTO optimization process ๐ญ. If you want a static library that works for both LTO and normal linking, compile its object files with -flto -ffat-lto-objects ๐ซถ.
Link-time optimizations don't need the whole program to be present to work โจ. If the program doesn't need any symbols exported, you can combine -flto and -fwhole-program so the interprocedural optimizers can make more aggressive assumptions, which may lead to better optimization opportunities ๐. You don't need -fwhole-program when the linker plugin is active (see -fuse-linker-plugin).
The current LTO implementation makes no attempt to generate bytecode that is 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 work well 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 parallel jobs, by utilizing an installed make program ๐โโ๏ธ. The environment variable MAKE can be used to override which program gets used.
You can also use -flto=jobserver to let GNU make's job server mode decide the number of parallel jobs ๐ง. This is super useful when the Makefile calling GCC is already running in parallel. You must prepend a + to the command recipe in the parent Makefile for this to work. This option likely only works if MAKE is GNU make.
Use -flto=auto to use GNU make's job server if it's available, or otherwise fall back to autodetecting the number of CPU threads on your system ๐ง .
-flto-partition=algโ picks the partitioning algorithm the link-time optimizer uses ๐ฐ. The value is either1to1, which partitions to mirror your 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 isbalanced. While1to1can be used as a workaround for various code ordering issues,maxpartitioning is intended for internal testing only โ ๏ธ. The valueonemeans exactly one partition gets used, whilenoneskips partitioning and runs the link-time optimization step directly from the WPA phase.-flto-odr-type-mergingโ turns on streaming of mangled type names of C++ types, plus their unification at link time ๐งฌ. It makes LTO object files bigger, but in return you get diagnostics about One Definition Rule violations ๐.-flto-compression-level=nโ sets how hard the intermediate language written to LTO object files gets compressed ๐๏ธ. Valid values are0(no compression) through9(maximum compression). Values outside that range get clamped to either0or9. If you don't give this option, a default balanced compression setting is used. It's only meaningful alongside LTO mode (-flto) ๐.-fuse-linker-pluginโ enables the use of a linker plugin during link-time optimization ๐. This relies on plugin support in the linker, which is available in gold or in GNU ld 2.21 or newer.
This option lets GCC extract object files with GIMPLE bytecode out of library archives ๐ค. That improves optimization quality by exposing more code to the link-time optimizer ๐. It also carries info about which symbols can be accessed externally (by a non-LTO object or during dynamic linking). The code quality improvements on binaries (and on shared libraries that use hidden visibility) are similar to -fwhole-program. See -flto for a description of what this flag does and how to use it.
This option is enabled by default when LTO support in GCC is enabled and GCC was configured for use with a linker that supports plugins (GNU ld 2.21 or newer, or gold) ๐ฅฐ.
-ffat-lto-objectsโ fat LTO objects are object files that contain both the intermediate language and the object code ๐ฑ. That makes them usable for both LTO linking and normal linking. This option is only effective when compiling with-flto, and it's ignored at link time.
-fno-fat-lto-objects speeds up compilation compared to plain LTO ๐๏ธ, but it requires the complete toolchain to be aware of LTO. It needs a linker with linker plugin support for basic functionality. On top of that, nm, ar and ranlib need to support linker plugins to allow a full-featured build environment (one that can build static libraries and so on). GCC provides the gcc-ar, gcc-nm and gcc-ranlib wrappers to pass the right options to these tools. With non-fat LTO, makefiles need to be modified to use them ๐ ๏ธ.
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-use,-fprofile-use=pathโ enables profile feedback-directed optimizations, plus the following optimizations, many of which are generally only profitable when profile feedback is available ๐ฅ:
-fbranch-probabilities -fprofile-values -funroll-loops
-fpeel-loops -ftracer -fvpt -finline-functions -fipa-cp
-fipa-cp-clone -fipa-bit-cp -fpredictive-commoning -fsplit-loops
-funswitch-loops -fgcse-after-reload -ftree-loop-vectorize
-ftree-slp-vectorize -fvect-cost-model=dynamic
-ftree-loop-distribute-patterns -fprofile-reorder-functions
Before you can use this option, you must first generate profiling information ๐.
By default, GCC emits an error message if the feedback profiles don't match the source code ๐จ. You can turn that error into a warning by using -Wno-error=coverage-mismatch. Just know this may result in poorly optimized code. Also, by default, GCC emits a warning message if the feedback profiles don't exist (see -Wmissing-profile).
If path is specified, GCC looks at that path to find the profile feedback data files. See -fprofile-dir.
-fauto-profile,-fauto-profile=pathโ enables sampling-based feedback-directed optimizations ๐ฏ, plus the following optimizations, many of which are generally only profitable with profile feedback available:
-fbranch-probabilities -fprofile-values -funroll-loops
-fpeel-loops -ftracer -fvpt -finline-functions -fipa-cp
-fipa-cp-clone -fipa-bit-cp -fpredictive-commoning -fsplit-loops
-funswitch-loops -fgcse-after-reload -ftree-loop-vectorize
-ftree-slp-vectorize -fvect-cost-model=dynamic
-ftree-loop-distribute-patterns -fprofile-correction
path is the name of a file containing AutoFDO profile information. If you leave it out, it defaults to fbdata.afdo in the current directory ๐.
Producing an AutoFDO profile data file requires running your program with the perf utility on a supported GNU/Linux target system ๐ง. For more information, see https://perf.wiki.kernel.org/.
E.g.
perf record -e br_inst_retired:near_taken -b -o perf.data \
-- your_program
Then use the create_gcov tool to convert the raw profile data into a format GCC can use ๐. You must also supply the unstripped binary for your program to this tool. See https://github.com/google/autofdo.
E.g.
create_gcov --binary=your_program.unstripped --profile=perf.data \
--gcov=profile.afdo
The following options control compiler behavior regarding floating-point arithmetic ๐ง. These options trade off between speed and correctness, so all of them must be specifically enabled โ๏ธ.
-ffloat-storeโ do not store floating-point variables in registers, and inhibit other options that might change whether a floating-point value is taken from a register or from memory ๐ โโ๏ธ.
Okay so the first thing to know about -ffloat-store ๐ is that it's all about stopping the excess precision drama on machines like the 68000, where the floating registers (of the 68881) keep more precision than a "double" is supposed to have. x86 has the same little problem too ๐ For most programs the extra precision is only a good thing, but a few programs rely on the exact IEEE floating point definition. For those besties, use -ffloat-store after you've updated them to store all the pertinent intermediate computations into variables ๐ซถ
๐ธ -fexcess-precision=style
Okay, 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 you get -fexcess-precision=fast, 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 it's giving chaos.
When you're compiling C and use -fexcess-precision=standard, the excess precision follows the rules in ISO C99. Casts and assignments both make values round to their semantic types, whereas -ffloat-store only affects assignments. This option is turned on by default for C if you use a strict conformance option like -std=c99 โจ Also, -ffast-math turns on -fexcess-precision=fast by default no matter whether you're using a strict conformance option or not.
๐-fexcess-precision=standardis not implemented for languages other than C. On x86, it does nothing if you specify-mfpmath=sseor-mfpmath=sse+387. With-mfpmath=sse, IEEE semantics apply without excess precision. With-mfpmath=sse+387, the rounding is unpredictable.
๐ฆ -ffast-math
This one is a whole vibe ๐๏ธ It sets -fno-math-errno, -funsafe-math-optimizations, -ffinite-math-only, -fno-rounding-math, -fno-signaling-nans, -fcx-limited-range and -fexcess-precision=fast all at once. It also makes the preprocessor macro __FAST_MATH__ get defined ๐ง
Not every -O option turns this on. Only -Ofast does, because it can give you incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. BUT it may yield faster code for programs that don't need the guarantees of those specifications, so it's a choice ๐
๐ -fno-math-errno
Do not set errno after calling math functions that run with a single instruction, for example sqrt. A program that relies on IEEE exceptions for math error handling might want this flag for the speed boost while still keeping IEEE arithmetic compatibility ๐
This is not turned on by any -O option, because it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It may, however, be faster for programs that don't need those guarantees ๐
The default is -fmath-errno.
On Darwin systems, the math library never sets errno. So there's no reason for the compiler to consider that it might, and -fno-math-errno is the default there ๐
๐ท -funsafe-math-optimizations
This one lets the compiler use optimizations for floating-point arithmetic that (a) assume arguments and results are valid and (b) may break IEEE or ANSI standards. When it's used at link time, it may pull in libraries or startup files that change the default FPU control word or do other similar optimizations ๐ญ
Also not turned on by any -O option, for the same reason: it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It may still yield faster code for programs that don't need those guarantees. This 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 series of floating-point operations. It violates the ISO C and C++ language standard because it might change the computation result ๐ Heads up, the re-ordering can change the sign of zero, ignore NaNs, and inhibit or create underflow or overflow. That means you can't use it on code that depends on rounding behavior like (x + 2**52) - 2**52.
It can also reorder floating-point comparisons, so don't use it when ordered comparisons are required. This option needs both -fno-signed-zeros and -fno-trapping-math to be in effect. Also, it doesn't make much sense with -frounding-math. For Fortran, the option gets turned on automatically when both -fno-signed-zeros and -fno-trapping-math are in effect โจ
The default is -fno-associative-math.
๐ง -freciprocal-math
Allows the reciprocal of a value to be used instead of dividing by the value, if that makes things more optimized. For example, x / y can be replaced with x * (1/y), which is handy if (1/y) is subject to common subexpression elimination. Just know that this loses precision and increases the number of flops operating on the value ๐
The default is -fno-reciprocal-math.
๐ซง -ffinite-math-only
This allows optimizations for floating-point arithmetic that assume arguments and results are not NaNs or +-Infs ๐ธ
Not turned on by any -O option, since it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions. It may still 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 says distinct +0.0 and -0.0 values behave in specific ways, which stops you from simplifying expressions like x+0.0 or 0.0*x, even with -ffinite-math-only. This option means the sign of a zero result isn't significant ๐ฆ
The default is -fsigned-zeros.
๐ซ -fno-trapping-math
This tells the compiler to assume floating-point operations cannot generate user-visible traps. Those traps include division by zero, overflow, underflow, inexact result and invalid operation ๐ณ It requires -fno-signaling-nans to be in effect. Turning this on may give faster code if you rely on "non-stop" IEEE arithmetic, for example.
โ ๏ธ This option should never be turned on by any -O option, since it can give incorrect output for programs that depend on an exact implementation of IEEE or ISO rules and specifications for math functions.
The default is -ftrapping-math.
๐ -frounding-math
This disables transformations and optimizations that assume the default floating-point rounding behavior. That's round-to-zero for all floating point to integer conversions, and round-to-nearest for all other arithmetic truncations. You should specify this for programs that change the FP rounding mode dynamically, or that might be executed with a non-default rounding mode ๐
It also disables constant folding of floating-point expressions at compile time (which can be affected by rounding mode), plus arithmetic transformations that are unsafe when sign-dependent rounding modes are involved.
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
This tells the compiler to assume IEEE signaling NaNs may generate user-visible traps during floating-point operations. Turning it on disables optimizations that might change the number of exceptions visible with signaling NaNs. It implies -ftrapping-math โจ
This option makes the preprocessor macro __SUPPORT_SNAN__ get defined ๐ฅ
The default is -fno-signaling-nans.
๐งช This option is experimental and does not currently guarantee to disable all GCC optimizations that affect signaling NaN behavior.
๐ญ -fno-fp-int-builtin-inexact
This stops the built-in functions ceil, floor, round and trunc (and their float and long double variants) from generating code that raises the inexact floating-point exception for noninteger arguments. ISO C99 and C11 let these functions raise the inexact exception, but ISO/IEC TS 18661-1:2014, the C bindings to IEEE 754-2008, does not ๐
โโ๏ธ
The default is -ffp-int-builtin-inexact, which allows the exception to be raised. This option does nothing unless -ftrapping-math is in effect.
๐ Even if you use-fno-fp-int-builtin-inexact, if the functions generate a call to a library function, then theinexactexception may still be raised if the library implementation doesn't follow TS 18661.
๐ -fsingle-precision-constant
This treats floating-point constants as single precision, instead of implicitly converting them to double-precision constants ๐
๐บ -fcx-limited-range
When enabled, this says a range reduction step isn't needed when performing complex division. There's also no checking for whether the result of a complex multiplication or division is "NaN + I*NaN", with an attempt to rescue the situation in that case ๐ซถ
The default is -fno-cx-limited-range, but it gets enabled by -ffast-math. This option controls the default setting of the ISO C99 CX_LIMITED_RANGE pragma. Even so, the option applies to all languages.
๐ -fcx-fortran-rules
Complex multiplication and division follow Fortran rules. Range reduction is done as part of complex division, but there's no checking for whether the result of a complex multiplication or division is "NaN + I*NaN", with an attempt to rescue the situation in that case ๐
The default is -fno-cx-fortran-rules.
The following options control optimizations that may improve performance, but they are not enabled by any -O options. Heads up bestie: this section includes experimental options that may produce broken code ๐
-fbranch-probabilitiesโ okay so, after you compile with-fprofile-arcsand run the program, you can compile it again with-fbranch-probabilitiesto get smarter optimizations based on how many times each branch actually got taken ๐ง . When a-fprofile-arcsprogram exits, it saves arc execution counts to a file calledsourcename.gcdafor each source file. That data file is super dependent on the exact 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 slaps aREG_BR_PROBnote on eachJUMP_INSNandCALL_INSN๐. These can be used to level up 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 figure out which path gets taken more often โจ. - Enabled by
-fprofile-useand-fauto-profile.
- With
-fprofile-valuesโ if you combine it with-fprofile-arcs, it adds code that gathers some data about the values of expressions in your program ๐.- With
-fbranch-probabilities, it reads back the data gathered from profiling those expression values so it can be used in optimizations. - Enabled by
-fprofile-generate,-fprofile-use, and-fauto-profile.
- With
-fprofile-reorder-functionsโ function reordering based on profile instrumentation records the first time each function runs, then puts the functions in ascending order by that time ๐.- Enabled with
-fprofile-use.
- Enabled with
-fvptโ if combined with-fprofile-arcs, this tells the compiler to add code that gathers info about values of expressions ๐ฆ.- With
-fbranch-probabilities, it reads back that data and actually performs optimizations based on it. Right now those optimizations include specialization of division operations using what it knows about the value of the denominator ๐ฅ. - Enabled with
-fprofile-useand-fauto-profile.
- With
-frename-registersโ tries to avoid false dependencies in scheduled code by making use of registers left over after register allocation ๐ธ. This optimization benefits processors with lots of registers the most. BUT, depending on the debug information format the target uses, it can make debugging impossible, since variables no longer stay in a "home register" ๐ญ.- Enabled by default with
-funroll-loops.
- Enabled by default with
-fschedule-fusionโ runs a target-dependent pass over the instruction stream to group instructions of the same type together ๐ง. The target machine can run them more efficiently when they're adjacent in the instruction flow.- Enabled at levels
-O2,-O3,-Os.
- Enabled at levels
-ftracerโ performs tail duplication to enlarge superblock size ๐. This simplifies the function's control flow, so other optimizations can do a better job.- Enabled by
-fprofile-useand-fauto-profile.
- Enabled by
-funroll-loopsโ unrolls loops whose 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 (i.e. complete removal of loops with a small constant number of iterations). Heads up though: this makes code larger, and it may or may not make it run faster ๐คทโโ๏ธ.- Enabled by
-fprofile-useand-fauto-profile.
- Enabled by
-funroll-all-loopsโ unrolls ALL the loops, even if their number of iterations is uncertain when the loop is entered ๐. This usually makes programs run more slowly.-funroll-all-loopsimplies the same options as-funroll-loops.-fpeel-loopsโ peels loops that have enough information to show they don't roll much (from profile feedback or static analysis) ๐. It also turns on complete loop peeling (i.e. complete removal of loops with small constant number of iterations).- Enabled by
-O3,-fprofile-use, and-fauto-profile.
- Enabled by
-fmove-loop-invariantsโ turns on the loop invariant motion pass in the RTL loop optimizer ๐ง.- Enabled at level
-O1and higher, except for-Og.
- Enabled at level
-fsplit-loopsโ splits a loop into two if it contains a condition that's always true for one side of the iteration space and false for the other โ๏ธ.- Enabled by
-fprofile-useand-fauto-profile.
- Enabled by
-funswitch-loopsโ moves branches with loop invariant conditions out of the loop, with duplicates of the loop on both branches (modified according to the result of the condition) ๐.- Enabled by
-fprofile-useand-fauto-profile.
- Enabled by
-fversion-loops-for-stridesโ if a loop iterates over an array with a variable stride, GCC creates another version of the loop that assumes the stride is always one ๐. For example:
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
becomes:
if (stride == 1)
for (int i = 0; i < n; ++i)
x[i] = ...;
else
for (int i = 0; i < n; ++i)
x[i * stride] = ...;
This is particularly useful for assumed-shape arrays in Fortran, where (for example) it allows better vectorization assuming contiguous accesses ๐ซถ. This flag is enabled by default at -O3. It is also enabled by -fprofile-use and -fauto-profile.
-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. 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/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 they 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 the locations are unknown until link time. An example of such an optimization is relaxing calls to short call instructions.
-fbranch-target-load-optimizeโ performs branch target register load optimization before prologue / epilogue threading ๐ฏ. The use of target registers can typically be exposed only during reload, so hoisting loads out of loops and doing inter-block scheduling need a separate optimization pass.-fbranch-target-load-optimize2โ performs branch target register load optimization after prologue / epilogue threading ๐ท.-fbtr-bb-exclusiveโ when doing branch target register load optimization, don't reuse branch target registers within any basic block ๐ซ.-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.- Here's an example. Take this function "foo":
static int a, b, c;
int foo (void) { return a + b + c; }
Normally it calculates the addresses of all three variables. But if you compile it with -fsection-anchors, it accesses the variables from a common anchor point instead ๐ช. The effect is similar to 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.
--param name=valueโ in some places, GCC uses various constants to control how much optimization gets done ๐๏ธ. For example, GCC does not inline functions that contain more than a certain number of instructions. You can control some of these constants on the command line using--param.- The names of specific parameters, and the meaning of the values, are tied to the internals of the compiler and are subject to change without notice in future releases โ ๏ธ.
- To get the minimal, maximal, and default value of a parameter, you can use
--help=param -Qoptions. - In each case, the value is an integer. The allowable choices for
nameare:predictable-branch-outcomeโ when a branch is predicted to be taken with a probability lower than this threshold (in percent), it is considered well predictable ๐ฎ.max-rtl-if-conversion-insnsโ RTL if-conversion tries to remove conditional branches around a block and replace them with conditionally executed instructions. This parameter gives the maximum number of instructions in a block that should be considered for if-conversion. The compiler will also use other heuristics to decide whether if-conversion is likely to be profitable.max-rtl-if-conversion-predictable-cost,max-rtl-if-conversion-unpredictable-costโ RTL if-conversion will try to remove conditional branches around a block and replace them with conditionally executed instructions. These parameters give the maximum permissible cost for the sequence that would be generated by if-conversion, depending on whether the branch is statically determined to be predictable or not. The units for this parameter are the same as those for the GCC internalseq_costmetric. The compiler will try to provide a reasonable default for this parameter using theBRANCH_COSTtarget macro ๐.
โจ OPTIONS โจ (the --param goodies, continued) ๐
max-crossjump-edgesโ okay so this is the max number of incoming edges GCC will even look at for cross-jumping ๐ฆ.-fcrossjumpingruns in O(N^2) time based on the edges coming into each block, so cranking this up is more aggressive optimization, but compile time goes up for probably a small win in executable size ๐.min-crossjump-insnsโ the minimum number of instructions that have to match at the end of two blocks before cross-jumping happens on them ๐. If every instruction in the block being cross-jumped from already matches, this value gets ignored, so don't stress ๐.max-grow-copy-bb-insnsโ the max code size expansion factor when GCC copies basic blocks instead of jumping to them ๐ธ. The expansion is measured relative to a jump instruction โจ.max-goto-duplication-insnsโ the max number of instructions that can be duplicated into a block that jumps to a computed goto ๐ง. GCC factors computed gotos early on to dodge O(N^2) behavior across a bunch of passes, then unfactors them as late as possible ๐ซถ. Only computed jumps sitting at the end of a basic block with no more thanmax-goto-duplication-insnsinstructions get unfactored ๐.max-delay-slot-insn-searchโ how many instructions GCC will consider while hunting for something to fill a delay slot ๐. Past this arbitrary number, the time saved by filling the slot is basically nothing, so GCC just stops searching ๐ญ. Cranking it up means more aggressive optimization and longer compile times, for probably a small boost in execution time ๐.max-delay-slot-live-searchโ when filling delay slots, the max number of instructions to check while looking for a block with valid live register information ๐. Bumping this arbitrary value is more aggressive optimization, which also means longer compile times โญ. This parameter should be removed once the delay slot code gets rewritten to maintain the control-flow graph ๐.max-gcse-memoryโ the approximate max memory GCC can allocate for global common subexpression elimination ๐. If the optimization needs more memory than this, it just doesn't happen ๐ฅบ.max-gcse-insertion-ratioโ if the ratio of expression insertions to deletions for any expression goes above this value, RTL PRE inserts or removes that expression ๐ธ. The result is that partially redundant computations get left behind in the instruction stream ๐ .max-pending-list-lengthโ the max number of pending dependencies the scheduler allows before it flushes the current state and starts over โจ. Big functions with few branches or calls can build up huge lists that waste memory and resources for no reason, so this keeps things tidy ๐งน.max-modulo-backtrack-attemptsโ the max backtrack attempts the scheduler makes when modulo scheduling a loop ๐. Larger values can blow up compilation time exponentially, so be careful bestie โ ๏ธ.max-inline-insns-singleโ several params control the tree inliner, and this one sets the max number of instructions (counted in GCC's internal representation) that a single function can have and still be considered for inlining ๐. It only affects functions declared inline and methods implemented in a class declaration (C++) ๐.max-inline-insns-autoโ iykyk: when you use-finline-functions(included in-O3), a whole bunch of functions that would normally never be considered for inlining get investigated ๐. Those functions get a different, more restrictive limit than functions declared inline ๐ฆ.max-inline-insns-smallโ the bound applied to calls that count as relevant with-finline-small-functions๐ท.max-inline-insns-sizeโ the bound applied to calls that are optimized for size ๐. A small amount of growth can be worth it to set up optimization opportunities that inlining opens up ๐.uninlined-function-insnsโ the number of instructions the inliner counts as function overhead, like the function prologue and epilogue ๐ง.uninlined-function-timeโ the extra time the inliner counts as function overhead, like the time it takes to run the function prologue and epilogue โฑ๏ธ.uninlined-thunk-insns,uninlined-thunk-timeโ same deal as--param uninlined-function-insnsand--param uninlined-function-time, but these apply to function thunks ๐ซถ.inline-min-speedupโ if the estimated performance improvement of caller plus callee runtime goes over this threshold (in percent), the function can be inlined no matter what the--param max-inline-insns-singleand--param max-inline-insns-autolimits say ๐.large-function-insnsโ the limit that defines really large functions ๐. For functions bigger than this after inlining, inlining gets constrained by--param large-function-growth๐ซง. This one is mostly there to avoid extreme compile times caused by non-linear back end algorithms ๐ตโ๐ซ.large-function-growthโ the max growth of a large function caused by inlining, in percent ๐. For example, a value of 100 limits large function growth to 2.0 times the original size ๐.large-unit-insnsโ the limit that defines a large translation unit ๐๏ธ. Growth from inlining into units bigger than this gets limited by--param inline-unit-growth, but for small units that might be too tight ๐ฅน. Say a unit has function A (inline) and function B, which just calls A three times ๐ค. If B is small compared to A, the unit growth 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 stop an exponential explosion of code size ๐ฅ. So for smaller units, the size gets bumped up to--param large-unit-insnsbefore--param inline-unit-growthgets applied ๐.inline-unit-growthโ the max overall growth of the compilation unit caused by inlining ๐ฆ. For example, a value of 20 limits unit growth to 1.2 times the original size ๐งฎ. Cold functions (marked cold with an attribute or by profile feedback) don't count toward the unit size ๐ง.ipcp-unit-growthโ the max overall growth of the compilation unit caused by interprocedural constant propagation ๐ข. For example, a value of 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 max growth of large stack frames caused by inlining, in percent ๐. For example, a value of 1000 limits large stack frame growth to 11 times the original size ๐ซ .max-inline-insns-recursive,max-inline-insns-recursive-autoโ the max number of instructions an out-of-line copy of a self-recursive inline function can grow into through recursive inlining ๐.--param max-inline-insns-recursiveapplies to functions declared inline ๐. For functions that aren't declared inline, recursive inlining only happens when-finline-functions(included in-O3) is enabled, and then--param max-inline-insns-recursive-autoapplies instead ๐ .max-inline-recursive-depth,max-inline-recursive-depth-autoโ the max recursion depth used for recursive inlining ๐ช.--param max-inline-recursive-depthapplies to functions declared inline ๐ธ. For functions that aren't declared inline, recursive inlining only happens when-finline-functions(included in-O3) is enabled, and then--param max-inline-recursive-depth-autoapplies instead ๐ซถ.min-inline-recursive-probabilityโ recursive inlining only pays off for functions with deep recursion on average ๐ณ. For functions with little recursion depth, it can hurt by increasing the prologue size, or the complexity of the function body for other optimizers ๐ฌ. When profile feedback is available (see-fprofile-generate), the actual recursion depth can be guessed from the probability that a function recurses via a given call expression ๐ฎ. This parameter limits inlining to only those call expressions whose probability goes over the threshold (in percent) ๐ฏ.early-inlining-insnsโ specifies how much growth the early inliner is allowed to make ๐ฑ. In effect, it bumps up the amount of inlining for code with a large abstraction penalty ๐๏ธโโ๏ธ.max-early-inliner-iterationsโ the limit on early inliner iterations ๐. This basically bounds how many nested indirect calls the early inliner can resolve ๐. Deeper chains still get handled by late inlining ๐ฐ๏ธ.comdat-sharing-probabilityโ the probability (in percent) that C++ inline functions with comdat visibility get shared across multiple compilation units ๐ค.profile-func-internal-idโ controls whether the function's internal id gets used in profile database lookups ๐๏ธ. If the value is 0, the compiler uses an id based on the function's assembler name and filename ๐ท๏ธ, which makes old profile data more forgiving of source changes, like function reordering ๐ฅฐ.min-vect-loop-boundโ the min number of iterations below which loops don't get vectorized when-ftree-vectorizeis used ๐ถ. The number of iterations after vectorization has to be greater than the value set here for vectorization to happen โจ.gcse-cost-distance-ratioโ okay so this one is the scaling factor for how far an expression can be moved by GCSE optimizations ๐ฆ Right now it only works in the code hoisting pass, and the bigger the ratio, the more aggressive the hoisting gets with simple expressions (the ones costing less thangcse-unrestricted-cost) ๐ฅ Setting it to0turns off hoisting of simple expressions completely ๐gcse-unrestricted-costโ this is the cost, roughly the price of one typical machine instruction โจ Once an expression hits this cost, GCSE stops putting a leash on how far it can travel. It's also only a thing in the code hoisting pass. The lower the cost, the more aggressive the hoisting, and0lets every expression wander as far as it wants ๐max-hoist-depthโ how deep the search goes up the dominator tree when looking for expressions to hoist ๐ธ It's there to keep the hoisting algorithm from going quadratic on us. A value of0means no limit on the search, but fair warning, it can slow down compilation of huge functions ๐ขmax-tail-merge-comparisonsโ the most similar bbs you're allowed to compare a bb against ๐ This keeps tree tail merging from going quadratic, so no spiraling.max-tail-merge-iterationsโ caps how many passes over the function the tree tail merging gets to make ๐ง It's basically a leash on compile time.store-merging-allow-unalignedโ lets the store merging pass introduce unaligned stores, but only if that's legal to do ๐ซถ Permission granted, with a big asterisk.max-stores-to-mergeโ the max number of stores the store merging pass will try to squish into wider stores ๐max-unrolled-insnsโ the most instructions a loop can have and still get unrolled โจ If it does get unrolled, this same number also decides how many times the loop body gets copied ๐max-average-unrolled-insnsโ same vibe as above, but it counts instructions biased by how likely they are to run ๐ Loops that qualify get unrolled, and this value sets how many times too.max-unroll-timesโ the max number of unrollings for a single loop ๐max-peeled-insnsโ the most instructions a loop can have and still get peeled ๐ฆ If it gets peeled, this parameter also decides how many times the loop code gets peeled.max-peel-timesโ the max number of peelings for a single loop ๐ธmax-peel-branchesโ the max number of branches allowed on the hot path through the peeled sequence ๐ฅmax-completely-peeled-insnsโ the max number of insns a completely peeled loop can have ๐max-completely-peel-timesโ the max number of iterations a loop can have and still be suitable for complete peeling ๐งmax-completely-peel-loop-nest-depthโ the deepest a loop nest can be and still be suitable for complete peeling ๐max-unswitch-insnsโ the max number of insns an unswitched loop can have ๐max-unswitch-levelโ the max number of branches that can get unswitched in a single loop ๐ซถlim-expensiveโ the minimum cost for something to count as an expensive expression in loop invariant motion ๐ Anything cheaper than this isn't considered expensive, bestie.iv-consider-all-candidates-boundโ this is the bound on how many candidates for induction variables there can be before the optimizer stops considering all of them for each use โจ Go over it, and only the most relevant candidates get looked at, so the time complexity doesn't go quadratic on us ๐iv-max-considered-usesโ the induction variable optimizations just give up on any loop with more induction variable uses than this ๐ญiv-always-prune-cand-set-boundโ if the candidate set is smaller than this value, the optimizer will always try to remove unnecessary ivs from the set whenever it adds a new one ๐ฆavg-loop-niterโ the average number of iterations a loop is expected to run ๐ธdse-max-object-sizeโ the max size, in bytes, of objects that dead store elimination tracks bytewise ๐ฅ Bigger values can mean longer compilation times, so keep that in mind, periodt.dse-max-alias-queries-per-storeโ the max number of queries into the alias oracle per store ๐ Crank this up and compilation takes longer, but you might get rid of more dead stores too.scev-max-expr-sizeโ the bound on how big the expressions in the scalar evolutions analyzer can get ๐ง Huge expressions make the analyzer slow, so this keeps things snappy.scev-max-expr-complexityโ the bound on how complex those scalar evolutions expressions can be ๐ Complicated expressions slow the analyzer down too, so same energy.max-tree-if-conversion-phi-argsโ the max number of arguments a PHI can have and still be supported by TREE if conversion ๐ The exception is a loop marked with the simd pragma, which gets to ignore this limit ๐ซถvect-max-version-for-alignment-checksโ when the vectorizer does loop versioning for alignment, this is the max number of run-time checks it can perform ๐vect-max-version-for-alias-checksโ same deal, but for alias checks during loop versioning in the vectorizer ๐vect-max-peeling-for-alignmentโ the max number of loop peels the vectorizer can do to get access alignment sorted ๐ Set it to-1and there's no limit at all ๐max-iterations-to-trackโ the max number of loop iterations that the brute-force algorithm will try to evaluate when it's figuring out how many iterations a loop runs ๐ฆhot-bb-count-ws-permilleโ a basic block profile count counts as hot if it contributes to the given permillage (so, 0...1000) of the entire profiled execution ๐ฅhot-bb-frequency-fractionโ picks the fraction of the entry block frequency that a basic block in a function needs to hit before it's considered hot ๐ธmax-predicted-iterationsโ the max number of loop iterations GCC will predict statically ๐ This matters when a function has one loop with a known bound and another with an unknown bound. The known count gets predicted correctly, but the unknown one averages out to roughly 10, which makes the unbounded loop look artificially cold compared to the other one ๐ฅถbuiltin-expect-probabilityโ controls the probability that an expression has the specified value ๐ง It takes a percentage, so 0 ... 100 as input โจbuiltin-string-cmp-inline-lengthโ the max length of a constant string for a builtin string cmp call to be eligible for inlining ๐align-thresholdโ picks the fraction of the maximal execution frequency of a basic block in a function that's needed before the basic block gets aligned ๐align-loop-iterationsโ any loop that's expected to iterate at least this many times gets aligned ๐ซถtracer-dynamic-coverageandtracer-dynamic-coverage-feedbackโ these limit superblock formation once the given percentage of executed instructions is covered ๐ That keeps the code from ballooning for no reason.
The tracer-dynamic-coverage-feedback parameter only gets used when profile feedback is available ๐ Real profiles are way less balanced than statically estimated ones, so the threshold can be set to a bigger value ๐
tracer-max-code-growthโ stops tail duplication once code growth reaches the given percentage ๐ Honestly this is a pretty artificial limit, since most of the duplicates get cleaned up later in cross jumping. So it can be set to way higher values than the code growth you actually want ๐ฆtracer-min-branch-ratioโ stops reverse growth when the reverse probability of the best edge drops below this threshold (in percent) ๐ฅtracer-min-branch-probabilityandtracer-min-branch-probability-feedbackโ stops forward growth if the best edge has a probability lower than this threshold ๐ธ
Same story as the dynamic coverage pair: there are two of these. tracer-min-branch-probability-feedback is for compilation with profile feedback, and tracer-min-branch-probability is for compilation without it. The feedback version needs to be more conservative (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 can cut down on the number of explicit probes, but if the value is bigger than the operating system's guard, your code is left open to stack clash style attacks. Not it ๐ โโ๏ธstack-clash-protection-probe-intervalโ stack clash protection means probing stack space as it gets allocated ๐ This one controls the max distance between probes into the stack, as 2 raised to num bytes. Higher values can reduce explicit probes, but a value bigger than the OS-provided guard leaves the code vulnerable to stack clash style attacks ๐max-cse-path-lengthโ the max number of basic blocks on a path that CSE considers ๐max-cse-insnsโ the max number of instructions CSE processes before it flushes ๐ซถggc-min-expandโ GCC uses a garbage collector to manage its own memory allocation โจ This sets the minimum percentage that the garbage collector's heap is allowed to expand between collections ๐ Tuning it might speed up compilation, but it has zero effect on code generation, so no vibe shift there ๐
The default is 30% + 70% * (RAM/1GB) with an upper bound of 100% when RAM >= 1GB ๐ If getrlimit is available, "RAM" means the smallest of actual RAM and RLIMIT_DATA or RLIMIT_AS ๐ If GCC can't work out RAM on a particular platform, the lower bound of 30% gets used ๐ฆ Setting this parameter and ggc-min-heapsize to zero forces a full collection at every opportunity ๐ฅ It's extremely slow, but it can be super useful for debugging ๐ธ
ggc-min-heapsizeโ okay so this is the smallest the garbage collector's heap can get before it even starts bothering to clean up ๐งน The first collection happens once the heap grows byggc-min-expand%pastggc-min-heapsize. Tuning this might speed up compilation โจ, but it has zero effect on code generation ๐- The default is the smaller of
RAM/8,RLIMIT_RSS, or a limit that tries to make sureRLIMIT_DATAorRLIMIT_ASdon't get exceeded ๐ซถ But it's clamped to a floor of4096(four megabytes) and a ceiling of131072(128 megabytes). - If GCC can't figure out RAM on a particular platform, the lower bound gets used ๐คทโโ๏ธ
- Setting this super large basically turns garbage collection off ๐
- Setting this and
ggc-min-expandto zero makes a full collection happen at every single opportunity ๐ญ
- The default is the smaller of
max-reload-search-insnsโ the max number of instructions reload will look backward through to find an equivalent register ๐ Bigger numbers mean more aggressive optimization, and compile time goes up for probably a slightly better performance glow-up ๐ธmax-cselib-memory-locationsโ how many memory locations cselib is allowed to take into account ๐ง Higher values mean more aggressive optimization, longer compile times, and probably slightly better performance โจmax-sched-ready-insnsโ the max number of instructions that are ready to be issued that the scheduler will consider at any given moment during the first scheduling pass ๐ Higher values mean more thorough searches, so compile time climbs with probably not a ton of benefit ๐max-sched-region-blocksโ the max number of blocks in a region that can be considered for interblock scheduling ๐งฑmax-pipeline-region-blocksโ the max number of blocks in a region that can be considered for pipelining in the selective scheduler ๐max-sched-region-insnsโ the max number of insns in a region that can be considered for interblock scheduling ๐ฆmax-pipeline-region-insnsโ the max number of insns in a region that can be considered for pipelining in the selective scheduler ๐min-spec-probโ the minimum probability (in percents) of reaching a source block for interblock speculative scheduling ๐ฏmax-sched-extend-regions-itersโ the max number of trips through the CFG when extending regions ๐ Setting this to0turns region extensions off ๐ซmax-sched-insn-conflict-delayโ the max conflict delay an insn can have and still be considered for speculative motion โณsched-spec-prob-cutoffโ the minimal probability of speculation success (in percents) needed before speculative insns actually get scheduled ๐ฎsched-state-edge-prob-cutoffโ the minimum probability an edge needs to have before the scheduler bothers saving its state across it ๐พsched-mem-true-dep-costโ the minimal distance (in CPU cycles) between a store and a load that are targeting the same memory locations ๐งselsched-max-lookaheadโ the max size of the lookahead window for selective scheduling ๐ It's basically how deep the search goes for available instructions ๐ต๏ธโโ๏ธselsched-max-sched-timesโ the max number of times an instruction can be scheduled during selective scheduling ๐ This caps how many iterations the instruction is allowed to be pipelined through ๐ฆselsched-insns-to-renameโ the max number of best instructions in the ready list that get considered for renaming in the selective scheduler โ๏ธsms-min-scโ the minimum stage count value that the swing modulo scheduler generates ๐ขmax-last-value-rtlโ the max size, measured in RTLs, that can be recorded in a combiner expression for a pseudo register as its last known value ๐max-combine-insnsโ the max number of instructions the RTL combiner will try to combine together ๐งฉinteger-share-limitโ small integer constants can use a shared data structure, which saves the compiler some memory and makes it faster ๐ This sets the max value that a shared integer constant can have ๐ขssp-buffer-sizeโ the minimum size of buffers (aka arrays) that get stack smashing protection when-fstack-protectionis used ๐ก๏ธ- Before Ubuntu 10.10, this default was
"8". Right now it's"4", so more functions get covered by the stack protector ๐
- Before Ubuntu 10.10, this default was
min-size-for-stack-sharingโ the minimum size of variables that take part in stack slot sharing when you're not optimizing ๐งบmax-jump-thread-duplication-stmtsโ the max number of statements a block can have when it needs to be duplicated for jump threading ๐งตmax-fields-for-field-sensitiveโ the max number of fields in a structure that gets treated in a field sensitive manner during pointer analysis ๐งฌprefetch-latencyโ an estimate of the average number of instructions that run before a prefetch finishes โฑ๏ธ The distance prefetched ahead is proportional to this number ๐ Raising it might also mean fewer streams get prefetched (seesimultaneous-prefetches) ๐simultaneous-prefetchesโ the max number of prefetches that can run at the same time ๐โโ๏ธ๐จl1-cache-line-sizeโ the size of a cache line in the L1 data cache, in bytes ๐ฆl1-cache-sizeโ the size of the L1 data cache, in kilobytes ๐๏ธl2-cache-sizeโ the size of the L2 data cache, in kilobytes ๐๏ธprefetch-dynamic-stridesโ whether the loop array prefetch pass should issue software prefetch hints for strides that are non-constant ๐ฒ Sometimes that's helpful, but a non-constant stride can make it really hard to tell when there's a clear benefit ๐ค- Set to
1if prefetch hints should be issued for non-constant strides โ - Set to
0if prefetch hints should only be issued for strides that are known to be constant and belowprefetch-minimum-stride๐ซ
- Set to
prefetch-minimum-strideโ the minimum constant stride, in bytes, before prefetch hints start getting used ๐ฃ๏ธ If the stride is less than this threshold, no prefetch hints will be issued ๐ โโ๏ธ- This setting is super useful for processors with hardware prefetchers ๐ In that case the hardware and software prefetchers can clash ๐ฌ If the hardware prefetchers have a max stride they can handle, put that value here so the software prefetchers get used more effectively โจ
- A value of
-1means there's no threshold, so prefetch hints can be issued for any constant stride ๐ - This setting only matters for strides that are known and constant ๐
loop-interchange-max-num-stmtsโ the max number of stmts in a loop that can be interchanged ๐loop-interchange-stride-ratioโ the minimum ratio between the strides of two loops for interchange to be profitable ๐min-insn-to-prefetch-ratioโ the minimum ratio between the number of instructions and the number of prefetches needed to enable prefetching in a loop ๐prefetch-min-insn-to-mem-ratioโ the minimum ratio between the number of instructions and the number of memory references needed to enable prefetching in a loop ๐งฎuse-canonical-typesโ whether the compiler should use the "canonical" type system ๐งโ๐ฌ This should always be1, since it uses a 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 it to0to turn canonical types off ๐ซswitch-conversion-max-branch-ratioโ switch initialization conversion refuses to create arrays that are 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 โ ๏ธ For some source code, the enhanced PRE can run away and eat all the memory on the host machine ๐ฑ This param caps the length of those sets so the runaway doesn't happen ๐- Setting this to
0allows an unlimited set length, so be careful with that one ๐
- Setting this to
rpo-vn-max-loop-depthโ the max loop depth that gets value-numbered optimistically ๐ข Once the limit is hit, the innermostrpo-vn-max-loop-depthloops and the outermost loop in the loop nest get value-numbered optimistically, and the remaining ones don't ๐งsccvn-max-alias-queries-per-accessโ the max number of alias-oracle queries we run when looking for redundancies in loads and stores ๐ If this limit is hit, the search is aborted and the load or store is not considered redundant ๐ โโ๏ธ The number of queries is algorithmically limited to the number of stores on all paths from the load to the function entry ๐ค๏ธira-max-loops-numโ IRA uses regional register allocation by default ๐บ๏ธ If a function has more loops than this number, only at most this many of the most frequently executed loops form regions for regional register allocation ๐ira-max-conflict-table-sizeโ IRA uses a fancy algorithm to compress the conflict table, but for huge functions the table can still eat an excessive amount of memory ๐ฝ๏ธ If the conflict table for a function could be bigger than the size in MB given by this parameter, the register allocator switches to a faster, simpler, and lower-quality algorithm that doesn't build a pseudo-register conflict table at all ๐ซถira-loop-reserved-regs: okay so IRA can get a more accurate read on register pressure inside loops ๐, which helps it decide whether to pull out loop invariants (see-O3) โจ. This parameter sets how many available registers get set aside for other purposes. The default is the best value found after numerous experiments ๐lra-inheritance-ebb-probability-cutoff: LRA likes to reuse values it already reloaded into registers for later insns, and that's called inheritance ๐ฆ. EBB is the region used for this. This parameter is the minimal fall-through edge probability, in percent, needed to add a BB to the inheritance EBB in LRA ๐ธ. The default was chosen from loads of SPEC2000 runs onx86-64๐loop-invariant-max-bbs-in-loop: loop invariant motion can get super expensive in both compilation time and compile-time memory when loops are huge ๐. Any loop with more basic blocks than this value just won't get loop invariant motion ๐ซloop-max-datarefs-for-datadeps: building data dependencies is costly for massive loops ๐. This caps how many data references in a loop get considered for data dependence analysis. Loops that are too big aren't handled by the optimizations that use loop data dependencies ๐max-vartrack-size: this caps the number of hash table slots used during variable tracking dataflow analysis of any function ๐งฉ. If the limit is exceeded with variable tracking at assignments enabled, analysis for that function gets retried without it, after all debug insns are removed from the function. If it's still over the limit without debug insns, var tracking analysis is completely disabled for that function ๐ญ. Setting it to0makes it unlimited ๐max-vartrack-expr-depth: this is the max number of recursion levels when mapping variable names or debug temporaries to value expressions. It's a trade-off: more compile time for more complete debug information โณ. If it's set too low, value expressions that could be represented in debug info might never get used ๐ฅฒ. Set it higher and the compiler can find fancier debug expressions, but compile time and memory use may grow ๐max-debug-marker-count: this sets a threshold on debug markers (like begin stmt markers) so complexity doesn't explode at inlining or RTL expansion ๐. If a function has more of these gimple stmts than the limit, they get dropped from the inlined copy of the function and from its RTL expansion โ๏ธmin-nondebug-insn-uid: this is the uid where nondebug insns start counting ๐ข. The range below it is reserved exclusively for debug insns created by-fvar-tracking-assignments. Debug insns can still get (non-overlapping) uids above it if that reserved range runs out ๐งipa-sra-ptr-growth-factor: IPA-SRA only swaps a pointer to an aggregate for one or more new parameters when their cumulative size is less than or equal toipa-sra-ptr-growth-factortimes the size of the original pointer parameter ๐sra-max-scalarization-size-Ospeedandsra-max-scalarization-size-Osize: the two Scalar Reduction of Aggregates passes (SRA and IPA-SRA) want to swap scalar parts of aggregates for independent scalar variables ๐ช. These control the max size, in storage units, of an aggregate that's considered for replacement when compiling for speed (sra-max-scalarization-size-Ospeed) or size (sra-max-scalarization-size-Osize) respectively ๐sra-max-propagations: this is the max number of artificial accesses that SRA will track per local variable, so copy propagation has something to work with ๐tm-max-aggregate-size: when copying thread-local variables in a transaction, this is the size in bytes after which variables get saved with the logging functions instead of save/restore code sequence pairs ๐. This 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 that SCoP ๐loop-block-tile-size: loop blocking or strip mining (enabled with-floop-blockor-floop-strip-mine) strip mines each loop in the nest by a given number of iterations ๐งฑ. The strip length can be changed with 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 cloning profitability and goes ahead with cloning opportunities whose scores exceedipa-cp-eval-threshold๐ipa-cp-recursion-penalty: this is the percentage penalty that recursive functions get when they're evaluated for cloning ๐ipa-cp-single-call-penalty: this is the percentage penalty that functions containing a single call to another function get 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 those values per parameteripa-cp-loop-hint-bonus: when IPA-CP figures out that a cloning candidate would make a loop's number of iterations known, it adds a bonus ofipa-cp-loop-hint-bonusto that candidate's profitability score ๐ipa-cp-array-index-hint-bonus: same energy: when IPA-CP determines that a cloning candidate would make an array access's index known, it adds a bonus ofipa-cp-array-index-hint-bonusto the candidate's profitability score ๐ipa-max-aa-steps: while analyzing function bodies, IPA-CP uses alias analysis to track values pointed to by function parameters ๐. So it doesn't spend forever on huge functions, it gives up and considers all memory clobbered after examiningipa-max-aa-stepsstatements that modify memory ๐ณ๏ธlto-partitions: this is the desired number of partitions produced during WHOPR compilation ๐ฐ. The number of partitions should exceed the number of CPUs used for compilation ๐ปlto-min-partition: this is the size of the minimal partition for WHOPR (in estimated instructions) ๐ง. It stops very small programs from being split into too many partitions ๐lto-max-partition: this is the size of the max partition for WHOPR (in estimated instructions) โฌ๏ธ. It gives an upper bound on the size of each individual partition. It's only meant to be used with balanced partitioning โ๏ธlto-max-streaming-parallelism: the max number of parallel processes used for LTO streaming ๐cxx-max-namespaces-for-diagnostic-help: the max number of namespaces to consult for suggestions when C++ name lookup fails for an identifier ๐sink-frequency-threshold: this is the max relative execution frequency (in percents) of the target block compared to a statement's original block, which lets that statement get sunk ๐. Bigger numbers mean more aggressive statement sinking. A small positive adjustment is applied to statements with memory operands, since those are even more profitable to sink ๐max-stores-to-sink: this is the max number of conditional store pairs that can be sunk ๐ณ๏ธ. Set it to0if either vectorization (-ftree-vectorize) or if-conversion (-ftree-loop-if-convert) is disabledallow-store-data-races: this lets optimizers introduce new data races on stores โ ๏ธ. Set it to1to allow that, otherwise set it to0.
โ ๏ธ bestie, data races are NOT a vibe. Only flip this on if you know exactly what you're doing ๐
case-values-threshold: this is the smallest number of different values for which a jump-table is better than a tree of conditional branches ๐ณ. If the value is0, the default for the machine is used ๐ฅ๏ธtree-reassoc-width: this sets the max number of instructions executed in parallel in a reassociated tree ๐งต. A non-zero value overrides the target-dependent heuristics used by default ๐ฏsched-pressure-algorithm: this lets you choose between the two implementations of-fsched-pressure๐ง . Algorithm 1 is the original implementation and is the more likely one to prevent instructions from being reordered ๐. Algorithm 2 was designed as a compromise between the relatively conservative approach of algorithm 1 and the rather aggressive approach of the default scheduler โ๏ธ. It relies 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: this sets the max number of existing candidates considered when seeking a basis for a new straight-line strength reduction candidate ๐ญasan-globals: this enables buffer overflow detection for global objects ๐ก๏ธ. This protection is enabled by default when you use the-fsanitize=addressoption. To disable global objects protection, use--param asan-globals=0๐asan-stack: this enables buffer overflow detection for stack objects ๐ฅ. This protection is enabled by default when using-fsanitize=address. To disable stack protection, use--param asan-stack=0option ๐asan-instrument-readsโ Turns on buffer overflow detection for memory reads ๐ก๏ธ It's already on by default with-fsanitize=address, but if you want it off, use--param asan-instrument-reads=0. ๐asan-instrument-writesโ Same energy, but for memory writes โ๏ธ Also on by default with-fsanitize=address. To turn it off, use--param asan-instrument-writes=0option.asan-memintrinโ Enables detection for built-in functions ๐ง On by default with-fsanitize=address. To disable this protection, use--param asan-memintrin=0.asan-use-after-returnโ Enables detection of use-after-return ๐ This is on by default when you use the-fsanitize=addressoption. To turn it off, use--param asan-use-after-return=0.- Note: this check is disabled at run time by default โ ๏ธ To enable it, add
"detect_stack_use_after_return=1"to the environment variableASAN_OPTIONS.
- Note: this check is disabled at run time by default โ ๏ธ To enable it, add
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 skip inline code entirely, use--param asan-instrumentation-with-call-threshold=0.use-after-scope-direct-emission-thresholdโ If a local variable is smaller than or equal to this many bytes, the shadow memory gets poisoned (or unpoisoned) directly ๐ช instead of relying on run-time callbacks.max-fsm-thread-path-insnsโ The maximum number of instructions copied when duplicating blocks on a finite state automaton jump thread path ๐งตmax-fsm-thread-lengthโ The maximum number of basic blocks allowed on a finite state automaton jump thread path ๐max-fsm-thread-pathsโ The maximum number of new jump thread paths GCC will create for a finite state automaton ๐ค๏ธparloops-chunk-sizeโ The chunk size of the omp schedule for loops that get parallelized by parloops ๐งฉparloops-scheduleโ The schedule type of the omp schedule for loops parallelized by parloops, which can bestatic,dynamic,guided,auto, orruntime๐๏ธparloops-min-per-threadโ The minimum number of iterations per thread in an innermost parallelized loop where the parallel version is preferred over the single-threaded one ๐งต Fair warning: 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 a use-def chain.hsa-gen-debug-storesโ Enables emission of special debug stores inside HSA kernels, which the libgomp plugin then reads and reports ๐ These stores are not generated by default, so use--param hsa-gen-debug-stores=1to turn them on.max-speculative-devirt-maydefsโ The maximum number of may-defs GCC analyzes while hunting for a must-def that specifies the dynamic type of an object invoking a virtual call. If it finds one, it may be able to devirtualize speculatively ๐ฎmax-vrp-switch-assertionsโ The maximum number of assertions added along the default edge of a switch statement during VRP ๐unroll-jam-min-percentโ The minimum percentage of memory references that must get optimized away for the unroll-and-jam transformation to be considered worth it ๐ธunroll-jam-max-unrollโ The maximum number of times the outer loop can be unrolled by the unroll-and-jam transformation ๐max-rtl-if-conversion-unpredictable-costโ The maximum cost allowed for the sequence the RTL if-conversion pass would generate for a branch that's considered unpredictable ๐ฒmax-variable-expansions-in-unrollerโ If-fvariable-expansion-in-unrolleris used, this is the maximum number of times a single variable gets expanded during loop unrolling ๐tracer-min-branch-probability-feedbackโ Stops forward growth if the probability of the best edge drops below this threshold (in percent). It's used when profile feedback is available ๐partial-inlining-entry-probabilityโ The maximum probability of the entry BB of a split region (in percent, relative to the entry BB of the function) that still lets partial inlining happen ๐งฉmax-tracked-strlensโ The maximum number of strings the strlen optimization pass will track 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 edge execution counts that permits redundancy elimination after reload ๐งฎmax-loop-header-insnsโ The maximum number of insns in a loop header that gets duplicated by the copy loop headers pass ๐ชvect-epilogues-nomaskโ Enables loop epilogue vectorization using a smaller vector size ๐ธslp-max-insns-in-bbโ The maximum number of instructions in a basic block that can be considered for SLP vectorization ๐งบavoid-fma-max-bitsโ The maximum number of bits for which GCC avoids creating FMAs โ๏ธsms-loop-average-count-thresholdโ A threshold on the average loop count the swing modulo scheduler considers ๐sms-dfa-historyโ The number of cycles the swing modulo scheduler looks at when checking for conflicts using DFA ๐ฐ๏ธhot-bb-count-fractionโ The fraction of the maximal repetition count of a basic block in the program that a block needs to reach to be considered hot (used in non-LTO mode) ๐ฅmax-inline-insns-recursive-autoโ The maximum number of instructions a non-inline function can grow to via recursive inlining ๐ฑgraphite-allow-codegen-errorsโ Whether codegen errors should be ICEs when-fcheckingis on ๐sms-max-ii-factorโ A factor for tuning the upper bound the swing modulo scheduler uses when scheduling a loop ๐๏ธlra-max-considered-reload-pseudosโ The max number of reload pseudos considered while spilling a non-reload pseudo ๐ฅmax-pow-sqrt-depthโ The maximum depth of sqrt chains used when synthesizing exponentiation by a real constant ๐งฎmax-dse-active-local-storesโ The maximum number of active local stores in RTL dead store elimination ๐๏ธasan-instrument-allocasโ Enables ASan protection for allocas and VLAs ๐ก๏ธmax-iterations-computation-costโ The bound on the cost of an expression used to compute the number of iterations ๐ญmax-isl-operationsโ The maximum number of isl operations.0means unlimited โพ๏ธgraphite-max-arrays-per-scopโ The maximum number of arrays per scop ๐ฆmax-vartrack-reverse-op-sizeโ The max size of a loc list for which reverse ops should be added ๐งญunlikely-bb-count-fractionโ The minimum fraction of profile runs a basic block's execution count must reach so it isn't considered unlikely ๐ โโ๏ธtracer-dynamic-coverage-feedbackโ The percentage of a function, weighted by execution frequency, that trace formation must cover. It's used when profile feedback is available ๐ฏmax-inline-recursive-depth-autoโ The maximum depth of recursive inlining for non-inline functions ๐ชfsm-scale-path-stmtsโ A scale factor applied to the number of statements in a threading path when comparing it to the number of (scaled) blocks ๐fsm-maximum-phi-argumentsโ The maximum number of arguments a PHI can have before the FSM threader stops trying to thread through its block ๐ซuninit-control-dep-attemptsโ The maximum number of nested calls used to search for control dependencies during uninitialized variable analysis ๐indir-call-topn-profileโ Tracks the top N target addresses in the indirect-call profile ๐ฏmax-once-peeled-insnsโ The maximum number of insns in a peeled loop that only rolls once ๐sra-max-scalarization-size-Osizeโ The maximum size, in storage units, of an aggregate that should be considered for scalarization when compiling for size ๐fsm-scale-path-blocksโ A scale factor applied to the number of blocks in a threading path when comparing it to the number of (scaled) statements ๐งฎsched-autopref-queue-depthโ A hardware autoprefetcher scheduler model control flag. It sets the number of lookahead cycles the model looks into. At' ', only the instruction sorting heuristic is enabled ๐งloop-versioning-max-inner-insnsโ The maximum number of instructions an inner loop can have before the loop versioning pass considers it too big to copy ๐ชloop-versioning-max-outer-insnsโ The maximum number of instructions an outer loop can have before the loop versioning pass considers it too big to copy. Instructions in inner loops that directly benefit from versioning don't count toward this total ๐ชssa-name-def-chain-limitโ The maximum number ofSSA_NAMEassignments to follow when figuring out a property of a variable, like its value. This caps how many iterations or recursive calls GCC makes when optimizing certain statements or checking whether they're valid before issuing diagnostics ๐
โจ Program Instrumentation Options โจ
GCC supports a bunch of command-line options that tell it to add run-time instrumentation to the code it normally generates ๐ Instrumentation can be used for profiling stats to find program hot spots, code coverage analysis, or profile-guided optimizations ๐ Another kind is run-time checking, which catches programming errors 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 that can be used to implement other forms of tracing or function-level instrumentation for debug or program analysis purposes ๐ฆ
-p,-pgโ okay bestie, these make your code spit out extra profiling info โจ-pis for theprofanalysis program and-pgis forgprof๐ฅ. You HAVE to use this when compiling the source files you want data about, and you have to use it when linking too, no skipping ๐
You can also use the function attribute no_instrument_function to stop profiling individual functions when compiling with these options ๐
-fprofile-arcsโ this one instruments the program flow arcs ๐ฆ While the program runs, it keeps count of 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 used as the type of a global variable properly ๐
When your compiled program exits, it saves this data to a file called auxname.gcda for each source file ๐ That data can be used for profile-directed optimizations (-fbranch-probabilities) or for test coverage analysis (-ftest-coverage) ๐ Each object file's auxname comes from the name of the output file, but only if you explicitly specified one and it's not the final executable. Otherwise it's the basename of the source file. Either way, any suffix gets removed. So you get foo.gcda for input file dir/foo.c, or dir/foo.gcda for output file specified as -o dir/foo.o ๐ง
--coverageโ this one's the all-in-one for coverage-instrumented code, for both compiling and linking ๐ It's a synonym for-fprofile-arcs -ftest-coverage(when compiling) and-lgcov(when linking). Check the docs for those options for more deets ๐ซถ The whole workflow goes like this:- Compile the source files with
-fprofile-arcsplus optimization and code generation options. For test coverage analysis, add the-ftest-coverageoption too. You don't need to profile every source file in a program ๐ - Compile the source files additionally with
-fprofile-abs-pathto create absolute path names in the.gcnofiles. This lets gcov find the correct sources in projects where compilations happen with different working directories ๐บ๏ธ - Link your object files with
-lgcovor-fprofile-arcs(the latter implies the former) ๐ - Run the program on a representative workload to generate the arc profile information. You can do this any number of times ๐ You can run concurrent instances of your program, and as long as the file system supports locking, the data files will be correctly updated ๐ Unless a strict ISO C dialect option is in effect,
forkcalls are detected and correctly handled without double counting ๐ด - For profile-directed optimizations, compile the source files again with the same optimization and code generation options plus
-fbranch-probabilitiesโจ - For test coverage analysis, use
gcovto produce human-readable info from the.gcnoand.gcdafiles. Refer to the gcov docs for further info ๐ค
- Compile the source files with
With -fprofile-arcs, for each function of your program GCC creates a program flow graph, then finds a spanning tree for that graph ๐ณ Only arcs that are not on the spanning tree have to be instrumented: the compiler adds code to count how many times those arcs are executed. When an arc is the only exit or only entrance to a block, the instrumentation code can go right into that block. Otherwise, a new basic block has to be created to hold it ๐ง
-ftest-coverageโ produces a notes file that the gcov code-coverage utility can use to show program coverage ๐ Each source file's note file is calledauxname.gcno. Check out the-fprofile-arcsoption up above for whatauxnamemeans and how to generate test coverage data ๐ฆ Coverage data matches your source files more closely if you don't optimize ๐-fprofile-abs-pathโ automatically converts relative source file names to absolute path names in the.gcnofiles ๐บ๏ธ This lets gcov find the correct sources in projects where compilations happen with different working directories ๐-fprofile-dir=pathโ sets the directory where profile data files get searched for, topath๐ This only affects profile data generated by-fprofile-generate,-ftest-coverage, and-fprofile-arcs, and the data 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 lives in the same directory as the object file. To prevent file name clashes, if the object file name isn't an absolute path, GCC mangles the absolute path of thesourcename.gcdafile and uses that as the.gcdafile name ๐
When an executable runs in a massive parallel environment, it's recommended to save profiles to different folders. You can do that with variables in path that get exported at run-time ๐ง
%pโ process ID%q{VAR}โ value of environment variableVAR
-fprofile-generateand-fprofile-generate=pathโ these turn on the options usually used for instrumenting an app, so you get a profile you can use later for recompiling with profile feedbackโbased optimization ๐ฅ You must use-fprofile-generateboth when compiling AND when linking your program ๐ซต
The following options get enabled: -fprofile-arcs, -fprofile-values, -finline-functions, and -fipa-bit-cp ๐
If path is specified, GCC looks there to find the profile feedback data files. See -fprofile-dir ๐
To optimize the program based on the collected profile info, use -fprofile-use ๐
-fprofile-update=methodโ alters the update method for an app instrumented for profile feedbackโbased optimization ๐งต Themethodargument should be one ofsingle,atomicorprefer-atomic. The first one is useful for single-threaded apps, while the second one prevents profile corruption by emitting thread-safe code ๐ก๏ธ
Warning: When an application doesn't properly join all of its threads (or creates a detached thread), a profile file can still get corrupted. ๐
Using prefer-atomic gets transformed into either atomic (when a target supports it) or single otherwise. The GCC driver automatically selects prefer-atomic when -pthread is present in the command line โจ
-fprofile-filter-files=regexโ instruments only functions from files whose names match any regular expression (separated by a semicolon) ๐
For example, -fprofile-filter-files=main.c;module.*.c will instrument only main.c and all C files starting with module ๐ง
-fprofile-exclude-files=regexโ instruments only functions from files whose names do not match all the regular expressions (separated by a semicolon) ๐ โโ๏ธ
For example, -fprofile-exclude-files=/usr/* will prevent instrumentation of all files located in the /usr/ folder ๐
-fsanitize=addressโ enables AddressSanitizer, a fast memory error detector ๐ต๏ธ Memory access instructions get instrumented to catch out-of-bounds and use-after-free bugs ๐ This option also enables-fsanitize-address-use-after-scope. For more details, seehttps://github.com/google/sanitizers/wiki/AddressSanitizer. The run-time behavior can be influenced with theASAN_OPTIONSenvironment variable. When set to"help=1", the available options get shown at startup of the instrumented program. For a list of supported options, seehttps://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, seehttps://github.com/google/kasan/wiki.-fsanitize=pointer-compareโ instruments comparison operations (<,<=,>,>=) with pointer operands ๐ This option must be combined with either-fsanitize=kernel-addressor-fsanitize=address. It cannot be combined with-fsanitize=thread.
Note: By default the check is disabled at run time. To enable it, add "detect_invalid_pointer_pairs=2" to the ASAN_OPTIONS environment variable. Using "detect_invalid_pointer_pairs=1" detects invalid operations only when both pointers are non-null ๐ซฃ
-fsanitize=pointer-subtractโ instruments subtraction with pointer operands ๐งฎ This option must be combined with either-fsanitize=kernel-addressor-fsanitize=address. It cannot be combined with-fsanitize=thread.
Note: By default the check is disabled at run time. To enable it, add "detect_invalid_pointer_pairs=2" to the ASAN_OPTIONS environment variable. Using "detect_invalid_pointer_pairs=1" detects invalid operations only when both pointers are non-null ๐ซฃ
-fsanitize=threadโ enables ThreadSanitizer, a fast data race detector ๐งต Memory access instructions get instrumented to catch data race bugs. For more details, seehttps://github.com/google/sanitizers/wiki#threadsanitizer. The run-time behavior can be influenced with theTSAN_OPTIONSenvironment variable. For a list of supported options, seehttps://github.com/google/sanitizers/wiki/ThreadSanitizerFlags. This option cannot be combined with-fsanitize=addressor-fsanitize=leak๐ซ
Note that sanitized atomic builtins cannot throw exceptions when operating on invalid memory addresses with non-call exceptions (-fnon-call-exceptions) โ ๏ธ
-fsanitize=leakโ enables LeakSanitizer, a memory leak detector ๐ง This option only matters for linking executables, and only when the executable is linked against a library that overridesmallocand other allocator functions. For more details, seehttps://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, seehttps://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html. The run-time behavior can be influenced with theUBSAN_OPTIONSenvironment variable. Current suboptions are:-fsanitize=shiftโ okay bestie, this one checks that the result of a shift isn't undefined ๐ธ What counts as undefined is a little different in C vs C++, and between ISO C90 and C99, etc. ๐ It has two suboptions:-fsanitize=shift-baseand-fsanitize=shift-exponent.-fsanitize=shift-exponentโ checks that the second argument of a shift is not negative and is smaller than the precision of the promoted first argument ๐ฆ-fsanitize=shift-baseโ if the second argument is in range, it checks that the shift result isn't undefined โจ Same C vs C++ and C90 vs C99 caveat applies, so no cap, read the room ๐-fsanitize=integer-divide-by-zeroโ catches integer division by zero, plusINT_MIN / -1division ๐-fsanitize=unreachableโ the compiler swaps the__builtin_unreachablecall for a diagnostics message call instead ๐ง
Reaching the __builtin_unreachable call is still undefined behavior. ๐ญ
-fsanitize=vla-boundโ checks that the size of a variable length array is positive ๐-fsanitize=nullโ pointer checking, the main character of pointer safety ๐ An app built with this will throw an error when it:- tries to dereference a NULL pointer,
- binds a reference (possibly an rvalue reference) to a NULL pointer, or
- invokes a method on an object pointed to by a NULL pointer.
-fsanitize=returnโ return statement checking ๐ Programs built with it error out when the end of a non-void function is reached without actually returning a value. This option works in C++ only.-fsanitize=signed-integer-overflowโ checks that the results of+,*, and both unary and binary-don't overflow in signed arithmetic ๐ฅ Integer promotion rules totally count here, so this is not an overflow:
signed char a = SCHAR_MAX;
a++;
-fsanitize=boundsโ instruments array bounds, so various out of bounds accesses get caught ๐ Flexible array members, flexible array member-like arrays, and initializers of variables with static storage are not instrumented, so those are skipped.-fsanitize=bounds-strictโ the stricter version ๐ช Most out of bounds accesses are detected, including flexible array members and flexible array member-like arrays. Initializers of variables with static storage still aren't instrumented.-fsanitize=alignmentโ checks pointer alignment when pointers are dereferenced, when a reference is bound to an insufficiently aligned target, or when a method or constructor is invoked on an insufficiently aligned object ๐งธ-fsanitize=object-sizeโ instruments memory references using the__builtin_object_sizefunction ๐ฆ Various out of bounds pointer accesses get detected.-fsanitize=float-divide-by-zeroโ detects floating-point division by zero ๐ธ Unlike other similar options, this one is not enabled by-fsanitize=undefined, since float division by zero can be a totally legit way to get infinities and NaNs ๐-fsanitize=float-cast-overflowโ checks floating-point to integer conversions and that the result doesn't overflow ๐ฅ Unlike other similar options, this is not enabled by-fsanitize=undefined. It also doesn't work well withFE_INVALIDexceptions enabled. ๐-fsanitize=nonnull-attributeโ instruments calls to check that null values aren't passed to arguments marked as requiring a non-null value by thenonnullfunction attribute ๐ซถ-fsanitize=returns-nonnull-attributeโ instruments return statements in functions marked with thereturns_nonnullfunction attribute, to catch null values being returned from those functions ๐-fsanitize=boolโ instruments loads frombool๐ If a value other than 0/1 gets loaded, a run-time error is issued.-fsanitize=enumโ instruments loads from an enum type โจ If a value outside the range of values for that enum type gets loaded, a run-time error is issued.-fsanitize=vptrโ C++ vibes ๐ง Instruments C++ member function calls, member accesses, and some conversions between pointers to base and derived classes, to verify the referenced object has the correct dynamic type.-fsanitize=pointer-overflowโ instruments pointer arithmetic ๐ If pointer arithmetic overflows, a run-time error is issued.-fsanitize=builtinโ instruments arguments to selected builtin functions ๐ฅ If an invalid value gets passed to one of those arguments, a run-time error is issued. E.g. passing0as the argument to__builtin_ctzor__builtin_clzinvokes undefined behavior, and this option diagnoses it ๐
While -ftrapv causes traps for signed overflows to be emitted, -fsanitize=undefined gives a diagnostic message ๐
This currently works only for the C family of languages ๐ธ
-fno-sanitize=allโ disables all previously enabled sanitizers ๐งน
-fsanitize=all is not allowed, as some sanitizers cannot be used together. ๐ญ
-fasan-shadow-offset=numberโ forces GCC to use a custom shadow offset in AddressSanitizer checks ๐งช It's handy for experimenting with different shadow memory layouts in Kernel AddressSanitizer ๐ฆ-fsanitize-sections=s1,s2,...โ sanitizes global variables in selected user-defined sections ๐simay contain wildcards.-fsanitize-recover[=opts]โ okay this one's a whole saga ๐-fsanitize-recover=controls the error recovery mode for the sanitizers in the comma-separated list ofopts. Turn it on for a sanitizer and it tries to keep the program running as if no error happened. That means multiple runtime errors can get reported in one run, and the exit code can say success even when errors were reported. The-fno-sanitize-recover=option changes this: only the first detected error is reported, and then the program exits with a non-zero exit code ๐
Right now this 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 compiler-side, it also needs to be enabled on the runtime library side, otherwise the failures are still fatal ๐ญ The runtime library defaults to halt_on_error=0 for ThreadSanitizer and UndefinedBehaviorSanitizer, while the default value for AddressSanitizer is halt_on_error=1. You can override this by setting the halt_on_error flag in the corresponding environment variable ๐ซถ
Syntax without an explicit opts parameter is deprecated ๐ It's equivalent to specifying an opts list of:
undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
-fsanitize-address-use-after-scopeโ enables sanitization of local variables to catch 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 doesn't get 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 calls to:__sanitizer_cov_trace_cmp1,__sanitizer_cov_trace_cmp2,__sanitizer_cov_trace_cmp4or__sanitizer_cov_trace_cmp8for integral comparisons where both operands are 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, and__sanitizer_cov_trace_switchfor switch statements.
-fcf-protection=[full|branch|return|none|check]โ enables code instrumentation of control-flow transfers to boost program security ๐ก๏ธ It checks that the target addresses of control-flow transfer instructions (such as indirect function calls, function returns, and indirect jumps) are valid, which stops the flow of control from getting diverted to an unexpected target ๐ This is meant to protect against threats like Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP) ๐
Okay so branch tells the compiler to check that control-flow transfers are valid at indirect branch instructions, aka call/jmp instructions ๐ฆ. return does that same check when a function returns ๐. And full is the bestie combo, an alias for asking for both branch and return ๐. none just turns the instrumentation off ๐.
check is for the final link with link-time optimization (LTO) โจ. If LTO object files were compiled with different -fcf-protection values, you get an error, so double-check your builds ๐. check gets ignored at compile time, so it's not doing anything there ๐
.
The macro __CET__ gets defined whenever you use -fcf-protection ๐. Its first bit is set to 1 for branch, and its second bit is set to 1 for return ๐.
You can also slap the nocf_check attribute on stuff to pick which functions and calls get skipped from instrumentation ๐.
Right now the x86 GNU/Linux target has an implementation based 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 enabled by default for C, C++, ObjC, ObjC++, if none of-fno-cf-protectionnor-fcf-protection=*are found. ๐ซถ
-fstack-protectorโ Emit extra code to check for buffer overflows, like stack smashing attacks ๐ก๏ธ. It adds a guard variable to functions with vulnerable objects, which includes functions that callallocaand functions with buffers larger than 8 bytes. The guards get set up when a function is entered and checked when it exits. If a guard check fails, an error message is printed and the program exits ๐.-fstack-protector-allโ Same energy as-fstack-protector, except now all functions are protected ๐.-fstack-protector-strongโ Like-fstack-protector, but it adds more functions to the protected list: the ones with local array definitions, or ones that have references to local frame addresses ๐.-fstack-protector-explicitโ Like-fstack-protector, but it only protects the functions that have thestack_protectattribute ๐ฏ.-fstack-checkโ Generates code to verify that you don't go beyond the boundary of the stack ๐ง. You should use this if you're running in an environment with multiple threads. In a single-threaded environment you rarely need it, since stack overflow is automatically detected on nearly all systems when there's only one stack ๐.- Heads up: this switch doesn't actually do the checking. The operating system or the language runtime has to do that. The switch just generates code so they can see the stack being extended ๐.
- You can add a string parameter too:
nomeans no checking,genericforces the old-style checking, andspecificuses the best checking method and is equivalent to bare-fstack-checkโจ. - Old-style checking is a generic mechanism. It needs no specific target support in the compiler, but it comes with these drawbacks:
- Modified allocation strategy for large objects: they're always allocated dynamically if their size goes over a fixed threshold. This may change the semantics of some code ๐ฌ.
- Fixed limit on the size of the static frame of functions: when it's topped by a particular function, stack checking isn't reliable and the compiler issues a warning ๐จ.
- Inefficiency: the modified allocation strategy plus the generic implementation means code performance takes a hit ๐.
- Old-style stack checking is also the fallback method for
specificif no target support has been added in the compiler ๐. -fstack-check=was made for Ada's needs, to detect infinite recursion and stack overflows.specificis an excellent choice when compiling Ada code ๐ธ. It's not generally enough to protect against stack-clash attacks, though. For that, you want-fstack-clash-protection๐ก๏ธ.
-fstack-clash-protectionโ Generates code to prevent stack clash style attacks. With this enabled, the compiler only allocates one page of stack space at a time, and each page is accessed right after allocation. That way, allocations can't jump over any stack guard page the operating system provides ๐งฑ.- Most targets don't fully support stack clash protection. On the ones that do,
-fstack-clash-protectionprotects 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 ๐.
- Most targets don't fully support stack clash protection. On the ones that do,
-fstack-limit-register=reg,-fstack-limit-symbol=sym,-fno-stack-limitโ Generates code to make sure the stack doesn't grow beyond a certain value, either the value of a register or the address of a symbol ๐ง. If a bigger stack is needed, a signal gets raised at run time. On most targets the signal goes off before the stack overruns the boundary, so you can catch it without taking special precautions ๐ฆ.- For example, say the stack starts at absolute address
0x80000000and grows downwards. You can use the flags-fstack-limit-symbol=__stack_limitand-Wl,--defsym,__stack_limit=0x7ffe0000to enforce a stack limit of 128KB ๐. Just know this may only work with the GNU linker โ ๏ธ. - You can locally override stack limit checking with the
no_stack_limitfunction attribute ๐ โโ๏ธ.
- For example, say the stack starts at absolute address
-fsplit-stackโ Generates code that automatically splits 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, because you no longer have to calculate a good stack size for each thread ๐งต. It's currently only implemented for x86 targets running GNU/Linux ๐ฅ๏ธ.- When code compiled with
-fsplit-stackcalls code compiled without-fsplit-stack, there may not be much stack space left for the latter code to run in ๐ฐ. If compiling all code, library code included, with-fsplit-stackisn't an option, the linker can fix up these calls so that code compiled without-fsplit-stackalways gets a large stack. This is implemented in the gold linker in GNU binutils release 2.21 and later ๐ง.
- When code compiled with
-fvtable-verify=[std|preinit|none]โ This one is C++ only ๐. It turns on (or off, if you use-fvtable-verify=none) the security feature that checks at run time, for every virtual call, that the vtable pointer used for the call is valid for the type of the object and hasn't been corrupted or overwritten ๐. If an invalid vtable pointer gets detected at run time, an error is reported and execution of the program halts right away ๐.- This option builds run-time data structures at program startup, and those are used to verify the vtable pointers โฐ. The
stdandpreinitvalues control when those data structures get built. In both cases, they're built before execution reachesmain๐.-fvtable-verify=stdbuilds them after shared libraries have been loaded and initialized.-fvtable-verify=preinitbuilds them before shared libraries have been loaded and initialized ๐. - If this option shows up more than once on the command line with different values,
nonetakes the highest priority over bothstdandpreinit, andpreinittakes priority overstd๐.
- This option builds run-time data structures at program startup, and those are used to verify the vtable pointers โฐ. The
-fvtv-debugโ Used together with-fvtable-verify=stdor-fvtable-verify=preinit, this makes the debug versions of the runtime functions for vtable verification get called ๐. It also makes the compiler log which vtable pointers it finds for each class ๐. That info gets written to a file namedvtv_set_ptr_data.login the directory named by the environment variableVTV_LOGS_DIRif 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, delete any existing one first ๐งน.
-fvtv-countsโ A debugging flag ๐. Used together with-fvtable-verify=stdor-fvtable-verify=preinit, it makes the compiler keep track of the total number of virtual calls it encounters and the number of verifications it inserts ๐ข. It also counts how many calls to certain run-time library functions it inserts, and logs that info for each compilation unit ๐. The compiler writes this to a file namedvtv_count_data.login the directory named byVTV_LOGS_DIRif that's defined, or the current working directory otherwise. It also counts the size of the vtable pointer sets for each class and writes that tovtv_class_set_sizes.login the same directory ๐.- Note: this feature appends data to the log files. To get fresh log files, delete any existing ones ๐๏ธ.
-finstrument-functionsโ Generates instrumentation calls for function entry and exit ๐ฌ. Just after a function is entered, and just before it exits, the following profiling functions get called with the address of the current function and its call site ๐ก. (On some platforms,__builtin_return_addressdoesn't work beyond the current function, so the call site info 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 ๐บ๏ธโจ.
Okay so this instrumentation also happens for functions that get expanded inline into other functions ๐โจ The profiling calls basically mark where the inline function is conceptually entered and exited. That means addressable versions of those functions still have to exist, bestie ๐ซถ If every single use of a function gets expanded inline, that can mean extra code size ๐ And if you use extern inline in your C code, you have to provide an addressable version of those functions. (This is normally the case anyway, but if you get lucky and the optimizer always inlines them, you might have gotten away without providing static copies ๐)
A function can be given the attribute no_instrument_function, and then this instrumentation just isn't done for it ๐
This is useful for things like the profiling functions above, high-priority interrupt routines, and any functions the profiling functions can't safely be called from. Think signal handlers, if the profiling routines generate output or allocate memory ๐จ
-finstrument-functions-exclude-file-list=file,file,...โ Okay, this one lets you make a list of files whose functions get skipped by -finstrument-functions ๐ฆ If the file with a function's definition matches one of the entries, that function isn't instrumented. The matching is done on substrings, so if yourfilevalue is a substring of the file name, it counts as a match.
For example:
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
That excludes any inline function defined in files whose pathnames contain /bits/stl or include/sys ๐ธ
If, for some reason, you want to include a comma inside one of the sym values, write two commas in a row (,,). For example, -finstrument-functions-exclude-file-list=',,tmp' (note the single quotes around the option, so your shell doesn't mess it up ๐).
-finstrument-functions-exclude-function-list=sym,sym,...โ This is basically the same vibe as the file list, except this one excludes by function name instead ๐ง The name it matches is the user-visible one, likevector<int> blah(const vector<int> &), not the internal mangled name (like_Z4blahRSt6vectorIiSaIiEE). Matching is also substring-based: if yoursymis a substring of the function name, it's a match. For C99 and C++ extended identifiers, the function name has to be written in UTF-8, not with universal character names ๐-fpatchable-function-entry=N[,M]โ This one generatesNNOPs right at the start of each function, with the function entry point sitting before theMth NOP โจ IfMis left out, it defaults to0, so the entry point is the address right at the first NOP. Those NOPs reserve extra space that you can patch instrumentation into at run time, as long as the code segment is writable ๐ฅ You control the amount of space indirectly through the number of NOPs. The NOP instruction used matches the one emitted by the internal GCC back-end interfacegen_nop. This behavior is target-specific and may also depend on the architecture variant and/or other compilation options ๐
For run-time identification, the starting addresses of these areas (which correspond to their function entries minus M) are also collected in the __patchable_function_entries section of the resulting binary ๐
Note that the value of __attribute__ ((patchable_function_entry (N,M))) takes precedence over the command-line option -fpatchable-function-entry=N,M ๐ This is handy for making the area bigger, or removing it completely, on a single function. If N=0, no pad location is recorded.
The NOP instructions are inserted at (and maybe before, depending on M) the function entry address, even before the prologue ๐ซถ
โจ Options Controlling the Preprocessor โจ
These options control the C preprocessor, which runs on each C source file before the actual compilation ๐
If you use the -E option, nothing is done except preprocessing. Some of these options only make sense together with -E, because they make the preprocessor output unsuitable for actual compilation ๐
In addition to the options listed here, there are a bunch of options that 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 showed up during translation phase three in a#definedirective. Heads up: the definition gets cut off at any embedded newline characters ๐ญ
If you're calling the preprocessor from a shell (or something shell-like), you might need the shell's quoting syntax to protect characters like spaces that mean something to the shell ๐
Wanna define a function-like macro on the command line? Write its argument list in surrounding parentheses before the equals sign (if there is one). Parentheses mean stuff to most shells, so you should quote the option. With sh and csh, -D'name(args...)=definition' works ๐ธ
-D and -U options get processed in the order they show up on the command line. All -imacros file and -include file options get processed after all the -D and -U options ๐ง
-U nameโ Cancel any previous definition ofname, whether it was built in or provided with a-Doption ๐-include fileโ Processesfileas if#include "file"appeared as the very first line of the primary source file ๐ The difference is that the first directory searched forfileis the preprocessor's working directory, not the directory containing the main source file. If it's not found there, it's searched for in the rest of the#include "..."search chain as normal.
If you give multiple -include options, the files get included in the order they appear on the command line โจ
-imacros fileโ Exactly like-include, except any output produced by scanningfilegets thrown away. The macros it defines stay defined. This lets you grab all the macros from a header without also processing its declarations ๐
All files specified by -imacros are processed before all files specified by -include โญ
-undefโ Don't predefine any system-specific or GCC-specific macros. The standard predefined macros stay defined ๐ โโ๏ธ-pthreadโ Defines additional macros required for using the POSIX threads library ๐งต You should use this option consistently for both compilation and linking. It's supported on GNU/Linux targets, most other Unix derivatives, and also on x86 Cygwin and MinGW targets ๐-Mโ Instead of outputting the preprocessed result, this outputs 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. That includes ones coming from-includeor-imacroscommand-line options.
Unless you specify it explicitly (with -MT or -MQ), the object file name is the source file name with any suffix swapped for the object file suffix, and with any leading directory parts removed ๐ฆ If there are lots of included files, the rule gets split into several lines using \-newline. The rule has no commands.
This option does not suppress the preprocessor's debug output, like -dM. To avoid mixing that debug output with your dependency rules, specify the dependency output file explicitly with -MF, or use an environment variable like DEPENDENCIES_OUTPUT ๐ญ Debug output still goes 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 don't mention header files found in system header directories, or header files included (directly or indirectly) from such a header ๐
This means the choice of angle brackets or double quotes in an #include directive doesn't, on its own, decide whether that header shows up in -MM dependency output โจ
-MF fileโ When used with-Mor-MM, this specifies a file to write the dependencies to ๐ If you don't give a-MFswitch, 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 -, the dependencies get written to stdout ๐ซถ
-MGโ In conjunction with an option like-Mthat requests dependency generation,-MGassumes missing header files are generated files. It adds them to the dependency list without raising an error ๐ ๏ธ The dependency filename is taken directly from the#includedirective, without prepending any path.-MGalso suppresses preprocessed output, since a missing header file makes that useless ๐ โโ๏ธ
This feature is used in automatic updating of makefiles ๐ง
-MPโ This option tells CPP to add a phony target for each dependency other than the main file, so each one depends on nothing ๐ธ These dummy rules work around errorsmakegives if you remove header files without updating the Makefile to match ๐ญ
This is typical output:
test.o: test.c test.h
test.h:
-MT targetโ Changes the target of the rule emitted by dependency generation ๐ By default, CPP takes the name of the main input file, deletes any directory components and any file suffix such as.c, and appends the platform's usual object suffix. That result is the target.
An -MT option sets the target to be exactly the string you specify. If you want multiple targets, you can specify them as a single argument to -MT, or use multiple -MT options ๐ฆ
For example, -MT '$(objpfx)foo.o' might give:
$(objpfx)foo.o: foo.c
-MQ targetโ Same as-MT, but it quotes any characters that are special to Make ๐ฅ-MQ '$(objpfx)foo.o'gives:
$$(objpfx)foo.o: foo.c
The default target is automatically quoted, as if it were given with -MQ ๐
-MDโ okay bestie, this is-M -MF filebut without the implied-E๐ The driver picks the output name like this: if you gave it an-o, it uses your argument with a.dsuffix. If not, it grabs the input file name, strips any directory parts and the suffix, and slaps a.don the end โจ- If you use
-MDtogether with-E, any-oswitch is understood to name the dependency output file. Without-E, each-onames a target object file instead ๐ง - Since
-Eisn't implied,-MDcan make a dependency output file as a side effect of compiling. No extra steps needed, it's giving efficiency ๐ฆ
- If you use
-MMDโ like-MD, but it only mentions user header files and skips system header files ๐ธ-fpreprocessedโ tells the preprocessor "hey, this is already preprocessed, don't redo it" ๐ It skips macro expansion, trigraph conversion, escaped newline splicing, and most directives. Comments still get recognized and removed, so you can feed it a file preprocessed with-Cno problem. In this mode the integrated preprocessor is basically just a tokenizer for the front ends ๐-fpreprocessedis implicit if the input file has one of the extensions.i,.iior.mi. Those are the ones GCC uses for preprocessed files made by-save-temps.
-fdirectives-onlyโ when preprocessing, handle directives but do not expand macros. How it behaves depends on-Eand-fpreprocessed:- With
-E, preprocessing is limited to directives like"#define","#ifdef", and"#error". Macro expansion and trigraph conversion aren't happening. The-dDoption also gets implicitly enabled ๐ - With
-fpreprocessed, predefinition of the command line and most builtin macros is disabled. Contextual macros like"__LINE__"are handled normally. This lets you compile files previously preprocessed with"-E -fdirectives-only"๐ - With both
-Eand-fpreprocessed, the-fpreprocessedrules take precedence. This enables full preprocessing of files previously preprocessed with"-E -fdirectives-only"โจ
- With
-fdollars-in-identifiersโ accept$in identifiers ๐-fextended-identifiersโ accept universal character names in identifiers. This is enabled by default for C99 (and later C standards) and C++ ๐-fno-canonical-system-headersโ when preprocessing, don't shorten system header paths with canonicalization ๐งผ-ftabstop=widthโ sets the distance between tab stops ๐ This helps the preprocessor report correct column numbers in warnings or errors, even if tabs show up on the line. If the value is less than 1 or greater than 100, the option is ignored. The default is 8.-ftrack-macro-expansion[=level]โ tracks token locations across macro expansions, so the compiler can show the current macro expansion stack when an error happens inside a macro ๐ Heads up: it makes the preprocessor and compiler eat more memory. Thelevelparameter lets you pick how precisely tokens are tracked, so you can dial memory use down if needed.- Level
0deactivates this option. - Level
1tracks token locations in a degraded mode for minimal memory overhead. In this mode, all tokens from expanding an argument of a function-like macro share the same location. - Level
2tracks token locations completely. It's the most memory hungry ๐ฝ๏ธ - When given no argument, the default parameter value is
2. - Note that
"-ftrack-macro-expansion=2"is activated by default.
- Level
-fmacro-prefix-map=old=newโ when preprocessing files in directoryold, expands the"__FILE__"and"__BASE_FILE__"macros as if the files lived in directorynewinstead ๐บ๏ธ Use.fornewto turn an absolute path into a relative one, which can give more reproducible, location-independent builds. This also affects"__builtin_FILE()"during compilation. See also-ffile-prefix-map.-fexec-charset=charsetโ sets the execution character set, used for string and character constants ๐ค The default is UTF-8.charsetcan be any encoding the system'siconvlibrary routine supports.-fwide-exec-charset=charsetโ sets the wide execution character set, used for wide string and character constants ๐ช The default is UTF-32 or UTF-16, whichever matches the width of"wchar_t". Just like-fexec-charset,charsetcan be anyiconvencoding, but you'll have problems with encodings that don't fit exactly in"wchar_t"โ ๏ธ-finput-charset=charsetโ sets the input character set, for translating from the input file's character set to the source character set GCC uses ๐ If the locale doesn't specify it, or GCC can't get it from the locale, the default is UTF-8. The locale or this command-line option can override that, but right now the command-line option wins if there's a conflict.charsetcan be any encoding the system'siconvroutine supports.-fpch-depsโ when using precompiled headers, this makes the dependency-output flags also list files from the precompiled header's dependencies ๐ฆ Without it, only the precompiled header gets listed, not the files used to create it, since those aren't consulted when a PCH is used.-fpch-preprocessโ lets you use a precompiled header together with-E๐งฉ It inserts a special#pragma,#pragma GCC pch_preprocess "filename", into the output to mark where the precompiled header was found, plus its filename. When-fpreprocessedis in use, GCC recognizes this#pragmaand loads the PCH.- This option is off by default, because the resulting preprocessed output is only really suitable as input to GCC. It gets switched on by
-save-temps. - You should not write this
#pragmain your own code ๐ โโ๏ธ But it's safe to edit the filename if the PCH file is available in a different location. The filename can be absolute or relative to GCC's current directory.
- This option is off by default, because the resulting preprocessed output is only really suitable as input to GCC. It gets switched on by
-fworking-directoryโ enables linemarkers in the preprocessor output that tell the compiler the working directory at preprocessing time ๐๏ธ When it's on, after the initial linemarker the preprocessor emits a second linemarker with the current working directory followed by two slashes. GCC uses that directory, when it's present in the preprocessed input, as the working directory in some debugging information formats. This is implicitly enabled if debugging information is enabled, but you can inhibit it with the negated form-fno-working-directory. If the-Pflag is in the command line, this option has no effect, since no"#line"directives are emitted whatsoever.-A predicate=answerโ makes an assertion with the predicatepredicateand the answeranswer๐ This form is preferred to the older-A predicate(answer)form, which is still supported, because it doesn't use shell special characters.-A -predicate=answerโ cancels an assertion with the predicatepredicateand the answeranswer๐ซ-Cโ don't discard comments ๐ฌ All comments are passed through to the output file, except comments in processed directives, which get deleted along with the directive.- Be prepared for side effects with
-C, since it makes the preprocessor treat comments as tokens in their own right. For example, comments at the start of what would be a directive line turn that line into an ordinary source line, since the first token on the line is no longer a#.
- Be prepared for side effects with
-CCโ don't discard comments, including during macro expansion ๐ง This is like-C, except comments contained within macros also get passed through to the output file where the macro is expanded.- On top of the
-Cside effects,-CCconverts all C++-style comments inside a macro into C-style comments. This stops a later use of that macro from accidentally commenting out the rest of the source line. -CCis generally used to support lint comments.
- On top of the
-Pโ inhibits linemarkers in the output from the preprocessor ๐ This might be useful when running the preprocessor on something that isn't C code and will be sent to a program that could get confused by the linemarkers.-traditional,-traditional-cppโ try to imitate pre-standard C preprocessors, as opposed to ISO C preprocessors ๐ฐ๏ธ See the GNU CPP manual for details.- GCC doesn't otherwise try to emulate a pre-standard C compiler, and these options only work with the
-Eswitch, or when invoking CPP explicitly.
- GCC doesn't otherwise try to emulate a pre-standard C compiler, and these options only work with the
-trigraphsโ support ISO C trigraphs ๐บ These are three-character sequences, all starting with??, that ISO C defines to stand for single characters. For example,??/stands for\, so'??/n'is a character constant for a newline.
The nine trigraphs and their replacements are:
Trigraph: ??( ??) ??< ??> ??= ??/ ??' ??! ??-
Replacement: [ ] { } # \ ^ | ~
By default GCC ignores trigraphs, but in standard-conforming modes it converts them. See the -std and -ansi options.
-remapโ enables special code to work around file systems that only permit very short file names, like MS-DOS ๐-Hโ prints the name of each header file used, in addition to the other normal stuff ๐ช Each name is indented to show how deep it sits in the#includestack. Precompiled header files get printed too, even if they turn out to be invalid: an invalid one is printed with...x, and a valid one with...!.-dlettersโ okay so this one tells GCC to make debugging dumps during compilation, based on whatever letters you hand it ๐ The ones here are for the preprocessor. Other letters are handled by the compiler proper or saved for future GCC versions, so they get quietly ignored ๐ซถ If you mix letters whose behavior clashes, the result is undefined ๐-dMโ skip the normal output and get a list of#definedirectives for every macro the preprocessor defined, predefined ones included ๐ง It's the best way to peek at what your preprocessor already has baked in. Assuming you don't have a filefoo.h, run this:
touch foo.h; cpp -dM foo.h
and boom, all the predefined macros show up โจ If you use -dM without the -E option, it's treated as a synonym for -fdump-rtl-mach ๐ค
-dDโ same energy as-dM, but with two twists: it leaves out the predefined macros, and it outputs both the#definedirectives and the result of preprocessing ๐ Both kinds of output go to the standard output file.-dNโ like-dD, but only the macro names come through, not their expansions ๐ฆ-dIโ outputs#includedirectives on top of the result of preprocessing ๐ธ-dUโ like-dD, except only macros that get expanded, or whose definedness gets tested in preprocessor directives, make the cut ๐ The output is delayed until that macro is used or tested, and#undefdirectives also show up for macros that were tested but undefined at that point ๐
-fdebug-cppโ this one is only useful if you're debugging GCC itself ๐ญ When it's used from CPP or with-E, it dumps debugging info about location maps, and every token in the output gets preceded by the dump of the map its location belongs to ๐ฅ When used from GCC without-E, it does absolutely nothing ๐-Wp,optionโ lets you skip the compiler driver and passoptionstraight through to the preprocessor ๐ Ifoptionhas commas, it gets split into multiple options at the commas. Here's the tea though: lots of options get modified, translated, or interpreted by the driver before they reach the preprocessor, and-Wptotally bypasses that step.
The preprocessor's direct interface is undocumented and subject to change, so whenever possible, avoid -Wp and let the driver handle the options instead ๐ซ
-Xpreprocessor optionโ passesoptionalong to the preprocessor ๐ Use it for system-specific preprocessor options that GCC doesn't recognize.- If you want to pass an option that takes an argument, you have to use
-Xpreprocessortwice, once for the option and once for the argument ๐
- If you want to pass an option that takes an argument, you have to use
-no-integrated-cppโ runs preprocessing as a separate pass before compilation ๐งฉ By default GCC preprocesses as an integrated part of input tokenization and parsing, but with this option, the right language front end (cc1, cc1plus, or cc1obj for C, C++, and Objective-C, respectively) gets invoked twice: once for preprocessing only, and once for actual compilation of the preprocessed input. This may be useful alongside the-Bor-wrapperoptions to specify an alternate preprocessor, or to do extra processing on 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 ๐ Ifoptionhas commas, it gets split into multiple options at the commas.-Xassembler optionโ also passesoptionto the assembler ๐ฆ Use it for system-specific assembler options that GCC doesn't recognize.- If you want to pass an option that takes an argument, you must use
-Xassemblertwice, once for the option and once for the argument ๐
- If you want to pass an option that takes an argument, you must use
โจ 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 expect them to do anything otherwise ๐
object-file-nameโ a file name that doesn't end in a special recognized suffix is considered to name an object file or library ๐๏ธ (The linker tells object files and libraries apart by checking the file contents.) If linking happens, these object files get used as input to the linker.-c,-S,-Eโ if any of these is used, the linker doesn't run, and object file names shouldn't be used as arguments ๐ซ-flinker-output=typeโ this one controls the code generation of the link time optimizer โ๏ธ By default the linker output gets determined by the linker plugin automatically. For debugging the compiler, or when you want incremental linking to non-LTO object files, it may be useful to control the type manually ๐งexecโ code generation is set up to produce a static binary, and then-fpicand-fpieare both disabled ๐ชจdynโ code generation is set up to produce a shared library.-fpicor-fPICis preserved, but not enabled automatically ๐ This makes it possible to build shared libraries without position independent code on architectures where that's possible, i.e. on x86.pieโ code generation is set up to produce a-fpieexecutable ๐ฏ This gives similar optimizations asexec, except-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. Also, if-ffat-lto-objectsis specified, binary code is produced for future non-LTO linking. The object file from incremental linking is smaller than a static library made from the same object files, and at link time, the result of incremental linking also loads faster to the compiler than a static library, assuming most objects in the library are used โจnolto-relโ configures the compiler for incremental linking where code generation is forced, the final binary is produced, and the intermediate code for later link-time optimization is stripped ๐ When multiple object files get linked together, the resulting code is optimized better than with link time optimizations disabled (for example, cross-module inlining will happen), but most of the benefits of whole program optimizations are however lost.
During the incremental link (by -r), the linker plugin defaults to rel ๐ With current interfaces to GNU Binutils, it isn't possible to link incrementally LTO objects and non-LTO objects into a single mixed object file. If any object files in an incremental link can't be used for link-time optimization, the linker plugin outputs 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's possible to use H.J. Lu's binutils with support for mixed objects ๐ซถ
-fuse-ld=bfdโ uses the bfd linker instead of the default linker ๐ ๏ธ-fuse-ld=goldโ uses the gold linker instead of the default linker ๐ฅ-fuse-ld=lldโ uses the LLVM lld linker instead of the default linker ๐-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 ๐
The -l option gets passed directly to the linker by GCC, so check your linker documentation for the exact details ๐ The general description below applies to the GNU linker.
The linker searches a standard list of directories for the library ๐บ๏ธ The directories it searches include several standard system directories, plus any you specify with -L.
Static libraries are archives of object files, and they 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 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 get passed to the linker, and options specifying linkage of the system libraries, such as-static-libgccor-shared-libgcc, are ignored ๐ง The standard startup files are still used normally, unless-nostartfilesis used.
The compiler may generate calls to "memcmp", "memset", "memcpy" and "memmove". These entries are usually resolved by entries in libc. When this option is specified, these entry points should be supplied through some other mechanism ๐จ
-nolibcโ don't use the C library, or the system libraries tightly coupled with it, when linking ๐งผ It still links with the startup files, libgcc, or toolchain-provided language support libraries such as libgnat, libgfortran, or libstdc++, unless options preventing their inclusion are used as well. This typically removes-lcfrom the link command line, along with system libraries that normally go with it and become meaningless when a C library is assumed to be absent, for example-lpthreador-lmin some configurations. This is intended for bare-board targets when there is indeed no C library available ๐ค-nostdlibโ don't use the standard system startup files or libraries when linking ๐ซฅ No startup files get 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 too ๐ซ
Okay so the compiler might generate calls to memcmp, memset, memcpy and memmove all on its own ๐ซถ Usually libc is the one that resolves those for you, but when this option is on, those entry points have to be supplied some other way, bestie ๐
Plot twist: one of the standard libraries that -nostdlib and -nodefaultlibs skip is libgcc.a ๐ง It's a library of internal subroutines GCC uses to work around shortcomings of particular machines, or to cover special needs for some languages.
Here's the thing though: you usually still need libgcc.a even when you're ditching the other standard libraries ๐ญ So when you specify -nostdlib or -nodefaultlibs, you should usually specify -lgcc as well. That way you don't end up with unresolved references to internal GCC library subroutines. (An example of one of those is __main, which makes sure C++ constructors get called ๐ธ)
-e entry,--entry=entryโ Sets the program entry point to entry. The linker is the one who interprets this, and the GNU linker will take either a symbol name or an address ๐ฆ-pieโ Makes a dynamically linked position independent executable on targets that support it โจ For predictable results, you also have to use the same options you used for compilation (-fpie,-fPIE, or model suboptions) when you pass this linker option.-no-pieโ Nope, don't make a dynamically linked position independent executable ๐-static-pieโ Makes a static position independent executable on targets that support it. It's giving static executable energy, but it can be loaded at any address without a dynamic linker ๐ For predictable results, use the same options used for compilation (-fpie,-fPIE, or model suboptions) here too.-pthreadโ Links with the POSIX threads library ๐งต This works on GNU/Linux, most other Unix derivatives, and also x86 Cygwin and MinGW targets. On some targets it also sets flags for the preprocessor, so use it consistently for both compiling and linking.-rโ Produces a relocatable object as output. This is also known as partial linking ๐-rdynamicโ Passes-export-dynamicto the ELF linker, on targets that support it. This tells the linker to add all symbols to the dynamic symbol table, not only the used ones. It's needed for some uses ofdlopen, or to get backtraces from inside a program ๐-sโ Removes all symbol table and relocation information from the executable ๐งน-staticโ On systems that support dynamic linking, this overrides-pieand stops linking with the shared libraries. On other systems it has no effect ๐-sharedโ Produces a shared object that can then be linked with other objects to form an executable. Not every system supports this one. For predictable results, use the same options used for compilation (-fpic,-fPIC, or model suboptions) when you pass this linker option.[1]-shared-libgcc,-static-libgccโ On systems that provide libgcc as a shared library, these force the use of the shared or static version, respectively ๐ If no shared version of libgcc was built when the compiler was configured, these do nothing.
There are a few situations where an app should use the shared libgcc instead of the static one ๐ The most common is when the app wants to throw and catch exceptions across different shared libraries. In that case, each of the libraries as well as the application itself should use the shared libgcc.
So the G++ driver automatically adds -shared-libgcc whenever you build a shared library or a main executable, because C++ programs typically use exceptions. That's the right thing to do, periodt โจ
If you use the GCC driver to create 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 the option --eh-frame-hdr, it links the shared version of libgcc into shared libraries by default. Otherwise, it takes advantage of the linker and optimizes away the linking with the shared version, so it links with the static version of libgcc by default. This lets exceptions propagate through those shared libraries without incurring relocation costs at library load time.
However, if a library or main executable is supposed to throw or catch exceptions, you must link it using the G++ driver, or using the option -shared-libgcc, so it gets linked with the shared libgcc. Don't skip this one, bestie ๐ญ
-static-libasanโ When the-fsanitize=addressoption is used to link a program, the GCC driver automatically links against libasan ๐ก๏ธ If libasan is available as a shared library and-staticisn't used, it links against the shared version of libasan. The-static-libasanoption tells the GCC driver to link libasan statically, without necessarily linking other libraries statically.-static-libtsanโ When the-fsanitize=threadoption is used to link a program, the GCC driver automatically links against libtsan ๐งต If libtsan is available as a shared library and-staticisn't used, it links against the shared version of libtsan. The-static-libtsanoption tells the GCC driver to link libtsan statically, without necessarily linking other libraries statically.-static-liblsanโ When the-fsanitize=leakoption is used to link a program, the GCC driver automatically links against liblsan ๐ง If liblsan is available as a shared library and-staticisn't used, it links against the shared version of liblsan. The-static-liblsanoption tells the GCC driver to link liblsan statically, without necessarily linking other libraries statically.-static-libubsanโ When the-fsanitize=undefinedoption is used to link a program, the GCC driver automatically links against libubsan ๐ If libubsan is available as a shared library and-staticisn't used, it links against the shared version of libubsan. The-static-libubsanoption tells the GCC driver to link libubsan statically, without necessarily linking other libraries statically.-static-libstdc++โ When theg++program links a C++ program, it normally links against libstdc++ automatically ๐ If libstdc++ is available as a shared library and-staticisn't used, it links against the shared version, and that's normally fine. Sometimes, though, it's useful to freeze the version of libstdc++ your program uses without going all the way to a fully static link. The-static-libstdc++option tells theg++driver to link libstdc++ statically, without necessarily linking other libraries statically.-symbolicโ Binds references to global symbols when building a shared object. It warns about any unresolved references, unless you override that with the link editor option-Xlinker -z -Xlinker defs. Only a few systems support this option ๐-T scriptโ Uses script as the linker script. This option 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 along to the linker as an option. This is your go-to for system-specific linker options that GCC doesn't recognize ๐ง
If you want to pass an option that takes a separate argument, you have to use -Xlinker twice: once for the option and once for the argument. For example, to pass -assert definitions, you write -Xlinker -assert -Xlinker definitions. Writing -Xlinker "-assert definitions" does not work, because it passes the entire string as one single argument, and that's not what the linker expects ๐ค
When you're using the GNU linker, it's usually more convenient to pass arguments to linker options with the option=value syntax instead of as separate arguments. For example, you can write -Xlinker -Map=output.map rather than -Xlinker -Map -Xlinker output.map. Other linkers may not support this syntax for command-line options.
-Wl,optionโ Passes option along to the linker as an option. If option contains commas, it gets split into multiple options at those commas. You can use this syntax to pass an argument to the option. For example,-Wl,-Map,output.mappasses-Map output.mapto the linker. 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, which forces linking of the library modules that define it ๐ฏ You can use-umultiple times with different symbols to force loading of additional library modules.-z keywordโ-zgets passed straight to the linker along with the keyword. Check the section in your linker's documentation for the permitted values and what they mean ๐
๐๏ธ Options for Directory Search
These options specify directories to search for header files, for libraries and for parts of the compiler:
-I dir,-iquote dir,-isystem dir,-idirafter dirโ Adds the directory dir to the list of directories searched for header files during preprocessing ๐งญ If dir begins with=or$SYSROOT, then that=or$SYSROOTgets replaced by the sysroot prefix. See--sysrootand-isysrootfor more.
Directories specified with -iquote only apply to the quote form of the directive, #include "file". Directories specified with -I, -isystem, or -idirafter apply to the lookup for both #include "file" and #include <file> directives ๐ธ
You can specify any number or combination of these options on the command line to search for header files in several directories ๐ The lookup order goes like this:
- For the quote form of the include directive, the directory of the current file is searched first.
- okay bestie, for the quote form of the include directive, the
-iquotedirs get searched left-to-right, in whatever order they show up on the command line ๐ - next up,
-Idirs get scanned left-to-right ๐ฆ - then the
-isystemdirs get scanned left-to-right too ๐ - standard system dirs get scanned ๐ธ
- last but not least,
-idirafterdirs get scanned left-to-right ๐ซถ
Ngl, this order is iconic. You can use -I to override a system header file and swap in your own version, because these dirs get searched before the standard system header file dirs โจ But please don't use this to add dirs full of vendor-supplied system header files. Use -isystem for that ๐
The -isystem and -idirafter options also mark the directory as a system directory, so it gets the same special treatment as the standard system directories ๐
If a standard system include directory, or a directory given with -isystem, also shows up with -I, then the -I option gets ignored ๐ The directory still gets searched, just as a system directory at its normal spot in the system include chain. This keeps GCC's procedure for fixing buggy system headers and the ordering for the #include_next directive from getting accidentally messed up ๐ง If you really, truly need to change the search order for system directories, use the -nostdinc and/or -isystem options.
-I-โ Split the include path. This option has been deprecated, so please use-iquoteinstead for-Idirectories before the-I-, and remove the-I-option ๐ฅ
Any directories given with -I options before -I- only get searched for headers requested with #include "file". They're not searched for #include <file>. If additional directories are given with -I options after the -I-, those directories get searched for all #include directives โจ
Also, -I- stops the directory of the current file from being used as the first search directory for #include "file". There's no way to override this effect of -I- ๐
โโ๏ธ
-iprefix prefixโ Set prefix as the prefix for subsequent-iwithprefixoptions. If the prefix represents a directory, you should include the final/๐-iwithprefix dir,-iwithprefixbefore dirโ Tack dir onto the prefix you set earlier with-iprefix, and add the resulting directory to the include search path.-iwithprefixbeforeputs it in the same place-Iwould, while-iwithprefixputs it where-idirafterwould ๐-isysroot dirโ This one's like 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 the--sysrootoption for more info ๐-imultilib dirโ Use dir as a subdirectory of the directory that holds the target-specific C++ headers ๐ธ-nostdincโ Do not search the standard system directories for header files. Only the directories you explicitly give with-I,-iquote,-isystem, and/or-idirafteroptions get searched, plus the directory of the current file if it's appropriate ๐-nostdinc++โ Don't search for header files in the C++-specific standard directories, but do still search the other standard directories. This option is used when building the C++ library ๐ง-iplugindir=dirโ Set the directory to search for plugins that get passed by-fplugin=nameinstead of-fplugin=path/name.so. This one isn't really meant for users. Only the driver passes it along ๐ค-Ldirโ Add directory dir to the list of directories to be searched for-l๐ฆ-Bprefixโ This option tells the compiler where to find its own executables, libraries, include files, and data files ๐ซถ
The compiler driver program runs one or more of the subprograms cpp, cc1, as and ld. It tries prefix as a prefix for each program it tries to run, both with and without machine/version/ for the corresponding target machine and compiler version ๐
For each subprogram, the compiler driver first tries the -B prefix, if there is one. If that name isn't found, or if -B isn't specified at all, the driver tries two standard prefixes, /usr/lib/gcc/ and /usr/local/lib/gcc/. If neither of those turns up a file that exists, the unmodified program name gets searched for in the directories listed in your PATH environment variable ๐ฅ
The compiler checks whether the path given by -B refers to a directory. If it's necessary, it adds a directory separator character to the end of the path ๐ธ
-B prefixes that effectively specify directory names also apply to libraries in the linker, because the compiler translates these options into -L options for the linker. They also apply to include files in the preprocessor, because the compiler translates these options into -isystem options for the preprocessor. In this case, the compiler appends include to the prefix ๐ง
The runtime support file libgcc.a can also be searched for using the -B prefix, if needed. If it isn't found there, the two standard prefixes above get tried, and that's all. If those means don't find it either, the file gets left out of the link ๐
Another way to specify a prefix that's a lot like the -B prefix is the environment variable GCC_EXEC_PREFIX ๐
As a special kludge, if the path given by -B is [dir/]stageN/, where N is a number in the range 0 to 9, then it gets replaced by [dir/]include. This is there to help with boot-strapping the compiler ๐ ๏ธ
-no-canonical-prefixesโ Do not expand any symbolic links, resolve references to/../or/./, or make the path absolute when generating a relative prefix ๐ฆ--sysroot=dirโ Use dir as the logical root directory for headers and libraries. For example, if the compiler normally searches for headers in/usr/includeand libraries in/usr/lib, it instead searchesdir/usr/includeanddir/usr/lib๐
If you use both this option and the -isysroot option, then --sysroot applies to libraries, but -isysroot applies to header files ๐
The GNU linker (beginning with version 2.16) has the necessary support for this option. If your linker doesn't support it, the header file side of --sysroot still works, but the library side doesn't ๐ญ
--no-sysroot-suffixโ For some targets, a suffix gets added to the root directory specified with--sysroot, depending on the other options you used. That means headers might be found indir/suffix/usr/includeinstead ofdir/usr/include. This option turns off the addition of that suffix ๐
โจ Options for Code Generation Conventions โจ
These machine-independent options control the interface conventions used in code generation ๐ง
Most of them have both positive and negative forms, and the negative form of -ffoo is -fno-foo. In the 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_level can be all, named_vars, or none. all enables stack reuse for all local variables and temporaries, named_vars enables reuse only for user defined local variables with names, and none disables stack reuse completely. The default value is all ๐
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, where temporaries' stack space is not reused. 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โ okay bestie, this one tells the compiler to assume that signed arithmetic overflow from addition, subtraction and multiplication just wraps around, using twos-complement representation ๐โจ. It turns some optimizations on and others off.-ftrapvand-fwrapvcancel each other out, so-ftrapv -fwrapvon the command line results in-fwrapvbeing effective ๐ . Only active options override, though, so-ftrapv -fwrapv -fno-wrapvon the command line results in-ftrapvbeing effective ๐.-fwrapv-pointerโ same energy, but for pointers ๐ธ. It tells the compiler to assume pointer arithmetic overflow on addition and subtraction wraps around using twos-complement representation. It also disables some optimizations that would otherwise assume pointer overflow is invalid ๐.-fstrict-overflowโ this one implies-fno-wrapv -fno-wrapv-pointer๐. When it's negated, it implies-fwrapv -fwrapv-pointer๐ฆ.-fexceptionsโ enables exception handling โจ and generates the extra code needed to propagate exceptions ๐ง. For some targets, this implies GCC generates frame unwind information for all functions. That can add a pretty big data size overhead ๐ญ, although it doesn't affect execution ๐.
If you don't specify this option, GCC turns it on by default for languages like C++ that normally require exception handling, and turns it off for languages like C that don't ๐. You might still need to enable it when compiling C code that has to interoperate properly with exception handlers written in C++ ๐ซถ. You might also want to disable it if you're compiling older C++ programs that don't use exception handling ๐.
-fnon-call-exceptionsโ makes trapping instructions able to throw exceptions ๐ฅ. Heads up: this needs platform-specific runtime support, and that support doesn't exist everywhere โ ๏ธ. It only lets trapping instructions throw exceptions, meaning memory references or floating-point instructions ๐ง . It does not let exceptions get thrown from arbitrary signal handlers, like"SIGALRM"๐ .-fdelete-dead-exceptionsโ instructions that may throw exceptions but don't otherwise contribute to the program's execution can be optimized away ๐๏ธ. This is enabled by default for the Ada front end, which the Ada language specification permits ๐. Optimization passes that remove dead exceptions are enabled independently at different optimization levels ๐ฅ.-funwind-tablesโ kinda like-fexceptions, except it only generates any needed static data and doesn't affect the generated code in any other way ๐ฆ. You normally don't need to enable it yourself, since a language processor that needs this handling turns it on for you ๐ซถ.-fasynchronous-unwind-tablesโ generates an unwind table in DWARF format, if the target machine supports it ๐. The table is exact at each instruction boundary, so it can be used for stack unwinding from asynchronous events, like a debugger or garbage collector ๐.-fno-gnu-uniqueโ on systems with a recent GNU assembler and C library, the C++ compiler uses theSTB_GNU_UNIQUEbinding. This keeps definitions of template static data members and static local variables in inline functions unique, even withRTLD_LOCALโจ. That's needed so a library used by two differentRTLD_LOCALplugins doesn't end up depending on a definition in one and disagreeing with the other about the symbol's binding ๐ต. The catch is thatdlclosegets ignored for affected DSOs ๐. If your program relies on reinitializing a DSO throughdlcloseanddlopen, 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 compiled by other compilers, especially the Portable C Compiler (pcc) ๐ค.
The precise convention for returning structures in memory depends on the target configuration macros ๐ ๏ธ.
Short structures and unions are the ones whose size and alignment match that of some integer type ๐.
Warning: code compiled with-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 when possible ๐. This is more efficient for small structures than-fpcc-struct-return๐ช.
If you specify neither -fpcc-struct-return nor -freg-struct-return, GCC defaults to whichever convention is standard for the target ๐ฏ. If there's no standard convention, GCC defaults to -fpcc-struct-return, except on targets where GCC is the principal compiler ๐. In those cases, GCC can choose the standard itself, and it chose the more efficient register return alternative ๐
.
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โ allocates anenumtype only as many bytes as it needs for the declared range of possible values ๐ข. Specifically, theenumtype is equivalent to the smallest integer type that has enough room ๐งธ.
Warning: the -fshort-enums switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to conform to a non-default application binary interface โ ๏ธ.
-fshort-wcharโ overrides the underlying type forwchar_tto beshort unsigned intinstead of the target's default ๐ช. This is useful for building programs to run under WINE ๐ท.
Warning: the -fshort-wchar 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 โ ๏ธ.
-fno-commonโ in C code, this controls where global variables defined without an initializer get placed. These are known as tentative definitions in the C standard ๐ฆ. Tentative definitions are different from declarations of a variable with theexternkeyword, which don't allocate storage ๐ .
Unix C compilers have traditionally put storage for uninitialized global variables in a common block ๐งฑ. That lets the linker resolve all tentative definitions of the same variable in different compilation units to the same object, or to a non-tentative definition ๐. This is the behaviour -fcommon specifies, and it's the default for GCC on most targets ๐. But ISO C doesn't require it, and on some targets it may carry a speed or code size penalty on variable references ๐ค.
-fno-common tells the compiler to place uninitialized global variables in the BSS section of the object file instead ๐ฏ. This stops the linker from merging tentative definitions, so you get a multiple-definition error if the same variable is defined in more than one compilation unit ๐ฅ. It's useful on targets where it performs better, or if you want to verify that your program works on other systems that always treat uninitialized variable definitions this way ๐.
-fno-identโ ignores the#identdirective ๐.-finhibit-size-directiveโ doesn't output a.sizeassembler directive, or anything else that would cause trouble if the function gets split in the middle and the two halves end up far apart in memory ๐งฉ. This option is used when compilingcrtstuff.c. You shouldn't need it for anything else ๐ซ.-fverbose-asmโ adds extra commentary to the generated assembly code to make it way more readable ๐. This is really only useful for people who actually need to read the generated assembly, like when debugging the compiler itself ๐ค.
-fno-verbose-asm, the default, leaves the extra information out, which is handy when comparing two assembler files ๐.
The added comments include:
- information on the compiler version and command-line options,
- the source code lines associated with the assembly instructions, in the form
FILENAME:LINENUMBER:CONTENT OF LINE, - hints on which high-level expressions correspond to the various assembly instruction operands.
For example, given this C source file:
int test (int n)
{
int i;
int total = 0;
for (i = 0; i < n; i++)
total += i * i;
return total;
}
Compiling to (x86_64) assembly via -S and emitting the result direct to stdout via -o -:
gcc -S test.c -fverbose-asm -Os -o -
gives output similar to this:
.file "test.c"
# GNU C11 (GCC) version 7.0.0 20160809 (experimental) (x86_64-pc-linux-gnu)
[...snip...]
# options passed:
[...snip...]
Okay bestie, the assembly listing is the output you get from -fverbose-asm, and it's giving "here's what the compiler actually spat out" ๐ง Look at all those little # comments tying each instruction back to test.c ๐
.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 for humans, not machines, so the exact format of them can change whenever. Don't build anything that depends on it ๐
-frecord-gcc-switchesโ this one tells the compiler to stash the exact command line you used into the object file it's making ๐
This only works on some targets, and the format depends on both the target and the binary file format. Usually it's a section full of ASCII text. It's related to -fverbose-asm, but that one only writes info into the assembler output as comments, so it never makes it into the object file. For another way to store compiler options in the object file, check out -grecord-gcc-switches โจ
-fpicโ generate position-independent code (PIC) that's good for shared libraries, if the target machine supports it ๐ฆ
This code reaches every constant address through a global offset table (GOT). The dynamic loader fills in the GOT entries when the program starts up. (The dynamic loader isn't part of GCC, it's part of the operating system, so no it's not GCC's fault ๐)
If the GOT for your linked executable goes over a machine-specific max size, the linker throws an error saying -fpic doesn't work. In that case, recompile with -fPIC instead. (The maximums are 8k on the SPARC, 28k on AArch64, and 32k on the m68k and RS/6000. The x86 has no such limit, so it's living its best life ๐)
PIC needs special support, so it only works on certain machines. On x86, GCC does PIC for System V but not for the Sun 386i. Code for the IBM RS/6000 is always position-independent ๐
When this flag is set, the macros __pic__ and __PIC__ get defined to 1 โจ
-fPICโ if the target machine supports it, this emits position-independent code that works for dynamic linking and has no size limit on the global offset table ๐ It makes a real difference on AArch64, m68k, PowerPC, and SPARC ๐ฅ
PIC needs special support, so again, only certain machines can do it ๐
When this flag is set, __pic__ and __PIC__ get defined to 2 ๐
-fpie,-fPIEโ these are like-fpicand-fPIC, but the position-independent code they make can only be linked into executables ๐ง You'll usually use them for code that's going to be linked with the-pieGCC option.
Both -fpie and -fPIE define the macros __pie__ and __PIE__. They're 1 for -fpie and 2 for -fPIE ๐
-fno-pltโ skip the PLT for external function calls in position-independent code. Instead, load the callee address from the GOT at each call site and branch to it ๐ฆ
This gets you more efficient code, because it kills the PLT stubs and lets the GOT loads get optimized. On architectures like 32-bit x86, where PLT stubs expect the GOT pointer in one specific register, it gives the compiler more freedom with register allocation ๐
Lazy binding needs the PLT, so with -fno-plt, every external symbol gets resolved at load time instead.
Alternatively, you can use the function attribute noplt to avoid calls through the PLT for specific external functions โจ
In position-dependent code, a few targets will also switch calls to functions marked to skip the PLT over to use the GOT instead ๐ธ
-fno-jump-tablesโ don't use jump tables forswitchstatements, even when they'd be more efficient than other codegen strategies ๐
This is handy alongside -fpic or -fPIC when you're building code that's part of a dynamic linker and can't reference the address of a jump table. On some targets, jump tables don't need a GOT, so you don't need this option there ๐ซถ
-ffixed-regโ treat the register namedregas fixed, so generated code should never touch it (unless it's being used as the stack pointer, frame pointer, or some other fixed role) ๐
reg has to be an actual register name. The accepted names are machine-specific and get defined in the REGISTER_NAMES macro in the machine description macro file ๐ง
This flag has no negative form, since it's a three-way choice ๐
-fcall-used-regโ treat the register namedregas an allocable register that function calls clobber. It can get used for temporaries or variables that don't live across a call. Functions compiled this way don't save and restorereg๐
Using this flag with the frame pointer or stack pointer is an error ๐ซ Using it on other registers that have fixed, pervasive roles in the machine's execution model gives disastrous results ๐
This flag has no negative form, since it's a three-way choice โจ
-fcall-saved-regโ treat the register namedregas an allocable register that functions save. It can be allocated even for temporaries or variables that live across a call. Functions compiled this way save and restoreregif they use it ๐ฆ
Using this flag with the frame pointer or stack pointer is an error ๐ซ Using it on other registers with fixed, pervasive roles in the machine's execution model gives disastrous results ๐
A different kind of disaster happens if you use it on a register where function values get returned ๐ญ
This flag has no negative form, since it's a three-way choice ๐
-fpack-struct[=n]โ without a value, this packs all structure members together with no holes ๐งฉ If you give it a value, which has to be a small power of two, it packs the structure members according to that value, treating it as the maximum alignment. (That means objects with default alignment requirements bigger than this get output potentially unaligned at the next fitting location.) ๐
Warning: -fpack-struct makes GCC generate code that is NOT binary compatible with code made without it. It also makes the code suboptimal. Only use it when you need to conform to a non-default application binary interface ๐
-fleading-underscoreโ this one, along with its counterpart-fno-leading-underscore, forcibly changes how C symbols get represented in the object file ๐ง One reason to use it is to link with legacy assembly code ๐ซถ
Warning: -fleading-underscore makes GCC generate code that is NOT binary compatible with code made without it. Only use it to conform to a non-default application binary interface. Not every target fully supports this switch, so double-check before you rely on it ๐ญ
-ftls-model=modelโ change the thread-local storage model.modelshould be one ofglobal-dynamic,local-dynamic,initial-exec, orlocal-exec๐ธ
The choice is subject to optimization. The compiler might use a more efficient model for symbols that aren't visible outside the translation unit, or if -fpic isn't given on the command line. (That's the "it's giving smart compiler" energy ๐ง )
The default without -fpic is initial-exec. With -fpic, the default is global-dynamic ๐
-ftrampolinesโ for targets that normally need trampolines for nested functions, this always generates them instead of using descriptors. For targets that don't need them, like HP-PA or IA-64, it does nothing ๐ฆ
A trampoline is a tiny bit of code created at run time on the stack when the address of a nested function is taken. It's used to call the nested function indirectly. That means the stack has to be made executable for the program to work properly ๐ญ
-fno-trampolines is enabled by default on a language-by-language basis. That lets the compiler skip making trampolines when it works out that's safe, and swap in descriptors instead. Descriptors are made of data only, but the generated code has to be ready to deal with them ๐ As of this writing, -fno-trampolines is enabled by default only for Ada ๐
Code compiled with -ftrampolines and code compiled with -fno-trampolines are not binary compatible if nested functions are present. So this option has to be used program-wide, and you need to handle it with extreme care ๐
-fvisibility=[default|internal|hidden|protected]โ this sets the default ELF image symbol visibility to whatever option you pick. Every symbol gets marked with it unless the code overrides it ๐
This can seriously speed up linking and load times for shared object libraries, make the code more optimized, give you near-perfect API export, and stop symbol clashes. It's strongly recommended for any shared objects you distribute ๐ซถ
Despite the name, default actually means public, i.e., it can be linked against from outside the shared object ๐ธ protected and internal are pretty useless in real-world use, so the only other one you'll commonly see is hidden ๐ If you don't specify -fvisibility, the default is default, which means every symbol is public โจ
Okay so if you want the full tea on why ELF symbol visibility matters, read "How To Write Shared Libraries" by Ulrich Drepper, found at https://www.akkadia.org/drepper/ ๐๐ค But the lowkey iconic move this option unlocks is making the default hidden and only marking the stuff you actually want public โจ Instead of marking everything hidden when the default is public (so much typing ๐), you flip it. That's the norm with DLLs on Windows. With -fvisibility=hidden plus __attribute__ ((visibility("default"))) instead of __declspec(dllexport), you get almost identical semantics with identical syntax ๐ซถ Cross-platform projects, this is your moment ๐
For people adding visibility to existing code, #pragma GCC visibility is giving ๐ You wrap the declarations you care about in #pragma GCC visibility push(hidden) and close it with #pragma GCC visibility pop ๐ Real talk though: symbol visibility is part of your API interface contract, so all new code should always specify visibility whenever it isn't the default. Declarations that only get used inside the local DSO should always be marked explicitly as hidden, so you dodge PLT indirection overheads ๐
โโ๏ธ Being this clear also makes the code way more readable and self-documenting, no cap ๐ Also, because of ISO C++ specification requirements, operator new and operator delete must always be default visibility ๐
Heads up, bestie: headers from outside your project, like system headers and headers from any other library you use, might not be expecting anything other than default visibility ๐ฌ You may need to say #pragma GCC visibility push(default) before including any of those ๐ก๏ธ
extern declarations aren't affected by -fvisibility, so a lot of code can be recompiled with -fvisibility=hidden with zero modifications โจ BUT (plot twist ๐ญ) calls to extern functions with no explicit visibility go through the PLT. So it's way more effective to use __attribute ((visibility)) and/or #pragma GCC visibility to tell the compiler which extern declarations should be treated as hidden ๐ง
Also, -fvisibility does affect C++ vague linkage entities ๐ So an exception class that gets thrown between DSOs must be explicitly marked with default visibility, so the type_info nodes get unified between the DSOs. Don't skip this one, it's a whole bug just waiting to happen ๐
An overview of all these techniques, their benefits, and how to use them lives at http://gcc.gnu.org/wiki/Visibility ๐ฆ
๐ธ -fstrict-volatile-bitfields
Use this when you want accesses to volatile bit-fields (or other structure fields, although the compiler usually honors those types anyway) to be a single access at the width of the field's type, aligned to a natural alignment if 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) to force GCC into 16-bit accesses, instead of a maybe-more-efficient 32-bit access ๐ง
If this option is disabled, the compiler goes for the most efficient instruction ๐๏ธ In the example above, 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 unrelated to the one being updated ๐ฌ
In some cases, like when the packed attribute is applied to a structure field, it might not be possible to access the field with one read or write that's correctly aligned for the target machine. In that situation GCC falls back to generating multiple accesses, rather than code that will fault or truncate the result at run time ๐
Note: due to restrictions of the C/C++11 memory model, write accesses are not allowed to touch non bit-field members. So it's recommended to define all bits of the field's type as bit-field members ๐
The default value of this option is determined by the application binary interface for the target processor ๐งพ
๐ง -fsync-libcalls
This option controls whether any out-of-line instance of the __sync family of functions may be used to implement the C++11 __atomic family of functions ๐งต The default is enabled, so the only useful form of the option is -fno-sync-libcalls ๐ This option is used in the implementation of the libatomic runtime library ๐
โจ GCC Developer Options โจ
This section covers command-line options that are mainly for GCC developers ๐งโ๐ป Think compiler testing, investigating compiler bugs, and compile-time performance problems. That includes options that produce debug dumps at various points, options that print statistics like memory use and execution time, and options that print info about GCC's configuration, like where it searches for libraries ๐ Honestly, you should rarely need any of these for ordinary compiling and linking, so don't go wild ๐
Many developer options that make GCC dump output to a file take an optional =filename suffix. You can use stdout or - to dump to standard output, and stderr for standard error ๐ค
If you leave out =filename, GCC builds a default dump file name by sticking together the base dump file name, a pass number, a phase letter, and the pass name ๐งฉ The base dump file name is the name of the output file if you explicitly specified one and it isn't an executable. Otherwise it's the source file name. The pass number comes from the order passes are registered with the compiler's pass manager. That's usually the same as 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 ๐
๐ฅ -dletters, -fdump-rtl-pass, -fdump-rtl-pass=filename
These make debugging dumps during compilation at the times specified by the letters. This is the move for debugging the RTL-based passes of the compiler ๐ ๏ธ
Heads up: some -dletters switches mean something different when you use -E for preprocessing ๐
You can enable debug dumps with a -fdump-rtl switch or with some -d option letters. Here are the possible values for pass and the letters, and what each one means ๐
-fdump-rtl-alignmentsโ dumps right after branch alignments have been computed ๐-fdump-rtl-asmconsโ dumps after fixing rtl statements that have unsatisfied in/out constraints ๐งฉ-fdump-rtl-auto_inc_decโ dumps after auto-inc-dec discovery. This pass only runs on architectures that have auto inc or auto dec instructions ๐ค-fdump-rtl-barriersโ dumps after cleaning up the barrier instructions ๐งน-fdump-rtl-bbpartโ dumps after partitioning hot and cold basic blocks ๐ฅ๐ง-fdump-rtl-bbroโ dumps after block reordering ๐-fdump-rtl-btl1,-fdump-rtl-btl2โ turn on dumping after the two branch target load optimization passes ๐ฏ-fdump-rtl-bypassโ dumps after jump bypassing and control flow optimizations ๐ฆ-fdump-rtl-combineโ dumps after the RTL instruction combination pass ๐ง-fdump-rtl-compgotosโ dumps after duplicating the computed gotos ๐ฏ-fdump-rtl-ce1,-fdump-rtl-ce2,-fdump-rtl-ce3โ turn on dumping after the three if conversion passes ๐-fdump-rtl-cprop_hardregโ dumps after hard register copy propagation ๐-fdump-rtl-csaโ dumps after combining stack adjustments ๐ฅ-fdump-rtl-cse1,-fdump-rtl-cse2โ turn on dumping after the two common subexpression elimination passes ๐-fdump-rtl-dceโ dumps after the standalone dead code elimination passes ๐๏ธ-fdump-rtl-dbrโ dumps after delayed branch scheduling โณ-fdump-rtl-dce1,-fdump-rtl-dce2โ turn on dumping after the two dead store elimination passes ๐ป-fdump-rtl-ehโ dumps after the finalization of EH handling code ๐จ-fdump-rtl-eh_rangesโ dumps after conversion of EH handling range regions ๐-fdump-rtl-expandโ dumps after RTL generation ๐ฑ-fdump-rtl-fwprop1,-fdump-rtl-fwprop2โ turn on dumping after the two forward propagation passes โก๏ธ-fdump-rtl-gcse1,-fdump-rtl-gcse2โ turn on dumping after global common subexpression elimination ๐-fdump-rtl-init-regsโ dumps after the initialization of the registers ๐-fdump-rtl-initvalsโ dumps after the computation of the initial value sets ๐ฌ-fdump-rtl-into_cfglayoutโ dumps after converting to cfglayout mode ๐๏ธ-fdump-rtl-iraโ dumps after iterated register allocation ๐ง-fdump-rtl-jumpโ dumps after the second jump optimization ๐ธ-fdump-rtl-loop2โ turns on dumping after the rtl loop optimization passes ๐-fdump-rtl-machโ dumps after the machine dependent reorganization pass, if that pass exists ๐๏ธ-fdump-rtl-mode_swโ dumps after removing redundant mode switches โ๏ธ-fdump-rtl-rnregโ dumps after register renumbering ๐ข-fdump-rtl-outof_cfglayoutโ dumps after converting from cfglayout mode ๐-fdump-rtl-peephole2โ dumps after the peephole pass ๐-fdump-rtl-postreloadโ dumps after post-reload optimizations ๐ง-fdump-rtl-pro_and_epilogueโ dumps after generating the function prologues and epilogues ๐ญ-fdump-rtl-sched1,-fdump-rtl-sched2โ turn on dumping after the basic block scheduling passes ๐๏ธ-fdump-rtl-reeโ dumps after sign/zero extension elimination โ-fdump-rtl-seqabstrโ dumps after common sequence discovery ๐ช-fdump-rtl-shortenโ okay bestie, this one drops a dump right after branch shortening โจ-fdump-rtl-siblingโ dumps after the sibling call optimizations, so you can peek at all the tail-call magic ๐ฆ-fdump-rtl-split1,-fdump-rtl-split2,-fdump-rtl-split3,-fdump-rtl-split4,-fdump-rtl-split5โ the splitting squad ๐ these enable dumping after each of the five rounds of instruction splitting-fdump-rtl-smsโ dumps after modulo scheduling ๐ธ but ngl, this pass only runs on some architectures-fdump-rtl-stackโ dumps after GCC converts its "flat register file" registers into the x87's stack-like registers ๐ฅ this pass only runs on x86 variants-fdump-rtl-subreg1,-fdump-rtl-subreg2โ the two subreg expansion passes get their own dumps ๐ง both of these enable dumping after each pass-fdump-rtl-unshareโ dumps after all the rtl has been unshared ๐-fdump-rtl-vartrackโ dumps after variable tracking ๐-fdump-rtl-vregsโ dumps after virtual registers get converted to hard registers ๐-fdump-rtl-webโ dumps after live range splitting ๐-fdump-rtl-regclass,-fdump-rtl-subregs_of_mode_init,-fdump-rtl-subregs_of_mode_finish,-fdump-rtl-dfinit,-fdump-rtl-dfinishโ these ones are kinda ghosts ๐ป they're defined, but they always produce empty files, so don't waste your time staring at them-da,-fdump-rtl-allโ produces all the dumps listed above ๐ the full buffet ๐ฐ-dAโ annotates the assembler output with miscellaneous debugging information ๐-dDโ dumps all macro definitions at the end of preprocessing, on top of the normal output ๐ง-dHโ produces a core dump whenever an error occurs ๐-dpโ annotates the assembler output with a comment showing which pattern and alternative is used ๐ฅ the length and cost of each instruction get printed too-dPโ dumps the RTL in the assembler output as a comment before each instruction ๐ซถ this also turns on-dpannotation-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 address output ๐ this makes it way more feasible to usediffon debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations-freport-bugโ if an internal compiler error (ICE) happens, collects and dumps debug information into a temporary file ๐ญ-fdump-unnumberedโ when doing debugging dumps, suppresses instruction numbers and address output โจ this makesdiffway easier for compiler invocations with different options, in particular with and without-g-fdump-unnumbered-linksโ when doing debugging dumps (see-doption above), suppresses instruction numbers for the links to the previous and next instructions in a sequence ๐ง-fdump-ipa-switch,-fdump-ipa-switch-optionsโ controls dumping at various stages of inter-procedural analysis, language tree to 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 possible dumps are:allโ enables all inter-procedural analysis dumpscgraphโ dumps information about call-graph optimization, unused function removal, and inlining decisionsinlineโ dumps after function inlining
Additionally, the options -optimized, -missed, -note, and -all can be provided, with the same meaning as for -fopt-info, defaulting to -optimized. For example, -fdump-ipa-inline-optimized-missed will emit information on callsites that were inlined, along with callsites that were not inlined. By default, the dump will contain messages about successful optimizations (equivalent to -optimized) together with low-level details about the analysis.
-fdump-lang-all,-fdump-lang-switch,-fdump-lang-switch-options,-fdump-lang-switch-options=filenameโ controls the dumping of language-specific information ๐ the options and filename bits work exactly like in the-fdump-treeoption. The switch values accepted are:allโ enables all language-specific dumpsclassโ dumps class hierarchy information ๐ virtual table information is emitted unlessslimis specified. This is C++ only.rawโ dumps the raw internal tree data ๐ this is C++ only too
-fdump-passesโ prints on stderr the list of optimization passes that are turned on and off by the current command-line options ๐ฆ-fdump-statistics-optionโ enables and controls dumping of pass statistics in a separate file ๐ the file name is your source file name with a suffix ending in.statistics, and it's created in the same directory as the output file. With the-optionform,-statssums counters over the whole compilation unit, while-detailsdumps every event as the passes generate them. With no option, the default is to sum counters for each function compiled.-fdump-tree-all,-fdump-tree-switch,-fdump-tree-switch-options,-fdump-tree-switch-options=filenameโ controls dumping at various stages of processing the intermediate language tree to a file ๐ธ if the-optionsform is used, options is a list of-separated options that control the details of the dump. Not every option works with every dump, and the ones that aren't meaningful get ignored. The available options are:addressโ prints the address of each node ๐ this is usually not meaningful, since it changes according to the environment and source file. Its main use is tying a dump file to a debug environment.asmnameโ ifDECL_ASSEMBLER_NAMEhas been set for a given decl, uses that in the dump instead ofDECL_NAME๐ฅ its main use is making it easier to work backward from mangled names in the assembly file.slimโ when dumping front-end intermediate representations, inhibits dumping members of a scope or body of a function just because that scope has been reached. Only dumps those items when they're directly reachable by some other path. When dumping pretty-printed trees, this inhibits dumping the bodies of control structures. When dumping RTL, prints it in slim (condensed) form instead of the default LISP-like representation.rawโ prints a raw representation of the tree. By default, trees are pretty-printed into a C-like representation.detailsโ enables more detailed dumps (not honored by every dump option) ๐ also includes information from the optimization passes.statsโ enables dumping various statistics about the pass (not honored by every dump option).blocksโ enables showing basic block boundaries (disabled in raw dumps).graphโ for each of the other indicated dump files (-fdump-rtl-pass), dumps a representation of the control flow graph suitable for viewing with GraphViz tofile.passid.pass.dot๐ธ๏ธ each function in the file is pretty-printed as a subgraph, so GraphViz can render them all in a single plot. This option currently only works for RTL dumps, and the RTL is always dumped in slim form.vopsโ enables showing virtual operands for every statement.linenoโ enables showing line numbers for statements.uidโ enables showing the unique ID (DECL_UID) for each variable.verboseโ enables showing the tree dump for each statement.ehโ enables showing the EH region number holding each statement.scevโ enables showing scalar evolution analysis details.optimizedโ enables showing optimization information (only available in certain passes).missedโ enables showing missed optimization information (only available in certain passes).noteโ enables other detailed optimization information (only available in certain passes).allโ turns on all options, exceptraw,slim,verboseandlineno.optallโ turns on all optimization options, i.e.,optimized,missed, andnote.
To figure out what tree dumps are available or find the dump for a pass you're interested in, follow these steps:
- Invoke GCC with
-fdump-passesand look in the stderr output for a code that matches the pass you're after. For example, the codestree-evrp,tree-vrp1, andtree-vrp2correspond to the three Value Range Propagation passes. The number at the end tells the distinct invocations of the same pass apart. - To enable creation of the dump file, append the pass code to the
-fdump-option prefix and invoke GCC with it. For example, to enable the dump from the Early Value Range Propagation pass, invoke GCC with the-fdump-tree-evrpoption. Optionally, you may specify the name of the dump file. If you don't specify one, GCC creates 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. Note that the numeric codes are not stable and may change from one version of GCC to another โ ๏ธ
-fopt-info,-fopt-info-options,-fopt-info-options=filenameโ controls optimization dumps from various optimization passes ๐ฅ if the-optionsform is used, options is a list of-separated option keywords that select the dump details and optimizations.
The options can be divided into three groups:
- ๐ options that decide what kinds of messages get printed,
- ๐ options that set how verbose the dump is, and
- โก options that decide which optimizations get included.
Mix and match from each group all you want, because they don't overlap at all ๐ . If there's ever a clash on the command line, the later option wins, so the last one you type is the one that slays ๐.
๐ Message kinds
optimizedโ Prints info whenever an optimization successfully lands โจ. Each pass decides what's relevant, so the vectorizer passes will tell you the source location of loops they successfully vectorize ๐ฆ.missedโ Prints info about optimizations that got missed ๐ฅฒ. Individual passes control what goes into the output.noteโ Verbose info about optimizations, like certain transformations and more detailed messages about decisions ๐ง.allโ Full detail, no skipping! This includesoptimized,missed, andnote๐ฅ.
๐ Dump verbosity
internalsโ By default you only get the "high-level" messages ๐. Turn this on to unlock extra, more detailed messages, which are mostly of interest to GCC developers ๐ค.
๐ฏ Optimization groups
One or more of these keywords can be used to describe a whole group of optimizations:
ipaโ Enables dumps from all interprocedural optimizations ๐.loopโ Enables dumps from all loop optimizations ๐.inlineโ Enables dumps from all inlining optimizations ๐ฆ.ompโ Enables dumps from all OMP (Offloading and Multi Processing) optimizations ๐.vecโ Enables dumps from all vectorization optimizations ๐.optallโ Enables dumps from all optimizations, and it's a superset of 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 tagged as "internals" ๐.
If you give a filename, the dumps from all the applicable optimizations get concatenated into it. Otherwise the dump goes to stderr ๐. You can type as many -fopt-info options as you want, but only one of them can include a filename ๐
. If other filenames sneak in, every option after the first one gets ignored ๐ซ .
Heads up, bestie: the output filename gets overwritten when there are multiple translation units. If you want a combined output from several translation units, use stderr instead โ ๏ธ.
Let's look at some examples ๐ง. This one sends the optimization info to stderr:
gcc -O3 -fopt-info
This one outputs the missed optimization report from all the passes into missed.all:
gcc -O3 -fopt-info-missed=missed.all
And this one prints info about missed optimization opportunities from the vectorization passes to stderr:
gcc -O2 -ftree-vectorize -fopt-info-vec-missed
Note that -fopt-info-vec-missed is equivalent to -fopt-info-missed-vec. The order of the optimization group names and message types listed after -fopt-info doesn't matter ๐.
As another example:
gcc -O3 -fopt-info-inline-optimized-missed=inline.txt
This outputs info about missed optimizations, as well as optimized locations, from all the inlining passes into inline.txt ๐ช.
Finally, consider:
gcc -fopt-info-vec-missed=vec.miss -fopt-info-loop-optimized=loop.opt
Here the two output filenames vec.miss and loop.opt are in conflict, since only one output file is allowed ๐ฅ. In this case, only the first option takes effect and the subsequent options are ignored. Thus only vec.miss is produced, and it contains dumps from the vectorizer about missed opportunities.
๐พ -fsave-optimization-record
Writes a SRCFILE.opt-record.json.gz file detailing what optimizations were performed, for those optimizations that support -fopt-info ๐.
This option is experimental, and the format of the data inside the compressed JSON file is subject to change ๐งช.
It's roughly a machine-readable version of -fopt-info-all, as a collection of messages with source file, line number and column number. Each message also gets these extras:
- 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 is inlined into several different places (which might themselves be inlined), the reader can tell the copies apart ๐ช
- objects identifying the parts of the message that refer to expressions, statements or symbol-table nodes, which of these categories they are, and, when available, their source code location
- the GCC pass that emitted the message, and
- the location in GCC's own code from which the message was emitted
Also, some messages are logically nested within other messages, reflecting implementation details of the optimization passes ๐ชบ.
๐ง -fsched-verbose=n
On targets that use instruction scheduling, this option controls how much debugging output the scheduler prints to the dump files ๐ง.
For n greater than zero, -fsched-verbose outputs the same information as -fdump-rtl-sched1 and -fdump-rtl-sched2. For n greater than one, it also outputs basic block probabilities, detailed ready list information and unit/insn info. For n greater than two, it includes RTL at abort point, control-flow and regions info. And for n over four, -fsched-verbose also includes dependence info ๐งฉ.
๐๏ธ -fenable-kind-pass, -fdisable-kind-pass=range-list
These are a set of options used to explicitly disable or enable optimization passes ๐น๏ธ. They're intended for debugging GCC.
Compiler users should use the regular options for enabling and disabling passes instead โ ๏ธ.
-fdisable-ipa-passโ Disables the IPA pass pass, where pass is the pass name ๐ซ. If the same pass is statically invoked in the compiler multiple times, append a sequential number starting from 1 to the pass name.-fdisable-rtl-pass,-fdisable-rtl-pass=range-listโ Disables the RTL pass pass ๐. The same numbering rule applies: if the pass is statically invoked more than once, append a sequential number starting from 1. range-list is a comma-separated list of function ranges or assembler names. Each range is a number pair separated by a colon, and it's inclusive at both ends. If the range is trivial, the number pair can be simplified to a single number. If the function's call graph node's uid falls within one of the specified ranges, the pass is disabled for that function ๐ฏ. The uid is shown in the function header of a dump file, and you can dump the pass names by using-fdump-passes๐.-fdisable-tree-pass,-fdisable-tree-pass=range-listโ Disables the tree pass pass. See-fdisable-rtlfor the description of option arguments.-fenable-ipa-passโ Enables the IPA pass pass, where pass is the pass name โ . If the same pass is statically invoked in the compiler multiple times, append a sequential number starting from 1 to the pass name.-fenable-rtl-pass,-fenable-rtl-pass=range-listโ Enables the RTL pass pass. See-fdisable-rtlfor option argument description and examples.-fenable-tree-pass,-fenable-tree-pass=range-listโ Enables the tree pass pass. See-fdisable-rtlfor the description of option arguments.
Here are some examples showing these options in action ๐งช:
# disable ccp1 for all functions
-fdisable-tree-ccp1
# disable complete unroll for function whose cgraph node uid is 1
-fenable-tree-cunroll=1
# disable gcse2 for functions at the following ranges [1,1],
# [300,400], and [400,1000]
# disable gcse2 for functions foo and foo2
-fdisable-rtl-gcse2=foo,foo2
# disable early inlining
-fdisable-tree-einline
# disable ipa inlining
-fdisable-ipa-inline
# enable tree full unroll
-fenable-tree-unroll
๐ช -fchecking, -fchecking=n
Enables internal consistency checking ๐. The default depends on the compiler configuration. -fchecking=2 enables further internal consistency checking that might affect code generation โ ๏ธ.
๐ฒ -frandom-seed=string
This option provides a seed that GCC uses in place of random numbers when generating certain symbol names that have to be different in every compiled file ๐. It's also used to place unique stamps in coverage data files and the object files that produce them. You can use the -frandom-seed option to produce reproducibly identical object files ๐.
The string can either be a number (decimal, octal or hex) or an arbitrary string. An arbitrary string gets converted to a number by computing CRC32 ๐ข.
The string should be different for every file you compile ๐ซถ.
๐ -save-temps, -save-temps=cwd
Stores the usual "temporary" intermediate files permanently ๐๏ธ. They get placed in the current directory and named based on the source file. So compiling foo.c with -c -save-temps produces foo.i and foo.s, as well as foo.o ๐ฆ. This creates a preprocessed foo.i output file even though the compiler now normally uses an integrated preprocessor ๐ง.
When you use -save-temps together with the -x command-line option, it's smart enough to avoid overwriting an input source file that has the same extension as an intermediate file ๐. If you want the corresponding intermediate file, just rename the source file before using -save-temps ๐.
If you run GCC in parallel ๐ญ on files that share a base name, like foo.c, in different subdirectories, or the same file compiled for several output destinations, the compilers can totally step on each other and overwrite each other's temp files ๐. Check this out:
gcc -save-temps -o outdir1/foo.o indir1/foo.c&
gcc -save-temps -o outdir2/foo.o indir2/foo.c&
Heads up, bestie ๐จ: this can end withfoo.iandfoo.obeing written to at the same time by both compilers. Not a vibe.
-save-temps=objโ Keeps the usual "temporary" intermediate files forever ๐พโจ. If you use-o, the temp files get named after the object file. If you don't use-o,-save-temps=objacts exactly like-save-temps๐ซถ.
For example, these commands:
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
create foo.i, foo.s, dir/xbar.i, dir/xbar.s, dir2/yfoobar.i, dir2/yfoobar.s, and dir2/yfoobar.o. Iconic organization ๐๐.
-time[=file]โ Reports the CPU time each subprocess in the compilation sequence takes โฑ๏ธ. For C source files, that's the compiler proper and the assembler, plus the linker if you're linking ๐.
If you don't give an output file, the output looks like this:
# cc1 0.12 0.01
# as 0.00 0.01
The first number on each line is the "user time", which is the time spent running the program itself ๐ง . The second number is the "system time", which is the time spent in operating system routines on the program's behalf ๐ป. Both numbers are in seconds โญ.
If you do give an output file, the output gets appended to that file, and it looks like this:
0.12 0.01 cc1 <options>
0.00 0.01 as <options>
Here the "user time" and "system time" get moved in front of the program name, and the options passed to the program are shown too. That way you can later figure out which file was being compiled and with which 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's name comes from adding.gkdto the compilation output file name.-fcompare-debug[=*opts*]โ If compilation doesn't hit any errors, GCC runs the compiler a second time ๐. This second run gets opts and-fcompare-debug-secondadded to its arguments. It dumps the final internal representation in both compilations and prints an error if they differ ๐ฅบ.
If you leave out the equal sign, the default -gtoggle is used.
The environment variable GCC_COMPARE_DEBUG ๐ธ, if it's defined, non-empty, and nonzero, implicitly enables -fcompare-debug. If GCC_COMPARE_DEBUG is defined 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 the same as -fno-compare-debug ๐ซ. That one turns off the dumping of the final representation and the second compilation, and it even stops GCC_COMPARE_DEBUG from taking effect. Hard stop ๐.
To check for full coverage during -fcompare-debug testing, set GCC_COMPARE_DEBUG to -fcompare-debug-not-overridden. GCC rejects that as an invalid option in any real compilation (as opposed to preprocessing, assembly, or linking) ๐
โโ๏ธ. If you just want a warning instead, setting GCC_COMPARE_DEBUG to -w%n-fcompare-debug not overridden will do the trick โจ.
-fcompare-debug-secondโ This is passed to the compiler implicitly for the second compilation requested by-fcompare-debug๐ช. It comes along with options that silence warnings, and it leaves out any other options that would make the compiler write output to files or to standard output as a side effect ๐. During that second compilation, dump files and preserved temporary files get the extra.gkextension, so they don't overwrite the ones from the first run ๐ .
When you pass this option to the compiler driver, the first compilation gets skipped. That makes it pretty much only useful for debugging the compiler itself ๐ง.
-gtoggleโ Turns off debug info generation if leaving this option out would generate it. Otherwise, it turns debug info on at level 2 ๐. Where you put it on the command line doesn't matter. It takes effect after all the other options are processed, and it only does its thing once, no matter how many times you pass it ๐ฏ. It's mainly meant to be used with-fcompare-debug.-fvar-tracking-assignments-toggleโ Toggles-fvar-tracking-assignments, the same way-gtoggletoggles-g๐ฆ.-Qโ Makes the compiler print out each function name as it gets compiled, and print some statistics about each pass when it finishes ๐.-ftime-reportโ Makes the compiler print some statistics about the time each pass consumed when it finishes โฐ.-ftime-report-detailsโ Records the time consumed by infrastructure parts separately for each pass ๐งฉ.-fira-verbose=nโ Controls how verbose the dump file for the integrated register allocator is. The default value is5. If the value n is greater than or equal to10, the dump output goes to stderr in the same format as n minus 10 ๐.-flto-reportโ Prints a report with internal details on how the link-time optimizer works ๐. What's in this report changes from version to version. It's meant for GCC developers, for when they're processing object files in LTO mode (via-flto) ๐ ๏ธ.
Disabled by default.
-flto-report-wpaโ Like-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 before or after interprocedural optimization ๐.-fprofile-reportโ Makes the compiler print some statistics about the consistency of the (estimated) profile and the effect of individual passes ๐.-fstack-usageโ Makes the compiler output stack usage info for your program, broken down per function ๐ฅ. The dump filename is made by appending.suto the auxname. The auxname comes from the output file name if you explicitly specified one and it's not an executable. Otherwise, it's the basename of the source file ๐. Each entry has three fields:- The name of the function.
- A number of bytes.
- One or more qualifiers: "static", "dynamic", "bounded".
The "static" qualifier means the function manages the stack statically ๐งฑ. A fixed number of bytes gets allocated for the frame on function entry and released on function exit, and no other stack adjustments get made in the function. The second field is this fixed number of bytes.
The "dynamic" qualifier means the function manages the stack dynamically ๐. On top of the static allocation above, stack adjustments happen in the body of the function, like pushing and popping arguments around function calls. If the "bounded" qualifier is also there, the amount of these adjustments is bounded at compile time, and the second field is an upper bound on the total stack used by the function โ . If it's not present, the amount of 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_bound:upper_boundtuples, which set the lower and upper bound of each debug counter name. Thelower_boundis optional and is zero-initialized if it isn't set. All debug counters start with an upper bound of"UINT_MAX", sodbg_cntalways returns true unless this option sets the upper bound ๐. For example, with-fdbg-cnt=dce:2:4,tail_call:10,dbg_cnt(dce)only returns true for the third and fourth invocations. 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 for the multilib selected by any other switches on the command line ๐. This directory is supposed to exist inGCC_EXEC_PREFIX๐ท.-print-multi-libโ Prints the mapping from multilib directory names to the compiler switches that enable them ๐๏ธ. The directory name is separated from the switches by;. Each switch starts with an@instead of a-, and there are no spaces between multiple switches. This is supposed to make shell processing easier ๐.-print-multi-os-directoryโ Prints the path to the OS libraries for the selected multilib, relative to somelibsubdirectory ๐. If the OS libraries live in thelibsubdirectory and no multilibs are used, this is usually just.. If the OS libraries live inlibsuffixsibling directories, it prints things like../lib64,../lib, or../lib32. If they live inlib/subdirsubdirectories, it prints things likeamd64,sparcv9, orev6๐งฉ.-print-multiarchโ Prints the path to the OS libraries for the selected multiarch, relative to somelibsubdirectory ๐ฆ.-print-prog-name=*program*โ Works like-print-file-name, but searches for a program such ascpp๐.-print-libgcc-file-nameโ Same as-print-file-name=libgcc.a๐.
This is useful when you use -nostdlib or -nodefaultlibs but you still want to link with libgcc.a ๐ซถ. You can do:
gcc -nostdlib <files>... `gcc -print-libgcc-file-name`
-print-search-dirsโ okay so this one is a lifesaver ๐ง It prints the name of the configured installation directory AND the list of program and library directories gcc searches, and then it just stops. Nothing else gets done. Literally that's it ๐
This one is super handy when gcc throws 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โ this prints the target sysroot directory used during compilation ๐ธ It's the one set either at configure time or with the--sysrootoption, and it might come with an extra suffix depending on your compilation options. If no target sysroot is set, this option prints nothing at all. Silent queen behavior ๐-print-sysroot-headers-suffixโ prints the suffix that gets added to the target sysroot when gcc goes searching for headers ๐ If the compiler wasn't configured with a suffix, you'll get an error instead. And again, it won't do anything else โจ-dumpmachineโ prints the compiler's target machine, likei686-pc-linux-gnu๐ฆ Then it stops. No extra steps, no drama ๐-dumpversionโ prints the compiler version, like3.0,6.3.0or7๐ Then it stops too. This is the version used in filesystem paths and specs, and depending on how the compiler was configured, it can be one number (the major version), two numbers separated by a dot (major and minor), or three numbers separated by dots (major, minor and patchlevel) ๐-dumpfullversionโ prints the full compiler version and then stops ๐ The output is always three numbers separated by dots: major, minor and patchlevel. Always. No exceptions bestie ๐-dumpspecsโ prints the compiler's built-in specs and then stops ๐ This one is used when GCC itself is being built, so it's kind of an insider thing ๐
๐ Machine-Dependent Options ๐
Every target machine GCC supports can have its own options ๐ง For example, you can compile for a particular processor variant or ABI, or control optimizations that are specific to that machine. By convention, the names of machine-specific options start with -m ๐
Some configurations of the compiler also support extra target-specific options, usually so they can stay compatible with other compilers on the same platform ๐ซถ
๐ฆ AArch64 Options ๐ฆ
These options are defined for AArch64 implementations โจ
-mabi=nameโ generates code for the specified data model ๐ The allowed values areilp32, which is a SysV-like data model whereint,long intand pointers are 32 bits, andlp64, which is also SysV-like but whereintis 32 bits whilelong intand pointers are 64 bits ๐ธ
The default depends on the specific target configuration.
๐ญ Heads up: the LP64 and ILP32 ABIs are NOT link-compatible. You must compile your entire program with the same ABI, and link it with a compatible set of libraries.
-mbig-endianโ generates big-endian code ๐ This is the default when GCC is configured for anaarch64_be-*-*target.-mgeneral-regs-onlyโ generates code that only uses the general-purpose registers ๐ This stops the compiler from using 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, so you get it automatically โจ-mcmodel=largeโ generates code for the large code model ๐ It makes no assumptions about the addresses and sizes of sections, which is very chill but also very limited: programs can be statically linked only ๐-mstrict-align,-mno-strict-alignโ these let you avoid (-mstrict-align) or allow (-mno-strict-align) generating memory accesses that might not be aligned on a natural object boundary, as described in the architecture specification ๐งฑ-momit-leaf-frame-pointer,-mno-omit-leaf-frame-pointerโ these omit (-momit-leaf-frame-pointer) or keep (-mno-omit-leaf-frame-pointer) the frame pointer in leaf functions ๐ The omit behavior is the default.-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ this generates stack protection code using a canary atguard๐ก๏ธ The supported locations areglobal(for a global canary) orsysreg(for a canary in an appropriate system register).
With the sysreg 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 for this. It's entirely for use within the Linux kernel, so don't go sprinkling it everywhere.
-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ this is the exact same entry again, so the same deal applies ๐ It generates stack protection code using a canary atguard. The supported locations areglobalfor a global canary orsysregfor a canary in an appropriate system register.
With the sysreg choice, -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset furthermore specify which system register to use as the 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, so it's the one you get if you don't pick anything ๐-mtls-dialect=traditionalโ uses traditional TLS as the thread-local storage mechanism for dynamic accesses of TLS variables ๐ฐ๏ธ-mtls-size=sizeโ specifies the bit size of immediate TLS offsets ๐ The valid values are12,24,32and48. Heads up: this option needs binutils 2.26 or newer โ ๏ธ-mfix-cortex-a53-835769,-mno-fix-cortex-a53-835769โ enables (-mfix-cortex-a53-835769) or disables (-mno-fix-cortex-a53-835769) the workaround for ARM Cortex-A53 erratum number 835769 ๐ ๏ธ The workaround involves inserting a NOP instruction between memory instructions and 64-bit integer multiply-accumulate instructions.-mfix-cortex-a53-843419,-mno-fix-cortex-a53-843419โ enables or disables the workaround for ARM Cortex-A53 erratum number 843419 ๐ง This erratum workaround is made at link time, so this option only passes the corresponding flag to the linker ๐-mlow-precision-recip-sqrt,-mno-low-precision-recip-sqrtโ enables or disables the reciprocal square root approximation ๐งฎ This only does anything if-ffast-mathor-funsafe-math-optimizationsis also used. When it's on, reciprocal square root results lose precision, down to about 16 bits for single precision and 32 bits for double precision ๐-mlow-precision-sqrt,-mno-low-precision-sqrtโ enables or disables the square root approximation ๐ This only has an effect if-ffast-mathor-funsafe-math-optimizationsis also used. When enabled, square root results drop to about 16 bits for single precision and 32 bits for double precision. If you enable it, it implies-mlow-precision-recip-sqrttoo ๐ช-mlow-precision-div,-mno-low-precision-divโ enables or disables the division approximation โ This only has an effect if-ffast-mathor-funsafe-math-optimizationsis also used. When enabled, division results drop to about 16 bits for single precision and 32 bits for double precision ๐ฒ-mtrack-speculation,-mno-track-speculationโ enables or disables generating additional code that tracks speculative execution through conditional branches ๐ต๏ธ The tracking state can then be used by the compiler when expanding calls to__builtin_speculation_safe_copy, so it can generate a more efficient code sequence ๐ง-moutline-atomics,-mno-outline-atomicsโ enables or disables calls to out-of-line helpers that implement atomic operations โก At runtime, these helpers figure out whether the LSE instructions from ARMv8.1-A can be used. If they can't, they fall back to the load/store-exclusive instructions that are present in the base ARMv8.0 ISA ๐งฉ
This option only applies when 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 ๐ซ
-march=nameโ specifies the name of the target architecture and, optionally, one or more feature modifiers ๐๏ธ This option has the form-march=arch{+[no]feature}*.
The permissible values for arch are armv8-a, armv8.1-a, armv8.2-a, armv8.3-a, armv8.4-a, armv8.5-a or native ๐
The value armv8.5-a implies armv8.4-a and enables compiler support for the ARMv8.5-A architecture extensions ๐
The value armv8.4-a implies armv8.3-a and enables compiler support for the ARMv8.4-A architecture extensions ๐
The value armv8.3-a implies armv8.2-a and enables compiler support for the ARMv8.3-A architecture extensions ๐
The value armv8.2-a implies armv8.1-a and enables compiler support for the ARMv8.2-A architecture extensions ๐
The value armv8.1-a implies armv8-a and enables compiler support for the ARMv8.1-A architecture extension. In particular, it enables the +crc, +lse, and +rdma features ๐
The value native is available on native AArch64 GNU/Linux and makes the compiler pick the architecture of the host system. This option has no effect if the compiler is unable to recognize the architecture of the host system, ๐ซ
The permissible values for feature are listed in the sub-section on aarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. Where conflicting feature modifiers are specified, the right-most feature is used ๐
GCC uses name to determine what kind of instructions it can 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 implementing the target architecture ๐ธ
โจ OPTIONS โจ
-mtune=nameโ okay bestie, this one tells GCC which target processor to tune the performance of your code for ๐ The valid values aregeneric,cortex-a35,cortex-a53,cortex-a55,cortex-a57,cortex-a72,cortex-a73,cortex-a75,cortex-a76,ares,exynos-m1,emag,falkor,neoverse-e1,neoverse-n1,neoverse-n2,neoverse-v1,neoverse-512tvb,qdf24xx,saphira,phecda,xgene1,vulcan,octeontx,octeontx81,octeontx83,a64fx,thunderx,thunderxt88,thunderxt88p1,thunderxt81,tsv110,thunderxt83,thunderx2t99,zeus,cortex-a57.cortex-a53,cortex-a72.cortex-a53,cortex-a73.cortex-a35,cortex-a73.cortex-a53,cortex-a75.cortex-a55,cortex-a76.cortex-a55, andnative๐ฆ
The dotted pairs cortex-a57.cortex-a53, cortex-a72.cortex-a53, cortex-a73.cortex-a35, cortex-a73.cortex-a53, cortex-a75.cortex-a55, and cortex-a76.cortex-a55 are the big.LITTLE combos ๐ง They tell GCC to tune for a big.LITTLE system, so yeah, iykyk.
neoverse-512tvb is giving very specific energy โจ It means GCC tunes for Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits per cycle. Translation: those cores can run 4 128-bit Advanced SIMD arithmetic instructions a cycle, plus an equivalent number of SVE arithmetic instructions a cycle (2 for 256-bit SVE, 4 for 128-bit SVE). It's more general than tuning for one specific core like Neoverse V1, but more specific than the default tuning down below ๐ธ
On native AArch64 GNU/Linux systems, the value native tunes performance to whatever host system you're on ๐ฅ If the compiler can't recognize the processor of the host system, this option just has no effect. No drama.
If none of -mtune=, -mcpu=, or -march= are specified, the code gets tuned to perform well across a range of target processors ๐
This option cannot be suffixed by feature modifiers ๐
-mcpu=nameโ this is the target processor name, and it can be suffixed by one or more feature modifiers ๐ The form is-mcpu=cpu{+[no]feature}*, and the permissible values forcpuare the same ones you get for-mtune. For the permissiblefeaturevalues, check out the sub-section onaarch64-feature-modifiers,,-march and -mcpu Feature Modifiers. If you specify conflicting feature modifiers, the right-most one wins, periodt ๐
GCC uses name to figure out what kind of instructions it's allowed to emit when generating assembly code (same as -march), and to pick the target processor it tunes performance for (same as -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 refer to one specific core. It refers to all Neoverse cores that (a) implement SVE and (b) have a total vector bandwidth of 512 bits a cycle โจ Unless you override it with -march, -mcpu=neoverse-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 forstringare not guaranteed to stay consistent across releases.
โ ๏ธ This option is only intended to be useful when developing GCC. Don't go poking at it in your everyday builds, bestie ๐ญ
-mverbose-cost-dumpโ turns on verbose cost model dumping in the debug dump files ๐ It's provided for debugging the compiler, so it's really for compiler nerds.-mpc-relative-literal-loads,-mno-pc-relative-literal-loadsโ these enable or disable PC-relative literal loads ๐ With this on, literal pools get accessed with 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 which functions get return address signing ๐ The permissible values arenone, which turns return address signing off;non-leaf, which enables pointer signing for functions that aren't leaf functions; andall, which enables pointer signing for all functions. The default isnone.
๐ This option has been deprecated by -mbranch-protection. Switch over when you can!
-mbranch-protection=none|standard|pac-ret[+leaf]|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, which means signing functions that save the return address to memory (non-leaf functions practically always do this) using the a-key. The optionalleafargument extends the signing to include leaf functions.btiturns on the branch target identification mechanism.-mharden-sls=optsโ enables compiler hardening against straight line speculation (SLS) ๐งฑoptsis a comma-separated list of the following options:retbrblr
On top of that, -mharden-sls=all enables all SLS hardening, and -mharden-sls=none disables all of it.
-msve-vector-bits=bitsโ sets the number of bits in an SVE vector register ๐ This option only has an effect when SVE is enabled.
GCC supports two forms of SVE code generation. There's "vector-length agnostic" output that works with any size of vector register, and "vector-length specific" output that lets GCC make assumptions about the vector length when that helps optimization ๐ง The possible values of bits are scalable, 128, 256, 512, 1024, and 2048. Specifying scalable selects vector-length agnostic output. Right now, -msve-vector-bits=128 also generates vector-length agnostic output. All other values generate vector-length specific code. These values might change in future releases, so the only value you should rely on for code that's portable across different hardware SVE vector lengths is scalable.
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. It's enabled by default for-march=armv8.4-a. Using this option with architectures prior to Armv8.2-A is not supported ๐ซrcpcโ enables the RcPc extension. This doesn't change code generation from GCC, but it 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. This option only enables the extension at the assembler level and doesn't affect code generation.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.
Heads up on the chain reactions ๐ Enabling crypto implies aes, sha2, and simd, which in turn implies fp. Going the other way, nofp implies nosimd, which implies nocrypto, noaes, and nosha2.
Adapteva Epiphany Options
These -m options are defined for Adapteva Epiphany ๐
-mhalf-reg-fileโ don't allocate any register in the range"r32"..."r63". That lets your code run on hardware variants that lack these registers ๐ง-mprefer-short-insn-regsโ preferentially allocates registers that allow short instruction generation. This can increase the instruction count, so it may either reduce or increase overall code size.-mbranch-cost=numโ okay so this sets the cost of branches to roughlynum"simple" instructions ๐ธ. It's only a heuristic, though, so don't expect the same results across releases ๐.-mcmoveโ turns on the generation of conditional moves โจ.-mnops=numโ emitsnumNOPs before every other instruction that gets generated ๐ง.-mno-soft-cmpsfโ for single-precision floating-point comparisons, this emits anfsubinstruction and tests the flags. It's faster than a software comparison, but it can give incorrect results when NaNs are involved, or when two different small numbers get compared and their difference is calculated as zero ๐ญ. The default is-msoft-cmpsf, which uses software comparisons that are slower but IEEE-compliant ๐.-mstack-offset=numโ sets the offset between the top of the stack and the stack pointer. E.g., a value of8means the eight bytes in the range "sp+0...sp+7" can be used by leaf functions without stack allocation ๐ฆ. Values other than8or16are untested and unlikely to work ๐. Also, this option changes the ABI, so compiling a program with a different stack offset than the libraries were built with generally does not work ๐ซ.
Heads up bestie: this option changes the ABI! If you want to test whether a different stack offset gives you better code, this is a fine place to poke around. But if you want to build programs that actually work with a different stack offset, the recommended move is to configure the toolchain with the appropriate --with-stack-offset=num option ๐ฅ.
-mno-round-nearestโ makes the scheduler assume the rounding mode has been set to truncating ๐. The default is-mround-nearest.-mlong-callsโ if an attribute doesn't say otherwise, this assumes all calls might be beyond the offset range of the "b" / "bl" instructions. So it loads the function address into a register before doing a (otherwise direct) call ๐. This is the default.-mshort-callsโ if an attribute doesn't say otherwise, this assumes all direct calls are in range of the "b" / "bl" instructions, so those instructions get used for direct calls ๐. The default is-mlong-calls.-msmall16โ assumes addresses can be loaded as 16-bit unsigned values ๐. This doesn't apply to function addresses that have-mlong-callssemantics in effect.-mfp-mode=modeโ sets the prevailing mode of the floating-point unit โจ. This decides which floating-point mode gets provided and expected at function call and return time. Matching this to the mode you mostly need at function start can make your programs smaller and faster by avoiding unnecessary mode switches ๐.
mode can be set to one of the following values:
callerโ any mode at function entry is valid, and it gets retained or restored when the function returns and when it calls other functions ๐ซถ. This one is great for libraries or other compilation units you want to drop into programs with different prevailing FPU modes. Being able to use a single object file is worth the extra size and speed overhead of any mode switching, compared with a more specific choice of prevailing FPU mode ๐ .truncateโ the mode used for floating-point calculations with truncating (i.e. round towards zero) rounding mode. That includes conversion from floating point to integer ๐ฆ.round-nearestโ the mode used for floating-point calculations with round-to-nearest-or-even rounding mode ๐ธ.intโ the mode used to perform integer calculations in the FPU, e.g. integer multiply, or integer multiply-and-accumulate ๐งฎ.
The default is -mfp-mode=caller ๐.
-mno-split-lohi,-mno-postinc,-mno-postmodifyโ code generation tweaks that disable, respectively, splitting of 32-bit loads, generation of post-increment addresses, and generation of post-modify addresses ๐. The defaults aremsplit-lohi,-mpost-inc, and-mpost-modify.-mnovect-doubleโ changes the preferred SIMD mode toSImode๐. The default is-mvect-double, which usesDImodeas the preferred SIMD mode.-max-vect-align=numโ the maximum alignment for SIMD vector mode types ๐.nummay be4or8, and the default is8. Heads up: this is an ABI change, even though lots of library function interfaces are unaffected as long as they don't use SIMD vector modes in places that affect the size and/or alignment of relevant types ๐ฅ.-msplit-vecmove-earlyโ splits vector moves into single word moves before reload ๐ง. In theory this can give better register allocation, but so far the reverse seems to be the usual outcome ๐ญ.-m1reg-regโ specifies a register to hold the constant-1, which makes loading small negative constants and certain bitmasks faster โญ. Allowable values forregarer43andr63, which specify using that register as a fixed register, andnone, which means no register is used for this purpose ๐. The default is-m1reg-none.
โจ AMD GCN Options โจ
These options are defined specifically for the AMD GCN port ๐.
-march=gpu,-mtune=gpuโ sets the architecture type or tuning forgpu๐ฅ. Supported values forgpuare:fijiโ compiles for GCN3 Fiji devices (gfx803) ๐.gfx900โ compiles for GCN5 Vega 10 devices (gfx900) ๐ .
-mstack-size=bytesโ specifies how many bytes of stack space get requested for each GPU thread (wave-front) ๐ซถ. Beware that there may be many threads and limited memory available ๐. The size of the stack allocation may also have an impact on run-time performance. The default is 32KB when using OpenACC or OpenMP, and 1MB otherwise โจ.
๐ธ ARC Options ๐ธ
The following options control the architecture variant that code is being compiled for ๐ฆ.
-mbarrel-shifterโ generates instructions supported by the barrel shifter ๐. This is the default unless-mcpu=ARC601or-mcpu=ARCEMis in effect.-mjli-alwaysโ forces a function to be called using thejli_sinstruction ๐ง. This option is valid only for the ARCv2 architecture.-mcpu=cpuโ sets the architecture type, register usage, and instruction scheduling parameters forcpu๐. There are also shortcut alias options for backward compatibility and convenience. Supported values forcpuare:arc600โ compiles for ARC600. Aliases:-mA6,-mARC600.arc601โ compiles for ARC601. Alias:-mARC601.arc700โ compiles for ARC700. Aliases:-mA7,-mARC700. This is the default when configured with--with-cpu=arc700๐.arcemโ compiles for ARC EM ๐.archsโ compiles for ARC HS ๐.emโ compiles for ARC EM CPU with no hardware extensions ๐.em4โ compiles for ARC EM4 CPU ๐งฎ.em4_dmipsโ compiles for ARC EM4 DMIPS CPU ๐ซถ.em4_fpusโ compiles for ARC EM4 DMIPS CPU with the single-precision floating-point extension โจ.em4_fpudaโ compiles for ARC EM4 DMIPS CPU with single-precision floating-point and double assist instructions ๐ฅ.hsโ compiles for ARC HS CPU with no hardware extensions except the atomic instructions ๐ .hs34โ compiles for ARC HS34 CPU โญ.hs38โ compiles for ARC HS38 CPU ๐ฆ.hs38_linuxโ compiles for ARC HS38 CPU with all hardware extensions on ๐ธ.arc600_normโ compiles for ARC 600 CPU with "norm" instructions enabled ๐.arc600_mul32x16โ compiles for ARC 600 CPU with "norm" and 32x16-bit multiply instructions enabled ๐.arc600_mul64โ compiles for ARC 600 CPU with "norm" and "mul64"-family instructions enabled ๐ง.arc601_normโ compiles for ARC 601 CPU with "norm" instructions enabled ๐.arc601_mul32x16โ compiles for ARC 601 CPU with "norm" and 32x16-bit multiply instructions enabled ๐.arc601_mul64โ compiles for ARC 601 CPU with "norm" and "mul64"-family instructions enabled ๐.nps400โ compiles for ARC 700 on NPS400 chip ๐.em_miniโ compiles for 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โ disables "lr" and "sr" instructions from using FPX extension aux registers โจ.-meaโ generates extended arithmetic instructions ๐ฅ. Currently only "divaw", "adds", "subs", and "sat16" are supported. This is always enabled for-mcpu=ARC700๐ .-mno-mpyโ does not generate "mpy"-family instructions for ARC700 โญ. Deprecated bestie, so maybe don't reach for it ๐.-mmul32x16โ generates 32x16-bit multiply and multiply-accumulate instructions ๐ฆ.-mmul64โ generates "mul64" and "mulu64" instructions ๐ธ. Only valid for-mcpu=ARC600.-mnormโ generates "norm" instructions ๐. This is the default if-mcpu=ARC700is in effect.-mspfp,-mspfp-compactโ generates single-precision FPX instructions, tuned for the compact implementation ๐.-mspfp-fastโ generates single-precision FPX instructions, tuned for the fast implementation ๐ง.-msimdโ enables generation of ARC SIMD instructions via target-specific builtins ๐. Only valid for-mcpu=ARC700.-msoft-floatโ this option is ignored ๐; it's only provided for compatibility purposes. Software floating-point code is emitted by default, and this default can be overridden by FPX options:-mspfp,-mspfp-compact, or-mspfp-fastfor single precision, and-mdpfp,-mdpfp-compact, or-mdpfp-fastfor double precision ๐.-mswapโ generates "swap" instructions ๐.-matomicโ enables use of the locked load/store conditional extension to implement atomic memory built-in functions ๐. Not available for ARC 6xx or ARC EM cores.-mdiv-remโ enables "div" and "rem" instructions for ARCv2 cores ๐.-mcode-densityโ enables code density instructions for ARC EM ๐งฎ. This option is on by default for ARC HS.-mll64โ enables double load/store operations for ARC HS cores ๐ซถ.-mtp-regno=regnoโ specifies the thread pointer register number โจ.-mmpy-option=multoโ Okay so this one picks your multiplier design for ARCv2 code ๐งฎโจ You can passmultoas either a string or a number, andwlh1is the default. Here's the full menu:0ornoneโ No multiplier available, bestie ๐1orwโ 16x16 multiplier, fully pipelined. You getmpywandmpyuw๐ฅ2orwlh1โ 32x32 multiplier, fully pipelined (1 stage). This one also unlocksmpy,mpyu,mpym,mpymu, andmpy_s๐3orwlh2โ 32x32 multiplier, fully pipelined (2 stages). Same extras as above:mpy,mpyu,mpym,mpymu, andmpy_s๐ฆ4orwlh3โ Two 16x16 multipliers, blocking and sequential. Also unlocksmpy,mpyu,mpym,mpymu, andmpy_s๐ธ5orwlh4โ One 16x16 multiplier, blocking and sequential. Same bonus list:mpy,mpyu,mpym,mpymu, andmpy_sโจ6orwlh5โ One 32x4 multiplier, blocking and sequential. Also gives youmpy,mpyu,mpym,mpymu, andmpy_s๐7orplus_dmpyโ ARC HS SIMD support ๐8orplus_macdโ ARC HS SIMD support ๐9orplus_qmacwโ ARC HS SIMD support โญ
This option is only available for ARCv2 cores, so don't try it on the others ๐ โโ๏ธ
-mfpu=fpuโ This one turns on specific floating-point hardware extensions for ARCv2 cores ๐ฆ Here are thefpuvalues you can use:fpusโ Single-precision floating-point hardware extensions, enabled ๐fpudโ Double-precision floating-point hardware extensions. The single-precision extension comes along for the ride too. Not available for ARC EM ๐fpudaโ Double-precision floating-point using double-precision assist instructions. The single-precision extension is also enabled. This one is only for ARC EM ๐fpuda_divโ Double-precision floating-point using double-precision assist instructions. The single-precision, square-root, and divide extensions are also enabled. ARC EM only ๐ฅfpuda_fmaโ Double-precision floating-point using double-precision assist instructions. The single-precision and fused multiply and add extensions are also enabled. ARC EM only โจfpuda_allโ Double-precision floating-point using double-precision assist instructions. Every single-precision floating-point extension is also enabled. ARC EM only ๐fpus_divโ Single-precision floating-point, plus the square-root and divide extensions ๐ธfpud_divโ Double-precision floating-point, plus the square-root and divide extensions. This one includesfpus_div. Not available for ARC EM ๐fpus_fmaโ Single-precision floating-point, plus the fused multiply and add extensions ๐งfpud_fmaโ Double-precision floating-point, plus the fused multiply and add extensions. This one includesfpus_fma. Not available for ARC EM ๐fpus_allโ Every single-precision floating-point hardware extension ๐fpud_allโ Every single- and double-precision floating-point hardware extension. Not available for ARC EM ๐ซถ
-mirq-ctrl-saved=register-range, blink, lp_countโ This tells the processor which general-purpose registers to automatically save and restore on interrupt entry and exit. Theregister-rangeis two registers separated by a dash. The range always starts withr0, and the upper limit is thefpregister.blinkandlp_countare optional. This option is only valid for ARC EM and ARC HS cores ๐งก-mrgf-banked-regs=numberโ This sets how many registers get replicated in the second register bank when you enter a fast interrupt. Fast interrupts are the ones with the highest priority level, P0. They only savePCandSTATUS32to skip memory transactions during entry and exit, so use this when you're doing fast interrupts on an ARC V2 family processor. Permitted values are4,8,16, and32๐ฆ-mlpc-width=widthโ Sets the width of thelp_countregister. Valid widths are 8, 16, 20, 24, 28, and 32 bits, and the default is fixed at 32 bits. If the width is less than 32, the compiler won't try to turn your loops into the zero-delay loop mechanism unless it knowslp_countcan actually hold the loop-counter value. Depending on the width, the compiler and run-time library might still use the loop mechanism for various needs. This option defines the macro__ARC_LPC_WIDTH__with the value ofwidth๐งฎ-mrf16โ Tells the compiler to generate code for a 16-entry register file. This option defines the__ARC_RF16__preprocessor macro ๐-mbranch-indexโ Enables the use ofbiorbihinstructions to implement jump tables โจ
These next options are passed through to the assembler, and they also define preprocessor macro symbols ๐
-mdsp-packaโ Passed down to the assembler to enable the DSP Pack A extensions. It also sets the preprocessor symbol__Xdsp_packa. This option is deprecated ๐-mdvbfโ Passed down to the assembler to enable the dual Viterbi butterfly extension. It also sets the preprocessor symbol__Xdvbf. This option is deprecated ๐-mlockโ Passed down to the assembler to enable the locked load/store conditional extension. It also sets the preprocessor symbol__Xlock๐-mmac-d16โ Passed down to the assembler. It also sets the preprocessor symbol__Xxmac_d16. This option is deprecated ๐-mmac-24โ Passed down to the assembler. It also sets the preprocessor symbol__Xxmac_24. This option is deprecated ๐-mrtscโ Passed down to the assembler to enable the 64-bit time-stamp counter extension instruction. It also sets the preprocessor symbol__Xrtsc. This option is deprecated ๐-mswapeโ Passed down to the assembler to enable the swap byte ordering extension instruction. It also sets the preprocessor symbol__Xswape๐-mtelephonyโ Passed down to the assembler to enable dual- and single-operand instructions for telephony. It also sets the preprocessor symbol__Xtelephony. This option is deprecated ๐-mxyโ Passed down to the assembler to enable the XY memory extension. It also sets the preprocessor symbol__Xxy๐ง
These options control how the assembly code gets annotated ๐
-misizeโ Annotates assembler instructions with estimated addresses ๐-mannotate-alignโ Explains which alignment considerations led to the decision to make an instruction short or long ๐ค
These options are passed through to the linker ๐
-marclinuxโ Passed through to the linker to specify thearclinuxemulation. This one is on 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 thearclinux_profemulation. This one is on by default in tool chains built forarc-linux-uclibcandarceb-linux-uclibctargets when profiling is requested ๐ธ
These options control the semantics of the generated code ๐ง
-mlong-callsโ Generates calls as register indirect calls, so you get access to the full 32-bit address range ๐-mmedium-callsโ Doesn't use less than a 25-bit addressing range for calls, which is the offset available for an unconditional branch-and-link instruction. Conditional execution of function calls is suppressed so the 25-bit range can be used, instead of the 21-bit range you'd get with conditional branch-and-link. This is the default for tool chains built forarc-linux-uclibcandarceb-linux-uclibctargets ๐ฆ-G numโ Puts definitions of externally-visible data in a small data section if that data is no bigger thannumbytes. The default value ofnumis4for any ARC configuration, or8when you have double load/store operations ๐ฆ-mno-sdataโ Don'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 ๐โโ๏ธ
These options fine-tune code generation ๐
-malign-callโ Does alignment optimizations for call instructions โจ-mauto-modify-regโ Enables the use of pre/post modify with register displacement ๐ง-mbbit-peepholeโ Enables bbit peephole2 ๐งฉ-mno-brccโ This disables a target-specific pass inarc_reorgthat generates compare-and-branch (brcc) instructions. It has no effect on the generation of these instructions when they're driven by the combiner pass ๐ โโ๏ธ-mcase-vector-pcrelโ Uses PC-relative switch case tables to enable case table shortening. This is the default for-Os๐ท-mcompact-casesiโ Enables the compactcasesipattern. This is the default for-Os, and it's only available for ARCv1 cores. This option is deprecated ๐-mno-cond-execโ Disables the ARCompact-specific pass that generates conditional execution instructions ๐
Okay so the ARC port has its own special pass, and bestie, it's giving main character energy ๐
. The target-independent conditional execution pass is kinda lacking because of delay slot scheduling and how operand numbers, literal sizes, instruction lengths, and conditional execution support all interact ๐ญ. So ARC runs an extra pass that hunts for more conditional execution chances after register allocation, branch shortening, and delay slot scheduling are done โจ. It usually (not always!) makes performance and code size better, but it costs extra compile time, which is why there's an option to switch it off ๐ซถ. If your call instructions are going out of their allowed offset range because they got conditionalized, try -mmedium-calls instead ๐ฆ.
-mearly-cbranchsiโ Turns on pre-reload use of thecbranchsipattern ๐ธ.-mexpand-adddiโ Expandsadddi3andsubdi3at RTL generation time intoadd.f,adcetc. โ ๏ธ This one is deprecated, so it's on its way out ๐.-mindexed-loadsโ Turns on indexed loads ๐. Heads up, this can be problematic, because some optimizers then assume indexed stores exist, and they don't on this target ๐.-mlraโ Turns on Local Register Allocation. It's still experimental for ARC, so by default the compiler uses standard reload, which is the same as-mno-lra๐งช.-mlra-priority-noneโ Doesn't indicate any priority for target registers ๐.-mlra-priority-compactโ Indicates target register priority forr0..r3/r12..r15๐.-mlra-priority-noncompactโ Reduces target register priority forr0..r3/r12..r15๐.-mmillicodeโ When you're optimizing for size (with-Os), prologues and epilogues that have to save or restore a lot 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 if you link in a nonstandard way, so this option lets you turn millicode call generation on or off ๐.-mcode-density-frameโ Lets the compiler emitenterandleaveinstructions ๐ฆ. These are only valid for CPUs with the code-density feature, so don't use them on anything else ๐ .-mmixed-codeโ Tweaks register allocation to help 16-bit instruction generation โจ. Generally it makes the average instruction size smaller, but the instruction count goes up ๐.-mq-classโ Enables q instruction alternatives. This is the default for-Os๐.-mRcqโ Enables Rcq constraint handling. Most short code generation depends on this, and it's the default ๐.-mRcwโ Enables Rcw constraint handling. Most ccfsm condexec depends on this, and it's the default too ๐ธ.-msize-level=levelโ Fine-tunes size optimization with regards to instruction lengths and alignment ๐ . The recognized values forlevelare:0โ No size optimization. This level is deprecated and treated like1๐.1โ Short instructions are used opportunistically ๐ฆ.2โ On top of that, alignment of loops and of code after barriers gets dropped ๐.3โ On top of that, optional data alignment gets dropped, and the option-Osis enabled ๐.
It defaults to 3 when -Os is in effect ๐ฅ. Otherwise, if you don't set it, it works the same as level 1 ๐ซถ.
-mtune=cpuโ Sets instruction scheduling parameters forcpu, overriding whatever-mcpu=implied ๐. The supported values forcpuare:ARC600โ Tunes for ARC600 CPU ๐ง.ARC601โ Tunes for ARC601 CPU ๐.ARC700โ Tunes for ARC700 CPU with standard multiplier block โจ.ARC700-xmacโ Tunes for ARC700 CPU with XMAC block ๐.ARC725Dโ Tunes for ARC725D CPU ๐ฆ.ARC750Dโ Tunes for ARC750D CPU ๐ธ.
-mmultcost=numโ Sets the cost to assume for a multiply instruction, with4being equal to a normal instruction ๐ฅ.-munalign-prob-threshold=probabilityโ Sets the probability threshold for unaligning branches ๐ง . When you're tuning for ARC700 and optimizing for speed, branches without a filled delay slot are usually emitted unaligned and long, unless profiling shows the probability of the branch being taken is belowprobability๐. The default is(REG_BR_PROB_BASE/2), which is5000๐.
The following options are kept around for backward compatibility, but they're now deprecated and will be removed in a future release ๐ญ. Please migrate off them ๐ซถ.
-margonautโ Obsolete FPX ๐.-mbig-endian,-EBโ Compiles code for big-endian targets. Using these is deprecated now ๐. Big-endian code is supported by configuring GCC to buildarceb-elf32andarceb-linux-uclibctargets, where big endian is already the default ๐.-mlittle-endian,-ELโ Compiles code for little-endian targets. Using these is deprecated now ๐. Little-endian code is supported by configuring GCC to buildarc-elf32andarc-linux-uclibctargets, where little endian is already the default ๐.-mbarrel_shifterโ Replaced by-mbarrel-shifter๐.-mdpfp_compactโ Replaced by-mdpfp-compact๐.-mdpfp_fastโ Replaced by-mdpfp-fast๐.-mdsp_packaโ Replaced by-mdsp-packa๐.-mEAโ Replaced by-mea๐.-mmac_24โ Replaced by-mmac-24๐.-mmac_d16โ Replaced by-mmac-d16๐.-mspfp_compactโ Replaced by-mspfp-compact๐.-mspfp_fastโ Replaced by-mspfp-fast๐.-mtune=cpuโ The valuesarc600,arc601,arc700andarc700-xmacforcpuare replaced byARC600,ARC601,ARC700andARC700-xmacrespectively ๐.-multcost=numโ Replaced by-mmultcost๐.
โจ ARM Options โจ
okay bestie, these -m options are defined for the ARM port ๐:
-mabi=nameโ Generates code for the specified ABI ๐ง. The permissible values areapcs-gnu,atpcs,aapcs,aapcs-linuxandiwmmxt๐.-mapcs-frameโ Generates a stack frame that follows the ARM Procedure Call Standard for all functions, even when it's not strictly needed for the code to run correctly ๐. Specifying-fomit-frame-pointerwith this option means stack frames won't be generated for leaf functions ๐. The default is-mno-apcs-frame๐ . This option is deprecated ๐.-mapcsโ A synonym for-mapcs-frame, and it's deprecated too ๐.-mthumb-interworkโ Generates code that supports calling between the ARM and Thumb instruction sets ๐ฅ. Without this option, on pre-v5 architectures, the two instruction sets can't be reliably used inside one program ๐ฌ. The default is-mno-thumb-interwork, since slightly larger code gets generated when-mthumb-interworkis specified ๐ซถ. In AAPCS configurations this option is meaningless ๐คท.-mno-sched-prologโ Stops the reordering of instructions in the function prologue, and stops those instructions from being merged with the instructions in the function's body ๐. That means every function starts with a recognizable set of instructions (or one from a small set of different prologues), so you can use that to find where functions start inside an executable piece of code ๐. The default is-msched-prologโจ.-mfloat-abi=nameโ Specifies which floating-point ABI to use ๐งฎ. The permissible values aresoft,softfpandhard๐.softmakes GCC generate output with library calls for floating-point operations ๐.softfplets you generate code using hardware floating-point instructions, but it still uses the soft-float calling conventions ๐ธ.hardallows floating-point instructions and uses FPU-specific calling conventions โก.
The default depends on your specific target configuration ๐ฏ. Heads up: the hard-float and soft-float ABIs are not link-compatible, so you have to compile your whole 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, these select between the BE8 and BE32 formats ๐งฉ. They have no effect on little-endian images and get ignored there ๐. The default depends on the selected target architecture: for ARMv6 and later it's BE8, and for older architectures it's BE32 ๐. 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 kind of instructions it can emit when generating assembly code ๐ง . You can use this option together with-mcpu=, or instead of it ๐.
The permissible names are: armv4t, armv5t, armv5te, armv6, armv6j, armv6k, armv6kz, armv6t2, armv6z, armv6zk, armv7, armv7-a, armv7ve, armv8-a, armv8.1-a, armv8.2-a, armv8.3-a, armv8.4-a, armv8.5-a, armv7-r, armv8-r, armv6-m, armv6s-m, armv7-m, armv7e-m, armv8-m.base, armv8-m.main, iwmmxt and iwmmxt2 ๐.
On top of that, these architectures lack support for the Thumb execution state, so they're recognized but support is deprecated: armv4 ๐ญ.
Lots of these architectures support extensions ๐งฉ. You can add them by appending +extension to the architecture name โ. Extension options are processed in order, and capabilities accumulate ๐. An extension also turns on any base extensions it depends on, so for example the +crypto extension will always enable the +simd extension ๐. The exception to the additive rule is extensions prefixed with +no...: those disable the specified option, along with any other extensions that depend on it ๐ซ.
For example, -march=armv7-a+simd+nofp+vfpv4 is equivalent to writing -march=armv7-a+vfpv4, since the +simd option gets entirely disabled by the +nofp option that follows it ๐โจ.
Okay so bestie, most extension names are super generic ๐
but what they actually do depends on which architecture you slap them onto โจ Like +simd works on both armv7-a and armv8-a, but on armv7-a it turns on the original ARMv7-A Advanced SIMD (Neon) stuff, and on armv8-a it gives you the ARMv8-A version ๐ฅ The table below is the full tea on what each architecture supports. Anything not mentioned? Sorry bestie, no extensions for it ๐
โจ armv5te, armv6, armv6j, armv6k, armv6kz, armv6t2, armv6z, armv6zk โจ
All of these architectures share the same two extensions ๐ฆ
+fpโ the VFPv2 floating-point instructions.+vfpv2works as an alias for this one ๐+nofpโ turns the floating-point instructions off ๐
๐ธ armv7 ๐ธ
This is 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โ turns the floating-point instructions off
๐ฆ armv7-a ๐ฆ
+mpโ the multiprocessing extension ๐ง+secโ the security extension ๐+fpโ the VFPv3 floating-point instructions, with 16 double-precision registers.+vfpv3-d16is an alias ๐+simdโ the Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions.+neonand+neon-vfpv3are both aliases for this one ๐ฅ+vfpv3โ the VFPv3 floating-point instructions, but 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 conversion operations ๐+vfpv4-d16โ the VFPv4 floating-point instructions, with 16 double-precision registers ๐+vfpv4โ the VFPv4 floating-point instructions, with 32 double-precision registers ๐+neon-fp16โ the Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions, with the half-precision conversion operations โจ+neon-vfpv4โ the Advanced SIMD (Neon) v2 plus the VFPv4 floating-point instructions ๐+nosimdโ disables the Advanced SIMD instructions (floating-point stays on, though) ๐+nofpโ disables the floating-point and Advanced SIMD instructions ๐
๐ armv7ve ๐
This is the extended version of the ARMv7-A architecture, with support for virtualization ๐ง
+fpโ the VFPv4 floating-point instructions, with 16 double-precision registers.+vfpv4-d16is an alias for this one ๐+simdโ the Advanced SIMD (Neon) v2 plus the VFPv4 floating-point instructions.+neon-vfpv4is an alias for this one ๐ฅ+vfpv3-d16โ the VFPv3 floating-point instructions, with 16 double-precision registers ๐+vfpv3โ the VFPv3 floating-point instructions, with 32 double-precision registers ๐+vfpv3-d16-fp16โ the VFPv3 floating-point instructions with 16 double-precision registers and the half-precision conversion operations ๐+vfpv3-fp16โ the VFPv3 floating-point instructions with 32 double-precision registers and the half-precision conversion operations ๐+vfpv4-d16โ the VFPv4 floating-point instructions, with 16 double-precision registers ๐+vfpv4โ the VFPv4 floating-point instructions, with 32 double-precision registers ๐+neonโ the Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions.+neon-vfpv3is an alias for this one โจ+neon-fp16โ the Advanced SIMD (Neon) v1 plus the VFPv3 floating-point instructions, with the half-precision conversion operations ๐+nosimdโ disables the Advanced SIMD instructions (floating-point stays on) ๐+nofpโ disables the floating-point and Advanced SIMD instructions ๐
๐ armv8-a ๐
+crcโ the Cyclic Redundancy Check (CRC) instructions ๐งฎ+simdโ the ARMv8-A Advanced SIMD and floating-point instructions ๐ฅ+cryptoโ the cryptographic instructions ๐+nocryptoโ disables the cryptographic instructions ๐+nofpโ disables the floating-point, Advanced SIMD, and cryptographic instructions ๐+sbโ the Speculation Barrier Instruction ๐ก๏ธ+predresโ the Execution and Data Prediction Restriction Instructions ๐ก๏ธ
โญ armv8.1-a โญ
+simdโ the ARMv8.1-A Advanced SIMD and floating-point instructions ๐ฅ+cryptoโ the cryptographic instructions. This also turns on the Advanced SIMD and floating-point instructions ๐+nocryptoโ disables the cryptographic instructions ๐+nofpโ disables the floating-point, Advanced SIMD, and cryptographic instructions ๐+sbโ the Speculation Barrier Instruction ๐ก๏ธ+predresโ the Execution and Data Prediction Restriction Instructions ๐ก๏ธ
๐ armv8.2-a, armv8.3-a ๐
Both of these architectures share the same extensions ๐
+fp16โ the half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions ๐+fp16fmlโ the half-precision floating-point fmla extension. This also enables the half-precision floating-point extension, plus the Advanced SIMD and floating-point instructions ๐+simdโ the ARMv8.1-A Advanced SIMD and floating-point instructions ๐ฅ+cryptoโ the cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions ๐+dotprodโ enables the Dot Product extension. This also enables Advanced SIMD instructions ๐ฆ+nocryptoโ disables the cryptographic extension ๐+nofpโ disables the floating-point, Advanced SIMD, and cryptographic instructions ๐+sbโ the Speculation Barrier Instruction ๐ก๏ธ+predresโ the Execution and Data Prediction Restriction Instructions ๐ก๏ธ
๐ง armv8.4-a ๐ง
+fp16โ the half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions, as well as the Dot Product extension and the half-precision floating-point fmla extension ๐+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, as well as the Dot Product extension ๐ฅ+cryptoโ the cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions, as well as the Dot Product extension ๐+nocryptoโ disables the cryptographic extension ๐+nofpโ disables the floating-point, Advanced SIMD, and cryptographic instructions ๐+sbโ the Speculation Barrier Instruction ๐ก๏ธ+predresโ the Execution and Data Prediction Restriction Instructions ๐ก๏ธ
๐ armv8.5-a ๐
+fp16โ the half-precision floating-point data processing instructions. This also enables the Advanced SIMD and floating-point instructions, as well as the Dot Product extension and the half-precision floating-point fmla extension ๐+simdโ the ARMv8.3-A Advanced SIMD and floating-point instructions, as well as the Dot Product extension ๐ฅ+cryptoโ the cryptographic instructions. This also enables the Advanced SIMD and floating-point instructions, as well as the Dot Product extension ๐+nocryptoโ disables the cryptographic extension ๐+nofpโ disables the floating-point, Advanced SIMD, and cryptographic instructions ๐
๐ฆ armv7-r ๐ฆ
+fp.spโ the single-precision VFPv3 floating-point instructions.+vfpv3xdis an alias for this one ๐+fpโ the VFPv3 floating-point instructions with 16 double-precision registers.+vfpv3-d16is an alias for this one ๐+vfpv3xd-d16-fp16โ the single-precision VFPv3 floating-point instructions with 16 double-precision registers and the half-precision conversion operations ๐+vfpv3-d16-fp16โ the VFPv3 floating-point instructions with 16 double-precision registers and the half-precision conversion operations ๐+nofpโ disables the floating-point extension ๐+idivโ the ARM-state integer division instructions โ+noidivโ disables the ARM-state integer division extension ๐
๐ armv7e-m ๐
+fpโ the single-precision VFPv4 floating-point instructions ๐ฅ+fpv5โ the single-precision FPv5 floating-point instructions ๐ฅ+fp.dpโ the single- and double-precision FPv5 floating-point instructions ๐+nofpโ disables the floating-point extensions ๐
Okay so the ARMv8 squad gets their own little lists ๐
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 ๐
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. Big vibe check, bestie ๐ญ
-march=native makes the compiler auto-detect the architecture of the build computer. Right now this only works on GNU/Linux, and not every architecture gets recognized. If the auto-detect doesn't work out, the option has no effect at all ๐ซ
๐ -mtune=name
This one tells GCC which target ARM processor to tune the performance of the code for. Some ARM chips run noticeably better when you use it ๐ Here are the names you can pick from:
arm7tdmi, arm7tdmi-s, arm710t,
arm720t, arm740t, strongarm, strongarm110, strongarm1100,
0strongarm1110, arm8, arm810, arm9, arm9e, arm920, arm920t, arm922t,
arm946e-s, arm966e-s, arm968e-s, arm926ej-s, arm940t, arm9tdmi,
arm10tdmi, arm1020t, arm1026ej-s, arm10e, arm1020e, arm1022e,
arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1156t2-s,
arm1156t2f-s, arm1176jz-s, arm1176jzf-s, generic-armv7-a, cortex-a5,
cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17,
cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57,
cortex-a72, cortex-a73, cortex-a75, cortex-a76, ares, cortex-r4,
cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, cortex-m0,
cortex-m0plus, cortex-m1, cortex-m3, cortex-m4, cortex-m7,
cortex-m23, cortex-m33, cortex-m1.small-multiply,
cortex-m0.small-multiply, cortex-m0plus.small-multiply, exynos-m1,
marvell-pj4, neoverse-n1, neoverse-n2, neoverse-v1, xscale, iwmmxt,
iwmmxt2, ep9312, fa526, fa626, fa606te, fa626te, fmp626, fa726te,
xgene1.
Also, this option can tune for a big.LITTLE system, which is a whole mood ๐ The 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 architecture arch ๐ง The goal is code that runs well on the most popular chips right now, balancing the optimizations that help some CPUs in that range while avoiding the performance potholes of others. The effects of this option may shift in future GCC versions as CPU models come and go, so don't be shocked if it changes ๐
-mtune takes the same extension options as -mcpu, but the extension options don't affect how the generated code gets tuned ๐
-mtune=native makes the compiler auto-detect the CPU of the build computer. Right now this only works on GNU/Linux, and not every architecture is recognized. If the auto-detect is unsuccessful, the option has no effect ๐
๐ -mcpu=name[+extension...]
This one names the target ARM processor. GCC uses that name to figure out the target ARM architecture (as if you'd used -march) and the processor type to tune performance for (as if you'd used -mtune). If you use this option together with -march or -mtune, those options take precedence over the matching part of this one ๐
Lots of the supported CPUs come with optional architectural extensions, and those are usually enabled by default. If some versions of a CPU are missing an extension, you can use the extension syntax to turn off the ones that got left out. For floating-point and Advanced SIMD (Neon) instructions, you also have to think about -mfloat-abi and -mfpu. Floating-point and Advanced SIMD instructions only get used if -mfloat-abi isn't set to soft, and any -mfpu setting other than auto overrides the available floating-point and SIMD extension instructions ๐ซถ
For example, cortex-a9 shows up in three main flavours: integer only, with just a floating-point unit, or with floating-point and Advanced SIMD. By default it enables all the instructions, but +nosimd and +nofp can switch off just the SIMD, or both SIMD and floating-point, respectively ๐ฅ
Permissible names for this option are the same as the ones for -mtune.
The following extension options are shared by the listed CPUs:
+nodspโ disables the DSP instructions oncortex-m33.+nofpโ disables the floating-point instructions onarm9e,arm946e-s,arm966e-s,arm968e-s,arm10e,arm1020e,arm1022e,arm926ej-s,arm1026ej-s,cortex-r5,cortex-r7,cortex-r8,cortex-m4,cortex-m7andcortex-m33. Ongeneric-armv7-a,cortex-a5,cortex-a7,cortex-a8,cortex-a9,cortex-a12,cortex-a15,cortex-a17,cortex-a15.cortex-a7,cortex-a17.cortex-a7,cortex-a32,cortex-a35,cortex-a53andcortex-a55, it disables the floating-point and SIMD instructions instead ๐ญ+nofp.dpโ disables the double-precision part of the floating-point instructions oncortex-r5,cortex-r7,cortex-r8,cortex-r52andcortex-m7.+nosimdโ disables the SIMD instructions (but keeps floating-point) ongeneric-armv7-a,cortex-a5,cortex-a7andcortex-a9.+cryptoโ enables the cryptographic instructions oncortex-a32,cortex-a35,cortex-a53,cortex-a55,cortex-a57,cortex-a72,cortex-a73,cortex-a75,exynos-m1,xgene1,cortex-a57.cortex-a53,cortex-a72.cortex-a53,cortex-a73.cortex-a35,cortex-a73.cortex-a53andcortex-a75.cortex-a55. ๐
Also, the generic-armv7-a pseudo target defaults to VFPv3 with 16 double-precision registers. It supports these extension options: mp, sec, vfpv3-d16, vfpv3, vfpv3-d16-fp16, vfpv3-fp16, vfpv4-d16, vfpv4, neon, neon-vfpv3, neon-fp16 and neon-vfpv4. They mean the same thing as the extensions to -march=armv7-a โจ
-mcpu=generic-arch is also allowed, and it's the same as -march=arch -mtune=generic-arch. Check out -mtune for more deets ๐ธ
-mcpu=native makes the compiler auto-detect the CPU of the build computer. Right now this only works on GNU/Linux, and not every architecture is recognized. If the auto-detect is unsuccessful, the option has no effect ๐
๐ฆ -mfpu=name
This one says 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-armv8, crypto-neon-fp-armv8
neon is an alias for neon-vfpv3, and vfp is an alias for vfpv2 ๐
The setting auto is the default and it's special. It makes the compiler pick the floating-point and Advanced SIMD instructions based on the settings of -mcpu and -march ๐ง
Heads up, bestie ๐จ If the selected floating-point hardware includes the NEON extension (e.g.-mfpu=neon), GCC's auto-vectorization pass won't generate floating-point operations unless-funsafe-math-optimizationsis also specified. That's because NEON hardware doesn't fully implement the IEEE 754 standard for floating-point arithmetic (in particular, denormal values are treated as zero), so using NEON instructions 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 ๐ช
๐ -mfp16-format=name
This specifies the format of the "__fp16" half-precision floating-point type. Permissible names are none, ieee and alternative. The default is none, which means the "__fp16" type isn't defined at all ๐ซฅ
๐ -mstructure-size-boundary=n
The sizes of all structures and unions get rounded up to a multiple of the number of bits set by this option. Permissible values are 8, 32 and 64. The default value varies between toolchains, and for the COFF targeted toolchain the default is 8. A value of 64 is only allowed if the underlying ABI supports it ๐งฉ
Going bigger can produce faster, more efficient code, but it can also make your program bigger. Different values are potentially incompatible, too. Code compiled with one value can't necessarily be expected to work with code or libraries compiled with another value, if they pass information around using structures or unions ๐ โโ๏ธ
This option is deprecated, so please don't build new stuff around it ๐ฅ
๐ง -mabort-on-noreturn
This generates a call to the function "abort" at the end of a "noreturn" function. It runs if the function tries to return ๐
๐ธ -mlong-calls, -mno-long-calls
These tell the compiler to make function calls by first loading the address of the function into a register, and then doing a subroutine call on that register. You need this switch if the target function lives outside the 64-megabyte addressing range of the offset-based version of the subroutine call instruction ๐ฆ
Even with this switch on, not every function call becomes a long call. The heuristic is that these are not turned into long calls: static functions, functions with the "short_call" attribute, functions inside the scope of a #pragma no_long_calls directive, and functions whose definitions have already been compiled within the current compilation unit. The exceptions are that weak function definitions, functions with the "long_call" attribute or the "section" attribute, and functions inside the scope of a #pragma long_calls directive are always turned into long calls ๐
This one's off by default, bestie ๐ Use -mno-long-calls to get back to normal, or wrap the calls in a #pragma long_calls_off directive ๐. Just know these switches don't change how calls through function pointers get generated ๐.
-msingle-pic-baseโ treats the register used for PIC addressing as read-only ๐ instead of loading it in the prologue for every function. The runtime system has to set that register to an appropriate value before execution begins ๐ง-mpic-register=regโ picks the register used for PIC addressing ๐ . For the standard PIC base case, the default is any suitable register the compiler chooses ๐ค. For the single PIC base case, the default isR9if the target is EABI based or stack-checking is enabled, otherwise it'sR10๐-mpic-data-is-text-relativeโ assumes the gap between the text and data segments is locked in at static link time ๐. That means you can use PC-relative addressing to reach data you know lives in the data segment โจ. For non-VxWorks RTP targets this is on by default ๐. If you turn it off on those targets,-msingle-pic-basegets switched on by default instead ๐ฆ-mpoke-function-nameโ writes the name of each function into the text section, right before the function prologue ๐ช. The generated code is basically this:
t0
.ascii "arm_poke_function_name", 0
.align
t1
.word 0xff000000 + (t1 - t0)
arm_poke_function_name
mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4
When you're doing a stack backtrace, code can check the pc stored at fp + 0 ๐. If the trace function then looks at location pc - 12 and the top 8 bits are set, we know there's a function name embedded right before that spot, and it has length ((pc[-3]) & 0xff000000) ๐ซถ
-mthumb,-marmโ choose whether the code runs in ARM state or Thumb state ๐. Most configurations default to 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") and target("arm") function attributes or pragmas ๐ซ
-mflip-thumbโ switches ARM and Thumb modes on alternating functions ๐. This is only here for regression testing of mixed Thumb/ARM code generation ๐งช, so please don't use it for normal compiling ๐ โโ๏ธ-mtpcs-frameโ generates a stack frame that's compliant with the Thumb Procedure Call Standard for all non-leaf functions ๐. (A leaf function is one that doesn't call any other functions ๐.) The default is-mno-tpcs-frameโจ-mtpcs-leaf-frameโ generates a stack frame that's compliant with the Thumb Procedure Call Standard for all leaf functions ๐. (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 header switches to Thumb mode before the rest of the function runs ๐, so these functions can be called from non-interworking code ๐ซถ. This option is not valid in AAPCS configurations, because interworking is already enabled by default ๐-mcaller-super-interworkingโ lets calls via function pointers (including virtual functions) run correctly whether or not the target code was compiled for interworking ๐ช. Heads up: there's a small overhead in the cost of executing a function pointer when this is enabled ๐ข. This option is not valid in AAPCS configurations either, since interworking is enabled by default-mtp=nameโ sets 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 straight fromcp15(supported in the arm6k architecture) ๐; andauto, which uses the best available method for the selected processor ๐ค. The default setting isauto-mtls-dialect=dialectโ picks the dialect used for accessing thread local storage ๐งต. Two dialects are supported:gnuandgnu2๐ฏ. Thegnudialect is the original GNU scheme for supporting local and global dynamic TLS models ๐ฐ๏ธ. Thegnu2dialect is the GNU descriptor scheme, which gives better performance for shared libraries ๐. It's compatible with the original scheme, but it does require new assembler, linker and library support ๐ ๏ธ. Initial and local exec TLS models aren't affected by this option and always use the original scheme ๐-mword-relocationsโ only generates absolute relocations on word-sized values (i.e.R_ARM_ABS32) ๐ฏ. This is enabled by default on targets (uClinux, SymbianOS) where the runtime loader imposes this restriction, and whenever-fpicor-fPICis specified ๐. This option conflicts with-mslow-flash-dataโ ๏ธ-mfix-cortex-m3-ldrdโ some Cortex-M3 cores can cause data corruption whenldrdinstructions with overlapping destination and base registers are used ๐ฑ. This option avoids generating those instructions ๐ก๏ธ. It's enabled by default when-mcpu=cortex-m3is specified-munaligned-access,-mno-unaligned-accessโ enables (or disables) reading and writing of 16- and 32-bit values from addresses that aren't 16- or 32-bit aligned ๐. By default, unaligned access is disabled for all pre-ARMv6, all ARMv6-M and for ARMv8-M Baseline architectures, and enabled for all other architectures. If unaligned access isn't enabled, words in packed data structures get accessed one 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, the preprocessor symbol __ARM_FEATURE_UNALIGNED is also defined โจ
-mneon-for-64bitsโ enables using Neon to handle scalar 64-bit operations ๐ถ. It's disabled by default, since the cost of moving data from core registers to Neon is high ๐ธ-mslow-flash-dataโ assumes loading data from flash is slower than fetching instructions ๐ข. Literal loads get minimized for better performance โก. This option is only supported when compiling for ARMv7 M-profile and is off by default ๐ . It conflicts with-mword-relocationsโ ๏ธ-masm-syntax-unifiedโ assumes inline assembler is using unified asm syntax ๐. The default is currently off, which implies divided syntax. This option has no impact on Thumb2 ๐คท, though that may change in future releases of GCC. Divided syntax should be considered deprecated ๐-mrestrict-itโ restricts generation of IT blocks so they conform to the rules of ARMv8-A ๐. IT blocks can only contain a single 16-bit instruction from a select set of instructions ๐ฏ. This option is on by default for ARMv8-A Thumb mode ๐-mprint-tune-infoโ prints CPU tuning information as a comment in the assembler file ๐. This is an option used only for regression testing of the compiler, and it's not intended for ordinary use in compiling code ๐งช. It's disabled by default-mverbose-cost-dumpโ enables verbose cost model dumping in the debug dump files ๐. This option is provided for debugging the compiler ๐ ๏ธ-mpure-codeโ does not allow constant data to be placed in code sections ๐ซ. Additionally, when compiling for ELF object format, it gives all text sections the ELF processor-specific section attributeSHF_ARM_PURECODE๐ท๏ธ. This option is only available when generating non-pic code for M-profile targets ๐-mcmseโ generates secure code as per the "ARMv8-M Security Extensions: Requirements on Development Tools Engineering Specification" ๐. You can find that spec athttps://developer.arm.com/documentation/ecm0359818/latest/๐
โจ AVR Options โจ
These options are defined for AVR implementations, so if you're working with those chips, this part's for you ๐
-mmcu=mcuโ picks the Atmel AVR instruction set architecture (ISA) or MCU type ๐ . The default for this option isavr2๐
GCC supports the following AVR devices and ISAs:
avr2โ "Classic" devices with up to 8 KiB of program memory ๐ฐ๏ธ. mcu values:attiny22,attiny26,at90s2313,at90s2323,at90s2333,at90s2343,at90s4414,at90s4433,at90s4434,at90c8534,at90s8515,at90s8535avr25โ "Classic" devices with up to 8 KiB of program memory and with theMOVWinstruction ๐. mcu values: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,at86rf401avr3โ "Classic" devices with 16 KiB up to 64 KiB of program memory ๐งฉ. mcu values:at76c711,at43usb355avr31โ "Classic" devices with 128 KiB of program memory ๐. mcu values:atmega103,at43usb320avr35โ "Classic" devices with 16 KiB up to 64 KiB of program memory and with theMOVWinstruction ๐ฆ. mcu values:attiny167,attiny1634,atmega8u2,atmega16u2,atmega32u2,ata5505,ata6617c,ata664251,at90usb82,at90usb162avr4โ "Enhanced" devices with up to 8 KiB of program memory ๐ธ. mcu values: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
- MCUs:
avr51โ โจ "Enhanced" devices with 128 KiB of program memory ๐- MCUs:
atmega128,atmega128a,atmega128rfa1,atmega128rfr2,atmega1280,atmega1281,atmega1284,atmega1284p,atmega1284rfr2,at90can128,at90usb1286,at90usb1287
- MCUs:
avr6โ โจ "Enhanced" devices with a 3-byte PC, i.e. with more than 128 KiB of program memory ๐ฆ- MCUs:
atmega256rfr2,atmega2560,atmega2561,atmega2564rfr2
- MCUs:
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
- MCUs:
avrxmega3โ ๐ง "XMEGA" devices with up to 64 KiB of combined program memory and RAM, where the program memory is visible in the RAM address space ๐- 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
- MCUs:
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
- MCUs:
avrxmega5โ ๐ "XMEGA" devices with more than 64 KiB and up to 128 KiB of program memory, plus more than 64 KiB of RAM- MCUs:
atxmega64a1,atxmega64a1u
- MCUs:
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
- MCUs:
avrxmega7โ ๐ "XMEGA" devices with more than 128 KiB of program memory and more than 64 KiB of RAM- MCUs:
atxmega128a1,atxmega128a1u,atxmega128a4u
- MCUs:
avrtinyโ โญ "TINY" Tiny core devices with 512 B up to 4 KiB of program memory ๐ซถ- MCUs:
attiny4,attiny5,attiny9,attiny10,attiny20,attiny40
- MCUs:
avr1โ ๐ This ISA is baked into the minimal AVR core and is supported for the assembler only, so no C compiling here, bestie ๐- MCUs:
attiny11,attiny12,attiny15,attiny28,at90s1200
- MCUs:
-mabsdataโ ๐ง Assumes all data in static storage can be reached withLDS/STSinstructions. This only does anything on reduced Tiny devices like ATtiny40. See also theabsdataAVR Variable Attributes, variable attribute.-maccumulate-argsโ ๐ Piles up outgoing function arguments and grabs/releases the stack space for them once, in the function prologue/epilogue. Without this, outgoing arguments get pushed before each call and popped afterwards.
Popping arguments after a call can be pricey on AVR, so accumulating the stack space can give you smaller executables, since arguments don't need removing after each call. This can shrink code for functions that make several calls to functions taking their arguments on the stack, like printf-style functions. โจ
-mbranch-cost=costโ ๐ Sets the branch costs for conditional branch instructions tocost. Reasonable values forcostare small, non-negative integers. The default branch cost is0.-mcall-prologuesโ ๐ฆ Function prologues/epilogues get expanded as calls to appropriate subroutines. The code size comes out smaller.-mgas-isr-prologuesโ ๐ฅ Interrupt service routines (ISRs) may use the__gcc_isrpseudo instruction supported by GNU Binutils. If this option is on, you can still turn the feature off for individual ISRs with theno_gccisrfunction attribute (see AVR Function Attributes). This feature is on by default if optimization is on (but not with-Og, see Optimize Options), and if GNU Binutils supports PR21683 athttps://sourceware.org/PR21683. ๐ธ-mint8โ ๐ Assumesintis an 8-bit integer. This changes the sizes of all the types: acharis 1 byte, anintis 1 byte, alongis 2 bytes, and along longis 4 bytes. Heads up that this does not conform to the C standards, but the code comes out smaller. ๐-mmain-is-OS_taskโ ๐ Don't save registers inmain. The effect is the same as attaching theOS_taskfunction attribute tomain(see AVR Function Attributes). This is on by default if optimization is on. โจ-mn-flash=numโ ๐ Assumes the flash memory isnumtimes 64 KiB in size.-mno-interruptsโ ๐ The generated code is not compatible with hardware interrupts. The code size is smaller, but interrupts are a no-go ๐ญ-mrelaxโ ๐ซถ Tries to swap aCALLorJMPinstruction for the shorterRCALLorRJMPinstruction where that applies. Setting-mrelaxonly adds the--mlink-relaxoption to the assembler's command line and the--relaxoption to the linker's command line.
Jump relaxing is done by the linker, because jump offsets aren't known until the code is located. So the assembler code the compiler generates is the same, but the instructions in the executable might look different from the assembler code. ๐ง
Relaxing must be turned on if linker stubs are needed, see the section on "EIND" and linker stubs below. ๐
-mrmwโ ๐ Assumes the device supports the Read-Modify-Write instructionsXCH,LAC,LASandLAT. ๐ฅ-mshort-callsโ ๐ฆ AssumesRJMPandRCALLcan target the whole program memory.
This one is used internally for multilib selection. It's not an optimization option, so you don't need to set it by hand. ๐ โโ๏ธ
-msp8โ ๐ธ Treats the stack pointer register as an 8-bit register, i.e. 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 select and build multilibs for the avr2 and avr25 architectures. These architectures mix devices with and without SPH. For any setting other than -mmcu=avr2 or -mmcu=avr25, the compiler driver adds or removes this option from the compiler proper's command line, because the compiler then knows whether the device or architecture has an 8-bit stack pointer and therefore no SPH register. โจ
-mstrict-Xโ ๐ Uses the address registerXthe way the hardware intends. That meansXis only used in indirect, post-increment or pre-decrement addressing.
Without this option, the X register can be used the same way as Y or Z, which then gets emulated with extra instructions. For example, loading a value with X+const addressing, where const is a small non-negative number (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 changes the lower 8 bits of the stack pointer. โญ-mfract-convert-truncateโ ๐ฆ Allows 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โ ๐ง Don't add-specs=device-specs/specs-<mcu>to the compiler driver's command line. You're on the hook for giving the subprocesses (compiler proper, assembler and linker) the right command line options yourself. ๐-Waddr-space-convertโ ๐ Warns about conversions between address spaces where the resulting address space isn't contained in the incoming address space. โ ๏ธ-Wmisspelled-isrโ ๐ Warns if the ISR is misspelled, i.e. without 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 ๐ฆ
Okay bestie, so on devices with more than 128 Ki bytes of program memory there's this super special function register called EIND ๐. It's the most significant part of the target address whenever EICALL or EIJMP instructions get used. Iconic, right? ๐
Indirect jumps and calls on these devices are handled by the compiler in the following way, and they come with some limitations, so read this part carefully ๐
- The compiler never sets
EIND. ๐ โโ๏ธ - The compiler uses
EINDimplicitly inEICALL/EIJMPinstructions, or it might readEINDdirectly so it can fake an indirect call/jump with aRETinstruction. ๐ง - The compiler assumes that
EINDnever changes during the startup code or during the application. In particular,EINDis not saved/restored in function or interrupt service routine prologue/epilogue, so please don't mess with it ๐ - For indirect calls to functions and computed goto, the linker generates stubs. Stubs are jump pads, sometimes also called trampolines ๐ง. So the indirect call/jump lands on a stub, and the stub contains a direct jump to the address you actually wanted. โจ
- 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.
โ ๏ธ Bestie, watch out: there are corner cases where the linker is supposed to generate stubs but aborts without relaxation and without a helpful error message. Not it. ๐
- The default linker script is arranged for code with
EIND = 0. If your code is supposed to work for a setup withEIND != 0, you need a custom linker script ๐ ๏ธ to place the sections whose name start with.trampolinesinto the segment whereEINDpoints to. - The startup code from libgcc never sets
EIND. Notice that startup code is a blend of code from libgcc and AVR-LibC. For the impact of AVR-LibC onEIND, check out the AVR-LibC user manual ("http://nongnu.org/avr-libc/user-manual/") ๐ - It is totally legit for user-specific startup code to set up
EINDearly, for example by means of initialization code located in section.init3๐ . That code runs prior to the general startup code that initializes RAM and calls constructors, but after the bit of AVR-LibC startup code that setsEINDto the segment where the vector table is located.
#include <avr/io.h>
static void
__attribute__((section(".init3"),naked,used,no_instrument_function))
init3_set_eind (void)
{
__asm volatile ("ldi r24,pm_hh8(__trampolines_start)\n\t"
"out %i0,r24" :: "n" (&EIND) : "r24","memory");
}
The __trampolines_start symbol is defined in the linker script. ๐ซถ
- Stubs are generated automatically by the linker if the following two conditions are met:
- The address of a label is taken by means of the
gsmodifier (short for generate stubs), like so:
- The address of a label is taken by means of the
LDI r24, lo8(gs(<func>))
LDI r25, hi8(gs(<func>))
- The final location of that label is in a code segment outside the segment where the stubs are located.
- The compiler emits such
gsmodifiers for code labels in the following situations:- Taking address of a function or code label.
- Computed goto.
- If prologue-save function is used, see
-mcall-prologuescommand-line option. - Switch/case dispatch tables. If you do not want such dispatch tables you can specify the
-fno-jump-tablescommand-line option. - C and C++ constructors/destructors called during startup/shutdown.
- If the tools hit a
gs()modifier explained above.
- Jumping to non-symbolic addresses like this is not supported ๐ซ
int main (void)
{
/* Call function at word address 0x2 */
return ((int(*)(void)) 0x2)();
}
Instead, a stub has to be set up, i.e., the function has to be called through a symbol (func_4 in the example) ๐ฆ
int main (void)
{
extern int func_4 (void);
/* Call function at byte address 0x4 */
return func_4();
}
and the application be linked with -Wl,--defsym,func_4=0x4. Alternatively, func_4 can be defined in the linker script.
๐ธ Handling of the "RAMPD", "RAMPX", "RAMPY" and "RAMPZ" Special Function Registers ๐ธ
Some AVR devices support memories larger than the 64 KiB range that can be accessed with 16-bit pointers. To reach memory locations outside that 64 KiB range, the content of a RAMP register is used as the high part of the address. The X, Y, Z address register gets concatenated with the RAMPX, RAMPY, RAMPZ special function register, respectively, to make a wide address. Similarly, RAMPD is used together with direct addressing. ๐
- The startup code initializes the
RAMPspecial function registers with zero. ๐ฑ - If a named address space (see AVR Named Address Spaces) other than generic or
__flashis used, thenRAMPZis set as needed before the operation. โจ - If the device supports RAM larger than 64 KiB and the compiler needs to change
RAMPZto accomplish an operation,RAMPZis reset to zero after the operation. ๐ - If the device comes with a specific
RAMPregister, the ISR prologue/epilogue saves/restores that SFR and initializes it with zero, in case the ISR code might (implicitly) use it. ๐ก๏ธ - RAM larger than 64 KiB is not supported by GCC for AVR targets. If you use inline assembler to read from locations outside the 16-bit address range and change one of the
RAMPregisters, you must reset it to zero after the access. ๐ญ
๐ AVR Built-in Macros ๐
GCC defines several built-in macros so user code can test for the presence or absence of features. Almost any of the following built-in macros are deduced from device capabilities, and are therefore 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__"
This built-in macro resolves to a decimal number that identifies the architecture, and it depends on the -mmcu=mcu option. Possible values are:
2, 25, 3, 31, 35, 4, 5, 51, 6
for mcu="avr2", "avr25", "avr3", "avr31", "avr35", "avr4", "avr5", "avr51", "avr6",
respectively, and
100, 102, 103, 104, 105, 106, 107
for mcu="avrtiny", "avrxmega2", "avrxmega3", "avrxmega4", "avrxmega5", "avrxmega6", "avrxmega7", respectively. If mcu specifies a device, this built-in macro is set accordingly. For example, with -mmcu=atmega8 the macro is defined to 4. ๐
๐ฆ "__AVR_Device__"
Setting -mmcu=device defines this built-in macro, which reflects the device's name. For example, -mmcu=atmega8 defines the built-in macro "__AVR_ATmega8__", and -mmcu=attiny261a defines "__AVR_ATtiny261A__", etc. ๐ธ
The built-in macro names follow the scheme "__AVR_Device__", where Device is the device name as it appears in the AVR user manual. The difference between Device in the built-in macro and device in -mmcu=device is that the latter is always lowercase. ๐
If device is not a device but only a core architecture like avr51, this macro is not defined. ๐
๐
"__AVR_DEVICE_NAME__"
Setting -mmcu=device defines this built-in macro to the device's name. For example, with -mmcu=atmega8 the macro is defined to "atmega8". โญ
If device is not a device but only a core architecture like avr51, this macro is not defined. ๐
๐ "__AVR_XMEGA__"
The device or architecture belongs to the XMEGA family of devices. ๐ฅ
๐ซถ "__AVR_HAVE_ELPM__"
The device has the ELPM instruction. ๐
๐ซถ "__AVR_HAVE_ELPMX__"
The device has the ELPM Rn,Z and ELPM Rn,Z+ instructions. ๐ฆ
๐ซถ "__AVR_HAVE_MOVW__"
The device has the MOVW instruction, which performs 16-bit register-register moves. โจ
๐ซถ "__AVR_HAVE_LPMX__"
The device has the LPM Rn,Z and LPM Rn,Z+ instructions. ๐
๐ซถ "__AVR_HAVE_MUL__"
The device has a hardware multiplier. ๐ช
๐ซถ "__AVR_HAVE_JMP_CALL__"
The device has the JMP and CALL instructions. This is the case for devices with more than 8 KiB of program memory. ๐ธ
๐ซถ "__AVR_HAVE_EIJMP_EICALL__" and "__AVR_3_BYTE_PC__"
The device has the EIJMP and EICALL instructions. This is the case for devices with more than 128 KiB of program memory. This also means that the program counter (PC) is 3 bytes wide. ๐ง
๐ซถ "__AVR_2_BYTE_PC__"
The program counter (PC) is 2 bytes wide. This is the case for devices with up to 128 KiB of program memory. ๐
๐ซถ "__AVR_HAVE_8BIT_SP__" and "__AVR_HAVE_16BIT_SP__"
The stack pointer (SP) register is treated by the compiler as an 8-bit register or a 16-bit register, respectively. The definition of these macros is affected by -mtiny-stack. ๐
๐ซถ "__AVR_HAVE_SPH__" and "__AVR_SP8__"
The device has the SPH (high part of stack pointer) special function register, or has an 8-bit stack pointer, respectively. The definition of these macros is affected by -mmcu= and, in the cases of -mmcu=avr2 and -mmcu=avr25, also by -msp8. ๐ท
๐ซถ "__AVR_HAVE_RAMPD__", "__AVR_HAVE_RAMPX__", "__AVR_HAVE_RAMPY__" and "__AVR_HAVE_RAMPZ__"
The device has the RAMPD, RAMPX, RAMPY, RAMPZ special function register, respectively. ๐ง
๐ซถ "__NO_INTERRUPTS__"
This macro reflects the -mno-interrupts command-line option. ๐ซ
๐ซถ "__AVR_ERRATA_SKIP__" and "__AVR_ERRATA_SKIP_JMP_CALL__"
Some AVR devices (AT90S8515, ATmega103) must not skip 32-bit instructions because of a hardware erratum. The skip instructions are SBRS, SBRC, SBIS, SBIC and CPSE. The second macro is only defined if "__AVR_HAVE_JMP_CALL__" is also set. โ ๏ธ
๐ซถ "__AVR_ISA_RMW__"
The device has Read-Modify-Write instructions (XCH, LAC, LAS and LAT). ๐ฅ
๐ซถ "__AVR_SFR_OFFSET__=offset"
Instructions that can address I/O special function registers directly, like IN, OUT, SBI, etc., may use a different address than an instruction that accesses RAM, like LD or STS. This offset depends on the device architecture and has to be subtracted from the RAM address in order to get the respective I/O address. ๐
๐ซถ "__AVR_SHORT_CALLS__"
The -mshort-calls command-line option is set. ๐
โจ AVR Options (continued) โจ
__AVR_PM_BASE_ADDRESS__=addrโ okay so some devices can read from flash memory usingLD*instructions ๐ง The flash shows up in the data address space at an offset of__AVR_PM_BASE_ADDRESS__. If this macro isn't defined, the feature just isn't available ๐ญ If it is defined, the address space is linear, so there's no need to shove.rodatainto RAM. The default linker description file handles that, and it's currently available foravrtinyandavrxmega3. Even more convenient, you don't need address spaces like__flashor features like the attributeprogmemandpgm_read_*๐__WITH_AVRLIBC__โ the compiler is configured to work together with AVR-Libc ๐ See the--with-avrlibcconfigure option.
๐ธ Blackfin Options ๐ธ
-mcpu=cpu[-sirevision]โ choose your target Blackfin processor! cpu can be one of bf512, bf514, bf516, bf518, bf522, bf523, bf524, bf525, bf526, bf527, bf531, bf532, bf533, bf534, bf536, bf537, bf538, bf539, bf542, bf544, bf547, bf548, bf549, bf542m, bf544m, bf547m, bf548m, bf549m, bf561, or bf592 ๐- The optional sirevision picks the silicon revision of the target Blackfin processor, and any workarounds for that revision get enabled โจ
- If sirevision is
none, no workarounds are enabled. If it'sany, all workarounds for the targeted processor are enabled ๐ง - The
__SILICON_REVISION__macro gets defined to two hexadecimal digits, representing the major and minor numbers of the silicon revision. If sirevision isnone,__SILICON_REVISION__is not defined at all. If it'sany, it's defined to be0xffff. - If you skip the optional sirevision, GCC assumes the latest known silicon revision of the targeted Blackfin processor ๐ง
- GCC defines a preprocessor macro for the specified cpu. For the
bfin-elftoolchain, this option causes the hardware BSP provided by libgloss to get linked in, as long as-msimisn't given. - Without this option,
bf532is used as the processor by default ๐ - > Heads up bestie: support for
bf561is incomplete. Forbf561, only the preprocessor macro is defined ๐
-msimโ the program will run on the simulator ๐ฅ๏ธ This links in the simulator BSP provided by libgloss. It only has an effect for thebfin-elftoolchain. Certain other options, like-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 frees up an extra register 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_LOADSis defined.-mno-specld-anomalyโ don't generate extra code to stop speculative loads from happening ๐ โโ๏ธ-mcsync-anomalyโ when enabled, the compiler makes sure the generated code doesn't contain CSYNC or SSYNC instructions too soon after conditional branches ๐ If this option is used,__WORKAROUND_SPECULATIVE_SYNCSis defined.-mno-csync-anomalyโ don't generate extra code to stop CSYNC or SSYNC instructions from popping up 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โ generate code that supports shared libraries via the library ID method ๐ This lets you do execute in place and use shared libraries in an environment without virtual memory management. This option implies-fPIC. With abfin-elftarget, it also implies-msim.-mno-id-shared-libraryโ generate code that doesn't assume ID-based shared libraries are being used. This is the default ๐ท-mleaf-id-shared-libraryโ generate code that supports shared libraries via the library ID method, but assumes this library or executable won't link against any other ID shared libraries ๐โโ๏ธ That lets the compiler use faster code for jumps and calls.-mno-leaf-id-shared-libraryโ don't assume the code being compiled won't link against any ID shared libraries. Slower code is generated for jump and call instructions ๐ข-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 that number to be allocated to the current library, but it's no more space- or time-efficient than leaving this option out.-msep-dataโ generate 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, by getting rid of relocations against the text section.-mno-sep-dataโ generate code that assumes the data segment follows the text segment. This is the default ๐-mlong-calls,-mno-long-callsโ tells the compiler to do function calls by first loading the function's address into a register, then making a subroutine call on that register ๐ You need this switch if the target function lives outside the 24-bit addressing range of the offset-based version of the subroutine call instruction.- This feature is not enabled by default. Specifying
-mno-long-callsrestores the default behavior ๐ - These switches have no effect on how the compiler handles function calls made through function pointers ๐คทโโ๏ธ
- This feature is not enabled by default. Specifying
-mfast-fpโ link with the fast floating-point library โก It relaxes some of the IEEE floating-point standard's rules for checking inputs against Not-a-Number (NAN), in the name of performance.-minline-pltโ enable inlining of PLT entries in function calls to functions that aren't known to bind locally ๐งฉ It has no effect without-mfdpic.-mmulticoreโ build a standalone application for multicore Blackfin processors ๐ This option makes sure the proper start files and link scripts supporting multicore get used, and it defines the macro__BFIN_MULTICORE. It can only be used with-mcpu=bf561[-sirevision].- This option can be used with
-mcoreaor-mcoreb, which select the one-application-per-core programming model ๐ฏ - Without
-mcoreaor-mcoreb, the single-application/dual-core programming model is used. In this model, themainfunction of Core B should be namedcoreb_main๐ - If this option isn't used, the single-core application programming model is used ๐
- This option can be used with
-mcoreaโ build a standalone application for Core A of BF561 when using the one-application-per-core programming model ๐ ฐ๏ธ Proper start files and link scripts are used to support Core A, and the macro__BFIN_COREAis defined. This option can only be used together with-mmulticore.-mcorebโ build a standalone application for Core B of BF561 when using the one-application-per-core programming model ๐ ฑ๏ธ Proper start files and link scripts are used to support Core B, and the macro__BFIN_COREBis defined. When this option is used,coreb_mainshould be used instead ofmain. This option can only be used together with-mmulticore.-msdramโ build a standalone application for SDRAM ๐ง Proper start files and link scripts are used to put the application into SDRAM, and the macro__BFIN_SDRAMis defined. The loader should initialize SDRAM before loading the application.-micplbโ assume ICPLBs are enabled at run time ๐ This has an effect on certain anomaly workarounds. For Linux targets, the default is to assume ICPLBs are enabled. For standalone applications, the default is off.
๐ฆ C6X Options ๐ฆ
-march=nameโ specifies the name of the target architecture ๐๏ธ GCC uses this name to figure out what kind of instructions it can emit when generating assembly code. Permissible names are: c62x, c64x, c64x+, c67x, c67x+, and c674x.-mbig-endianโ generate code for a big-endian target ๐-mlittle-endianโ generate code for a little-endian target. This is the default ๐-msimโ choose startup files and a linker script that suit the simulator ๐ฅ๏ธ-msdata=defaultโ put 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 is adjacent to.neardata. Small read-only data goes into the.rodatasection. The sections used for large pieces of data are.fardata,.far, and.const.-msdata=allโ put all data, not just small objects, into the sections reserved for small data, and use addressing relative to theB14register to access them ๐-msdata=noneโ make no use of the sections reserved for small data, and use absolute addresses to access all data ๐งญ All initialized global and static data goes in the.fardatasection, all uninitialized data goes in the.farsection, and all constant data goes in the.constsection.
๐ท CRIS Options ๐ท
These options are defined specifically for the CRIS ports ๐
-march=architecture-type,-mcpu=architecture-typeโ generate code for the specified architecture ๐ ๏ธ The choices for architecture-type are v3, v8, and v10, for ETRAX 4, ETRAX 100, and ETRAX 100 LX respectively. The default is v0, except forcris-axis-linux-gnu, where the default is v10.-mtune=architecture-typeโ tune everything applicable about the generated code to architecture-type, except for the ABI and the set of available instructions ๐ถ The choices for architecture-type are the same as for-march=architecture-type.-mmax-stack-frame=nโ warn when the stack frame of a function goes over n bytes ๐จ-metrax4,-metrax100โ these are synonyms for-march=v3and-march=v8, respectively ๐
okay bestie, we're still in the CRIS vibes so let's keep going ๐ฆ
-mmul-bug-workaround,-mno-mul-bug-workaroundโ ๐ Patches up a bug in themulsandmuluinstructions on CPU models where it actually shows up. This one's on by default, so you get the fix for free โจ-mpdebugโ ๐ Turns on CRIS-specific verbose debug info in the assembly output. Heads up: it also switches off the#NO_APPmarker that normally gets dropped at the top of the assembly file for the assembler ๐-mcc-initโ ๐ง Stops GCC from trusting condition-code results left over from the previous instruction. Instead, it always puts in compare and test instructions before any condition codes get used. Extra safe, extra instructions, no cap ๐-mno-side-effectsโ ๐ซ No instructions with side effects in addressing modes, except post-increment. Post-increment is still allowed, bestie ๐-mstack-align,-mno-stack-align,-mdata-align,-mno-data-align,-mconst-align,-mno-const-alignโ ๐ Okay so the plain versions make the stack frame, individual data, and constants line up to the biggest single data access size for your chosen CPU model. Theno-versions cancel that alignment out. By default you get 32-bit alignment, and ABI stuff like structure layout doesn't get touched by any of these โจ
-m32-bit,-m16-bit,-m8-bitโ ๐ Same vibe as the stack, data, and const align options above, but these make the stack frame, writable data, and constants 32-bit, 16-bit, or 8-bit aligned. The default is 32-bit ๐ธ-mno-prologue-epilogue,-mprologue-epilogueโ โ ๏ธ With-mno-prologue-epilogue, the usual function prologue and epilogue that set up the stack frame get skipped, and no return instructions or return sequences show up in the code. Only use this if you're going to eyeball the compiled code yourself ๐ GCC won't warn or error when call-saved registers need saving or local variable storage needs allocating. Be careful out there ๐ญ-mno-gotplt,-mgotpltโ ๐ฆ With-fpicand-fPIC,-mno-gotpltmeans no instruction sequences that load function addresses from the PLT part of the GOT. The alternative, which is how other architectures usually do it, is calls to the PLT. The default is-mgotplt, so that's what you get unless you say otherwise ๐-melfโ ๐ชฆ A legacy no-op. It's only recognized with thecris-axis-elfandcris-axis-linux-gnutargets, so it's basically just vibing there doing nothing ๐-mlinuxโ ๐ชฆ Another legacy no-op, only recognized with thecris-axis-linux-gnutarget ๐-simโ ๐ง Recognized for thecris-axis-elftarget. It links in input-output functions from a simulator library. Code, initialized data, and zero-initialized data all get allocated right next to each other, one after the other โจ-sim2โ ๐ Same as-sim, but it also passes linker options so initialized data lands at0x40000000and zero-initialized data lands at0x80000000๐ฅ
โจ CR16 Options โจ
okay so these options are made specifically for the CR16 ports, so if that's your world, this section is for you ๐ซถ
-mmacโ ๐งฎ Turns on the multiply-accumulate instructions. It's disabled by default, so you have to ask for it ๐-mcr16cplus,-mcr16cโ ๐ฏ Generates code for the CR16C or CR16C+ architecture. CR16C+ is the default, so-mcr16cis how you opt into the older one ๐-msimโ ๐ Links in the librarylibsim.a, which works with the simulator. This one only applies to the ELF compiler, so keep that in mind ๐ธ-mint32โ ๐ข Makes the integer type 32-bit wide ๐-mbit-opsโ โก Generates"sbit"/"cbit"instructions for bit manipulation. Bit-twiddling, but make it efficient ๐-mdata-model=modelโ ๐๏ธ Picks a data model. Your choices arenear,far, ormedium, andmediumis the default. Watch out though:farisn't valid with-mcr16c, because the CR16C architecture doesn't support the far data model at all ๐ญ
โจ C-SKY Options โจ
GCC supports these options when you're compiling for C-SKY V2 processors, so if that's your chip, you're in the right place ๐ง
-march=archโ ๐๏ธ Specifies the C-SKY target architecture. Valid values forarchareck801,ck802,ck803,ck807, andck810. The default isck810๐-mcpu=cpuโ ๐๏ธ Specifies the C-SKY target processor. Valid values forcpuareck801,ck801t,ck802,ck802t,ck802j,ck803,ck803h,ck803t,ck803ht,ck803f,ck803fh,ck803e,ck803eh,ck803et,ck803eht,ck803ef,ck803efh,ck803ft,ck803eft,ck803efht,ck803r1,ck803hr1,ck803tr1,ck803htr1,ck803fr1,ck803fhr1,ck803er1,ck803ehr1,ck803etr1,ck803ehtr1,ck803efr1,ck803efhr1,ck803ftr1,ck803eftr1,ck803efhtr1,ck803s,ck803st,ck803se,ck803sf,ck803sef,ck803seft,ck807e,ck807ef,ck807,ck807f,ck810e,ck810et,ck810ef,ck810eft,ck810,ck810v,ck810f,ck810t,ck810fv,ck810tv,ck810ft, andck810ftv. That's a whole roster, bestie ๐ญ๐ซถ
-mbig-endian,-EB,-mlittle-endian,-ELโ ๐ Picks big-endian or little-endian code. Little-endian is the default ๐-mhard-float,-msoft-floatโ ๐ง Picks hardware or software floating-point. The default is soft float, so you need-mhard-floatif you want the hardware version โจ-mdouble-float,-mno-double-floatโ ๐ฏ When-mhard-floatis in effect,-mdouble-floatturns on double-precision float instructions. This is the default unless you're compiling for CK803 ๐ธ-mfdivdu,-mno-fdivduโ โ When-mhard-floatis in effect,-mfdivduturns on the"frecipd","fsqrtd", and"fdivd"instructions. Also the default unless you're compiling for CK803 ๐-mfpu=fpuโ ๐งฉ Selects the floating-point processor. This only works together with-mhard-float. The values forfpuarefpv2_sf(which is the same as-mno-double-float -mno-fdivdu),fpv2(-mdouble-float -mno-divdu), andfpv2_divd(-mdouble-float -mdivdu) ๐ฅ-melrw,-mno-elrwโ ๐ช Turns on the extended"lrw"instruction. It defaults to on for CK801 and off for everything else ๐-mistack,-mno-istackโ ๐ Turns on interrupt stack instructions. The default is off ๐
โ ๏ธ You need-mistackto handle the"interrupt"and"isr"function attributes. No-mistack, no interrupt handling, periodt ๐ญ
-mmpโ ๐งต Turns on multiprocessor instructions. Default is off ๐-mcpโ ๐ค Turns on coprocessor instructions. Default is off ๐ฆ-mcacheโ ๐๏ธ Turns on coprocessor instructions. Default is off. Yes, the original says the same thing as-mcp, so both of these are doing the coprocessor thing ๐-msecurityโ ๐ Turns on C-SKY security instructions. Default is off โจ-mtrustโ ๐ซก Turns on C-SKY trust instructions. Default is off ๐-mdsp,-medsp,-mvdspโ ๐ถ Turn on C-SKY DSP, Enhanced DSP, or Vector DSP instructions, respectively. They all default to off ๐-mdiv,-mno-divโ โ Generates divide instructions. Default is off ๐-msmart,-mno-smartโ ๐ง Generates code for Smart Mode, which only uses registers numbered 0-7 so you can use 16-bit instructions. This is ignored for CK801, where that's already the required behavior, and it defaults to on for CK802. For other targets, the default is off ๐ธ-mhigh-registers,-mno-high-registersโ ๐ Generates code using the high registers numbered 16-31. This isn't supported on CK801, CK802, or CK803, but it's enabled by default for other processors ๐-manchor,-mno-anchorโ โ Generates code using global anchor symbol addresses ๐-mpushpop,-mno-pushpopโ ๐ฅ Generates code using"push"and"pop"instructions. This option defaults to on ๐-mmultiple-stld,-mstm,-mno-multiple-stld,-mno-stmโ ๐งบ Generates code using"stm"and"ldm"instructions. This one isn't supported on CK801, but it's enabled by default on other processors ๐-mconstpool,-mno-constpoolโ ๐ Creates constant pools in the compiler, instead of leaving it to the assembler. This is the default and it's required for correct code generation on CK801 and CK802. It's optional on other processors ๐-mstack-size,-mno-stack-sizeโ ๐ Emits".stack_size"directives for each function in the assembly output. Defaults to off ๐-mccrt,-mno-ccrtโ ๐ ๏ธ Generates code for the C-SKY compiler runtime instead of libgcc. Defaults to off โจ-mbranch-cost=nโ ๐ค๏ธ Sets the branch costs to roughly"n"instructions. The default is 1 ๐ฆ-msched-prolog,-mno-sched-prologโ โฐ Permits scheduling of function prologue and epilogue sequences. Heads up, this can give you code that doesn't follow the C-SKY V2 ABI prologue requirements, and that code can't be debugged or backtraced. It's disabled by default, so only turn it on if you know what you're doing ๐ญ
โจ Darwin Options โจ
These options are defined for all architectures running the Darwin operating system ๐
Okay so FSF GCC on Darwin does not make "fat" object files. It makes an object file for the single architecture GCC was built to target. Apple's GCC, though, does make "fat" files if you use multiple -arch options. It does that by running the compiler or linker multiple times and then joining the results together with lipo ๐ซถ
The subtype of the file (like ppc7400, ppc970, or i686) gets decided by the flags that specify the ISA GCC is targeting, like -mcpu or -march. The -force_cpusubtype_ALL option can override that if you need it to ๐
The Darwin tools act differently when they hit an ISA mismatch, so pay attention ๐ The assembler, as, only lets instructions be used if they're valid for the subtype of the file it's generating. So no 64-bit instructions in a ppc750 object file, sorry bestie ๐ The linker for shared libraries, /usr/bin/libtool, fails and prints an error if you ask it to make a shared library with a less restrictive subtype than its input files. For example, putting a ppc970 object file in a ppc7400 library is a no-go ๐
โโ๏ธ The linker for executables, ld, quietly gives the executable the most restrictive subtype of any of its input files ๐คซ
-Fdirโ ๐ Adds the framework directorydirto the front of the list of directories searched for header files. These directories get mixed in with the ones from-Ioptions, and they're scanned left-to-right ๐ธ
A framework directory ๐๏ธ is just a folder full of frameworks, and a framework is a directory with a Headers and/or PrivateHeaders folder sitting directly inside it and a name ending in .framework ๐. The framework's name is that folder name minus the .framework part. Its headers live in one of those two folders, and Headers gets searched first ๐. A subframework is a framework tucked inside another framework's Frameworks directory. Subframework headers can only be included from a header of the framework that contains them, or from a sibling subframework's header ๐ซถ. Two subframeworks are siblings if they live in the same framework. A subframework shouldn't share a name with a framework, and the compiler warns you if it does ๐. Right now subframeworks can't have subframeworks of their own, but that might change later ๐. The standard frameworks live in /System/Library/Frameworks and /Library/Frameworks. An include looks like #include <Framework/header.h>, where Framework is the framework's name and header.h is found in the PrivateHeaders or Headers folder โจ.
-iframeworkdirโ This is like-F, except the directory gets treated as a system directory ๐ง. The big difference is that with-iframeworkthe compiler won't warn about constructs inside header files it finds through that directory. This only works for the C family of languages.-gusedโ Emits debugging info for symbols that are actually used ๐. For the stabs debugging format, this turns on-feliminate-unused-debug-symbols. It's ON by default, so you're already getting it ๐ .-gfullโ Emits debugging info for every symbol and type, no exceptions ๐.-mmacosx-version-min=versionโ The earliest version of MacOS X this executable will run on is version ๐. Typical values include10.1,10.2, and10.3.9. If the compiler was built to use the system's headers by default, the default for this option is the system version the compiler is running on. Otherwise, it picks choices that are compatible with as many systems and code bases as possible ๐ซง.-mkernelโ Turns on kernel development mode ๐ฅ. This sets-static,-fno-common,-fno-use-cxa-atexit,-fno-exceptions,-fno-non-call-exceptions,-fapple-kext,-fno-weakand-fno-rtti, where applicable. For PowerPC targets, it also sets-mno-altivec,-msoft-float,-fno-builtinand-mlong-branch๐.-mone-byte-boolโ Overrides the defaults forboolso thatsizeof(bool)==1๐ซ . By default,sizeof(bool)is 4 when compiling for Darwin/PowerPC and 1 when compiling for Darwin/x86, so this option does nothing on x86.
โ ๏ธ Warning: The -mone-byte-bool switch causes GCC to generate code that is not binary compatible with code generated without that switch. Using this switch may require recompiling all other modules in a program, including system libraries. Use this switch to conform to a non-default data model. ๐
-mfix-and-continue,-ffix-and-continue,-findirect-dataโ These generate code built for fast turnaround development โก, like letting GDB dynamically load.ofiles into programs that are already running ๐โโ๏ธ.-findirect-dataand-ffix-and-continueare only here for backwards compatibility ๐ฐ๏ธ.-all_loadโ Loads all members of static archive libraries ๐ฆ. Seeman ld(1)for more information.-arch_errors_fatalโ Makes errors about files with the wrong architecture fatal ๐.-bind_at_loadโ Marks the output file so the dynamic linker binds all undefined references when the file is loaded or launched ๐.-bundleโ Produces a Mach-o bundle format file ๐งณ. Seeman ld(1)for more information.-bundle_loader executableโ Specifies the executable that will load the build output file being linked ๐ฏ. Seeman ld(1)for more information.-dynamiclibโ When you pass this, GCC produces a dynamic library instead of an executable when linking, using the Darwinlibtoolcommand ๐ธ.-force_cpusubtype_ALLโ Gives GCC's output file the ALL subtype, instead of one controlled by the-mcpuor-marchoption ๐ฆ.- Darwin linker passthroughs โ Everything below is passed to the Darwin linker. The Darwin linker man page explains them in detail, so go there for the full tea โ:
-allowable_client client_name-client_name-compatibility_version-current_version-dead_strip-dependency-file-dylib_file-dylinker_install_name-dynamic-exported_symbols_list-filelist-flat_namespace-force_flat_namespace-headerpad_max_install_names-image_base-init-install_name-keep_private_externs-multi_module-multiply_defined-multiply_defined_unused-noall_load-no_dead_strip_inits_and_terms-nofixprebinding-nomultidefs-noprebind-noseglinkedit-pagezero_size-prebind-prebind_all_twolevel_modules-private_bundle-read_only_relocs-sectalign-sectobjectsymbols-whyload-seg1addr-sectcreate-sectobjectsymbols-sectorder-segaddr-segs_read_only_addr-segs_read_write_addr-seg_addr_table-seg_addr_table_filename-seglinkedit-segprot-segs_read_only_addr-segs_read_write_addr-single_module-static-sub_library-sub_umbrella-twolevel_namespace-umbrella-undefined-unexported_symbols_list-weak_reference_mismatches-whatsloaded
๐ฆ DEC Alpha Options ๐ฆ
These -m options are defined for the DEC Alpha implementations ๐.
-mno-soft-float,-msoft-floatโ Uses (or doesn't use) the hardware floating-point instructions for floating-point operations ๐ข. When-msoft-floatis specified, functions inlibgcc.aare used to do the floating-point work. Unless those get replaced by routines that emulate the floating-point operations, or get compiled to call such emulation routines, these routines will issue floating-point operations ๐ฌ. If you're compiling for an Alpha without floating-point operations, you have to make sure the library is built so it doesn't call them.
Note that Alpha implementations without floating-point operations are still required to have floating-point registers ๐ง .
-mfp-reg,-mno-fp-regsโ Generates code that uses (or doesn't use) the floating-point register set ๐.-mno-fp-regsimplies-msoft-float. If the floating-point register set isn't used, floating-point operands get passed in integer registers as if they were integers, and floating-point results get passed in$0instead of$f0. This is a non-standard calling sequence, so any function with a floating-point argument or return value that's called by code compiled with-mno-fp-regsmust also be compiled with that option ๐จ.
A typical use of this option is building a kernel that doesn't use, and so doesn't need to save and restore, any floating-point registers ๐งโ๐ป.
-mieeeโ The Alpha architecture has floating-point hardware that's optimized for max performance โก. It's mostly compliant with the IEEE floating-point standard, but full compliance needs some software help. This option generates fully IEEE-compliant code, except that the inexact-flag isn't maintained (see below). When you turn this on, the preprocessor macro"_IEEE_FP"gets defined during compilation. The resulting code is less efficient, but it can correctly support denormalized numbers and exceptional IEEE values like not-a-number and plus/minus infinity ๐. Other Alpha compilers call this option-ieee_with_no_inexact.-mieee-with-inexactโ This is like-mieee, except the generated code also maintains the IEEE inexact-flag ๐ซง. Turning this on makes the generated code implement fully-compliant IEEE math. On top of"_IEEE_FP", the preprocessor macro"_IEEE_FP_EXACT"also gets defined. On some Alpha implementations, the resulting code may run significantly slower than the default code ๐ข. Since there's very little code that depends on the inexact-flag, you should normally not specify this option ๐ โโ๏ธ. Other Alpha compilers call this option-ieee_with_inexact.-mfp-trap-mode=trap-modeโ Controls which floating-point related traps are enabled ๐ชค. Other Alpha compilers call this option-fptm trap-mode. The trap mode can be set to one of four values:nโ This is the default (normal) setting. The only traps enabled are the ones that can't be disabled in software (for example, the division by zero trap) ๐งฑ.uโ On top of the traps enabled byn, underflow traps are enabled too ๐.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. The rounding-mode can be one of:nโ Normal IEEE rounding mode. Floating-point numbers are rounded towards the nearest machine number, or towards the even machine number in case of a tie ๐ฒ.mโ Rounds towards minus infinity โฌ๏ธ.cโ Chopped rounding mode. Floating-point numbers are rounded towards zero โ๏ธ.dโ Dynamic rounding mode. A field in the floating-point control register (fpcr, see the Alpha architecture reference manual) controls the rounding mode in effect ๐๏ธ. The C library initializes this register for rounding towards plus infinity, so unless your program modifies thefpcr,dcorresponds to rounding towards plus infinity โฌ๏ธ.
-mtrap-precision=trap-precisionโ In the Alpha architecture, floating-point traps are imprecise ๐ตโ๐ซ. That means without software assistance it's impossible to recover from a floating trap, and program execution normally has to be terminated. GCC can generate code that helps operating system trap handlers figure out the exact location that caused a floating-point trap ๐ต๏ธโโ๏ธ. Depending on what your application needs, you can select different levels of precision:
Okay bestie, the -mtrap-precision values are where we pick up ๐ซถ
p๐ Program precision. This one's the default, and it means a trap handler can only tell which program caused a floating-point exception.f๐ Function precision. The trap handler can figure out which function caused a floating-point exception.i๐ฆ Instruction precision. The trap handler can pinpoint the exact instruction that caused a floating-point exception.
Other Alpha compilers have equivalent options called -scope_safe and -resumption_safe. iykyk ๐
-mieee-conformantโจ marks the generated code as IEEE conformant. โ ๏ธ You must not use this unless you also specify-mtrap-precision=iand either-mfp-trap-mode=suor-mfp-trap-mode=sui. That's the whole rule, no cap. All it actually does is 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 and checks whether it can build it from smaller constants in two or three instructions. If it can't, it outputs the constant as a literal and generates code that loads it from the data segment at run time. With this option, GCC is forced to build every integer constant with code, even if that takes more instructions (the maximum is six). Main character energy, but you asked for it ๐
You typically use this when building a shared library dynamic loader ๐ธ. It's a shared library itself, so it has to relocate itself in memory before it can find the variables and constants in its own data segment.
-mbwx,-mno-bwx,-mcix,-mno-cix,-mfix,-mno-fix,-mmax,-mno-max๐ decide whether GCC is allowed to generate code using the optional BWX, CIX, FIX and MAX instruction sets. By default, it uses whatever instruction sets the CPU type from-mcpu=supports, or the CPU the compiler was built on if you don't set one.-mfloat-vax,-mfloat-ieee๐ switch between generating code that uses VAX F and G floating-point arithmetic (-mfloat-vax) and code that doesn't use it, sticking with IEEE single and double precision (-mfloat-ieee).-mexplicit-relocs,-mno-explicit-relocs๐ฅ Okay, the history is kinda wild. Older Alpha assemblers had no way to generate symbol relocations except through assembler macros, and those macros don't allow optimal instruction scheduling. GNU binutils as of version 2.12 added a new syntax that lets the compiler explicitly mark which relocations apply to which instructions. This option is mostly useful for debugging, since GCC detects the assembler's capabilities when it's built and sets the default accordingly.-msmall-data,-mlarge-data๐ When-mexplicit-relocsis in effect, static data is accessed through gp-relative relocations. With-msmall-data, objects 8 bytes long or smaller get placed in a small data area (the ".sdata" and ".sbss" sections) and accessed through 16-bit relocations off the$gpregister. This caps the small data area at 64KB, but the variables can be accessed directly with a single instruction, which is so efficient ๐ญ
The default is -mlarge-data. With this option, the data area is limited to just below 2GB. Programs needing more than 2GB of data have to use "malloc" or "mmap" to allocate it on the heap instead of in the program's data segment.
When generating code for shared libraries, -fpic implies -msmall-data, and -fPIC implies -mlarge-data.
-msmall-text,-mlarge-text๐ฆ With-msmall-text, the compiler assumes the code for the entire program (or shared library) fits in 4MB, so it's reachable with a branch instruction. When-msmall-datais also used, the compiler can assume all local symbols share the same$gpvalue, which cuts the instructions needed for a function call from 4 down to 1. The default is-mlarge-text.-mcpu=cpu_type๐ sets the instruction set and instruction scheduling parameters for the machine typecpu_type. You can pass either the EV style name or the matching chip number. GCC has scheduling parameters for the EV4, EV5 and EV6 families, and picks the default instruction set from the processor you name. If you don't name one, GCC defaults to the processor the compiler was built on.
Supported values for cpu_type are:
ev4,ev45,21064: schedules as an EV4 and has no instruction set extensions.ev5,21164: schedules as an EV5 and has no instruction set extensions.ev56,21164a: schedules as an EV5 and supports the BWX extension.pca56,21164pc,21164PC: schedules as an EV5 and supports the BWX and MAX extensions.ev6,21264: schedules as an EV6 and supports the BWX, FIX, and MAX extensions.ev67,21264a: schedules as an EV6 and supports the BWX, CIX, FIX, and MAX extensions.
Native toolchains also accept native, which picks the best architecture option for the host processor. -mcpu=native does nothing if GCC doesn't recognize the processor.
-mtune=cpu_type๐ง sets only the instruction scheduling parameters forcpu_type. The instruction set stays exactly the same.
Native toolchains also accept native, which picks the best architecture option for the host processor. -mtune=native does nothing if GCC doesn't recognize the processor.
-mmemory-latency=timeโฑ๏ธ sets the latency the scheduler should assume for typical memory references, as the application sees them. This number depends a lot on the application's memory access patterns and on the size of the external cache on the machine.
Valid values for time are:
number: a decimal number of clock cycles.L1,L2,L3,main: GCC has estimates of clock cycles for "typical" EV4 & EV5 hardware at the Level 1, 2 and 3 caches (also called Dcache, Scache, and Bcache), plus main memory. Heads up:L3is only valid for EV5.
๐ง FR30 Options
These options are defined specifically for the FR30 port.
-msmall-model๐ธ uses the small address space model. This can produce smaller code, but it does assume 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 for real hardware. You have to provide your own runtime library for whatever I/O functions you need.-mlra๐งช enables Local Register Allocation. It's still experimental for FT32, so by default the compiler uses standard reload.-mnodiv๐ซ stops the compiler from usingdivandmodinstructions.-mft32b๐ฆ enables the extended instructions of the FT32B processor.-mcompress๐๏ธ compresses all code using the Ft32B code compression scheme.-mnopm๐ stops the compiler from generating code that reads program memory.
๐ FRV Options
-mgpr-32only uses the first 32 general-purpose registers.-mgpr-64uses all 64 general-purpose registers.-mfpr-32only uses the first 32 floating-point registers.-mfpr-64uses all 64 floating-point registers.-mhard-floatuses hardware instructions for floating-point operations.-msoft-floatuses library routines for floating-point operations.-malloc-ccdynamically allocates condition code registers.-mfixed-ccdoes not try to dynamically allocate condition code registers. It only uses "icc0" and "fcc0". ๐ซ-mdwordchanges the ABI to use double word insns.-mno-dworddoesn't use double word instructions.-mdoubleuses floating-point double instructions.-mno-doubledoesn't use floating-point double instructions.-mmediauses media instructions.-mno-mediadoesn't use media instructions.-mmuladduses multiply and add/subtract instructions.-mno-muladddoesn'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 a bfin-elf target, 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 when optimizing for speed and compiling shared libraries (i.e.,-fPICor-fpic), or when an optimization option such as-O3or above is on the command line.-mTLS๐ฆ assumes a large TLS segment when generating thread-local code.-mtls๐ชถ does not assume a large TLS segment when generating thread-local code.-mgprel-ro๐ enables the use of "GPREL" relocations in the FDPIC ABI for data 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 there. With-fPICor-fPIE, it trades 3 instructions for 4, one of which may be shared by multiple symbols, and it avoids needing a GOT entry for the referenced symbol, so it's more likely to be a win. If it isn't,-mno-gprel-rocan turn it off.-multilib-library-pic๐ links with the (library, not FD) pic libraries. It's implied by-mlibrary-pic, and by-fPICand-fpicwithout-mfdpic. You should never have to use it explicitly.-mlinked-fp๐ผ๏ธ follows the EABI requirement of always creating a frame pointer whenever a stack frame is allocated. This option is enabled by default and can be disabled with-mno-linked-fp.-mlong-callsโ okay so this one uses indirect addressing to call functions sitting outside the current compilation unit ๐ฆ. The functions can be placed anywhere within the 32-bit address space โจ.-malign-labelsโ this tries to align labels to an 8-byte boundary by slipping NOPs into the previous packet ๐ซถ. It only has an effect when VLIW packing is enabled, and it never creates new packets. It just adds NOPs to packets that already exist ๐ .-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โ does not pack VLIW instructions ๐.-mno-eflagsโ does not mark ABI switches ine_flags๐.-mcond-moveโ enables conditional-move instructions, and this is the default ๐. Mainly for debugging the compiler, and it'll likely be removed in a future version.-mno-cond-moveโ disables conditional-move instructions ๐ โโ๏ธ. Mainly for debugging the compiler, and it'll likely be removed in a future version.-msccโ enables conditional set instructions, and this is the default โจ. Mainly for debugging the compiler, and it'll likely be removed in a future version.-mno-sccโ disables conditional set instructions ๐ฅ. Mainly for debugging the compiler, and it'll likely be removed in a future version.-mcond-execโ enables conditional execution, and this is the default ๐ฆ. Mainly for debugging the compiler, and it'll likely be removed in a future version.-mno-cond-execโ disables conditional execution ๐ซ. Mainly for debugging the compiler, and it'll likely be removed in a future version.-mvliw-branchโ runs a pass that packs branches into VLIW instructions, and this is the default ๐. Mainly for debugging the compiler, and it'll likely be removed in a future version.-mno-vliw-branchโ does not run the pass that packs branches into VLIW instructions ๐ซ . Mainly for debugging the compiler, and it'll likely be removed in a future version.-mmulti-cond-execโ enables optimization of"&&"and"||"in conditional execution, and this is the default ๐ฅ. Mainly for debugging the compiler, and it'll likely be removed in a future version.-mno-multi-cond-execโ disables optimization of"&&"and"||"in conditional execution ๐ค. Mainly for debugging the compiler, and it'll likely be removed in a future version.-mnested-cond-execโ enables nested conditional execution optimizations, and this is the default ๐. Mainly for debugging the compiler, and it'll likely be removed in a future version.-mno-nested-cond-execโ disables nested conditional execution optimizations ๐. Mainly for debugging the compiler, and it'll likely be removed in a future version.-moptimize-membarโ removes redundant"membar"instructions from the compiler-generated code, and it's enabled by default ๐งน.-mno-optimize-membarโ disables the automatic removal of redundant"membar"instructions from the generated code ๐.-mtomcat-statsโ makesgasprint out tomcat statistics ๐.-mcpu=cpuโ picks the processor type to generate code for ๐ฅ๏ธ. The possible values arefrv,fr550,tomcat,fr500,fr450,fr405,fr400,fr300andsimple๐ .
โจ GNU/Linux Options โจ
These -m options are defined for GNU/Linux targets ๐ง:
-mglibcโ uses the GNU C library ๐. This is the default except on*-*-linux-*uclibc*,*-*-linux-*musl*and*-*-linux-*android*targets.-muclibcโ uses the uClibc C library ๐ท. This is the default on*-*-linux-*uclibc*targets.-mmuslโ uses the musl C library ๐. This is the default on*-*-linux-*musl*targets.-mbionicโ uses the Bionic C library ๐ค. This is the default on*-*-linux-*android*targets.-mandroidโ compiles code that's compatible with the Android platform ๐ฑ. This is the default on*-*-linux-*android*targets. When compiling, this option enables-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default. When linking, it makes the GCC driver pass Android-specific options to the linker. It also causes the preprocessor macro"__ANDROID__"to be defined ๐ซถ.-tno-android-ccโ turns off the compilation effects of-mandroid, i.e., doesn't enable-mbionic,-fPIC,-fno-exceptionsand-fno-rttiby default ๐ โโ๏ธ.-tno-android-ldโ turns off the linking effects of-mandroid, i.e., passes standard Linux linking options to the linker ๐.
โจ H8/300 Options โจ
These -m options are defined for the H8/300 implementations ๐ฆ:
-mrelaxโ shortens some address references at link time, when possible ๐ช. It uses the linker option-relax.-mhโ generates code for the H8/300H ๐ธ.-msโ generates code for the H8S ๐.-mnโ generates code for the H8S and H8/300H in the normal mode ๐ฐ. This switch must be used either with-mhor-ms.-ms2600โ generates code for the H8S/2600 ๐. This switch must be used with-ms.-mexrโ extended registers get stored on the stack before a function with the monitor attribute runs ๐. The default option is-mexr. This option is only valid for H8S targets.-mno-exrโ extended registers do not get stored on the stack before a function with the monitor attribute runs ๐. The default option is-mno-exr. This option is only valid for H8S targets.-mint32โ makes"int"data 32 bits by default ๐ข.-malign-300โ on the H8/300H and H8S, uses the same alignment rules as the H8/300 ๐. The default for the H8/300H and H8S is to align longs and floats on 4-byte boundaries, but-malign-300makes them align on 2-byte boundaries instead. This option has no effect on the H8/300 ๐ซ .
โจ HPPA Options โจ
These -m options are defined for the HPPA family of computers ๐จ๏ธ:
-march=architecture-typeโ generates code for the specified architecture ๐๏ธ. The choices for architecture-type are1.0for PA 1.0,1.1for PA 1.1, and2.0for PA 2.0 processors. Refer to/usr/lib/sched.modelson an HP-UX system to figure out the proper architecture option for your machine ๐ง. Code compiled for lower numbered architectures runs on higher numbered architectures, but not the other way around ๐ซ.-mpa-risc-1-0โ a synonym for-march=1.0๐.-mpa-risc-1-1โ a synonym for-march=1.1๐.-mpa-risc-2-0โ a synonym for-march=2.0๐.-mcaller-copiesโ the caller copies function arguments that get passed by hidden reference ๐งณ. This option should be used with care, because it isn't compatible with the default 32-bit runtime ๐ฌ. That said, only aggregates larger than eight bytes are passed by hidden reference, and this option gives better compatibility with OpenMP ๐ซถ.-mjump-in-delayโ this option is ignored and only exists for compatibility purposes ๐.-mdisable-fpregsโ stops floating-point registers from being used in any manner ๐ท. This is necessary for compiling kernels that do lazy context switching of floating-point registers ๐ง . If you use this option and then try to do floating-point operations, the compiler aborts ๐.-mdisable-indexingโ stops the compiler from using indexing address modes ๐ โโ๏ธ. This avoids some rather obscure problems when compiling MIG generated code under MACH ๐ต๏ธโโ๏ธ.-mno-space-regsโ generates code that assumes the target has no space registers ๐. This lets GCC generate faster indirect calls and use unscaled index address modes โก. Such code is suitable for level 0 PA systems and kernels ๐ง.-mfast-indirect-callsโ generates code that assumes calls never cross space boundaries ๐โโ๏ธ. This lets GCC emit code that performs faster indirect calls. This option does not work in the presence of shared libraries or nested functions ๐ญ.-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers ๐. A fixed register is one the register allocator can't use. This 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 ๐.-mlong-load-storeโ generates 3-instruction load and store sequences, which are sometimes required by the HP-UX 10 linker ๐ง. This is equivalent to the+koption to the HP compilers ๐ .-mportable-runtimeโ uses the portable calling conventions HP proposed for ELF systems ๐งณ.-mgasโ enables the use of assembler directives that only GAS understands ๐ง .-mschedule=cpu-typeโ schedules code according to the constraints for the machine type cpu-type ๐๏ธ. The choices for cpu-type are700 7100,7100LC,7200,7300and8000. Refer to/usr/lib/sched.modelson an HP-UX system to determine the proper scheduling option for your machine ๐. The default scheduling is8000โจ.-mlinker-optโ enables the optimization pass in the HP-UX linker ๐ ๏ธ. Heads up, this makes symbolic debugging impossible ๐. It also triggers a bug in the HP-UX 8 and HP-UX 9 linkers, where they give bogus error messages when linking some programs ๐.-msoft-floatโ generates output that contains library calls for floating point ๐งฎ.
Warning: the requisite libraries are not available for all HPPA targets ๐จ. Normally the facilities of the machine's usual C compiler are used, but this can't be done directly in cross-compilation. You must make your own arrangements to provide suitable library functions for cross-compilation ๐ซ .
-msoft-float changes the calling convention in the output file, so it's only useful if you compile all of a program with this option ๐งฉ. In particular, you need to compile libgcc.a, the library that comes with GCC, with -msoft-float in order for this to work ๐ซถ.
-msioโ generates the predefine"_SIO"for server IO ๐ง. The default is-mwsio. That one generates the predefines"__hp9000s700","__hp9000s700__"and"_WSIO"for workstation IO ๐ฅ๏ธ. These options are available under HP-UX and HI-UX ๐.-mgnu-ldโ okay, this one tells GCC to use the GNU ld options ๐. It passes-sharedto ld when you're building a shared library, and it's the default if GCC was configured with the GNU linker, explicitly or implicitly. It only changes which parameters get passed, not which ld gets called. That's decided by the--with-ldconfigure option, GCC's program search path, and then your PATH. To see the linker GCC is using, runwhich `gcc -print-prog-name=ld`๐ง. Only available on the 64-bit HP-UX GCC (hppa*64*-*-hpux*) ๐.-mhp-ldโ same vibe, but for the HP linker ๐ . It passes-bto ld when building a shared library and passes+Accept TypeMismatchto ld on all links. It's the default if GCC was configured with the HP linker, explicitly or implicitly. Like-mgnu-ld, it doesn't change which ld is called, just the parameters sent to it. The ld is picked by--with-ld, GCC's program search path, and then PATH. Check the linker withwhich `gcc -print-prog-name=ld`โจ. Only available on the 64-bit HP-UX GCC (hppa*64*-*-hpux*) ๐ธ.-mlong-callsโ generates long call sequences ๐ฆ. This makes sure a call can always reach linker-generated stubs. By default, long calls only kick in when the distance from the call site to the start of the function or translation unit (depending on the case) goes over a limit set by the branch type. Those limits are 7,600,000 bytes for normal calls on PA 2.0 and 240,000 bytes on PA 1.X. Sibcalls are always capped at 240,000 bytes ๐.
Distances are measured from the start of functions when you use -ffunction-sections, or when you use -mgas and -mno-portable-runtime together under HP-UX with the SOM linker.
Heads up: this usually isn't what you want, because it degrades performance ๐ญ. It might still be useful in big applications, especially when partial linking is used to build the app.
The kind of long calls used depends on what the assembler and linker can do, plus the type of code being generated. The hit on systems that support long absolute calls, and long PIC symbol-difference or pc-relative calls, should be pretty small. An indirect call is used on 32-bit ELF systems in PIC code, though, and it's quite long ๐.
-munix=unix-stdโ generates compiler predefines and picks a startfile for the UNIX standard you specify ๐. The choices are93,95, and98.93works on all HP-UX versions.95is available on HP-UX 10.10 and later.98is available on HP-UX 11.11 and later. The defaults are93for HP-UX 10.00,95for HP-UX 10.10 through 11.00, and98for HP-UX 11.11 and later ๐.
-munix=93 gives the same predefines as GCC 3.3 and 3.4. -munix=95 adds predefines for "XOPEN_UNIX" and "_XOPEN_SOURCE_EXTENDED", plus the startfile unix95.o. -munix=98 adds predefines for "_XOPEN_UNIX", "_XOPEN_SOURCE_EXTENDED", "_INCLUDE__STDC_A1_SOURCE" and "_INCLUDE_XOPEN_SOURCE_500", plus the startfile unix98.o ๐.
Warning, bestie ๐จ: this option changes the interfaces of various library routines and also affects how the C library behaves at runtime. Be extremely careful using it ๐ฌ.
Library code meant to work with more than one UNIX standard has to test, set, and restore the variable "__xpg4_extended_mask" as needed. Most GNU software doesn't offer this capability ๐ฅบ.
-nolibdldโ stops GCC from adding link options that searchlibdld.slwhen-staticis used on HP-UX 10 and later ๐.-staticโ okay, so the HP-UX version ofsetlocalein libc depends onlibdld.sl, and there's no archive version of it ๐. That means when you use-static, you need special link options to resolve the dependency โจ.
On HP-UX 10 and later, the GCC driver adds those options to link with libdld.sl when -static is specified. This makes the resulting binary dynamic, which is kind of ironic ๐. On the 64-bit port, the linkers make dynamic binaries by default anyway. If you don't want the driver adding these 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 ๐.
โจ IA-64 Options โจ
These are the -m options defined for the Intel IA-64 architecture ๐.
-mbig-endianโ generates code for a big-endian target. This is the default for HP-UX ๐.-mlittle-endianโ generates code for a little-endian target. This is the default for AIX5 and GNU/Linux ๐ธ.-mgnu-as/-mno-gnu-asโ generates (or doesn't) code for the GNU assembler. The default is-mgnu-as๐.-mgnu-ld/-mno-gnu-ldโ generates (or doesn't) code for the GNU linker. The default is-mgnu-ldโจ.-mno-picโ generates code that doesn't use a global pointer register ๐ . The result isn't position independent code, and it violates the IA-64 ABI ๐.-mvolatile-asm-stop/-mno-volatile-asm-stopโ generates (or doesn't) a stop bit immediately before and after volatile asm statements ๐ฅ.-mregister-names/-mno-register-namesโ generates (or doesn't)in,loc, andoutregister names for the stacked registers. This may make assembler output more readable ๐.-mno-sdata/-msdataโ disables (or enables) optimizations that use the small data section ๐ง. This may be useful for working around optimizer bugs ๐.-mconstant-gpโ generates code that uses a single constant global pointer value. This is useful when compiling kernel code ๐ซถ.-mauto-picโ generates code that is self-relocatable. This implies-mconstant-gp. It's useful when compiling firmware code ๐ฆ.-minline-float-divide-min-latencyโ generates code for inline divides of floating-point values using the minimum latency algorithm โญ.-minline-float-divide-max-throughputโ generates code for inline divides of floating-point values using the maximum throughput algorithm ๐.-mno-inline-float-divideโ doesn't generate inline code for divides of floating-point values ๐ .-minline-int-divide-min-latencyโ generates code for inline divides of integer values using the minimum latency algorithm ๐.-minline-int-divide-max-throughputโ generates code for inline divides of integer values using the maximum throughput algorithm ๐.-mno-inline-int-divideโ doesn't generate inline code for divides of integer values ๐ฅบ.-minline-sqrt-min-latencyโ generates code for inline square roots using the minimum latency algorithm ๐ธ.-minline-sqrt-max-throughputโ generates code for inline square roots using the maximum throughput algorithm ๐.-mno-inline-sqrtโ doesn't generate inline code for "sqrt" ๐.-mfused-madd/-mno-fused-maddโ does (or doesn't) generate code that uses the fused multiply/add or multiply/subtract instructions. The default is to use these instructions โจ.-mno-dwarf2-asm/-mdwarf2-asmโ doesn't (or does) generate assembler code for the DWARF line number debugging info. This may be useful when you're not using the GNU assembler ๐ง.-mearly-stop-bits/-mno-early-stop-bitsโ allows stop bits to be placed earlier than immediately 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. This is useful when compiling kernel code ๐ซถ. A register range is two registers separated by a dash, and you can specify 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 of "ld.a" instructions and the corresponding check instructions ("ld.c" / "chk.a") ๐ง . The default setting is disabled ๐.-msched-ar-data-spec/-mno-sched-ar-data-specโ (en/dis)ables data speculative scheduling after reload. This results in generation of "ld.a" instructions and the corresponding check instructions ("ld.c" / "chk.a") โญ. The default setting is enabled โจ.-mno-sched-control-spec/-msched-control-specโ (dis/en)ables control speculative scheduling. This feature is only available during region scheduling (i.e. before reload) ๐. It results in generation of the "ld.s" instructions and the corresponding check instructions "chk.s" ๐. The default setting is disabled ๐ .-msched-br-in-data-spec/-mno-sched-br-in-data-specโ (en/dis)ables speculative scheduling of instructions that depend on data speculative loads before reload ๐ฆ. This is only effective with-msched-br-data-specenabled. The default setting is enabled ๐ธ.-msched-ar-in-data-spec/-mno-sched-ar-in-data-specโ (en/dis)ables speculative scheduling of instructions that depend on data speculative loads after reload ๐. This is only effective with-msched-ar-data-specenabled. The default setting is enabled ๐.-msched-in-control-spec/-mno-sched-in-control-specโ (en/dis)ables speculative scheduling of instructions that depend on control speculative loads ๐ซถ. This is only effective with-msched-control-specenabled. The default setting is enabled ๐.-mno-sched-prefer-non-data-spec-insns,-msched-prefer-non-data-spec-insnsโ okay so when this is turned on, data-speculative instructions only get picked for scheduling if there are literally no other choices ๐ It makes data speculation way more conservative ๐ซถ The default is disabled ๐ธ-mno-sched-prefer-non-control-spec-insns,-msched-prefer-non-control-spec-insnsโ same energy, but for control-speculative instructions โจ When this is enabled they only get scheduled if nothing else is available, which makes control speculation super cautious ๐ฆ Default is disabled ๐-mno-sched-count-spec-in-critical-path,-msched-count-spec-in-critical-pathโ when enabled, speculative dependencies get counted while the scheduler figures out instruction priorities ๐ง That makes speculation a bit more conservative too ๐ The default is disabled ๐-msched-spec-ldcโ uses a simple data speculation check ๐ This one is on by default, so you get it without asking ๐-msched-control-spec-ldcโ uses a simple check for control speculation ๐ซถ Also on by default ๐ธ-msched-stop-bits-after-every-cycleโ places a stop bit after every cycle while scheduling โญ On by default, no notes ๐-msched-fp-mem-deps-zero-costโ assumes floating-point stores and loads won't likely cause a conflict when they land in the same instruction group ๐ฆ This one is disabled by default, so you have to opt in ๐-msel-sched-dont-check-control-specโ this one is kind of backwards in name vibes ๐ญ It generates checks for control speculation in selective scheduling, and it's disabled by default ๐ฅ-msched-max-memory-insns=max-insnsโ puts a limit on how many memory insns go into one instruction group ๐ Memory insns that try to schedule after the limit get lower priority, which is frequently useful for avoiding cache bank conflicts ๐ The default value is1โจ-msched-max-memory-insns-hard-limitโ turns the-msched-max-memory-insnslimit into a hard limit, so no more than that number is allowed in one instruction group ๐ Without it, the limit is "soft": non-memory operations get preferred once the limit is hit, but memory operations can still sneak in ๐ฅน
๐ LM32 Options ๐
These -m options are defined for the LatticeMico32 architecture ๐ง
-mbarrel-shift-enabledโ enables barrel-shift instructions ๐ธ-mdivide-enabledโ enables divide and modulus instructions ๐-mmultiply-enabledโ enables multiply instructions โจ-msign-extend-enabledโ enables sign extend instructions ๐-muser-enabledโ enables user-defined instructions ๐
๐ M32C Options ๐
-mcpu=nameโ picks the CPU you want code generated for ๐ฆ Thenamecan ber8cfor the R8C/Tiny series,m16cfor the M16C (up to /60) series,m32cmfor the M16C/80 series, orm32cfor the M32C/80 series ๐ซถ-msimโ tells the compiler the program will run on the simulator ๐ง This links in an alternate runtime library that supports things like file I/O ๐ Do not use this when making programs for real hardware ๐ญ You'd need to supply your own runtime library for whatever I/O functions you need ๐ฅ-memregs=numberโ sets how many memory-based pseudo-registers GCC uses during code generation ๐ These act like real registers, so it's a tradeoff between fitting code into the available registers and the performance hit of using memory instead ๐ Every module in a program has to be compiled with the same value for this option ๐ Because of that, don't use this option with GCC's default runtime libraries โ ๏ธ
๐ฆ M32R/D Options ๐ฆ
These -m options are defined for Renesas M32R/D architectures ๐ธ
-m32r2โ generates code for the M32R/2 ๐-m32rxโ generates code for the M32R/X โจ-m32rโ generates code for the M32R ๐ This is the default ๐-mmodel=smallโ assumes all objects live in the lower 16MB of memory, so their addresses can be loaded with theld24instruction ๐ง It also assumes all subroutines are reachable with theblinstruction ๐ซถ This is the default ๐
The addressability of a particular object can be set with the "model" attribute ๐ธ
-mmodel=mediumโ assumes objects may be anywhere in the 32-bit address space, so the compiler generatesseth/add3instructions to load their addresses ๐ฆ It still assumes all subroutines are reachable with theblinstruction ๐-mmodel=largeโ assumes objects may be anywhere in the 32-bit address space, usingseth/add3instructions to load their addresses ๐ This time subroutines may not be reachable with theblinstruction, so the compiler generates the much slowerseth/add3/jlinstruction sequence ๐ญ-msdata=noneโ disables use of the small data area ๐ Variables get put into one of.data,.bss, or.rodata(unless the "section" attribute has been specified) ๐ This is the default ๐
The small data area consists of the sections .sdata and .sbss โจ Objects can be explicitly put in the small data area with the "section" attribute using one of these sections ๐
-msdata=sdataโ puts small global and static data in the small data area, but doesn't generate 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 has to be set to eithersdataorusefor this option to do anything ๐ธ
All modules should be compiled with the same -G num value ๐ซถ Compiling with different values of num may or may not work ๐คทโโ๏ธ If it doesn't, the linker gives an error message, so incorrect code is not generated ๐ก๏ธ
-mdebugโ makes the M32R-specific code in the compiler display some statistics that might help you debug programs ๐-malign-loopsโ aligns all loops to a 32-byte boundary ๐-mno-align-loopsโ doesn't enforce a 32-byte alignment for loops ๐ This is the default ๐-missue-rate=numberโ issuesnumberinstructions per cycle ๐ง Thenumbercan 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 can't be flushed by using a trap ๐ญ-mflush-func=nameโ specifies the name of the operating system function to call to flush the cache ๐ง The default is_flush_cache, but a function call is only used if a trap isn't available ๐-mno-flush-funcโ indicates there's no OS function for flushing the cache ๐
๐ M680x0 Options ๐
These are the -m options defined for M680x0 and ColdFire processors โจ The default settings depend on which architecture was selected when the compiler was configured ๐ The defaults for the most common choices are given below ๐ซถ
-march=archโ generates code for a specific M680x0 or ColdFire instruction set architecture ๐ฆ For M680x0 architectures, the permissible values ofarchare:68000,68010,68020,68030,68040,68060andcpu32๐ ColdFire architectures are selected according to Freescale's ISA classification, and the permissible values are:isaa,isaaplus,isabandisac๐
GCC defines a macro __mcfarch__ whenever it's generating code for a ColdFire target ๐ง The arch in this macro is one of the -march arguments given above ๐
When used together, -march and -mtune select code that runs on a family of similar processors, but that is optimized for a particular microarchitecture ๐ธ
-mcpu=cpuโ generates code for a specific M680x0 or ColdFire processor ๐ฅ The M680x0 cpus are:68000,68010,68020,68030,68040,68060,68302,68332andcpu32๐ The ColdFire cpus are given in the table below, which also sorts the CPUs into families ๐ง
Family : -mcpu arguments
51 : 51 51ac 51ag 51cn 51em 51je 51jf 51jg 51jm 51mm 51qe 51qm
5206 : 5202 5204 5206
5206e : 5206e
5208 : 5207 5208
5211a : 5210a 5211a
5213 : 5211 5212 5213
5216 : 5214 5216
52235 : 52230 52231 52232 52233 52234 52235
5225 : 5224 5225
52259 : 52252 52254 52255 52256 52258 52259
5235 : 5232 5233 5234 5235 523x
5249 : 5249
5250 : 5250
5271 : 5270 5271
5272 : 5272
5275 : 5274 5275
5282 : 5280 5281 5282 528x
53017 : 53011 53012 53013 53014 53015 53016 53017
5307 : 5307
5329 : 5327 5328 5329 532x
5373 : 5372 5373 537x
5407 : 5407
5475 : 5470 5471 5472 5473 5474 5475 547x 5480 5481 5482 5483 5484
5485
-mcpu=cpuoverrides-march=archifarchis compatible withcpu. Other combinations of-mcpuand-marchare rejected!
GCC defines the macro __mcf_cpu_cpu when a ColdFire target cpu is selected ๐ It also defines __mcf_family_family, where the value of family is given by the table above ๐ซถ
-mtune=tuneโ tunes the code for a particular microarchitecture within the constraints set by-marchand-mcpu๐ฆ The M680x0 microarchitectures are:68000,68010,68020,68030,68040,68060andcpu32๐ The ColdFire microarchitectures are:cfv1,cfv2,cfv3,cfv4andcfv4eโจ
You can also use -mtune=68020-40 for code that needs to run relatively well on 68020, 68030 and 68040 targets ๐ -mtune=68020-60 is similar, but it includes 68060 targets as well ๐ง These two options select the same tuning decisions as -m68020-40 and -m68020-60 respectively ๐
GCC defines the macros __mcarch and __mcarch__ when tuning for 680x0 architecture arch ๐ธ It also defines mcarch unless either -ansi or a non-GNU -std option is used ๐ฅ If GCC is tuning for a range of architectures, as selected by -mtune=68020-40 or -mtune=68020-60, it defines the macros for every architecture in the range ๐
GCC also defines the macro __muarch__ when tuning for ColdFire microarchitecture uarch, where uarch is one of the arguments given above ๐
OKAY bestie, the M680x0 family is next and it's giving retro computer chaos ๐น๏ธ๐
-m68000,-mc68000โ ๐ธ Generates output for a 68000. This is the default when the compiler is configured for 68000-based systems, and it's the same as-march=68000. Use it for microcontrollers with a 68000 or EC000 core, like the 68008, 68302, 68306, 68307, 68322, 68328, and 68356. ๐-m68010โ ๐ฆ Generates 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, and it's equivalent to-march=68040. This one inhibits the use of 68881/68882 instructions that have to be emulated in software on the 68040, so use it if your 68040 doesn't have code to emulate those instructions. ๐-m68060โ ๐ Generates output for a 68060. This is the default when the compiler is configured for 68060-based systems, and it's equivalent to-march=68060. It inhibits the use of 68020 and 68881/68882 instructions that have to be emulated in software on the 68060, so only use it if your 68060 lacks code to emulate them. ๐-mcpu32โ ๐ Generates output for a CPU32. This is the default when the compiler is configured for CPU32-based systems, and it's the same as-march=cpu32. Use it 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, but it's now deprecated in favor of that option. Use it for microcontrollers with a 5200 core, like 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 the use of hardware floating-point instructions. It's equivalent to-mcpu=547x, and it's now deprecated in favor of that option. ๐-m68020-40โ ๐ Generates output for a 68040, without using any of the new instructions. The result is code that can run relatively efficiently on a 68020/68881, a 68030, or a 68040. The generated code does use the 68881 instructions that are emulated on the 68040. It's equivalent to-march=68020 -mtune=68020-40. ๐ซถ-m68020-60โ ๐ธ Generates output for a 68060, without using any of the new instructions. The result is code that can run relatively efficiently on a 68020/68881, a 68030, or a 68040. The generated code does use the 68881 instructions that are emulated on the 68060. It's equivalent to-march=68020 -mtune=68020-60. ๐-mhard-float,-m68881โ ๐ฆ Generates floating-point instructions. This is the default for the 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โ ๐ Does not generate floating-point instructions. Library calls are used instead. This is the default for 68000, 68010, and 68832 targets, and it's also the default for ColdFire devices that have no FPU. ๐-mdiv,-mno-divโ ๐ง Generates (or doesn't generate) ColdFire hardware divide and remainder instructions. If-marchis used without-mcpu, the default is"on"for ColdFire architectures and"off"for M680x0 architectures. Otherwise, the default comes from the target CPU, which is either the default CPU or the one specified by-mcpu. For example, the default is"off"for-mcpu=5206and"on"for-mcpu=5206e. GCC defines the macro"__mcfhwdiv__"when this option is enabled. โจ-mshortโ ๐ Treats type"int"as 16 bits wide, just like"short int". Parameters passed on the stack are also aligned to a 16-bit boundary, even on targets that mandate promotion to 32-bit. ๐-mno-shortโ ๐ Does not treat type"int"as 16 bits wide. This is the default. ๐-mnobitfield,-mno-bitfieldโ ๐ Doesn't use the bit-field instructions. The-m68000,-mcpu32, and-m5200options imply-mnobitfield. ๐ญ-mbitfieldโ ๐ซถ Does use the bit-field instructions. The-m68020option implies-mbitfield, and this is the default if you use a configuration designed for a 68020. ๐ธ-mrtdโ ๐ Uses a different function-calling convention, where functions that take a fixed number of arguments return with the"rtd"instruction. That instruction pops their arguments while returning, which saves one instruction in the caller since there's no need to pop the arguments there.
This calling convention is incompatible with the one normally used on Unix, so you can't use it if you need to call libraries compiled with the Unix compiler. You also must provide function prototypes for all functions that take variable numbers of arguments (including printf), or incorrect code gets generated for calls to those functions. And seriously incorrect code results if you call a function with too many arguments. (Normally, extra arguments are harmlessly ignored, so this one is a big deal!) ๐
The "rtd" instruction is supported by the 68010, 68020, 68030, 68040, 68060, and CPU32 processors, but not by the 68000 or 5200. The default is -mno-rtd. ๐ฅ
-malign-int,-mno-align-intโ ๐ฆ Controls whether GCC aligns"int","long","long long","float","double", and"long double"variables on a 32-bit boundary (-malign-int) or a 16-bit boundary (-mno-align-int). Aligning on 32-bit boundaries makes code run somewhat faster on processors with 32-bit busses, but it costs more memory. ๐ง
โ ๏ธ Warning: if you use the -malign-int switch, GCC aligns structures containing the above types differently than most published application binary interface specifications for the m68k. ๐
-mpcrelโ ๐ Uses the pc-relative addressing mode of the 68000 directly, instead of using a global offset table. Right now this option implies-fpic, which allows at most a 16-bit offset for pc-relative addressing.-fPICisn't presently supported with-mpcrel, though it could be supported for the 68020 and higher processors. ๐ซถ-mno-strict-align,-mstrict-alignโ ๐ Does not (or does) assume that unaligned memory references are handled by the system. ๐-msep-dataโ ๐ Generates code that lets the data segment live in a different area of memory from the text segment. This allows for execute-in-place in an environment without virtual memory management. This option implies-fPIC. โจ-mno-sep-dataโ ๐ Generates code that assumes the data segment follows the text segment. This is the default. ๐ธ-mid-shared-libraryโ ๐ฆ Generates code that supports shared libraries via the library ID method. This allows for execute-in-place and shared libraries in an environment without virtual memory management. This option implies-fPIC. ๐ง-mno-id-shared-libraryโ ๐ Generates code that doesn't assume ID-based shared libraries are being used. This is the default. ๐-mshared-library-id=nโ ๐ฅ Specifies the identification number of the ID-based shared library being compiled. Specifying a value of0generates more compact code. Specifying other values forces the allocation of that number to the current library, but it's no more space- or time-efficient than leaving this option out. ๐-mxgot,-mno-xgotโ ๐ญ When generating position-independent code for ColdFire, this generates code that works if the GOT has more than 8192 entries. That code is larger and slower than code generated without this option. On M680x0 processors this option isn't needed, since-fPICis enough. ๐
GCC normally uses a single instruction to load values from the GOT. That's pretty efficient, but it only works if the GOT is smaller than about 64k. Anything larger makes the linker report an error like this:
relocation truncated to fit: R_68K_GOT16O foobar
If that happens, recompile your code with -mxgot, 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 in"switch"tables. The default is to use 16-bit offsets. ๐
๐ MCore Options ๐
These are the -m options defined for the Motorola M*Core processors. ๐ซถ
-mhardlit,-mno-hardlitโ ๐ฅ Inlines constants into the code stream if it can be done in two instructions or less. ๐-mdiv,-mno-divโ ๐ฆ Uses the divide instruction. (Enabled by default.) โจ-mrelax-immediate,-mno-relax-immediateโ ๐ธ Allows arbitrary-sized immediates in bit operations. ๐ง-mwide-bitfields,-mno-wide-bitfieldsโ ๐ Always treats bit-fields as"int"-sized. ๐-m4byte-functions,-mno-4byte-functionsโ ๐ Forces all functions to be aligned to a 4-byte boundary. ๐-mcallgraph-data,-mno-callgraph-dataโ ๐ Emits callgraph information. ๐-mslow-bytes,-mno-slow-bytesโ ๐ญ Prefers word access when reading byte quantities. ๐
โจ Machine-Dependent Options (continued) โจ
-mlittle-endian,-mbig-endianโ generate code for a little-endian target ๐ธ-m210,-m340โ generate code for the 210 processor ๐-mno-lsimโ okay so this one assumes runtime support is already handled, so the simulator library (libsim.a) gets left off the linker command line ๐ง-mstack-increment=sizeโ sets the max amount for a single stack increment operation ๐ Big values can speed things up for programs with functions that need a huge chunk of stack, but they can also cause a segmentation fault if the stack gets extended too much ๐ญ The default is0x1000๐
๐ฆ MeP Options ๐ฆ
-mabsdiffโ enables theabsinstruction, which gives you the absolute difference between two registers โจ-mall-optsโ enables ALL the optional instructions ๐ฅ: average, multiply, divide, bit operations, leading zero, absolute difference, min/max, clip, and saturation-maverageโ enables theaveinstruction, which computes the average of two registers ๐ซถ-mbased=nโ variables of sizenbytes or smaller get placed in the".based"section by default. Based variables use$tpas their base register, and the".based"section has a 128-byte limit ๐-mbitopsโ enables the bit operation instructions: bit test (btstm), set (bsetm), clear (bclrm), invert (bnotm), and test-and-set (tas) ๐-mc=nameโ picks which section constant data gets placed in.namecan betiny,near, orfar๐-mclipโ enables theclipinstruction. Heads up, bestie:-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 bunch of coprocessors, optional instructions, and peripherals. The"MeP-Integrator"tool (not part of GCC!) provides these configurations through this option. Using this option is the same as using all the matching command-line options. The default configuration isdefault.-mcopโ enables the coprocessor instructions. By default this is a 32-bit coprocessor. The coprocessor is normally enabled through the-mconfig=option ๐ฆ-mcop32โ enables the 32-bit coprocessor's instructions-mcop64โ enables the 64-bit coprocessor's instructions-mivc2โ enables IVC2 scheduling. IVC2 is a 64-bit VLIW coprocessor ๐ฅ-mdcโ causes constant variables to get placed in the".near"section-mdivโ enables thedivanddivuinstructions-mebโ generate big-endian code-melโ generate little-endian code-mio-volatileโ tells the compiler that any variable marked with theioattribute is considered volatile ๐-mlโ causes variables to be assigned to the".far"section by default-mleadzโ enables theleadz(leading zero) instruction-mmโ causes variables to be assigned to the".near"section 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, used for low-overhead looping ๐-msโ causes all variables to default to the".tiny"section. There's a 65536-byte limit on this section, and accesses to these variables use the%gpbase register ๐-msaturโ enables the saturation instructions. Note that the compiler doesn't currently generate these itself, but this option is here for compatibility with other tools, likeas๐ง-msdramโ links the SDRAM-based runtime instead of the default ROM-based runtime-msimโ links the simulator run-time libraries-msimnovecโ links the simulator runtime libraries, but leaves out built-in support for reset and exception vectors and tables-mtfโ causes all functions to default to the".far"section. Without this option, functions default to the".near"section ๐ธ-mtiny=nโ variables that arenbytes or smaller get allocated to the".tiny"section, and they use the$gpbase register. The default for this option is 4, but there's a 65536-byte limit on the".tiny"section ๐
๐ MicroBlaze Options ๐
-msoft-floatโ uses software emulation for floating point (this is the default) ๐ซถ-mhard-floatโ uses hardware floating-point instructions โญ-mmemcpyโ doesn't optimize block moves, usesmemcpyinstead ๐ฆ-mno-clearbssโ ๐ deprecated. Use-fno-zero-initialized-in-bssinstead.
โ ๏ธ-mno-clearbssis deprecated, so switch over to-fno-zero-initialized-in-bss.
-mcpu=cpu-typeโ uses features of, and schedules code for, the given CPU. Supported values are in the formatvX.YY.Z, whereXis a major version,YYis the minor version, andZis compatibility code. Example values arev3.00.a,v4.00.b,v5.00.a,v5.00.b,v6.00.aโจ-mxl-soft-mulโ uses software multiply emulation (default) ๐-mxl-soft-divโ uses software emulation for divides (default) ๐ธ-mxl-barrel-shiftโ uses the hardware barrel shifter ๐ฅ-mxl-pattern-compareโ uses pattern compare instructions ๐ง-msmall-dividesโ uses table lookup optimization for small signed integer divisions ๐-mxl-stack-checkโ ๐ deprecated. Use-fstack-checkinstead.
โ ๏ธ-mxl-stack-checkis deprecated, so use-fstack-checkinstead.
-mxl-gp-optโ uses GP-relative".sdata"/".sbss"sections ๐-mxl-multiply-highโ uses multiply high instructions for the high part of a 32x32 multiply ๐-mxl-float-convertโ uses hardware floating-point conversion instructions ๐-mxl-float-sqrtโ uses the hardware floating-point square root instruction ๐ฆ-mbig-endianโ generate code for a big-endian target ๐-mlittle-endianโ generate code for a little-endian target ๐ซถ-mxl-reorderโ uses reorder instructions (swap and byte reversed load/store) โจ-mxl-mode-app-modelโ selects the application modelapp-model. Valid models are:executableโ normal executable (default), uses startup codecrt0.o๐ธ-mpic-data-is-text-relativeโ assumes the displacement between the text and data segments is fixed at static link time. This lets data get referenced by offset from the start of the text address instead of the GOT, since PC-relative addressing isn't supported ๐งxmdstubโ for use with the Xilinx Microprocessor Debugger (XMD) based software intrusive debug agent calledxmdstub. This uses startup filecrt1.oand sets the program's start address to0x800๐ฅbootstrapโ for applications that get loaded using a bootloader. This model uses startup filecrt2.o, which does NOT contain a processor reset vector handler. It's suitable for handing control back to the bootloader on a processor reset instead of the application ๐novectorsโ for applications that don't need any of the MicroBlaze vectors. This can be useful for apps running inside a monitoring application. This model usescrt3.oas its startup file ๐
Option -xl-mode-app-model is a deprecated alias for -mxl-mode-app-model ๐
๐ MIPS Options ๐
-EBโ generate big-endian code ๐-ELโ generate little-endian code. This is the default formips*el-*-*configurations ๐ธ-march=archโ generates code that runs onarch, which can be the name of a generic MIPS ISA or the name of a particular processor ๐ The ISA names are:mips1,mips2,mips3,mips4,mips32,mips32r2,mips32r3,mips32r5,mips32r6,mips64,mips64r2,mips64r3,mips64r5andmips64r6
The processor names are:
4kc,4km,4kp,4ksc,4kec,4kem,4kep,4ksd,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,24kec,24kef2_1,24kef1_1,34kc,34kf2_1,34kf1_1,34kn,74kc,74kf2_1,74kf1_1,74kf3_2,1004kc,1004kf2_1,1004kf1_1,i6400,i6500,interaptiv,loongson2e,loongson2f,loongson3a,gs464,gs464e,gs264e,m4k,m14k,m14kc,m14ke,m14kec,m5100,m5101,octeon,octeon+,octeon2,octeon3,orion,p5600,p6600,r2000,r3000,r3900,r4000,r4400,r4600,r4650,r4700,r5900,r6000,r8000,rm7000,rm9000,r10000,r12000,r14000,r16000,sb1,sr71000,vr4100,vr4111,vr4120,vr4130,vr4300,vr5000,vr5400,vr5500,xlrandxlp.
The special value from-abi selects the most compatible architecture for the selected ABI. That means mips1 for 32-bit ABIs and mips3 for 64-bit ABIs ๐ง
The native Linux/GNU toolchain also supports the value native, which selects the best architecture option for the host processor. -march=native has no effect if GCC doesn't recognize the processor ๐ฅ
In processor names, a final 000 can be abbreviated as k (for example, -march=r2k). Prefixes are optional, and vr may be written r ๐
Names of the form nf2_1 refer to processors with FPUs clocked at half the rate of the core. Names of the form nf1_1 refer to processors with FPUs clocked at the same rate as the core. Names of the form nf3_2 refer to processors with FPUs clocked at a 3:2 ratio with respect to the core. For compatibility reasons, nf is accepted as a synonym for nf2_1, while nx and bfx are accepted as synonyms for nf1_1 ๐ฆ
GCC defines two macros based on the value of this option. The first is "_MIPS_ARCH", which gives the name of the target architecture as a string. The second has the form "_MIPS_ARCH_foo", where foo is the capitalized value of "_MIPS_ARCH". For example, -march=r2000 sets "_MIPS_ARCH" to "r2000" and defines the macro "_MIPS_ARCH_R2000" โจ
Note that the "_MIPS_ARCH" macro uses the processor names given above. In other words, it has the full prefix and doesn't abbreviate 000 as k. In the case of from-abi, the macro names the resolved architecture (either "mips1" or "mips3"). It names the default architecture when no -march option is given ๐ธ
-mtune=archโ optimizes forarch๐ Among other things, this option controls the way instructions are scheduled, and the perceived cost of arithmetic operations. The list ofarchvalues is the same as for-march.
When this option isn't used, GCC optimizes for the processor specified by -march. By using -march and -mtune together, it's possible to generate code that runs on a family of processors but optimizes the code for one particular member of that family ๐
-mtune also defines the macros _MIPS_TUNE and _MIPS_TUNE_foo, which work exactly like the -march ones I just covered ๐
โจ
-mips1โ same as-march=mips1๐-mips2โ same as-march=mips2๐-mips3โ same as-march=mips3๐-mips4โ same as-march=mips4๐-mips32โ same as-march=mips32๐-mips32r3โ same as-march=mips32r3๐-mips32r5โ same as-march=mips32r5๐-mips32r6โ same as-march=mips32r6๐-mips64โ same as-march=mips64๐-mips64r2โ same as-march=mips64r2๐-mips64r3โ same as-march=mips64r3๐-mips64r5โ same as-march=mips64r5๐-mips64r6โ same as-march=mips64r6๐
-mips16,-mno-mips16โ okay so these tell GCC to generate (or not generate) MIPS16 code ๐ฆ If you're targeting a MIPS32 or MIPS64 architecture, it uses the MIPS16e ASE, which is lowkey iconic.
You can also control MIPS16 on a per-function basis with the mips16 and nomips16 attributes ๐
-mflip-mips16โ generates MIPS16 code on every other function ๐ง This one exists for regression testing of mixed MIPS16/non-MIPS16 code generation.
Not for ordinary use! Please don't use this when compiling your own code ๐
-minterlink-compressed,-mno-interlink-compressedโ these require (or don't require) that code using the standard, uncompressed MIPS ISA be link-compatible with MIPS16 and microMIPS code, and vice versa ๐ฅ
Here's the tea: code using the standard ISA encoding can't jump directly to MIPS16 or microMIPS code. It has to use a call or an indirect jump instead. So -minterlink-compressed turns off direct jumps unless GCC knows the jump's target isn't compressed ๐
-minterlink-mips16,-mno-interlink-mips16โ these are just aliases for-minterlink-compressedand-mno-interlink-compressedโจ They predate the microMIPS ASE and are kept around for backwards compatibility ๐ธ
-mabi=32,-mabi=o64,-mabi=n32,-mabi=64,-mabi=eabiโ generates code for the ABI you pick ๐
The EABI comes in a 32-bit and a 64-bit flavour. GCC normally makes 64-bit code when you pick a 64-bit architecture, but if you want 32-bit code instead, use -mgp32 ๐ซถ
For info about the O64 ABI, check out http://gcc.gnu.org/projects/mipso64-abi.html ๐
GCC also supports a version of the o32 ABI where the floating-point registers are 64 bits wide instead of 32. You can select that combo with -mabi=32 -mfp64 ๐ This one leans on the "mthc1" and "mfhc1" instructions, so it's only supported on MIPS32R2, MIPS32R3 and MIPS32R5 processors.
The argument and return value register assignments stay the same, but each scalar value gets passed in one 64-bit register instead of a pair of 32-bit ones. For example, scalar floating-point values are returned in $f0 only, not a $f0/$f1 pair. The set of call-saved registers is also unchanged, so the even-numbered double-precision registers still get saved โจ
Two more o32 variants exist to help you transition from 32-bit to 64-bit registers: FPXX (-mfpxx) and FP64A (-mfp64 -mno-odd-spreg) ๐ฆ FPXX says all code has to run correctly with either 32-bit or 64-bit registers. It can interlink with FP32 or FP64, but not both at once. FP64A is a lot like FP64 except it forbids odd-numbered single-precision registers. It can be paired with the "FRE" mode of FPUs in MIPS32R5 processors, so FP32 and FP64A code can interlink and run in the same process without switching FPU modes. Main character energy ๐
-mabicalls,-mno-abicallsโ generates (or doesn't generate) code that works with SVR4-style dynamic objects ๐ธ-mabicallsis the default on SVR4-based systems.-mshared,-mno-sharedโ generates (or doesn't generate) code that's fully position-independent, so it can be linked into shared libraries ๐ This only affects-mabicalls.
All -mabicalls code has traditionally been position-independent, no matter what -fPIC and -fpic say ๐ BUT, as an extension, the GNU toolchain lets executables use absolute accesses for locally-binding symbols. It can also use shorter GP initialization sequences and make direct calls to locally-defined functions. That mode is what you get with -mno-shared ๐ฅ
-mno-shared needs binutils 2.16 or higher, and the objects it makes can only be linked by the GNU linker. The good news is it doesn't change the ABI of the final executable, only the ABI of relocatable objects. Using -mno-shared usually makes executables both smaller and quicker ๐
-mshared is the default โจ
-mplt,-mno-pltโ assumes (or doesn't assume) that the static and dynamic linkers support PLTs and copy relocations ๐ง This only affects-mno-shared -mabicalls. For the n64 ABI, this option does nothing without-msym32.
You can make -mplt the default by configuring GCC with --with-mips-plt. Otherwise the default is -mno-plt ๐
-mxgot,-mno-xgotโ lifts (or doesn't lift) the usual size limits on the global offset table ๐
Normally GCC uses a single instruction to load values from the GOT. That's pretty efficient, but it only works if the GOT is smaller than about 64k. Anything bigger makes the linker throw an error that looks like this:
relocation truncated to fit: R_MIPS_GOT16 foobar
If that happens, recompile your code with -mxgot ๐ญ It works with very large GOTs, but the code is less efficient, because it takes three instructions to fetch the value of a global symbol.
Some linkers can create multiple GOTs. If you've got one of those, you should only need -mxgot when a single object file accesses more than 64k's worth of GOT entries. Very few do ๐
These options do nothing unless GCC is generating position-independent code ๐ซถ
-mgp32โ assumes general-purpose registers are 32 bits wide ๐ธ-mgp64โ assumes general-purpose registers are 64 bits wide ๐-mfp32โ assumes floating-point registers are 32 bits wide ๐ฆ-mfp64โ assumes floating-point registers are 64 bits wide ๐ฅ-mfpxxโ doesn't assume anything about how wide the floating-point registers are ๐ง-mhard-floatโ uses floating-point coprocessor instructions ๐-msoft-floatโ doesn't use floating-point coprocessor instructions. Instead, floating-point math is done with library calls ๐-mno-floatโ same as-msoft-float, but it also asserts that your program doesn't do any floating-point operations ๐ Right now this is only supported by some bare-metal MIPS configurations, which may pick a special set of libraries that don't have any floating-point support at all, including the floating-point "printf" formats.
If code compiled with -mno-float accidentally has floating-point operations in it, it'll probably fail at link time or at run time. Be careful, bestie ๐ญ
-msingle-floatโ assumes the floating-point coprocessor only supports single-precision operations ๐ธ-mdouble-floatโ assumes the floating-point coprocessor supports double-precision operations. This is the default ๐-modd-spreg,-mno-odd-spregโ enables (or disables) the use of odd-numbered single-precision floating-point registers for the o32 ABI โจ This is the default for processors that are known to support these registers. When you're using the o32 FPXX ABI,-mno-odd-spreggets set by default.
-mabs=2008,-mabs=legacyโ these control how the special not-a-number (NaN) IEEE 754 floating-point data gets handled by theabs.fmtandneg.fmtmachine instructions ๐ฅ
By default, or when you use -mabs=legacy, the legacy treatment is selected. Here, these instructions count as arithmetic and get avoided wherever correct operation is needed and the input might be a NaN. A longer sequence that manipulates the sign bit of the floating-point datum by hand gets used instead, unless -ffinite-math-only has also been specified ๐
-mabs=2008 selects the IEEE 754-2008 treatment. In this case the instructions count as non-arithmetic, so they work correctly in every case, including when the input operand is a NaN. 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 is encoded ๐ง
-mnan=legacy selects the legacy encoding. Quiet NaNs (qNaNs) are marked by the first bit of their trailing significand field being 0, while signaling NaNs (sNaNs) are marked by that first bit being 1 ๐ฆ
-mnan=2008 selects the IEEE 754-2008 encoding. Here qNaNs are marked by the first bit of their trailing significand field being 1, and sNaNs by that first bit being 0 ๐
The default is -mnan=legacy, unless GCC was configured with --with-nan=2008 ๐
-mllsc,-mno-llscโ uses (or doesn't use) thell,scandsyncinstructions to implement the atomic memory built-in functions ๐ซถ When you specify neither, GCC uses those instructions if the target architecture supports them.
-mllsc is handy if your 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 and --without-llsc respectively. --with-llsc is the default for some configurations, so check the installation documentation for the details โจ
-mdsp,-mno-dspโ uses (or doesn't use) revision 1 of the MIPS DSP ASE ๐ธ This option defines the preprocessor macro__mips_dsp. It also defines__mips_dsp_revto 1 ๐-mdspr2,-mno-dspr2โ uses (or doesn't use) revision 2 of the MIPS DSP ASE ๐ This option defines the preprocessor macros__mips_dspand__mips_dspr2. It also defines__mips_dsp_revto 2 ๐-msmartmips,-mno-smartmipsโ Turn it on or keep it off โจ This flips the MIPS SmartMIPS ASE on or off ๐-mpaired-single,-mno-paired-singleโ Turn on or skip the paired-single floating-point instructions ๐ธ Heads up, this one needs hardware floating-point support enabled first ๐ซถ-mdmx,-mno-mdmxโ Use or skip the MIPS Digital Media Extension instructions ๐ These only work when you're generating 64-bit code, and they also need hardware floating-point support turned on ๐ฅ-mips3d,-mno-mips3dโ Turn the MIPS-3D ASE on or off ๐ฆ Using-mips3dautomatically implies-mpaired-singleโจ-mmicromips,-mno-micromipsโ Generate or don't generate microMIPS code ๐ง You can also control microMIPS on a per-function basis with the"micromips"and"nomicromips"attributes ๐-mmt,-mno-mtโ Use or skip the MT Multithreading instructions ๐-mmcu,-mno-mcuโ Use or skip the MIPS MCU ASE instructions ๐-meva,-mno-evaโ Use or skip the MIPS Enhanced Virtual Addressing instructions ๐-mvirt,-mno-virtโ Use or skip the MIPS Virtualization (VZ) instructions ๐-mxpa,-mno-xpaโ Use or skip the MIPS eXtended Physical Address (XPA) instructions ๐ธ-mcrc,-mno-crcโ Use or skip the MIPS Cyclic Redundancy Check (CRC) instructions โญ-mginv,-mno-ginvโ Use or skip the MIPS Global INValidate (GINV) instructions ๐ซถ-mloongson-mmi,-mno-loongson-mmiโ Use or skip the MIPS Loongson MultiMedia extensions Instructions (MMI) ๐-mloongson-ext,-mno-loongson-extโ Use or skip the MIPS Loongson EXTensions (EXT) instructions ๐ฆ-mloongson-ext2,-mno-loongson-ext2โ Use or skip the MIPS Loongson EXTensions r2 (EXT2) instructions ๐ฅ-mlong64โ Forces "long" types to be 64 bits wide ๐ Check out-mlong32for the full scoop on the default and how the pointer size gets decided ๐ง-mlong32โ Forces "long", "int", and pointer types to be 32 bits wide ๐- The default size of "int"s, "long"s, and pointers depends on the ABI ๐
- Every supported ABI uses 32-bit "int"s โจ
- The n64 ABI uses 64-bit "long"s, and so does the 64-bit EABI. Everything else uses 32-bit "long"s ๐ธ
- Pointers are the same size as "long"s, or the same size as integer registers, whichever is smaller ๐ซถ
-msym32,-mno-sym32โ Assume (or don't assume) that all symbols have 32-bit values, no matter which ABI you picked ๐ฆ This is super handy with-mabi=64and-mno-abicallsbecause it lets GCC generate shorter and faster references to symbolic addresses ๐ฅ-G numโ Puts definitions of externally-visible data into a small data section, as long as that data is no bigger than num bytes ๐ GCC can then access the data more efficiently. Check out-mgpoptfor the details ๐ง- The default
-Gvalue depends on the configuration โจ
- The default
-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 large libraries with
-mno-local-sdata, so the libraries leave more room for the main program ๐ซถ
- If the linker complains that your app is using too much small data, try rebuilding the less performance-critical parts with
-mextern-sdata,-mno-extern-sdataโ Assume (or don't assume) that externally-defined data is in a small data section, as long as its size is within the-Glimit ๐ธ-mextern-sdatais the default for all configurations โญ- Okay, this part is important ๐ญ If you compile a module Mod with
-mextern-sdata -G num -mgpopt, and Mod references a variable Var that is no bigger than num bytes, you have to make sure Var ends up in a small data section ๐ฅ - If Var is defined by another module, you either need to compile that module with a high-enough
-Gsetting, or attach a"section"attribute to Var's definition ๐ - If Var is common, you need to link the application with a high-enough
-Gsetting ๐ - The easiest way to keep all of this from getting messy is to compile and link every module with the same
-Goption โจ - If you want a library that supports several different small data limits, compile it with the highest supported
-Gsetting and also use-mno-extern-sdata. That stops the library from making assumptions about externally-defined data ๐ง
- Okay, this part is important ๐ญ If you compile a module Mod with
-mgpopt,-mno-gpoptโ Use (or don't use) GP-relative accesses for symbols that are known to be in a small data section ๐ See-G,-mlocal-sdata, and-mextern-sdata๐-mgpoptis the default for all configurations ๐ฆ-mno-gpoptis useful when the$gpregister might not hold the value of"_gp"๐ For example, if your code is part of a library that might be used in a boot monitor, programs that call boot monitor routines pass an unknown value in$gp๐ญ- The boot monitor itself is usually compiled with
-G0in those situations ๐ซถ -mno-gpoptimplies-mno-local-sdataand-mno-extern-sdata๐ฅ
-membedded-data,-mno-embedded-dataโ Allocates variables to the read-only data section first if possible, then to the small data section if possible, and otherwise to data ๐ This gives slightly slower code than the default, but it reduces the amount of RAM needed while executing, so it might be the move for some embedded systems ๐-muninit-const-in-rodata,-mno-uninit-const-in-rodataโ Puts uninitialized "const" variables in the read-only data section ๐ธ This only means something when you're also using-membedded-data๐ง-mcode-readable=settingโ Tells GCC whether it may generate code that reads from executable sections ๐ฆ There are three possible settings, bestie ๐-mcode-readable=yesโ Instructions can freely access executable sections. This is the default setting โจ-mcode-readable=pcrelโ MIPS16 PC-relative load instructions can access executable sections, but other instructions must not ๐ This is useful on 4KSc and 4KSd processors when the code TLBs have the Read Inhibit bit set. It's also useful on processors that can be configured 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) the use of the%hi()and%lo()assembler relocation operators ๐ซถ This one has been superseded by-mexplicit-relocs, but it's kept around for backwards compatibility ๐ฅบ-mexplicit-relocs,-mno-explicit-relocsโ Use (or don't use) assembler relocation operators when dealing with symbolic addresses ๐ The alternative, selected by-mno-explicit-relocs, is to use assembler macros instead ๐ฆ-mexplicit-relocsis the default if GCC was configured to use an assembler that supports relocation operators ๐-mcheck-zero-division,-mno-check-zero-divisionโ Trap (or don't trap) on integer division by zero ๐ The default is-mcheck-zero-divisionโจ-mdivide-traps,-mdivide-breaksโ MIPS systems check for division by zero by generating either a conditional trap or a break instruction ๐ Traps give you smaller code, but they're only supported on MIPS II and later ๐ธ Also, some versions of the Linux kernel have a bug that stops trap from generating the proper signal ("SIGFPE") ๐ญ Use-mdivide-trapsto allow conditional traps on architectures that support them, and-mdivide-breaksto force the use of breaks ๐ง- The default is usually
-mdivide-traps, but you can override it at configure time using--with-divide=breaks๐ - Divide-by-zero checks can be completely disabled with
-mno-check-zero-division๐
- The default is usually
-mload-store-pairs,-mno-load-store-pairsโ Enable (or disable) an optimization that pairs consecutive load or store instructions to enable load/store bonding ๐ฅ It's enabled by default, but it only takes effect when the selected architecture is known to support bonding ๐-mmemcpy,-mno-memcpyโ Force (or don't force) the use of"memcpy"for non-trivial block moves ๐ The default is-mno-memcpy, which lets GCC inline most constant-sized copies ๐ฆ-mlong-calls,-mno-long-callsโ Disable (or don't disable) the use of the"jal"instruction ๐ธ Calling functions with"jal"is more efficient, but it requires the caller and callee to be in the same 256 megabyte segment ๐ซถ This option has no effect on abicalls code, and the default is-mno-long-callsโจ-mmad,-mno-madโ Enable (or disable) the use of the"mad","madu", and"mul"instructions, as provided by the R4650 ISA ๐-mimadd,-mno-imaddโ Enable (or disable) the use of the"madd"and"msub"integer instructions ๐ The default is-mimaddon architectures that support"madd"and"msub", except for the 74k architecture, where it was found to generate slower code ๐-mfused-madd,-mno-fused-maddโ Enable (or disable) the 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 ๐ญ That may be undesirable in some circumstances ๐
- On other processors, the result is numerically identical to the equivalent computation using separate multiply, add, subtract, and negate instructions ๐ง
-nocppโ Tells the MIPS assembler to not run its preprocessor over user assembler files (with a.ssuffix) when assembling them ๐ฆ-mfix-24k,-mno-fix-24kโ Works around the 24K E48 (lost data on stores during refill) errata ๐ฅ The workarounds are implemented by the assembler rather than by GCC ๐-mfix-r4000,-mno-fix-r4000โ Works around certain R4000 CPU errata ๐ซถ- A double-word or a variable shift may give an incorrect result if it's executed immediately after starting an integer division ๐
- bestie, a double-word or a variable shift can give you a wrong answer if it runs while an integer multiplication is still going ๐
- An integer division may give an incorrect result if it's started in a delay slot of a taken branch or a jump. ๐
-mfix-r4400,-mno-fix-r4400โ okay so this one patches some R4400 CPU errata ๐ that are lowkey chaotic:- 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โ this one fixes some R10000 errata ๐"ll"/"sc"sequences may not behave atomically on revisions prior to3.0. They may deadlock on revisions2.6and earlier. ๐
This option can only be used if the target architecture supports branch-likely instructions. -mfix-r10000 is the default when -march=r10000 is used, and -mno-fix-r10000 is the default otherwise. โจ
-mfix-r5900,-mno-fix-r5900โ ngl this one is a whole mood ๐ฆ It tells GCC not to try scheduling the preceding instruction into the delay slot of a branch placed at the end of a short loop of six instructions or fewer. Instead, it always puts anopthere. The short loop bug can make loops run only once or twice under certain conditions, because of a hardware bug in the R5900 chip. The workaround is handled by the assembler rather than by GCC. ๐ฅ-mfix-rm7000,-mno-fix-rm7000โ works around the RM7000dmult/dmultuerrata. The workarounds are done by the assembler, not GCC. ๐ง-mfix-vr4120,-mno-fix-vr4120โ fixes some VR4120 errata ๐ธdmultudoes not always produce the correct result.divandddivdo 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 the moment, these functions are only provided by the mips64vr*-elf configurations, so keep that in mind, bestie. ๐
Other VR4120 errata need a nop inserted between certain pairs of instructions. The assembler handles those, not GCC itself. ๐
-mfix-vr4130โ works around the VR4130mflo/mfhierrata. The workarounds are implemented by the assembler rather than GCC, though GCC avoids usingmfloandmfhiif the VR4130macc,macchi,dmaccanddmacchiinstructions are available instead. ๐-mfix-sb1,-mno-fix-sb1โ works around certain SB-1 CPU core errata. (This flag currently works around the SB-1 revision 2"F1"and"F2"floating-point errata.) ๐-mr10k-cache-barrier=settingโ this one is a whole saga, so grab a snack ๐ฟ It specifies whether GCC should insert cache barriers to avoid the side effects of speculation on R10K processors.
Like lots of processors, the R10K tries to guess the outcome of a conditional branch and speculatively runs instructions from the "taken" branch. It later aborts them if the guess was wrong. The catch is that on the R10K, even aborted instructions can have side effects. ๐ญ
This problem only affects kernel stores and, depending on the system, kernel loads. For 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 that "dirty" line is flushed, the cached data overwrites the DMA-ed data. Check the R10K processor manual for a full description, including other potential problems. ๐
One workaround is to insert cache barrier instructions before every memory access that might be speculatively executed and might have side effects even if aborted. -mr10k-cache-barrier=setting controls GCC's version of this workaround. It assumes that aborted accesses to any byte in the following regions do not have side effects:
- the memory occupied by the current function's stack frame;
- the memory occupied by an incoming stack argument;
- the memory occupied by an object with a link-time-constant address.
It is the kernel's job to make sure speculative accesses to these regions are actually safe. ๐ซถ
If your input program has a function declaration like this:
void foo (void);
then the implementation of foo must allow j foo and jal foo to be executed speculatively. GCC honors this for functions it compiles itself, and it expects non-GCC functions (like hand-written assembly) to do the same. ๐
The option has three forms:
-mr10k-cache-barrier=load-storeโ inserts a cache barrier before a load or store that might be speculatively executed and might have side effects even if aborted.-mr10k-cache-barrier=storeโ inserts a cache barrier before a store that might be speculatively executed and might have side effects even if aborted.-mr10k-cache-barrier=noneโ turns off cache barrier insertion. This is the default setting. โจ
-mflush-func=func,-mno-flush-funcโ picks the function to call to flush the I and D caches, or tells GCC not to call any such function. If one is called, it must take the same arguments as the common_flush_func: the address of the memory range being flushed, the size of that range, and the number3(to flush both caches). The default depends on the target GCC was configured for, but it's commonly either_flush_funcor__cpu_flush. ๐งmbranch-cost=numโ sets the cost of branches to roughlynum"simple" instructions. This 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โ turns Branch Likely instructions on or off, no matter what the selected architecture defaults to. By default, Branch Likely instructions may be generated if the selected architecture supports them. The exception is the MIPS32 and MIPS64 architectures, and processors that implement them. For those, Branch Likely instructions are not generated by default, because MIPS32 and MIPS64 specifically deprecate their use. ๐-mcompact-branches=never,-mcompact-branches=optimal,-mcompact-branches=alwaysโ these control which form of branches gets generated. The default is-mcompact-branches=optimal. ๐
-mcompact-branches=never makes sure compact branch instructions are never generated.
-mcompact-branches=always makes sure a compact branch instruction is generated if one is available. If it isn't, a delay slot form of the branch gets used instead.
-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 chosen when one is available.
These options are 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 at the expense of making it 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, are generated when__builtin___clear_cacheis compiled.
This option defaults to -mno-synci, but you can override the default by configuring GCC with --with-synci.
When compiling code for single processor systems, it's generally safe to use synci. But on many multi-core (SMP) systems, it doesn't invalidate the instruction caches on all cores and may lead to undefined behavior. Be careful out there, bestie. โ ๏ธ
-mrelax-pic-calls,-mno-relax-pic-callsโ tries to turn PIC calls that are normally dispatched via register$25into direct calls. This only works if the linker can resolve the destination at link time, and the destination is within range for a direct call. ๐ง
-mrelax-pic-calls is the default if GCC was configured to use an assembler and a linker that support the .reloc assembly directive, and -mexplicit-relocs is in effect. With -mno-explicit-relocs, this optimization can be done by the assembler and the linker alone, without help from the compiler. ๐
-mmcount-ra-address,-mno-mcount-ra-addressโ emits (or doesn't emit) code that lets_mcountmodify the calling function's return address. When enabled, this option extends the usual_mcountinterface with a new ra-address parameter. It has typeintptr_t *and is passed in register$12._mcountcan then modify the return address by doing both of the following:- Returning the new address in register
$31. - Storing the new address in
*ra-address, if ra-address is nonnull.
- Returning the new address in register
The default is -mno-mcount-ra-address. ๐ซถ
-mframe-header-opt,-mno-frame-header-optโ enables (or disables) frame header optimization in the o32 ABI. When you use the o32 ABI, calling functions allocate 16 bytes on the stack for the called function to write out register arguments. When this optimization is enabled, it suppresses that frame header allocation if it can be determined to be unused. ๐
This optimization is off by default at all optimization levels. ๐
-mlxc1-sxc1,-mno-lxc1-sxc1โ when applicable, enables (or disables) generation oflwxc1,swxc1,ldxc1andsdxc1instructions. It's enabled by default. ๐-mmadd4,-mno-madd4โ okay so this one is a switch for the 4-operandmadd.s,madd.dand friends. Where it applies, you can turn generation on or off. It's already on by default, so you don't have to lift a finger ๐
โจ MMIX Options โจ
These options are defined for the MMIX ๐ง
-mlibfuncs,-mno-libfuncsโ this tells GCC you're compiling intrinsic library functions, so every value gets passed in registers, no matter how big it is ๐ฅ-mepsilon,-mno-epsilonโ turn this on and you get floating-point comparison instructions that compare against therEepsilon register ๐ฆ-mabi=mmixware,-mabi=gnuโ-mabi=mmixwaremakes function parameters and return values show up as registers$0and up inside the called function.-mabi=gnuis the other vibe, where it uses global registers$231and up instead ๐-mzero-extend,-mno-zero-extendโ when you read data from memory in chunks shorter than 64 bits,-mzero-extendmakes zero-extending loads the default, while-mno-zero-extendkeeps sign-extending ones ๐-mknuthdiv,-mno-knuthdivโ-mknuthdivmakes the remainder of a division take the same sign as the divisor. The default,-mno-knuthdiv, has the remainder follow the sign of the dividend instead. Both are arithmetically valid, but the second one is the one basically everybody uses ๐-mtoplevel-symbols,-mno-toplevel-symbolsโ-mtoplevel-symbolsslaps a:in front of every global symbol, so your assembly code works with the"PREFIX"assembly directive.-mno-toplevel-symbolsskips the prefix ๐ธ-melfโ makes an executable in ELF format instead of the default mmo format that the mmix simulator uses ๐-mbranch-predict,-mno-branch-predictโ-mbranch-predictlets the compiler use the probable-branch instructions whenever static branch prediction says a branch is likely.-mno-branch-predictsays nope to that โจ-mbase-addresses,-mno-base-addressesโ-mbase-addresseshas the compiler generate code that uses base addresses. Using one automatically makes a request, which the assembler and linker take care of, for a constant that gets set up in a global register. That register then serves one or more base address requests within 0 to 255 from the value it holds. The upside is that the code comes out short and fast, but there's a limit on how many different data items you can address. So if your program has lots of static data, you might need-mno-base-addresses๐-msingle-exit,-mno-single-exitโ-msingle-exitforces the generated code to have one single exit point in each function.-mno-single-exitdoesn't force that ๐ฆ
๐ MN10300 Options ๐
These -m options are defined for Matsushita MN10300 architectures ๐
-mmult-bugโ generates code that avoids bugs in the multiply instructions for MN10300 processors. This is the default โจ-mno-mult-bugโ does not generate code to avoid those multiply bugs for MN10300 processors ๐-mam33โ generates code using features specific to the AM33 processor ๐ฅ-mno-am33โ no AM33-specific features in the generated code. 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โ schedules instructions using the timing characteristics of the CPU type you name. This doesn't change the processor type you're targeting. The CPU type has to be one ofmn10300,am33,am33-2oram34๐-mreturn-pointer-on-d0โ when generating a function that returns a pointer, the pointer gets returned in both"a0"and"d0". Otherwise it only comes back in"a0", and trying to call those functions without a prototype throws errors. This one is on by default, but you can flip it off with-mno-return-pointer-on-d0๐ซถ-mno-crt0โ doesn't link in the C run-time initialization object file ๐ธ-mrelaxโ tells the linker to run a relaxation pass that shortens branches, calls and absolute memory addresses. It only does anything when you use it on the command line for the final link step ๐ง
This option makes symbolic debugging impossible. Be careful with -mrelax if you're debugging ๐
-mliwโ lets the compiler generate Long Instruction Word instructions if the target is AM33 or later. This is the default. It also defines the preprocessor macro"__LIW__"๐-mno-liwโ no Long Instruction Word instructions for you. It defines the preprocessor macro"__NO_LIW__"๐-msetlbโ lets the compiler generate SETLB and Lcc instructions if the target is AM33 or later. This is the default. It defines the preprocessor macro"__SETLB__"โจ-mno-setlbโ no SETLB or Lcc instructions. It defines the preprocessor macro"__NO_SETLB__"๐
๐ธ Moxie Options ๐ธ
-mebโ generates big-endian code. This is the default formoxie-*-*configurations ๐ฆ-melโ generates little-endian code ๐-mmul.xโ generatesmul.xandumul.xinstructions. This is the default formoxiebox-*-*configurations ๐ฅ-mno-crt0โ doesn't link in the C run-time initialization object file ๐
๐ MSP430 Options ๐
These options are defined for the MSP430 ๐ง
-masm-hexโ forces assembly output to always use hex constants. Normally these are signed decimals, but this option is there for testsuite and/or aesthetic purposes ๐-mmcu=โ picks the MCU you're targeting. GCC uses that MCU name, converts it to upper case, and wraps it with__on both sides to make a C preprocessor symbol. Themsp430.hheader then uses that symbol to pick an MCU-specific supplementary header file ๐
This option also sets the ISA. If the MCU name is one that only supports the 430 ISA, that's the one selected. Otherwise you get the 430X ISA. The generic MCU name msp430 selects the 430 ISA, and the generic msp430x MCU name selects the 430X ISA ๐ฆ
An MCU-specific linker script also gets added to the linker command line. The script's name is the MCU name with .ld appended. So -mmcu=xxx defines the C preprocessor symbol "__XXX__" and makes the linker look for a script called xxx.ld ๐ฅ
This option is also passed on to the assembler โจ
-mwarn-mcu,-mno-warn-mcuโ these turn warnings on or off about conflicts between the MCU name from-mmcuand the ISA set by-mcpu, and/or the hardware multiply support set by-mhwmult. They also toggle warnings about unrecognized MCU names. This one is on by default ๐ซถ-mcpu=โ specifies the ISA to use. The 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, with 20-bit pointers and a 32-bit"size_t"๐-msmallโ uses small-model addressing, with 16-bit pointers and a 16-bit"size_t"๐ธ-mrelaxโ gets passed 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 your target supports. The accepted values arenonefor no hardware multiply,16bitfor the original 16-bit-only multiply in early MCUs,32bitfor the 16/32-bit multiply in later MCUs, andf5seriesfor the 16/32-bit multiply in F5-series MCUs. You can also give itauto, which tells GCC to figure out the hardware multiply support from the MCU name given by-mmcu. If there's no-mmcuoption or the MCU name isn't recognized, GCC assumes no hardware multiply support."auto"is the default setting ๐
Hardware multiplies are normally done by calling a library routine, which saves space in the generated code. When you compile at -O3 or higher, though, the hardware multiplier gets invoked inline. That makes the code bigger, but faster ๐ฅ
The hardware multiply routines turn off 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โ enables a minimum runtime environment, meaning no static initializers or constructors. This is meant for memory-constrained devices. The compiler includes special symbols in some objects that tell the linker and runtime which code fragments are required ๐-mcode-region=,-mdata-region=โ these tell the compiler where to place functions and data that don't have alower,upper,eitherorsectionattribute. The possible values arelower,upper,eitherorany. The first three behave like the matching attribute.anyis the default, and it leaves placement entirely up to the linker script and how it assigns the standard sections (.text,.data, etc) to the memory regions ๐ฆ-msilicon-errata=โ passes a request to the assembler to enable the fixes for the named silicon errata โจ-msilicon-errata-warn=โ passes a request to the assembler to turn on warning messages for when a silicon errata might need to be applied ๐
๐ NDS32 Options ๐
These options are defined for NDS32 implementations ๐ง
-mbig-endianโ generates code in big-endian mode ๐ธ-mlittle-endianโ generates code in little-endian mode ๐-mreduced-regsโ uses the reduced-set registers for register allocation ๐ฆ-mfull-regsโ uses the full-set registers for register allocation ๐-mcmovโ generates conditional move instructions ๐ฅ-mno-cmovโ does not generate conditional move instructions ๐-mext-perfโ generates performance extension instructions ๐-mno-ext-perfโ does not generate performance extension instructions ๐-mext-perf2โ generates performance extension 2 instructions โจ-mno-ext-perf2โ does not generate performance extension 2 instructions ๐-mext-stringโ generates string extension instructions ๐-mno-ext-stringโ does not generate string extension instructions ๐ซถ-mv3pushโ generates v3push25/pop25instructions ๐-mno-v3push: bestie, this one tells the compiler to skip the v3push25andpop25instructions ๐ โโ๏ธ-m16-bit: turns on 16-bit instructions ๐-mno-16-bit: nope, no 16-bit instructions allowed ๐-misr-vector-size=num: picks the size of each interrupt vector. It has to be either4or16๐ฅ-mcache-block-size=num: sets the size of each cache block. It must be a power of 2 between 4 and 512 ๐ฆ-march=arch: names the target architecture ๐๏ธ-mcmodel=code-model: sets the code model to one of these:small: All the data and read-only data segments must be within 512KB addressing space. The text segment must be within 16MB addressing space. ๐ฃmedium: The data segment must be within 512KB, while the read-only data segment can be within 4GB addressing space. The text segment should still be within 16MB addressing space. ๐large: All the text and data segments can be within 4GB addressing space. ๐
-mctor-dtor: enables the constructor/destructor feature โจ-mrelax: guides the linker to relax instructions ๐ฆ
๐ธ Nios II Options ๐ธ
These are the options defined for the Altera Nios II processor. ๐ง
-G num: puts global and static objects that are less than or equal tonumbytes into the small data or BSS sections, instead of the normal data or BSS sections. The default value ofnumis8๐-mgpopt=option,-mgpopt,-mno-gpopt: turns GP-relative accesses on or off. Use the first form to pick one of the option names below, or stick with the plain flags ๐none: Do not generate GP-relative accesses. ๐ โโ๏ธlocal: Generate GP-relative accesses for small data objects that are not external, weak, or uninitialized common symbols. GP-relative addressing is also used for objects that have been explicitly placed in a small data section via a"section"attribute. ๐ฏglobal: Same aslocal, but also generates GP-relative accesses for small data objects that are external, weak, or common. If you use this option, you must make sure that all parts of your program (including libraries) are compiled with the same-Gsetting. ๐คdata: Generates GP-relative accesses for all data objects in the program. If you use this option, the entire data and BSS segments of your program must fit in 64K of memory, and you must use an appropriate linker script to allocate them within the addressable range of the global pointer. ๐พall: Generates GP-relative addresses for function pointers as well as data pointers. If you use this option, the entire text, data, and BSS segments of your program must fit in 64K of memory, and you must use an appropriate linker script to allocate them within the addressable range of the global pointer. ๐
-mgpopt is equivalent to -mgpopt=local, and -mno-gpopt is equivalent to -mgpopt=none.
The default is -mgpopt, except when -fpic or -fPIC is specified to generate position-independent code.
Heads up: the Nios II ABI does not permit GP-relative accesses from shared libraries. ๐ซ
You may need to specify -mno-gpopt explicitly when building programs that include large amounts of small data, including large GOT data sections. In this case, the 16-bit offset for GP-relative addressing may not be large enough to allow access to the entire small data section. ๐ฅบ
-mgprel-sec=regexp: adds extra section names that can be accessed via GP-relative addressing. This one is most useful together with"section"attributes on variable declarations and a custom linker script. The regexp is a POSIX Extended Regular Expression ๐
This option does not affect how -G behaves. The sections you list are in addition to the standard ".sdata" and ".sbss" small-data sections that -mgpopt recognizes.
-mr0rel-sec=regexp: specifies names of sections that can be accessed via a 16-bit offset from"r0". That means they live in the low 32K or high 32K of the 32-bit address space. This is most useful together with"section"attributes on variable declarations and a custom linker script. The regexp is a POSIX Extended Regular Expression ๐บ๏ธ
Unlike GP-relative addressing for small data, zero-based addressing is never generated by default. There are also no conventional section names used in standard linker scripts for sections in the low or high areas of memory. ๐คทโโ๏ธ
-mel,-meb: generate little-endian (the default) or big-endian (experimental) code, respectively ๐-march=arch: specifies the name of the target Nios II architecture. GCC uses this name to figure out what kind of instructions it can emit when generating assembly code. Permissible names are:r1,r2๐๏ธ
The preprocessor macro __nios2_arch__ is available to programs. Its value is 1 or 2, which tells you the targeted ISA level ๐
-mbypass-cache,-mno-bypass-cache: forces all load and store instructions to always bypass the cache by using I/O variants of the instructions. The default is not to bypass the cache ๐โโ๏ธ-mno-cache-volatile,-mcache-volatile: volatile memory accesses bypass the cache by using the I/O variants of the load and store instructions. The default is not to bypass the cache ๐-mno-fast-sw-div,-mfast-sw-div: stops the use of table-based fast divide for small numbers. The default is to use the fast divide at-O3and above โก-mno-hw-mul,-mhw-mul,-mno-hw-mulx,-mhw-mulx,-mno-hw-div,-mhw-div: enables or disables the compiler emitting themul,mulx, anddivfamily of instructions. The default is to emitmul, and not to emitdivormulx๐งฎ-mbmx,-mno-bmx,-mcdx,-mno-cdx: enables or disables generation of Nios II R2 BMX (bit manipulation) and CDX (code density) instructions. Turning these on also requires-march=r2. Since they're optional extensions to the R2 architecture, the default is not to emit them ๐งฉ-mcustom-insn=N,-mno-custom-insn: each-mcustom-insn=Noption enables use of a custom instruction with encodingNwhen generating code that uses insn. For example,-mcustom-fadds=253generates custom instruction 253 for single-precision floating-point add operations, instead of the default behavior of using a library call ๐ ๏ธ
The following values of insn are supported. Unless noted otherwise, floating-point operations are expected to use normal IEEE 754 semantics and to correspond directly to the C operators or the equivalent GCC built-in functions. ๐ง
๐ Single-precision floating point ๐
fadds,fsubs,fdivs,fmuls: binary arithmetic operationsfnegs: unary negationfabss: unary absolute valuefcmpeqs,fcmpges,fcmpgts,fcmples,fcmplts,fcmpnes: comparison operationsfmins,fmaxs: floating-point minimum and maximum. These are only generated if-ffinite-math-onlyis specifiedfsqrts: unary square root operationfcoss,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 operationsfnegd: unary negationfabsd: unary absolute valuefcmpeqd,fcmpged,fcmpgtd,fcmpled,fcmpltd,fcmpned: comparison operationsfmind,fmaxd: double-precision minimum and maximum. These are only generated if-ffinite-math-onlyis specifiedfsqrtd: unary square root operationfcosd,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 precisionftruncds: conversion from double precision to single precisionfixsi,fixsu,fixdi,fixdu: conversion from floating point to signed or unsigned integer types, with truncation towards zeroround: conversion from single-precision floating point to signed integer, rounding to the nearest integer and ties away from zero. This corresponds to the__builtin_lroundffunction when-fno-math-errnois usedfloatis,floatus,floatid,floatud: conversion from signed or unsigned integer types to floating-point types
In addition, all of the following transfer instructions for internal registers X and Y must be provided before you can use any of the double-precision floating-point instructions. ๐จ
Custom instructions that take two double-precision source operands expect the first operand in the 64-bit register X. The other operand (or the only operand of a unary operation) is given to the custom arithmetic instruction, with the least significant half in source register src1 and the most significant half in src2. A custom instruction that returns a double-precision result returns the most significant 32 bits in the destination register, and the other half in 32-bit register Y. GCC automatically generates the necessary code sequences to write register X and/or read register Y when double-precision floating-point instructions are used. ๐ง
fwrx: writessrc1into the least significant half ofX, andsrc2into the most significant half ofXfwry: writessrc1intoYfrdxhi,frdxlo: read the most or least (respectively) significant half ofXand store it indestfrdy: reads the value ofYand stores it intodest
Want more local control over Nios II custom instruction generation? You can use the target("custom-insn=N") and target("no-custom-insn") function attributes or pragmas. ๐
-mcustom-fpu-cfg=name: enables a predefined, named set of custom instruction encodings (see-mcustom-insnabove). Currently, the following sets are defined:
Okay so the -mcustom-fpu-cfg presets are literally just bundles of -mcustom- flags in a trench coat ๐ง Here's what each one expands to:
-mcustom-fpu-cfg=60-1 is equivalent to: -mcustom-fmuls=252
-mcustom-fadds=253 -mcustom-fsubs=254 -fsingle-precision-constant
-mcustom-fpu-cfg=60-2 is equivalent to: -mcustom-fmuls=252
-mcustom-fadds=253 -mcustom-fsubs=254 -mcustom-fdivs=255
-fsingle-precision-constant
-mcustom-fpu-cfg=72-3 is equivalent to: -mcustom-floatus=243
-mcustom-fixsi=244 -mcustom-floatis=245 -mcustom-fcmpgts=246
-mcustom-fcmples=249 -mcustom-fcmpeqs=250 -mcustom-fcmpnes=251
-mcustom-fmuls=252 -mcustom-fadds=253 -mcustom-fsubs=254
-mcustom-fdivs=255 -fsingle-precision-constant
Here's the tea: if you set an individual -mcustom-insn= option, it wins over whatever -mcustom-fpu-cfg= gave you, no matter which one shows up first on the command line ๐
Also, if you want local control over which FPU config a specific function uses, you can do that with the target("custom-fpu-cfg=name") function attribute or pragma ๐
These extra -m options are available for the Altera Nios II ELF (bare-metal) target โจ
-mhalโ Links with the HAL BSP ๐ ๏ธ This skips the GCC-provided C runtime startup and termination code, and it's usually paired with-msys-crt0=so you can point at the alternate startup code that the HAL BSP brings along.-msmallcโ Links with a limited version of the C library,-lsmallc, instead of Newlib. Small and mighty ๐ฆ-msys-crt0=startfileโstartfileis the file name of the startfile (crt0) you want to use while linking. This one only does anything when you're also using-mhal๐ง-msys-lib=systemlibโsystemlibis the library name of the library that handles the low-level system calls the C library needs, like"read"and"write". This is usually how you link against a library that comes from a HAL BSP ๐ซถ
๐ Nvidia PTX Options ๐
These options are defined for Nvidia PTX, bestie ๐
-m32,-m64โ Generate code for the 32-bit or 64-bit ABI. Pick your fighter ๐-misa=ISA-stringโ Generate code for the PTX ISA you specify, likesm_35. ISA strings have to be lower-case (no caps lock allowed here ๐). Valid ISA strings includesm_30andsm_35. The default ISA issm_30.-mmainkernelโ Links in code for a__mainkernel. This is for stand-alone execution instead of offloading ๐ฅ-moptimizeโ Applies partitioned execution optimizations. This is the default whenever any level of optimization is selected, so you're probably already getting it โจ-msoft-stackโ Generates code that doesn't use".local"memory directly for stack storage. Instead, a per-warp stack pointer gets maintained explicitly. This lets you do variable-length stack allocation (with variable-length arrays or"alloca"). When global memory is the underlying storage, it also 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 just so the compiler can be tested. If you want code that links into programs using OpenMP offloading, use-mgompinstead.-muniform-simtโ Switches to a code generation variant that lets all threads in each warp execute, while keeping memory state and side effects the same as if only one thread in each warp was active outside of OpenMP SIMD regions. All atomic operations and calls to the runtime (malloc,free,vprintf) are conditionally executed (iff the current lane index equals the master lane index), and the register being assigned gets 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, which indicates 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. Lowkey a lot, but it's giving genius ๐-mgompโ Generates code for OpenMP offloading. This enables-msoft-stackand-muniform-simt, and selects the corresponding multilib variant ๐ฆ
๐ OpenRISC Options ๐
These options are defined for OpenRISC:
-mboard=nameโ Configures a board-specific runtime. This gets passed to the linker for newlib board library linking. The default isor1ksim๐ง-mnewlibโ For compatibility, it's always newlib for ELF now ๐-mhard-divโ Generates code for hardware that supports divide instructions. This is the default โจ-mhard-mulโ Generates code for hardware that supports multiply instructions. This is the default too ๐-mcmovโ Generates code for hardware that supports the conditional move (l.cmov) instruction.-mrorโ Generates code for hardware that supports rotate right instructions.-msextโ Generates code for hardware that supports sign-extension instructions.-msfimmโ Generates code for hardware that supports set flag immediate (l.sf*i) instructions.-mshftimmโ Generates code for hardware that supports shift-immediate related instructions (i.e.l.srai,l.srli,l.slli,1.rori). Note, to enable generation of thel.roriinstruction, the-mrorflag must also be specified โ ๏ธ-msoft-divโ Generates code for hardware that needs divide instruction emulation.-msoft-mulโ Generates code for hardware that needs multiply instruction emulation.
๐ฆ PDP-11 Options ๐ฆ
These options are defined for the PDP-11:
-mfpuโ Uses hardware FPP floating point. This is the default. (FIS floating point on the PDP-11/40 is not supported, sorry bestie ๐ฅบ) Implies-m45.-msoft-floatโ Does not use hardware floating point.-mac0โ Returns floating-point results inac0(fr0in Unix assembler syntax).-mno-ac0โ Returns floating-point results in memory. This is the default.-m40โ Generates code for a PDP-11/40. Implies-msoft-float -mno-split.-m45โ Generates code for a PDP-11/45. This is the default ๐-m10โ Generates code for a PDP-11/10. Implies-msoft-float -mno-split.-mint16,-mno-int32โ Uses 16-bit"int". This is the default.-mint32,-mno-int16โ Uses 32-bit"int".-msplitโ The target has split instruction and data space. Implies-m45.-munix-asmโ Uses Unix assembler syntax.-mdec-asmโ Uses DEC assembler syntax.-mgnu-asmโ Uses GNU assembler syntax. This is the default ๐-mlraโ Uses the new LRA register allocator. By default, the old"reload"allocator is used ๐ง
๐ง picoChip Options ๐ง
These -m options are defined for picoChip implementations:
-mae=ae_typeโ Sets the instruction set, register set, and instruction scheduling parameters for array element typeae_type. Supported values forae_typeareANY,MUL, andMAC.-mae=ANYselects a completely generic AE type. Code generated with this option runs on any of the other AE types. It's not as efficient as code compiled for a specific AE type, and some types of operation (e.g., multiplication) don't work properly on all types of AE ๐-mae=MULselects a MUL AE type. This is the most useful AE type for compiled code, and it's the default ๐-mae=MACselects a DSP-style MAC AE. Code compiled with this option may suffer from poor performance of byte (char) manipulation, since the DSP AE doesn't provide hardware support for byte load/stores ๐
-msymbol-as-addressโ Lets the compiler use a symbol name directly as an address in a load/store instruction, without loading it into a register first. Usually this makes larger programs that run faster than without the option. The results vary from program to program, though, so it's left as a user option instead of being permanently enabled ๐ฆ-mno-inefficient-warningsโ Disables warnings about the generation of inefficient code. These warnings can show up, for example, when compiling code that does byte-level memory operations on the MAC AE type. The MAC AE has no hardware support for byte-level memory operations, so every byte load/store has to be synthesized from word load/store operations. That's inefficient, so a warning tells you to rewrite the code to avoid byte operations, or to target an AE type with the necessary hardware support. This option turns those warnings off ๐
๐ธ PowerPC Options ๐ธ
These are listed under
Okay bestie, the text just trails off right there, so that's all the PowerPC tea I've got ๐ญ
๐ RISC-V Options ๐
These command-line options are defined for RISC-V targets:
-mbranch-cost=nโ Sets the cost of branches to roughlyninstructions.-mplt,-mno-pltโ When generating PIC code, do or don't allow the use of PLTs. This is ignored for non-PIC. The default is-mplt.-mabi=ABI-stringโ Specifies the integer and floating-point calling convention. The ABI string has two parts: the size of integer types, and the registers used for floating-point types. For example,-march=rv64ifd -mabi=lp64dmeans thatlongand pointers are 64-bit (implicitly makingint32-bit), and that floating-point values up to 64 bits wide get passed in F registers. Compare that with-march=rv64ifd -mabi=lp64f, which still lets the compiler generate code that uses the F and D extensions, but only allows floating-point values up to 32 bits long to be passed in registers. Or there's-march=rv64ifd -mabi=lp64, where no floating-point arguments get passed in registers at all ๐
The default for this argument is system dependent, so bestie, if you want a specific calling convention, specify one explicitly ๐ซถ The valid calling conventions are: ilp32, ilp32f, ilp32d, lp64, lp64f, and lp64d. Some calling conventions are impossible to implement on some ISAs. For example, -march=rv32if -mabi=ilp32d is invalid, because the ABI requires 64-bit values to be passed in F registers, but F registers are only 32 bits wide ๐ There's also the ilp32e ABI, which can only be used with the rv32e architecture. This ABI isn't well specified at present, and it's subject to change โ ๏ธ
-mfdiv,-mno-fdivโ Do or don't use hardware floating-point divide and square root instructions. This requires the F or D extensions for floating-point registers. The default is to use them if the specified architecture has these instructions โจ-mdiv,-mno-divโ okay so these let you choose whether to use hardware instructions for integer division ๐งฎ-mdivturns them on and-mno-divturns them off. You'll need theMextension for this to work ๐ซถ. By default they're used if the architecture you picked actually has those instructions โจ-march=ISA-stringโ tell GCC which RISC-V ISA to generate code for, likerv64im๐ฆ ISA strings have to be lower-case, no exceptions. Some vibes to try:rv64i,rv32g,rv32e, andrv32imaf.-mtune=processor-stringโ optimize the output for a specific processor, named by its microarchitecture ๐ฅ The valid picks arerocket,sifive-3-series,sifive-5-series,sifive-7-series, andsize.
When you skip -mtune= entirely, the default is rocket ๐
The size option isn't really meant for end-users ๐ It gets used when -Os is specified. It overrides the instruction cost info that -mtune= provides, but it does not override the pipeline info. Basically it helps shrink code size while still keeping good performance ๐ธ
-mpreferred-stack-boundary=numโ this tries to keep the stack boundary aligned to a 2 raised to num byte boundary ๐ If you don't set it, the default is4(16 bytes or 128-bits).
๐ Warning: if you use this switch, you have to build all modules with the same value, and that includes any libraries. System libraries and startup modules count too, so don't skip them!
-msmall-data-limit=nโ global and static data smaller than n bytes gets tucked into a special section ๐ง (this only happens on some targets, so don't count on it everywhere).-msave-restore,-mno-save-restoreโ these let you pick between smaller-but-slower prologue and epilogue code that uses library function calls (-msave-restore) or not (-mno-save-restore) ๐ข The default is fast inline prologues and epilogues, so you get speed out of the box โก-mstrict-align,-mno-strict-alignโ these control whether unaligned memory accesses get generated ๐ The first one says do not, the second one says do. The default depends on whether the processor you're optimizing for supports fast unaligned access or not.-mcmodel=medlowโ generates code for the medium-low code model ๐ The program and its statically defined symbols have to live inside one single 2 GiB address range, sitting between absolute addresses -2 GiB and +2 GiB. Programs can be statically or dynamically linked. This is the default code model, so you're already using it if you don't pick anything else ๐-mcmodel=medanyโ generates code for the medium-any code model ๐ Here the program and its statically defined symbols just need to be within any single 2 GiB address range. Programs can be statically or dynamically linked.-mexplicit-relocs,-mno-exlicit-relocsโ use or skip assembler relocation operators when dealing with symbolic addresses โจ The other route is assembler macros, which may limit optimization ๐ฅฒ (heads up, the negative flag is spelled-mno-exlicit-relocsin the official page, so copy it exactly ๐)-mrelax,-mno-relaxโ take advantage of linker relaxations to cut down on the number of instructions needed to materialize symbol addresses ๐ฆ The default is to take advantage of them.-memit-attribute,-mno-emit-attributeโ these emit (or don't emit) a RISC-V attribute that records extra info into ELF objects ๐งพ This feature needs at least binutils 2.32 ๐
๐ RL78 Options ๐
-msimโ links in extra target libraries so your stuff can run inside a simulator ๐ฅ๏ธ-mmul=none,-mmul=g10,-mmul=g13,-mmul=g14,-mmul=rl78โ this is where you pick which hardware multiplication and division support to use ๐งฎ The simplest choice is"none", which uses software for both multiplication and division, and it's the default."g13"is for the hardware multiply/divide peripheral on the RL78/G13 (S2 core) targets."g14"selects the multiplication and division instructions that the RL78/G14 (S3 core) parts support."rl78"is just an alias for"g14", and"mg10"is an alias for"none".
Setting this option also defines a C preprocessor macro based on what you picked ๐ง The possible values are __RL78_MUL_NONE__, __RL78_MUL_G13__, or __RL78_MUL_G14__.
-mcpu=g10,-mcpu=g13,-mcpu=g14,-mcpu=rl78โ pick which RL78 core you're targeting ๐ The default is the G14 core, also called an S3 core or just RL78. The G13 (or S2) core doesn't have multiply or divide instructions, so it uses a hardware peripheral for those jobs instead. The G10 (or S1) core doesn't have register banks, so it uses a different calling convention ๐ซ
If you set this option, it also picks the type of hardware multiply support, unless you override it with an explicit -mmul=none on the command line ๐
So -mcpu=g13 turns on the G13 hardware multiply peripheral, and -mcpu=g10 turns off hardware multiplications altogether.
Heads up, though: even though the RL78/G14 core is the default target, typing -mcpu=g14 or -mcpu=rl78 on the command line does change how the toolchain behaves, because it turns on G14 hardware multiply support ๐ If you don't specify these on the command line, software multiplication routines get used even though the code targets the RL78 core. This is only there for backwards compatibility with older toolchains that didn't have hardware multiply and divide support ๐ฅน
Same deal with the macros here: based on the setting, you get __RL78_G10__, __RL78_G13__, or __RL78_G14__ defined โจ
-mg10,-mg13,-mg14,-mrl78โ these are aliases for the matching-mcpu=option ๐ They're only around for backwards compatibility.-mallregsโ lets the compiler use every available register ๐ธ By default,r24..r31are reserved for interrupt handlers. With this option turned on, those registers can also be used in ordinary functions.-m64bit-doubles,-m32bit-doublesโ make thedoubledata type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) ๐ The default is-m32bit-doubles.-msave-mduc-in-interrupts,-mno-save-mduc-in-interruptsโ these tell interrupt handler functions whether they should preserve the MDUC registers ๐ก๏ธ You only really need this if normal code might touch the MDUC registers, for example because it does multiplication and division. The default is to ignore the MDUC registers, since that keeps the interrupt handlers faster โก You need to pass the target option-mg13for this to work, because 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 ๐ฆ
Here's the whole squad of flags ๐
-mpowerpc-gpopt
-mno-powerpc-gpopt
-mpowerpc-gfxopt
-mno-powerpc-gfxopt
-mpowerpc64
-mno-powerpc64
-mmfcrf
-mno-mfcrf
-mpopcntb
-mno-popcntb
-mpopcntd
-mno-popcntd
-mfprnd
-mno-fprnd
-mcmpb
-mno-cmpb
-mmfpgpr
-mno-mfpgpr
-mhard-dfp
-mno-hard-dfp
You use these to specify which instructions are available on the processor you're using ๐ง The default value of these options is determined when you configure GCC. Specifying -mcpu=cpu_type overrides whatever you set here. The devs recommend using the -mcpu=cpu_type option instead of the ones listed above, so that's the move ๐ซถ
Specifying -mpowerpc-gpopt lets GCC use the optional PowerPC architecture instructions in the General Purpose group, including floating-point square root โจ Specifying -mpowerpc-gfxopt lets GCC use the optional PowerPC architecture instructions in the Graphics group, including floating-point select ๐จ
The -mmfcrf option lets GCC generate the move from condition register field instruction, which is implemented on the POWER4 processor and other processors that support the PowerPC V2.01 architecture ๐ The -mpopcntb option lets GCC generate the popcount and double-precision FP reciprocal estimate instruction, implemented on the POWER5 processor and other processors that support the PowerPC V2.02 architecture ๐ The -mpopcntd option lets GCC generate the popcount instruction implemented on the POWER7 processor and other processors that support the PowerPC V2.06 architecture ๐ฅ The -mfprnd option lets GCC generate the FP round to integer instructions implemented on the POWER5+ processor and other processors that support the PowerPC V2.03 architecture ๐ง The -mcmpb option lets GCC generate the compare bytes instruction implemented on the POWER6 processor and other processors that support the PowerPC V2.05 architecture ๐ The -mmfpgpr option lets GCC generate the FP move to/from general-purpose register instructions implemented on the POWER6X processor and other processors that support the extended PowerPC V2.05 architecture ๐ฆ The -mhard-dfp option lets GCC generate the decimal floating-point instructions implemented on some POWER processors ๐
The -mpowerpc64 option lets GCC generate the additional 64-bit instructions found in the full PowerPC64 architecture, and it treats GPRs as 64-bit, doubleword quantities ๐ GCC defaults to -mno-powerpc64.
-mcpu=cpu_typeโ sets the architecture type, register usage, and instruction scheduling parameters for the machine type cpu_type ๐ฅ๏ธ These are the supported values: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,powerpc,powerpc64,powerpc64le,rs64, andnative.
-mcpu=powerpc, -mcpu=powerpc64, and -mcpu=powerpc64le specify pure 32-bit PowerPC (either endian), 64-bit big endian PowerPC, and 64-bit little endian PowerPC architecture machine types ๐ง An appropriate, generic processor model gets assumed for scheduling purposes.
Specifying native as the cpu type detects and selects the architecture option that matches the host processor doing the compilation ๐ซถ -mcpu=native has no effect if GCC doesn't recognize the processor ๐คทโโ๏ธ
The other options specify a specific processor ๐
โ ๏ธ Code generated under those options runs best on that processor, and it may not run at all on others. Be careful, bestie!
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
ngl the exact set of flags that gets picked for a CPU changes between compiler versions ๐
GCC goes with whatever seems to make the best code for that chip, so it doesn't necessarily match what the hardware can actually do ๐. Want one specific flag set differently? Put it after -mcpu like -mcpu=970 -mno-altivec โจ
On AIX, -maltivec and -mpowerpc64 don't get turned on or off by -mcpu right now, because AIX doesn't have full support for them yet ๐. You can still toggle them yourself if you're sure it'll work in your setup.
๐ -mtune=cpu_type
Okay this one is so useful ๐ง It sets the instruction scheduling parameters for the machine type cpu_type, but it does not touch the architecture or register usage the way -mcpu=cpu_type does. You use the same values for cpu_type as you would with -mcpu. If you pass both, the code uses 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 be up to a total of 4G in size. This is the default for 64-bit Linux ๐
๐ธ -mcmodel=large
Generates PowerPC64 code for the large model. The TOC can be up to 4G in size, and other data and code is only limited by the 64-bit address space ๐
โจ -maltivec / -mno-altivec
These generate code that uses (or doesn't use) AltiVec instructions, and they also unlock built-in functions that give you more direct access to the AltiVec instruction set ๐ฅ You might also need -mabi=altivec to tweak the current ABI with the AltiVec ABI enhancements.
When -maltivec is on, the element order for AltiVec intrinsics like "vec_splat", "vec_extract", and "vec_insert" matches the array element order for the target's endianness. So element zero is the leftmost element of a vector register on a big-endian target, and the rightmost one on a little-endian target ๐ซถ
๐ฆ -mvrsave / -mno-vrsave
Generates VRSAVE instructions when you're generating AltiVec code ๐
๐ฆ -msecure-plt
Generates code that lets ld and ld.so build executables and shared libraries with non-executable ".plt" and ".got" sections. This is a PowerPC 32-bit SYSV ABI option ๐ง
๐ฆ -mbss-plt
Generates code that uses a BSS ".plt" section, which ld.so fills in. It needs ".plt" and ".got" sections that are both writable and executable ๐ญ This is also a PowerPC 32-bit SYSV ABI option.
Heads up bestie:-mbss-pltrequires".plt"and".got"to be both writable and executable, so make sure that's okay for your situation before you reach for it ๐
๐ฆ -misel / -mno-isel
This switch enables or disables the generation of ISEL instructions ๐ธ
โจ -mvsx / -mno-vsx
These generate code that uses (or doesn't use) vector/scalar (VSX) instructions. They also turn on built-in functions for more direct access to the VSX instruction set ๐ฅ
โจ -mcrypto / -mno-crypto
Enables (or disables) the built-in functions that give direct access to the cryptographic instructions added in version 2.07 of the PowerPC ISA ๐
โจ -mhtm / -mno-htm
Enables (or disables) the built-in functions for direct access to the Hardware Transactional Memory (HTM) instructions, which were added in version 2.07 of the PowerPC ISA ๐
โจ -mpower8-fusion / -mno-power8-fusion
The -mpower8-fusion form generates code that keeps some integer operations next to each other, so the instructions can be fused together on POWER8 and later processors โจ The -mno-power8-fusion form does not keep them adjacent like that (the original text says "does not keeps", but the meaning is clear ๐).
โจ -mpower8-vector / -mno-power8-vector
These generate code that uses (or doesn't use) the vector and scalar instructions added in version 2.07 of the PowerPC ISA. -mpower8-vector also enables built-in functions for more direct access to the vector instructions ๐ฆ
โจ -mquad-memory / -mno-quad-memory
These generate code that uses (or doesn't use) the non-atomic quad word memory instructions. -mquad-memory needs 64-bit mode, so no skipping that part ๐
โจ -mquad-memory-atomic / -mno-quad-memory-atomic
These generate code that uses (or doesn't use) the atomic quad word memory instructions. -mquad-memory-atomic also needs 64-bit mode ๐
๐ -mfloat128 / -mno-float128
These enable (or disable) the __float128 keyword for IEEE 128-bit floating point, and pick between software emulation or hardware instructions for it ๐ฅ
The VSX instruction set (-mvsx, -mcpu=power7, -mcpu=power8) or -mcpu=power9 must be enabled to use IEEE 128-bit floating point support. Also, this support only works on PowerPC Linux systems, so it's not a vibe anywhere else ๐
-mfloat128 is enabled by default on PowerPC Linux systems using the VSX instruction set, and disabled on other systems ๐
If you use the ISA 3.0 instruction set (-mpower9-vector or -mcpu=power9) on a 64-bit system, IEEE 128-bit floating point support also enables generation of ISA 3.0 IEEE 128-bit floating point instructions. Otherwise, if you don't ask for ISA 3.0 instructions, or you're targeting a 32-bit big endian system, IEEE 128-bit floating point gets handled by software emulation ๐ซถ
๐ -mfloat128-hardware / -mno-float128-hardware
These enable (or disable) using ISA 3.0 hardware instructions to support the __float128 data type โจ
-mfloat128-hardware is enabled by default on PowerPC Linux systems using the ISA 3.0 instruction set, and disabled on other systems ๐
๐ง -m32 / -m64
These generate code for 32-bit or 64-bit environments on Darwin and SVR4 targets, including GNU/Linux ๐ธ
The 32-bit environment sets int, long and pointer to 32 bits, and generates code that runs on any PowerPC variant.
The 64-bit environment sets int to 32 bits and long and pointer to 64 bits, and generates code for PowerPC64, same as -mpowerpc64 ๐
๐ง -mfull-toc / -mno-fp-in-toc / -mno-sum-in-toc / -mminimal-toc
These modify how the TOC (Table Of Contents) gets generated, and every executable file gets one ๐
-mfull-toc is the default. In that case GCC allocates at least one TOC entry for each unique non-automatic variable reference in your program, and it also puts floating-point constants in the TOC. The catch is that only 16,384 entries are available in the TOC ๐
If the linker yells that you've overflowed the available TOC space, you can shrink TOC usage with -mno-fp-in-toc and -mno-sum-in-toc:
-mno-fp-in-tocโ stops GCC from putting floating-point constants in the TOC-mno-sum-in-tocโ forces GCC to calculate the sum of an address and a constant at run time, instead of stuffing that sum into the TOC
You can use one or both of these. Each one makes the code very slightly slower and larger, but it saves TOC space ๐ฆ
If you still run out of space even with both of those, try -mminimal-toc. It makes only one TOC entry per file. The code is slower and larger, but it uses extremely little TOC space. Maybe only use it on files with less frequently-executed code ๐
๐ -maix64 / -maix32
-maix64 enables the 64-bit AIX ABI and calling convention: 64-bit pointers, a 64-bit "long" type, and the infrastructure needed to support them. It implies -mpowerpc64.
-maix32 disables the 64-bit ABI and implies -mno-powerpc64.
GCC defaults to -maix32 ๐
๐
-mxl-compat / -mno-xl-compat
-mxl-compat produces code that matches IBM XL compiler semantics more closely when you're using the AIX-compatible ABI. Specifically:
- Floating-point arguments to prototyped functions beyond the register save area (RSA) go on the stack, in addition to argument FPRs.
- It doesn't assume the most significant double in a 128-bit
long doublevalue is properly rounded when comparing values and converting to double. - It uses XL symbol names for
long doublesupport routines.
The AIX calling convention got extended without being documented at first, to handle an obscure K&R C case: calling a function that takes the address of its arguments with fewer arguments than declared. IBM XL compilers read floating-point arguments that don't fit in the RSA from the stack when a subroutine is compiled without optimization. Always storing floating-point arguments on the stack is inefficient and rarely needed, so this option isn't on by default. You only really need it when calling subroutines compiled by IBM XL compilers without optimization ๐ง
๐ -mpe
This supports the IBM RS/6000 SP Parallel Environment (PE) ๐ It links an application that uses message passing with special startup code so it can run.
The system needs PE installed in the standard location (/usr/lpp/ppe.poe/), or you have to override the specs file with -specs= to point at the right directory.
Heads up: the Parallel Environment doesn't support threads, so -mpe and -pthread are incompatible ๐
๐ธ -malign-natural / -malign-power
On AIX, 32-bit Darwin, and 64-bit PowerPC GNU/Linux, -malign-natural overrides the ABI-defined alignment of larger types (like floating-point doubles) and puts them on their natural size-based boundary โจ
-malign-power tells GCC to follow the ABI-specified alignment rules instead.
GCC defaults to the standard alignment defined in the ABI.
On 64-bit Darwin, natural alignment is the default, and -malign-power is not supported ๐
๐ -msoft-float / -mhard-float
These generate code that doesn't use (or does use) the floating-point register set ๐ฆ
If you use -msoft-float, software floating-point emulation is provided, but you have to pass the option to GCC when linking too ๐
-mmultiple,-mno-multipleโ okay so these tell GCC whether to use (or skip) the load multiple word and store multiple word instructions ๐ง. They're on by default on POWER systems, but not on PowerPC systems. > ๐ Do not use-mmultipleon little-endian PowerPC systems, since those instructions don't work when the processor is in little-endian mode. The only exceptions are PPC740 and PPC750, which let these instructions run in little-endian mode ๐.-mupdate,-mno-updateโ makes GCC use (or not use) the load or store instructions that update the base register to the address of the calculated memory location ๐ . These are generated by default. > ๐ญ If you go with-mno-update, there's a small window between the time the stack pointer is updated and the address of the previous frame is stored. That means code that walks the stack frame across interrupts or signals may get corrupted data.-mavoid-indexed-addresses,-mno-avoid-indexed-addressesโ tries to avoid (or not avoid) the use of indexed load or store instructions ๐ธ. These can cost you a performance penalty on Power6 processors in certain situations, like stepping through large arrays that cross a 16M boundary. It's enabled by default when targeting Power6 and disabled otherwise.-mfused-madd,-mno-fused-maddโ uses (or doesn't use) the floating-point multiply and accumulate instructions ๐ฅ. They're generated by default if hardware floating point is used. The machine-dependent-mfused-maddis now mapped to the machine-independent-ffp-contract=fastoption, and-mno-fused-maddis mapped to-ffp-contract=off๐.-mmulhw,-mno-mulhwโ uses (or doesn't use) the half-word multiply and multiply-accumulate instructions on the IBM 405, 440, 464 and 476 processors โจ. These are generated by default when targeting those processors.-mdlmzb,-mno-dlmzbโ uses (or doesn't use) the string-searchdlmzbinstruction on the IBM 405, 440, 464 and 476 processors ๐ฆ. It's generated by default when targeting those processors.-mno-bit-align,-mbit-alignโ on System V.4 and embedded PowerPC systems, do not (or do) force structures and unions that contain bit-fields to be aligned to the base type of the bit-field ๐.
Example time ๐: by default, a structure containing nothing but 8 "unsigned" bit-fields of length 1 is aligned to a 4-byte boundary and has a size of 4 bytes. With -mno-bit-align, that same structure is aligned to a 1-byte boundary and is 1 byte in size.
-mno-strict-align,-mstrict-alignโ on System V.4 and embedded PowerPC systems, do not (or do) assume that unaligned memory references are handled by the system ๐ซถ.-mrelocatable,-mno-relocatableโ allows (or doesn't 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.got2and the 4-byte locations listed in the.fixupsection, which is a table of 32-bit addresses generated by this option. For this to work, all objects linked together must be compiled with-mrelocatableor-mrelocatable-lib. Also,-mrelocatablecode aligns the stack to an 8-byte boundary.-mrelocatable-lib,-mno-relocatable-libโ just like-mrelocatable, this generates a.fixupsection 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, do not (or do) assume that register 2 contains a pointer to a global area pointing to the addresses used in the program ๐ง.-mlittle,-mlittle-endianโ on System V.4 and embedded PowerPC systems, compiles code for the processor in little-endian mode ๐ธ. The-mlittle-endianoption is the same as-mlittle.-mbig,-mbig-endianโ on System V.4 and embedded PowerPC systems, compiles code for the processor in big-endian mode ๐. The-mbig-endianoption is the same as-mbig.-mdynamic-no-picโ on Darwin and Mac OS X systems, compiles code so it isn't relocatable itself, but its external references are relocatable ๐. The result is suitable for applications, but not shared libraries.-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.-mprioritize-restricted-insns=priorityโ controls the priority given to dispatch-slot restricted instructions during the second scheduling pass โญ. Thepriorityargument takes0,1, or2:0gives no priority,1gives the highest priority, and2gives the second-highest priority.-msched-costly-dep=dependence_typeโ 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โ controls which NOP insertion scheme gets used during the second scheduling pass ๐ฆ. Theschemeargument takes one of these values:noโ don't insert NOPs.padโ pad with NOPs any dispatch group that has vacant issue slots, according to the scheduler's grouping.regroup_exactโ insert NOPs to force costly dependent insns into separate groups. Insert exactly as many NOPs as needed to force an insn to a new group, according to the estimated processor grouping.numberโ insert NOPs to force costly dependent insns into separate groups. Insert number NOPs to force an insn to a new group.
-mcall-sysvโ on System V.4 and embedded PowerPC systems, 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โ specifies both-mcall-sysvand-meabi๐.-mcall-sysv-noeabiโ specifies both-mcall-sysvand-mno-eabi๐.-mcall-aixdescโ on System V.4 and embedded PowerPC systems, compiles code for the AIX operating system ๐ง.-mcall-linuxโ on System V.4 and embedded PowerPC systems, compiles code for the Linux-based GNU system ๐ซถ.-mcall-freebsdโ on System V.4 and embedded PowerPC systems, compiles code for the FreeBSD operating system ๐ธ.-mcall-netbsdโ on System V.4 and embedded PowerPC systems, compiles code for the NetBSD operating system ๐.-mcall-openbsdโ on System V.4 and embedded PowerPC systems, compiles code for the OpenBSD operating system โจ.-mtraceback=traceback_typeโ selects the type of traceback table ๐. Valid values fortraceback_typearefull,part, andno.-maix-struct-returnโ returns all structures in memory, as specified by the AIX ABI ๐.-msvr4-struct-returnโ returns structures smaller than 8 bytes in registers, as specified by the SVR4 ABI ๐ฅ.-mabi=abi-typeโ extends the current ABI with a particular extension, or removes one ๐ . Valid values arealtivec,no-altivec,ibmlongdouble,ieeelongdouble,elfv1, andelfv2.-mabi=ibmlongdoubleโ changes the current ABI to use IBM extended-precision long double ๐. > โ ๏ธ This is not likely to work if your system defaults to using IEEE extended-precision long double. If you change the long double type from IEEE extended-precision, the compiler will issue a warning unless you use-Wno-psabi. It requires-mlong-double-128to be enabled.-mabi=ieeelongdoubleโ changes the current ABI to use IEEE extended-precision long double ๐. > โ ๏ธ This is not likely to work if your system defaults to using IBM extended-precision long double. If you change the long double type from IBM extended-precision, the compiler will issue a warning unless you use-Wno-psabi. It requires-mlong-double-128to be enabled.-mabi=elfv1โ changes the current ABI to use the ELFv1 ABI ๐ง. This is the default ABI for big-endian PowerPC 64-bit Linux. > ๐ Overriding the default ABI requires special system support and is likely to fail in spectacular ways.-mabi=elfv2โ changes the current ABI to use the ELFv2 ABI ๐ซถ. This is the default ABI for little-endian PowerPC 64-bit Linux. > ๐ Overriding the default ABI requires special system support and is likely to fail in spectacular ways.-mgnu-attribute,-mno-gnu-attributeโ emits.gnu_attributeassembly directives to set tag/value pairs in a.gnu.attributessection โจ. Those pairs specify ABI variations in function parameters or return values.-mprototype,-mno-prototypeโ on System V.4 and embedded PowerPC systems, assumes that all calls to variable argument functions are properly prototyped ๐ฆ. Otherwise, the compiler has to insert an instruction before every non-prototyped call to set or clear bit 6 of the condition code register ("CR"), so it can indicate whether floating-point values are passed in the floating-point registers in case the function takes variable arguments. With-mprototype, only calls to prototyped variable argument functions set or clear that bit.-msimโ on embedded PowerPC systems, assumes that the startup module is calledsim-crt0.oand that the standard C libraries arelibsim.aandlibc.a๐. This is the default forpowerpc-*-eabisimconfigurations.-mmvmeโ on embedded PowerPC systems, assumes that the startup module is calledcrt0.oand that the standard C libraries arelibmvme.aandlibc.a๐.-madsโ ๐ okay so on embedded PowerPC systems, this one assumes the startup module is calledcrt0.oand the standard C libraries arelibads.aandlibc.a. Iconic setup ๐ง-myellowknifeโ ๐ on embedded PowerPC systems, this one assumes the startup module is calledcrt0.oand the standard C libraries arelibyk.aandlibc.a. Same energy, different libs ๐-mvxworksโ ๐ on System V.4 and embedded PowerPC systems, this tells the compiler you're building for a VxWorks system. Main character energy ๐-membโ โจ on embedded PowerPC systems, this sets the"PPC_EMB"bit in the ELF flags header to signal that eabi extended relocations are being used ๐ฆ-meabi,-mno-eabiโ ๐ธ on System V.4 and embedded PowerPC systems, you either do (-meabi) or do not (-mno-eabi) follow the Embedded Applications Binary Interface (EABI), which is basically a set of tweaks on top of the System V.4 specifications. ๐ซถ
With -meabi, the stack is aligned to an 8-byte boundary, a function "__eabi" gets 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, small initialized"const"global and static data goes in the.sdata2section, which is pointed to by registerr2. Small initialized non-"const"global and static data goes in the.sdatasection, pointed to by registerr13. Small uninitialized global and static data goes in the.sbsssection, which sits right next to.sdata.
Heads up: -msdata=eabi is incompatible with -mrelocatable. It also sets -memb for you ๐
-msdata=sysvโ ๐ on System V.4 and embedded PowerPC systems, small global and static data goes in the.sdatasection, pointed to by registerr13. Small uninitialized global and static data goes in the.sbsssection, which is adjacent to.sdata.
This one is incompatible with -mrelocatable too, so pick your side ๐ฅ
-msdata=default,-msdataโ ๐ท on System V.4 and embedded PowerPC systems, if-meabiis used, the code gets compiled the same as-msdata=eabi. Otherwise, it gets compiled the same as-msdata=sysv.-msdata=dataโ ๐ on System V.4 and embedded PowerPC systems, small global data goes in the.sdatasection, and small uninitialized global data goes in the.sbsssection. The catch is that registerr13is not used to address small data. This is the default behaviour unless other-msdataoptions are used.-msdata=none,-mno-sdataโ ๐ง on embedded PowerPC systems, all initialized global and static data goes in the.datasection, and all uninitialized data goes in the.bsssection. No small data shenanigans here ๐ฅฒ-mreadonly-in-sdataโ ๐ read-only objects get put in the.sdatasection as well. This is the default, so you're already getting it ๐-mblock-move-inline-limit=numโ ๐ inlines all block moves (like calls to"memcpy"or structure copies) that are less than or equal to num bytes. The minimum value for num is 32 bytes on 32-bit targets and 64 bytes on 64-bit targets. The default value is target-specific, so it depends on your setup ๐ง-mblock-compare-inline-limit=numโ ๐ generates non-looping inline code for all block compares (like calls to"memcmp"or structure compares) that are less than or equal to num bytes. If num is0, all inline expansion (both non-loop and loop) of block compare is disabled. The default value is target-specific ๐-mblock-compare-inline-loop-limit=numโ ๐ generates an inline expansion using loop code for all block compares that are less than or equal to num bytes, but greater than the limit for non-loop inline block compare expansion. If the block length isn't constant, at most num bytes get compared before"memcmp"is called to compare the rest of the block. The default value is target-specific ๐ธ-mstring-compare-inline-limit=numโ ๐งต compares at most num string bytes with inline code. If the difference or end of string isn't found at the end of the inline compare, a call to"strcmp"or"strncmp"takes care of the rest. The default is 64 bytes ๐ฆ-G numโ ๐ฆ on embedded PowerPC systems, global and static items less than or equal to num bytes go 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. Every module should be compiled with the same-G numvalue, bestie, or things get messy ๐ซ-mregnames,-mno-regnamesโ ๐ท๏ธ on System V.4 and embedded PowerPC systems, you do (-mregnames) or do not (-mno-regnames) emit register names in the assembly language output using symbolic forms.-mlongcall,-mno-longcallโ ๐ by default, the compiler assumes that all calls are far away, so a longer and more expensive calling sequence is required. This is needed for calls farther than 32 megabytes (33,554,432 bytes) from the current location. A short call only gets generated if the compiler knows the call cannot be that far away.
This setting can be overridden by the shortcall function attribute, or by #pragma longcall(0). โจ
Some linkers are capable of detecting out-of-range calls and generating glue code on the fly. On these systems, long calls are unnecessary and generate slower code. As of this writing, the AIX linker can do this, as can the GNU linker for PowerPC/64. It is planned to add this feature to the GNU linker for 32-bit PowerPC systems as well.
On PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers, GCC can generate long calls using an inline PLT call sequence (see -mpltseq). PowerPC with -mbss-plt and PowerPC64 ELFv1 (big-endian) do not support inline PLT calls. ๐
On Darwin/PPC systems, #pragma longcall generates jbsr callee, L42, plus a branch island (glue code). The two target addresses represent the callee and the branch island. The Darwin/PPC linker prefers the first address and generates a bl callee if the PPC bl instruction reaches the callee directly. Otherwise, the linker generates bl L42 to call the branch island. The branch island is appended to the body of the calling function, and it computes the full 32-bit address of the callee and jumps to it. ๐งฉ
On Mach-O (Darwin) systems, this option directs the compiler to emit the glue for every direct call, and the Darwin linker decides whether to use or discard it.
In the future, GCC may ignore all longcall specifications when the linker is known to generate glue. ๐ฎ
-mpltseq,-mno-pltseqโ ๐ช implements (-mpltseq) or does not implement (-mno-pltseq)-fno-pltand long calls using an inline PLT call sequence. This supports lazy linking and long calls to functions indlopen'dshared libraries.
Inline PLT calls are only supported on PowerPC64 ELFv2 and 32-bit PowerPC systems with newer GNU linkers. They are enabled by default if the support is detected when configuring GCC. In the case of 32-bit PowerPC, they're also enabled if GCC is configured with --enable-secureplt.
Heads up: -mpltseq code and -mbss-plt 32-bit PowerPC relocatable objects may not be linked together. ๐ซ
-mtls-markers,-mno-tls-markersโ ๐ณ๏ธโ๐ marks (-mtls-markers) or does not mark (-mno-tls-markers) calls to"__tls_get_addr"with a relocation specifying the function argument. The relocation lets the linker reliably associate the function call with the argument setup instructions for TLS optimization, which in turn lets GCC schedule the sequence better ๐ง-mrecip,-mno-recipโ โก this enables use of the reciprocal estimate and reciprocal square root estimate instructions, with additional Newton-Raphson steps to increase precision. These are used instead of doing a divide, or a square root and divide, for floating-point arguments.
You should use -ffast-math when using -mrecip, or at least -funsafe-math-optimizations, -ffinite-math-only, -freciprocal-math and -fno-trapping-math. ๐ซถ
The throughput of the sequence is generally higher than the throughput of the non-reciprocal instruction. But the precision of the sequence can be decreased by up to 2 ulp (i.e. the inverse of 1.0 equals 0.99999994) for reciprocal square roots. Keep that in mind, bestie ๐
-mrecip=optโ ๐๏ธ this controls which reciprocal estimate instructions may be used.optis a comma-separated list of options, and any of them can be preceded by a!to invert the option:allโ enables all estimate instructions ๐defaultโ enables the default instructions, which is equivalent to-mrecip๐งnoneโ disables all estimate instructions, which is equivalent to-mno-recip๐ โโ๏ธdivโ enables the reciprocal approximation instructions for both single and double precision โdivfโ enables the single-precision reciprocal approximation instructions ๐นdivdโ enables the double-precision reciprocal approximation instructions ๐ทrsqrtโ enables the reciprocal square root approximation instructions for both single and double precision ๐rsqrtfโ enables the single-precision reciprocal square root approximation instructions ๐rsqrtdโ enables the double-precision reciprocal square root approximation instructions ๐
So, for example, -mrecip=all,!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. Iykyk ๐
-mrecip-precision,-mno-recip-precisionโ ๐ฏ assumes (-mrecip-precision) or does not assume (-mno-recip-precision) that the reciprocal estimate instructions provide higher-precision estimates than the PowerPC ABI mandates. Selecting-mcpu=power6,-mcpu=power7or-mcpu=power8automatically selects-mrecip-precision.
The double-precision square root estimate instructions aren't generated by default on low-precision machines, since they don't provide an estimate that converges after three steps. Not me being picky, it's just the math ๐ค
-mveclibabi=typeโ okay bestie, this one picks the ABI type for vectorizing intrinsics with an external library ๐ The only type supported right now ismass, which means IBM's Mathematical Acceleration Subsystem (MASS) libraries ๐ When you're generating code forpower7, GCC emits calls to these functions:
acosd2, acosf4, acoshd2, acoshf4, asind2, asinf4, asinhd2, asinhf4,
atan2d2, atan2f4, atand2, atanf4, atanhd2, atanhf4, cbrtd2, cbrtf4,
cosd2, cosf4, coshd2, coshf4, erfcd2, erfcf4, erfd2, erff4, exp2d2,
exp2f4, expd2, expf4, expm1d2, expm1f4, hypotd2, hypotf4, lgammad2,
lgammaf4, log10d2, log10f4, log1pd2, log1pf4, log2d2, log2f4, logd2,
logf4, powd2, powf4, sind2, sinf4, sinhd2, sinhf4, sqrtd2, sqrtf4,
tand2, tanf4, tanhd2, tanhf4
But wait, bestie, both -ftree-vectorize and -funsafe-math-optimizations have to be enabled too ๐ฅ And the MASS libraries must be specified at link time ๐
-mfriz,-mno-frizโ you can make GCC generate (or not generate) thefrizinstruction ๐ธ It's used when-funsafe-math-optimizationsis on, to optimize rounding floating-point values to 64-bit integers and back to floats.
โ ๏ธ Heads up: friz 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โ this decides whether GCC generates code to load the static chain register (r11) when calling through a pointer on AIX and 64-bit Linux systems โจ On those systems a function pointer points to a 3-word descriptor that holds the function address, the TOC value to load into registerr2, and the static chain value to load into registerr11.-mpointers-to-nested-functionsis on by default.
๐จ Danger zone: 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.-mcompat-align-parm,-mno-compat-align-parmโ generate (or don't generate) code that passes structure parameters with a maximum alignment of 64 bits, so it stays compatible with older versions of GCC ๐ Older versions (before 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 make code that works with functions built by the older GCC.-mno-compat-align-parmis the default.-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offset,-mstack-protector-guard-symbol=symbolโ generate stack protection code that uses 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). Withtls, the options-mstack-protector-guard-reg=regand-mstack-protector-guard-offset=offsettell GCC which register to use as the base register for reading the canary, and what offset from that base to use. The defaults for those come from the relevant ABI.-mstack-protector-guard-symbol=symboloverrides the offset with a symbol reference to a canary in the TLS block.
โจ RX Options โจ
These command-line options are defined for RX targets ๐ฆ
-m64bit-doubles,-m32bit-doublesโ makes thedoubledata type 64 bits (-m64bit-doubles) or 32 bits (-m32bit-doubles) in size ๐ The default is-m32bit-doubles, and that's because RX floating-point hardware only works on 32-bit values.-fpu,-nofpuโ enables (-fpu) or disables (-nofpu) 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.
Note: if-fpuis enabled, then-funsafe-math-optimizationsis also enabled automatically ๐ซถ That's because the RX FPU instructions are themselves unsafe.
-mcpu=nameโ selects the type of RX CPU to target ๐ Three types are supported: 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 theMVTIPLinstruction. 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โ stores data (but not code) in the big-endian format ๐ฌ The default is-mlittle-endian-data, meaning data is stored in the little-endian format.-msmall-data-limit=Nโ specifies the maximum size in bytes of global and static variables that can be placed into the small data area ๐ฅ Using the small data area can lead to smaller and faster code, but the area is limited in size, and it's up to you to make sure it doesn't overflow ๐ฌ Also, when the small data area is used, one of the RX's registers (usuallyr13) is reserved to point to this area, so the compiler can't use it anymore. This could make code slower and/or larger if variables get pushed onto the stack instead of living in that register.
Common variables (variables that haven't been initialized) and constants are NOT placed into the small data area, because they get assigned to other sections in the output executable.
The default value is zero, which disables this feature ๐ It's not 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 holding the small data area pointer gets chosen.
-msim,-mno-simโ uses the simulator runtime ๐งช The default is to use the libgloss board-specific runtime.-mas100-syntax,-mno-as100-syntaxโ when generating assembler output, uses a syntax that's compatible with Renesas's AS100 assembler ๐ This syntax can also be handled by the GAS assembler, but it has some restrictions, so it isn't generated by default.-mmax-constant-size=Nโ specifies the maximum size, in bytes, of a constant that can be used as an operand in an RX instruction ๐ฆ The RX instruction set does allow constants up to 4 bytes long, but a longer value means a longer instruction. So sometimes it's beneficial to restrict the size of constants used in instructions. Constants that are too big get placed into a constant pool instead and are referenced via register indirection. The valueNcan be between 0 and 4. A value of 0 (the default) or 4 means constants of any size are allowed.-mrelaxโ enables linker relaxation ๐ง This is a process where the linker tries to shrink your program by finding shorter versions of various instructions. It's disabled by default.-mint-register=Nโ specifies the number of registers to reserve for fast interrupt handler functions โก The valueNcan be between 0 and 4. A value of 1 means registerr13is reserved for the exclusive use of fast interrupt handlers. A value of 2 reservesr13andr12. A value of 3 reservesr13,r12andr11, and a value of 4 reservesr13throughr10. A value of 0, the default, doesn't reserve any registers.-msave-acc-in-interruptsโ specifies that interrupt handler functions should preserve the accumulator register ๐ธ This is only necessary if normal code might use the accumulator register, for example because it does 64-bit multiplications. The default is to ignore the accumulator, since that makes the interrupt handlers faster.-mpid,-mno-pidโ enables the generation of position independent data ๐ When enabled, any access to constant data is done via an offset from a base address held in a register. This lets the location of constant data be determined at run time without the executable having to be relocated, which is a big win for embedded apps with tight memory constraints. Data that can be modified isn't affected by this option.
Heads up: using this feature reserves a register, usually r13, for the constant data base address ๐ญ That can result in slower and/or larger code, especially in complicated functions.
The actual register chosen to hold the constant data base address depends on whether the -msmall-data-limit and/or the -mint-register command-line options are enabled. Starting with register r13 and proceeding downwards, registers are allocated first to satisfy the requirements of -mint-register, then -mpid, and finally -msmall-data-limit. So it's possible for the small data area register to be r8 if both -mint-register=4 and -mpid are specified on the command line.
By default this feature is not enabled, and the default can be restored via the -mno-pid command-line option.
-mno-warn-multiple-fast-interrupts,-mwarn-multiple-fast-interruptsโ prevents GCC from issuing a warning message if it finds more than one fast interrupt handler while compiling a file ๐ The default is to issue a warning for each extra fast interrupt handler found, because the RX only supports one such interrupt.-mallow-string-insns,-mno-allow-string-insnsโ okay so this pair switches the string manipulation instructions on or off:SMOVF,SCMPU,SMOVB,SMOVU,SUNTIL,SWHILE, and also theRMPAinstruction ๐ง. These can prefetch data, which is not safe if you're touching an I/O register ๐ (see section 12.2.7 of the RX62N Group User's Manual for more info).- The default is to allow these instructions. GCC can't reliably catch every case where a string instruction might hit an I/O register, so turning them off automatically isn't possible ๐ญ Instead, it's on the programmer to use
-mno-allow-string-insnsif the program accesses I/O space. - When the instructions are enabled, GCC defines the C preprocessor symbol
__RX_ALLOW_STRING_INSNS__. Otherwise it defines__RX_DISALLOW_STRING_INSNS__๐ธ.
- The default is to allow these instructions. GCC can't reliably catch every case where a string instruction might hit an I/O register, so turning them off automatically isn't possible ๐ญ Instead, it's on the programmer to use
-mjsr,-mno-jsrโ use only (or not only)JSRinstructions to access functions ๐ฆ. This is handy when your code size goes past the range ofBSRinstructions. Note that-mno-jsrdoesn't mean "don't useJSR" โ it just means any type of branch can be used.
Note: the generic GCC command-line option -ffixed-reg has special vibes for the RX port when it's paired with the interrupt function attribute ๐. That attribute marks a function meant to handle fast interrupts. GCC makes sure it only uses the registers r10, r11, r12 and/or r13, and only if the normal use of those registers has been restricted via the -ffixed-reg or -mint-register command-line options.
โจ S/390 and zSeries Options โจ
These are the -m options defined for the S/390 and zSeries architecture ๐.
-mhard-float,-msoft-floatโ use (or don't use) the hardware floating-point instructions and registers for floating-point operations. With-msoft-float, functions inlibgcc.ado the floating-point work. With-mhard-float, the compiler generates IEEE floating-point instructions. This is the default ๐.-mhard-dfp,-mno-hard-dfpโ use (or don't use) the hardware decimal-floating-point instructions for decimal-floating-point operations. With-mno-hard-dfp, functions inlibgcc.ahandle the decimal-floating-point operations. With-mhard-dfp, the compiler generates decimal-floating-point hardware instructions. This is the default for-march=z9-ecor higher โจ.-mlong-double-64,-mlong-double-128โ these control the size of thelong doubletype. A size of 64 bits makeslong doubleequivalent todouble. This is the default ๐.-mbackchain,-mno-backchainโ store (or don't store) the address of the caller's frame as the backchain pointer in the callee's stack frame. A backchain may be needed for debugging with tools that don't understand DWARF call frame information ๐.- When
-mno-packed-stackis in effect, the backchain pointer is stored at the bottom of the stack frame. When-mpacked-stackis in effect, the backchain goes into the topmost word of the 96/160 byte register save area. - In general, code compiled with
-mbackchainis 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. - The default is to not maintain the backchain.
- When
Heads up bestie ๐จ: the combination of-mbackchain,-mpacked-stackand-mhard-floatis not supported. If you're building a Linux kernel, use-msoft-float.
-mpacked-stack,-mno-packed-stackโ use (or don't use) the packed stack layout ๐ง.- With
-mno-packed-stack, the compiler uses all fields of the 96/160 byte register save area only for their default purpose. Unused fields still take up stack space. - With
-mpacked-stack, register save slots are densely packed at the top of the register save area, and unused space gets reused for other purposes. That means more efficient use of the available stack space. However, when-mbackchainis 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-stackis 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. - The default is to not use the packed stack layout.
- With
Same energy here ๐จ: the combination of-mbackchain,-mpacked-stackand-mhard-floatis not supported. To build a Linux kernel, use-msoft-float.
-msmall-exec,-mno-small-execโ generate (or don't generate) code using thebrasinstruction for subroutine calls. This only works reliably if the total executable size doesn't go over 64k ๐. The default is to use thebasrinstruction instead, which doesn't have this limitation.-m64,-m31โ with-m31, generate code compliant with the GNU/Linux for S/390 ABI. With-m64, generate code compliant with the GNU/Linux for zSeries ABI. This lets GCC generate 64-bit instructions in particular ๐. For the s390 targets, the default is-m31, while the s390x targets default to-m64.-mzarch,-mesaโ with-mzarch, generate code using the instructions available on z/Architecture. With-mesa, generate code using the instructions available on ESA/390. Note that-mesais not possible with-m64. When generating code compliant with the GNU/Linux for S/390 ABI, the default is-mesa. When generating code compliant with the GNU/Linux for zSeries ABI, the default is-mzarch๐ .-mhtm,-mno-htmโ the-mhtmoption enables a set of builtins that make use of instructions from the transactional execution facility, introduced with the IBM zEnterprise EC12 machine generation S/390 System z Built-in Functions.-mhtmis enabled by default when using-march=zEC12๐ฆ.-mvx,-mno-vxโ with-mvx, generate code using the instructions from the vector extension facility introduced with the IBM z13 machine generation. This option changes the ABI for some vector type values when it comes to alignment and calling conventions. If vector type values are used in an ABI-relevant context, a GAS.gnu_attributecommand gets added to mark the resulting binary with the ABI used.-mvxis enabled by default when using-march=z13โจ.-mzvector,-mno-zvectorโ-mzvectorenables vector language extensions and builtins using instructions from the vector extension facility introduced with the IBM z13 machine generation ๐ฅ. It adds support forvectoras a keyword to define vector type variables and arguments.vectoris only available when GNU extensions are enabled. It won't be expanded when requesting strict standard compliance, e.g. with-std=c99. On top of the GCC low-level builtins,-mzvectorenables a set of builtins added for compatibility with AltiVec-style implementations like Power and Cell. To use these builtins, the header filevecintrin.hneeds to be included.-mzvectoris disabled by default.-mmvcle,-mno-mvcleโ generate (or don't generate) code using themvcleinstruction to perform block moves. With-mno-mvcle, amvcloop is used instead. This is the default unless optimizing for size ๐.-mdebug,-mno-debugโ print (or don't print) additional debug information when compiling. The default is to not print debug information ๐.-march=cpu-typeโ generate code that runs oncpu-type, which is the name of a system representing a certain processor type. Possible values forcpu-typearez900/arch5,z990/arch6,z9-109,z9-ec/arch7,z10/arch8,z196/arch9,zEC12,z13/arch11,z14/arch12, andnative๐ง.- The default is
-march=z900. - Specifying
nativeas the cpu type can be used to select the best architecture option for the host processor.-march=nativehas no effect if GCC doesn't recognize the processor.
- The default is
-mtune=cpu-typeโ tune everything applicable about the generated code tocpu-type, except for the ABI and the set of available instructions ๐. The list ofcpu-typevalues is the same as for-march. The default is the value used for-march.-mtpf-trace,-mno-tpf-traceโ generate code that adds (or doesn't add) TPF OS-specific branches to trace routines in the operating system. This option is off by default, even when compiling for the TPF OS ๐.-mfused-madd,-mno-fused-maddโ generate code that uses (or doesn't use) the floating-point multiply and accumulate instructions. These instructions are generated by default if hardware floating point is used โญ.-mwarn-framesize=framesizeโ emit a warning if the current function exceeds the given frame size. Because this is a compile-time check, it doesn't need to be a real problem when the program runs. It's meant to flag functions that most probably cause a stack overflow ๐ญ. It's useful in an environment with a limited stack size, e.g. the Linux kernel.-mwarn-dynamicstackโ emit a warning if the function callsallocaor uses dynamically-sized arrays. This is generally a bad idea with a limited stack size ๐.-mstack-guard=stack-guard,-mstack-size=stack-sizeโ okay so these make the S/390 backend sneak extra instructions into the function prologue ๐ง Once they're on, a trap fires when the stack getsstack-guardbytes abovestack-size. (Remember the S/390 stack grows downward, so the math is flipped ๐) If you skipstack-guard, GCC picks the smallest power of 2 that's bigger than the compiled function's frame size. These are meant for chasing down stack overflow bugs ๐ The extra code adds only a little overhead, so you can even use it on production-like systems without a big performance hit ๐ The values have to be exact powers of 2,stack-sizehas to be bigger thanstack-guard, and it can't go past 64k. To be efficient, the extra code assumes the stack starts at an address aligned to thestack-sizevalue. Andstack-guardonly works if you're also usingstack-sizeโจ-mhotpatch=pre-halfwords,post-halfwordsโ if this is enabled, a "hot-patching" function prologue gets generated for every function in the compilation unit ๐ฅ The function label gets prepended with the given number of two-byte NOP instructions (pre-halfwords, max1000000). After the label,2 * post-halfwordsbytes get tacked on, using the biggest NOP-like instructions the architecture allows (max1000000).
If both arguments are zero, hotpatching is disabled ๐ โโ๏ธ
This option can be overridden for individual functions with the hotpatch attribute ๐
๐ Score Options
These options are defined for Score implementations ๐ธ
-mebโ compile code for big-endian mode. This is the default ๐-melโ compile code for little-endian mode ๐ฆ-mnhwloopโ disable generation ofbcnzinstructions ๐-mulsโ enable generation of unaligned load and store instructions โจ-mmacโ enable the use of multiply-accumulate instructions. Disabled by default ๐-mscore5โ target the SCORE5 architecture ๐-mscore5uโ target the SCORE5U architecture ๐-mscore7โ target the SCORE7 architecture. This is the default ๐-mscore7dโ target the SCORE7D 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, in a way 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 in a way that no double-precision floating-point operations get used ๐ธ-m4-200โ generate code for SH4-200 ๐ฆ-m4-200-nofpuโ generate code for SH4-200, in a way that the floating-point unit isn't used ๐-m4-200-singleโ generate code for SH4-200, assuming the floating-point unit is in single-precision mode by default ๐ธ-m4-200-single-onlyโ generate code for SH4-200 in a way that no double-precision floating-point operations get used ๐ธ-m4-300โ generate code for SH4-300 ๐ฆ-m4-300-nofpuโ generate code for SH4-300, in a way that the floating-point unit isn't used ๐-m4-300-singleโ generate code for SH4-300 in a way that no double-precision floating-point operations get used ๐ธ-m4-300-single-onlyโ generate code for SH4-300 in a way 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 in a way 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 ๐คทโโ๏ธ-mbโ compile code for the processor in big-endian mode ๐-mlโ compile code for the processor in little-endian mode ๐ฆ-mdalignโ align doubles at 64-bit boundaries. Heads up, this changes the calling conventions, so some functions from the standard C library won't work unless you recompile them first with-mdalign๐ญ-mrelaxโ shorten some address references at link time, when possible. This uses the linker option-relaxโจ-mbigtableโ use 32-bit offsets inswitchtables. The default is 16-bit offsets ๐ง-mbitopsโ enable the use of bit manipulation instructions on SH2A ๐-mfmovdโ enable the use of thefmovdinstruction. Check-mdalignfor alignment constraints ๐ซถ-mrenesasโ comply with the calling conventions defined by Renesas ๐-mno-renesasโ comply with the calling conventions GCC used before the Renesas conventions existed. This is the default for all targets of the SH toolchain ๐-mnomacsaveโ mark theMACregister as call-clobbered, even if-mrenesasis given ๐-mieee,-mno-ieeeโ control the IEEE compliance of floating-point comparisons, which affects how unordered comparison results get handled ๐ง By default-mieeeis implicitly enabled. If-ffinite-math-onlyis enabled,-mno-ieeegets implicitly set, which makes floating-point greater-equal and less-equal comparisons faster. You can override the implicit settings by specifying either-mieeeor-mno-ieee๐ฅ-minline-ic_invalidateโ inline code that invalidates instruction cache entries after setting up nested function trampolines. This has no effect if-musermodeis in effect and the selected code generation option (e.g.-m4) doesn't allow the use of theicbiinstruction ๐ If the selected code generation option doesn't allowicbiand-musermodeisn't in effect, the inlined code manipulates the instruction cache address array directly with an associative write.
โ ๏ธ That last bit is a big deal: it requires privileged mode at run time, and it fails if the cache line had been mapped via the TLB and has since become unmapped. Proceed with caution, bestie ๐ญ
-misizeโ dump instruction size and location in the assembly code ๐-mpadstructโ this option is deprecated ๐ซ It pads structures to a multiple of 4 bytes, which is incompatible with the SH ABI.-matomic-model=modelโ sets the model of atomic operations, plus additional parameters, as a comma separated list ๐ For details on the atomic built-in functions, see__atomic Builtins. These models and parameters are supported:noneโ disable compiler-generated atomic sequences and emit library calls for atomic operations. This is the default if the target isn'tsh*-*-linux*๐ โโ๏ธsoft-gusaโ generate GNU/Linux compatible gUSA software atomic sequences for the atomic built-in functions ๐ง These sequences need extra support from the system's interrupt/exception handling code, and they're only suitable for SH3* and SH4* single-core systems. This option is enabled by default when the target issh*-*-linux*and SH3* or SH4*. When the target is SH4A, this option also partially uses the hardware atomic instructionsmovli.landmovco.lto make more efficient code, unlessstrictis specified ๐ฅsoft-tcbโ generate software atomic sequences that use a variable in the thread control block ๐ฆ This is a variation of the gUSA sequences that can also be used on SH1* and SH2* targets. These sequences need extra support from the system's interrupt/exception handling code and are only suitable for single-core systems. When using this model, thegbr-offset=parameter has to be specified as well ๐soft-imaskโ generate software atomic sequences that temporarily disable interrupts by settingSR.IMASK = 1111๐ This model only works when the program runs in privileged mode, and it's only suitable for single-core systems. You don't need extra support from the system's interrupt/exception handling code for it. This model is enabled by default when the target issh*-*-linux*and SH1* or SH2* ๐hard-llcsโ generate hardware atomic sequences using only themovli.landmovco.linstructions ๐ This is only available on SH4A and is suitable for multi-core systems. Since the hardware instructions only support 32-bit atomic variable access, 8- and 16-bit variable access is emulated with 32-bit accesses. Code compiled with this option is also compatible with other software atomic model interrupt/exception handling systems if it runs on an SH4A system. You don't need extra support from the system's interrupt/exception handling code for this model ๐ซถ
gbr-offset=โ okay so this one sets the byte offset of the variable inside the thread control block structure that the generated atomic sequences use, but only when you've picked thesoft-tcbmodel ๐ง. For every other model it gets ignored completely ๐ซ . The value has to be an integer multiple of4and sit somewhere in the range0-1020๐ .strictโ this one stops you from mixing multiple atomic models, even when they'd be compatible ๐ โโ๏ธ. It makes the compiler generate atomic sequences of just the model you asked for ๐.-mtasโ generates thetas.bopcode for__atomic_test_and_set๐ฅ. Heads up, bestie: depending on your hardware and software setup, this can actually drag down overall performance because of the operand cache line flushes thattas.bimplies ๐ญ. On multi-core SH4A processors you have to be extra careful withtas.b, since it can cause data corruption with certain cache configurations ๐.-mprefergotโ when you're generating position-independent code, function calls go through the Global Offset Table instead of the Procedure Linkage Table ๐ธ.-musermode,-mno-usermodeโ-musermodemeans the compiler won't generate privileged mode code, and-mno-usermodemeans it's allowed ๐. Using-musermodealso implies-mno-inline-ic_invalidateif the inlined code wouldn't work in user mode ๐.-musermodeis the default when the target issh*-*-linux*โจ. If the target is SH1* or SH2*,-musermodedoes nothing, since there's no user mode on those ๐คทโโ๏ธ.-multcost=numberโ sets the cost the compiler should assume for a multiply insn ๐งฎ.-mdiv=strategyโ picks the division strategy for integer division operations ๐.strategycan be one of:call-div1โ calls a library function that uses the single-step division instructiondiv1to do the job. Division by zero gives an unspecified result and doesn't trap. This is the default except for SH4, SH2A, and SHcompact ๐ง.call-fpโ calls a library function that does the operation in double precision floating point. Division by zero causes a floating-point exception ๐ฅ. This is the default for SHcompact with FPU. Specifying it for targets without a double precision FPU defaults tocall-div1๐ซถ.call-tableโ calls a library function that uses a lookup table for small divisors and thediv1instruction with case distinction for larger divisors ๐. Division by zero gives an unspecified result and doesn't trap. This is the default for SH4. Specifying it for targets without dynamic shift instructions defaults tocall-div1๐.
If you don't specify a division strategy, the compiler picks the default based on your current target ๐ฏ. For SH2A, the default is to use the divs and divu instructions instead of library function calls โก.
-maccumulate-outgoing-argsโ reserves space once for outgoing arguments in the function prologue, rather than around each call ๐ง . It's generally great for performance and size ๐ช. It's also needed for unwinding, so the stack frame doesn't get changed around conditional code ๐ฆ.-mdivsi3_libfunc=nameโ sets the name of the library function used for 32-bit signed division toname๐. This only changes the name used in the call division strategies. The compiler still expects the same sets of input, output, and clobbered registers as if this option weren't there ๐.-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers ๐. A fixed register is one the register allocator isn't allowed to use, which makes this super useful when compiling kernel code ๐ ๏ธ. A register range is written as two registers separated by a dash, and you can separate multiple ranges with a comma ๐งฉ.-mbranch-cost=numโ tells the compiler to assumenumis the cost of a branch instruction ๐ฟ. Higher numbers make the compiler try to generate more branch-free code when it can ๐. If you don't specify it, the value is picked based on the processor type you're compiling for ๐ฅ๏ธ.-mzdcbranch,-mno-zdcbranchโ assumes (or doesn't assume) that the zero displacement conditional branch instructionsbtandbfare fast ๐๏ธ. With-mzdcbranch, the compiler prefers zero displacement branch code sequences. This is enabled by default for SH4 and SH4A, and you can explicitly turn it off with-mno-zdcbranch๐ซ.-mcbranch-force-delay-slotโ forces the use of delay slots for conditional branches, stuffing the delay slot with anopif no suitable instruction can be found ๐ค. It's disabled by default. You can turn it on to work around hardware bugs found in the original SH7055 ๐.-mfused-madd,-mno-fused-maddโ generates code that does (or doesn't) use the floating-point multiply and accumulate instructions ๐งฎ. These get generated by default if hardware floating point is in use. The machine-dependent-mfused-maddis now mapped to the machine-independent-ffp-contract=fast, and-mno-fused-maddis mapped to-ffp-contract=off๐.-mfsca,-mno-fscaโ allows (or disallows) the compiler to emit thefscainstruction for sine and cosine approximations ๐. The option-mfscamust be used together with-funsafe-math-optimizations. It's enabled by default for SH4A. Using-mno-fscadisables sine and cosine approximations, even if-funsafe-math-optimizationsis in effect ๐ โโ๏ธ.-mfsrra,-mno-fsrraโ allows (or disallows) the compiler to emit thefsrrainstruction for reciprocal square root approximations ๐. The option-mfsrramust be used together with-funsafe-math-optimizationsand-ffinite-math-only. It's enabled by default for SH4A. Using-mno-fsrradisables reciprocal square root approximations, even if-funsafe-math-optimizationsand-ffinite-math-onlyare in effect ๐ซ.-mpretend-cmoveโ prefers zero-displacement conditional branches for conditional move instruction patterns ๐. This can 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 the current machine doesn't support, but still check at runtime whether or not to use them ๐.-mimpure-textโ used in addition to-shared, this tells the compiler not to pass-z textto the linker when linking a shared object ๐ฆ. With it, you can link position-dependent code into a shared object ๐ .
Heads up:-mimpure-textsuppresses the "relocations remain against allocatable but non-writable sections" linker error message. However, the necessary relocations trigger copy-on-write, so the shared object is not actually shared across processes ๐ฌ. Instead of using-mimpure-text, you should compile all source code with-fpicor-fPIC๐ซถ.
These switches are supported in addition to the above on Solaris 2 โจ:
-pthreadsโ this is a synonym for-pthread๐งต.
SPARC Options
These -m options are supported on the SPARC ๐ฆ:
-mno-app-regs,-mapp-regsโ-mapp-regsgenerates output using the global registers 2 through 4, which the SPARC SVR4 ABI reserves for applications ๐. Just like global register 1, each of global registers 2 through 4 is then treated as an allocable register that gets clobbered by function calls. This is the default ๐.
To be fully SVR4 ABI-compliant (with some performance loss), use -mno-app-regs. You should compile libraries and system software with this option ๐ ๏ธ.
-mflat,-mno-flatโ with-mflat, the compiler doesn't generate save/restore instructions and uses a "flat" or single register window model ๐ช. This model is compatible with the regular register window model. The local registers and the input registers (0--5) are still treated as "call-saved" registers and get saved on the stack as needed ๐.
With -mno-flat (the default), the compiler generates save/restore instructions, except for leaf functions. This is the normal operating mode ๐ธ.
-mfpu,-mhard-floatโ generates output containing floating-point instructions โก. This is the default ๐.-mno-fpu,-msoft-floatโ generates output containing library calls for floating point ๐.
Warning: the requisite libraries are not available for all SPARC targets ๐จ. Normally the facilities of the machine's usual C compiler are used, but this can't be done directly in cross-compilation. You must make your own arrangements to provide suitable library functions for cross-compilation ๐. The embedded targetssparc-*-aoutandsparclite-*-*do provide software floating-point support ๐งก.
-msoft-float changes the calling convention in the output file, so it's only useful if you compile all of a program with this option ๐. In particular, you need to compile libgcc.a, the library that comes with GCC, with -msoft-float for this to work ๐งฉ.
-mhard-quad-floatโ generates output containing quad-word (long double) floating-point instructions ๐.-msoft-quad-floatโ generates output containing library calls for quad-word (long double) floating-point instructions ๐ฆ. The functions called are the ones specified in the SPARC ABI. This is the default ๐ซก.
As of this writing, there are no SPARC implementations with hardware support for the quad-word floating-point instructions ๐ญ. They all invoke a trap handler for one of these instructions, and then the trap handler emulates the effect of the instruction. Because of that trap handler overhead, this is much slower than calling the ABI library routines ๐ข. So the -msoft-quad-float option is the default ๐.
-mno-unaligned-doubles,-munaligned-doublesโ-mno-unaligned-doublesassumes that doubles have 8-byte alignment, and that's the default ๐.
So with -munaligned-doubles, GCC only assumes doubles have 8-byte alignment if they're tucked inside another type or have an absolute address. Otherwise it assumes 4-byte alignment ๐. Turning it on dodges some rare compatibility drama with code from other compilers, but it's not the default because it costs performance, especially for floating-point code ๐ญ.
-muser-mode,-mno-user-modeโ Stops GCC from generating code that can only run in supervisor mode ๐. This only matters for thecasainstruction emitted for the LEON3 processor. This is the default, so you're already set ๐.-mfaster-structs,-mno-faster-structsโ With-mfaster-structs, the compiler assumes structures should have 8-byte alignment โก. That unlocks pairs oflddandstdinstructions for copies in structure assignment, instead of twice as manyldandstpairs. Ngl, it's a speed glow-up, but the changed alignment directly violates the SPARC ABI ๐.
Only use this on targets where the developer acknowledges that the resulting code isn't directly in line with the rules of the ABI. It's a "know what you're doing" option, bestie ๐.
-mstd-struct-return,-mno-std-struct-returnโ With-mstd-struct-return, the compiler adds checking code to functions that return structures or unions ๐ง. That code catches size mismatches between the two sides of a function call, as per the 32-bit ABI. The default is-mno-std-struct-return. This option has no effect in 64-bit mode.-mlra,-mno-lraโ Turns on Local Register Allocation ๐ง . This has been the default for SPARC since GCC 7, so if you want the old Reload vibes back, you have to pass-mno-lra๐ฐ๏ธ.-mcpu=cpu_typeโ Sets the instruction set, register set, and instruction scheduling parameters for the machine type cpu_type ๐. The supported values arev7,cypress,v8,supersparc,hypersparc,leon,leon3,leon3v7,sparclite,f930,f934,sparclite86x,sparclet,tsc701,v9,ultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7andm8.
Native Solaris and GNU/Linux toolchains also accept native, which picks the best architecture option for your host processor โจ. -mcpu=native does nothing if GCC doesn't recognize the processor ๐คทโโ๏ธ.
Default instruction scheduling parameters get used for values that pick an architecture rather than a specific implementation. Those are v7, v8, sparclite, sparclet and v9.
Here's the lowdown on each architecture and the implementations that live under it ๐:
v7โcypress,leon3v7v8โsupersparc,hypersparc,leon,leon3sparcliteโf930,f934,sparclite86xsparcletโtsc701v9โultrasparc,ultrasparc3,niagara,niagara2,niagara3,niagara4,niagara7,m8
By default (unless configured otherwise), GCC generates code for the V7 variant of the SPARC architecture ๐ธ. With -mcpu=cypress, the compiler also optimizes for the Cypress CY7C602 chip, as used in the SPARCStation/SPARCServer 3xx series. This is also a good fit for the older SPARCStation 1, 2, IPX etc. ๐ฆ
With -mcpu=v8, GCC generates code for the V8 variant of the SPARC architecture ๐. The only difference from V7 code is that the compiler emits the integer multiply and integer divide instructions that exist in SPARC-V8 but not in SPARC-V7. With -mcpu=supersparc, the compiler also optimizes for the SuperSPARC chip, as used in the SPARCStation 10, 1000 and 2000 series.
With -mcpu=sparclite, GCC generates code for the SPARClite variant of the SPARC architecture ๐ฆ. This adds the integer multiply, integer divide step and scan ("ffs") instructions that exist in SPARClite but not in SPARC-V7. With -mcpu=f930, the compiler also optimizes for the Fujitsu MB86930 chip, which is the original SPARClite, with no FPU. With -mcpu=f934, it optimizes for the Fujitsu MB86934 chip, which is the more recent SPARClite with FPU.
With -mcpu=sparclet, GCC generates code for the SPARClet variant of the SPARC architecture ๐ง. This adds the integer multiply, multiply/accumulate, integer divide step and scan ("ffs") instructions that exist in SPARClet but not in SPARC-V7. With -mcpu=tsc701, the compiler also optimizes for the TEMIC SPARClet chip.
With -mcpu=v9, GCC generates code for the V9 variant of the SPARC architecture ๐. This adds 64-bit integer and floating-point move instructions, 3 additional floating-point condition code registers and conditional move instructions. With -mcpu=ultrasparc, the compiler also optimizes for the Sun UltraSPARC I/II/IIi chips. With -mcpu=ultrasparc3, it optimizes for the Sun UltraSPARC III/III+/IIIi/IIIi+/IV/IV+ chips. With -mcpu=niagara, it optimizes for Sun UltraSPARC T1 chips. With -mcpu=niagara2, it optimizes for Sun UltraSPARC T2 chips. With -mcpu=niagara3, it optimizes for Sun UltraSPARC T3 chips. With -mcpu=niagara4, it optimizes for Sun UltraSPARC T4 chips. With -mcpu=niagara7, it optimizes for Oracle SPARC M7 chips. With -mcpu=m8, it optimizes for Oracle M8 chips ๐ฅ.
-mtune=cpu_typeโ Sets the instruction scheduling parameters for the machine type cpu_type, but leaves the instruction set and register set alone ๐ฏ. That's the difference from-mcpu=cpu_type.
The same values work for -mtune=cpu_type, but the only useful ones are those that pick a specific CPU implementation ๐
. Those are cypress, supersparc, hypersparc, leon, leon3, leon3v7, f930, f934, sparclite86x, tsc701, ultrasparc, ultrasparc3, niagara, niagara2, niagara3, niagara4, niagara7 and m8. With native Solaris and GNU/Linux toolchains, native can also be used.
-mv8plus,-mno-v8plusโ With-mv8plus, GCC generates code for the SPARC-V8+ ABI ๐ซถ. The difference from the V8 ABI is that the global and out registers are treated as 64 bits wide. This is on by default on Solaris in 32-bit mode for all SPARC-V9 processors.-mvis,-mno-visโ With-mvis, GCC generates code that takes advantage of the UltraSPARC Visual Instruction Set extensions ๐จ. The default is-mno-vis.-mvis2,-mno-vis2โ With-mvis2, GCC generates code that takes advantage of version 2.0 of the UltraSPARC Visual Instruction Set extensions ๐. The default is-mvis2when targeting a CPU that supports such instructions, such as UltraSPARC-III and later. Setting-mvis2also sets-mvis.-mvis3,-mno-vis3โ With-mvis3, GCC generates code that takes advantage of version 3.0 of the UltraSPARC Visual Instruction Set extensions ๐ฆ. The default is-mvis3when targeting a CPU that supports such instructions, such as niagara-3 and later. Setting-mvis3also sets-mvis2and-mvis.-mvis4,-mno-vis4โ With-mvis4, GCC generates code that takes advantage of version 4.0 of the UltraSPARC Visual Instruction Set extensions ๐. The default is-mvis4when targeting a CPU that supports such instructions, such as niagara-7 and later. Setting-mvis4also sets-mvis3,-mvis2and-mvis.-mvis4b,-mno-vis4bโ With-mvis4b, GCC generates code that takes advantage of version 4.0 of the UltraSPARC Visual Instruction Set extensions, plus the extra VIS instructions introduced in the Oracle SPARC Architecture 2017 ๐ซ. The default is-mvis4bwhen targeting a CPU that supports such instructions, such as m8 and later. Setting-mvis4balso sets-mvis4,-mvis3,-mvis2and-mvis.-mcbcond,-mno-cbcondโ With-mcbcond, GCC generates code that takes advantage of the UltraSPARC Compare-and-Branch-on-Condition instructions ๐. The default is-mcbcondwhen targeting a CPU that supports such instructions, such as Niagara-4 and later.-mfmaf,-mno-fmafโ With-mfmaf, GCC generates code that takes advantage of the UltraSPARC Fused Multiply-Add Floating-point instructions ๐งฎ. The default is-mfmafwhen targeting a CPU that supports such instructions, such as Niagara-3 and later.-mfsmuld,-mno-fsmuldโ With-mfsmuld, GCC generates code that takes advantage of the Floating-point Multiply Single to Double (FsMULd) instruction โ๏ธ. The default is-mfsmuldwhen targeting a CPU supporting the architecture versions V8 or V9 with FPU, except-mcpu=leon.-mpopc,-mno-popcโ With-mpopc, GCC generates code that takes advantage of the UltraSPARC Population Count instruction ๐ข. The default is-mpopcwhen targeting a CPU that supports such an instruction, such as Niagara-2 and later.-msubxc,-mno-subxcโ With-msubxc, GCC generates code that takes advantage of the UltraSPARC Subtract-Extended-with-Carry instruction โ. The default is-msubxcwhen targeting a CPU that supports such an instruction, such as Niagara-7 and later.-mfix-at697fโ Enables the documented workaround for the single erratum of the Atmel AT697F processor (which corresponds to erratum #13 of the AT697E processor) ๐ฉน.-mfix-ut699โ Enables the documented workarounds for the floating-point errata and the data cache nullify errata of the UT699 processor ๐ ๏ธ.-mfix-ut700โ Enables the documented workaround for the back-to-back store errata of the UT699E/UT700 processor ๐ง.-mfix-gr712rcโ Enables the documented workaround for the back-to-back store errata of the GR712RC processor ๐งฐ.
These -m options are supported in addition to the above on SPARC-V9 processors in 64-bit environments ๐:
-m32,-m64โ Generates code for a 32-bit or 64-bit environment ๐. The 32-bit environment setsint,longand pointer to 32 bits. The 64-bit environment setsintto 32 bits andlongand pointer to 64 bits.-mcmodel=whichโ Sets the code model to one of the following ๐งฉ:medlowโ The Medium/Low code model: 64-bit addresses, programs must be linked in the low 32 bits of memory. Programs can be statically or dynamically linked.medmidโ The Medium/Middle code model: 64-bit addresses, programs must be linked in the low 44 bits of memory, the text and data segments must be less than 2GB in size and the data segment must be located within 2GB of the text segment.
medanyโ okay so this is the Medium/Anywhere code model ๐ You get 64-bit addresses and programs can be linked anywhere in memory. The text and data segments each have to be under 2GB, and the data segment has to sit within 2GB of the text segment ๐ฆembmedanyโ the embedded-systems version of Medium/Anywhere ๐ง You still get 64-bit addresses, and the text and data segments must be under 2GB each, but they can both start anywhere in memory (that gets decided at link time). The global register%g4points to the base of the data segment. Programs are statically linked and PIC is not supported, so no PIC for you ๐
๐ -mmemory-model=mem-model ๐
This sets the memory model the processor runs with, and you pick one of these:
defaultโ the default memory model for the processor and operating system โจrmoโ Relaxed Memory Orderpsoโ Partial Store Ordertsoโ Total Store Orderscโ Sequential Consistency
These are formally defined in Appendix D of the SPARC-V9 architecture manual, and they get set in the processor's PSTATE.MM field ๐
๐ฆ -mstack-bias / -mno-stack-bias ๐ฆ
-mstack-biasโ with this one, GCC assumes the stack pointer (and the frame pointer, if there is one) is offset by-2047, and that offset has to be added back whenever it makes stack frame references. This is the default in 64-bit mode ๐ฅ-mno-stack-biasโ no offset is assumed to be there at all
๐ธ SPU Options ๐ธ
These -m options are supported on the SPU ๐ง
-mwarn-reloc,-merror-relocโ the SPU loader doesn't handle dynamic relocations, so by default GCC throws an error when it generates code that needs one ๐ญ-mno-error-relocturns that error off, and-mwarn-relocgives you a warning instead-msafe-dma,-munsafe-dmaโ instructions that start DMA or check whether it's finished can't get reordered with loads and stores of the memory being accessed ๐ซถ With-munsafe-dmayou have to use the"volatile"keyword to protect those memory accesses, but that can make the code inefficient in places where the memory is known not to change. Instead of marking everything volatile, you can use-msafe-dmato tell the compiler to treat the DMA instructions as potentially affecting all memory-mbranch-hintsโ by default GCC makes a branch hint instruction so you don't get pipeline stalls on always-taken or probably-taken branches โจ A hint never gets generated closer than 8 instructions away from its branch. There's not much reason to turn these off, except for debugging or to make an object a little smaller-msmall-mem,-mlarge-memโ by default GCC assumes addresses are never bigger than 18 bits. With-mlarge-mem, the code is generated to assume a full 32-bit address ๐-mstdmainโ by default you link against startup code that assumes the SPU-style main function interface, which has a pretty unconventional parameter list ๐ With-mstdmain, your program links against startup code that assumes a C99-style interface tomain, including a local copy of"argv"strings-mfixed-range=register-rangeโ generates code that treats the given register range as fixed registers ๐ A fixed register is one the register allocator isn't allowed to use, which is super useful when you're compiling kernel code. A register range is written as two registers separated by a dash, and you can put multiple ranges in separated by a comma-mea32,-mea64โ compiles code assuming that pointers to the PPU address space, accessed through the"__ea"named address space qualifier, are either 32 or 64 bits wide. The default is 32 bits. This is an ABI-changing option, so all object code in an executable has to be compiled with the same setting โ ๏ธ-maddress-space-conversion,-mno-address-space-conversionโ allows or disallows treating the"__ea"address space as a superset of the generic address space ๐ Allowing it enables explicit type casts between"__ea"and generic pointers, as well as implicit conversions of generic pointers to"__ea"pointers. The default is to allow address space pointer conversions-mcache-size=cache-sizeโ this one controls which version of libgcc the compiler links into an executable, and it selects a software-managed cache for accessing variables in the"__ea"address space with a particular cache size ๐ The possible values forcache-sizeare 8, 16, 32, 64 and 128, and the default cache size is 64KB-matomic-updates,-mno-atomic-updatesโ also controls the libgcc version, and picks whether atomic updates to the software-managed cache of PPU-side variables are used ๐ฆ If you use atomic updates, changes to a PPU variable from SPU code using the"__ea"named address space qualifier won't interfere with changes to other PPU variables sitting in the same cache line from PPU code. If you don't use them, that interference may happen, but writing back cache lines is more efficient. The default is to use atomic updates-mdual-nops,-mdual-nops=nโ by default GCC inserts NOPs to boost dual issue when it expects that to improve performance ๐ncan be anything from 0 to 10, and a smallerninserts fewer NOPs. 10 is the default, and 0 is the same as-mno-dual-nops. This gets disabled with-Os-mhint-max-nops=nโ the maximum number of NOPs to insert for a branch hint ๐ง A branch hint has to be at least 8 instructions away from the branch it's affecting. GCC inserts up tonNOPs to enforce this, and otherwise it just doesn't generate the branch hint-mhint-max-distance=nโ the encoding of the branch hint instruction limits the hint to within 256 instructions of the branch it's affecting โจ By default, GCC makes sure it's within 125-msafe-hintsโ works around a hardware bug that can make the SPU stall indefinitely ๐ญ By default, GCC inserts the"hbrp"instruction to make sure that stall won't happen
๐ Options for System V ๐
These extra options are available on System V Release 4, for compatibility with other compilers on those systems ๐
-Gโ creates a shared object ๐ It's recommended to use-symbolicor-sharedinstead-Qyโ identifies the versions of each tool the compiler used, and puts them in a".ident"assembler directive in the output-Qnโ refrains from adding".ident"directives to the output file, which is the default ๐ซถ-YP,dirsโ searches the directoriesdirs, and no others, for libraries specified with-l-Ym,dirโ looks in the directorydirto find the M4 preprocessor ๐ฅ The assembler uses this option
๐ฆ TILE-Gx Options ๐ฆ
These -m options are supported on the TILE-Gx ๐
-mcmodel=smallโ generates code for the small model ๐ The distance for direct calls is limited to 500M in either direction, PC-relative addresses are 32 bits, and absolute addresses support the full address range-mcmodel=largeโ generates code for the large model ๐ There's no limitation on call distance, PC-relative addresses, or absolute addresses-mcpu=nameโ selects the type of CPU to target. Right now the only supported type istilegxโจ-m32,-m64โ generates code for a 32-bit or 64-bit environment ๐ง The 32-bit environment setsint,long, and pointer to 32 bits. The 64-bit environment setsintto 32 bits, andlongand pointer to 64 bits-mbig-endian,-mlittle-endianโ generates code in big or little endian mode, respectively ๐
๐ท TILEPro Options ๐ท
These -m options are supported on the TILEPro ๐ธ
-mcpu=nameโ selects the type of CPU to target. Right now the only supported type istileproโจ-m32โ generates code for a 32-bit environment, which setsint,long, and pointer to 32 bits ๐ This is the only supported behavior, so the flag is basically ignored ๐
๐ V850 Options ๐
These -m options are defined for V850 implementations ๐ซถ
-mlong-calls,-mno-long-callsโ treats all calls as being far away (near) ๐ฅ If calls are assumed to be far away, the compiler always loads the function's address into a register, and calls indirect through the pointer-mno-ep,-mepโ-mno-epmeans don't optimize basic blocks that use the same index pointer 4 or more times to copy the pointer into the"ep"register, and use the shorter"sld"and"sst"instructions.-mepmeans do optimize them. The-mepoption is on by default if you optimize โจ-mno-prolog-function,-mprolog-functionโ-mno-prolog-functionmeans don't use external functions to save and restore registers at the prologue and epilogue of a function, and-mprolog-functionmeans do use them. The external functions are slower, but they use less code space if more than one function saves the same number of registers. The-mprolog-functionoption is on by default if you optimize ๐-mspaceโ tries to make the code as small as possible ๐ง At present, this just turns on the-mepand-mprolog-functionoptions-mtda=nโ puts static or global variables whose size isnbytes or less into the tiny data area that the"ep"register points to ๐ฆ The tiny data area can hold up to 256 bytes in total, or 128 bytes for byte references-msda=nโ puts static or global variables whose size isnbytes or less into the small data area that the"gp"register points to ๐ The small data area can hold up to 64 kilobytes-mzda=nโ puts static or global variables whose size isnbytes or less into the first 32 kilobytes of memory ๐ธ-mv850โ specifies that the target processor is the V850 ๐-mv850e3v5โ specifies that the target processor is the V850E3V5 ๐ The preprocessor constant"__v850e3v5__"is defined if this option is used-mv850e2v4โ specifies that the target processor is the V850E3V5 ๐ซถ This is an alias for the-mv850e3v5option-mv850e2v3โ specifies that the target processor is the V850E2V3 โจ The preprocessor constant"__v850e2v3__"is defined if this option is used-mv850e2โ specifies that the target processor is the V850E2 ๐ The preprocessor constant"__v850e2__"is defined if this option is used-mv850e1โ specifies that the target processor is the V850E1 ๐ฅ The preprocessor constants"__v850e1__"and"__v850e__"are defined if this option is used-mv850esโ specifies that the target processor is the V850ES ๐ This is an alias for the-mv850e1option-mv850eโ okay so this one tells GCC the target is the V850E ๐ and defines the preprocessor constant__v850e__when you use it โจ
If none of -mv850, -mv850e, -mv850e1, -mv850e2, -mv850e2v3, or -mv850e3v5 are defined, GCC picks a default target processor for you and defines the matching __v850*__ preprocessor constant ๐ซถ
The preprocessor constants __v850 and __v851__ are always defined, no matter which processor variant is the target ๐
-mdisable-callt,-mno-disable-calltโ these suppress generation of theCALLTinstruction for the v850e, v850e1, v850e2, v850e2v3, and v850e3v5 flavors of V850 ๐ธ
-mdisable-callt is turned on by default when the RH850 ABI is in use (see -mrh850-abi), and off by default when the GCC ABI is in use. If CALLT instructions are being generated, the C preprocessor symbol __V850_CALLT__ gets defined ๐ฆ
-mrelax,-mno-relaxโ passes (or doesn't pass) the-mrelaxcommand-line option along to the assembler ๐ง-mlong-jumps,-mno-long-jumpsโ-mlong-jumpsturns off generation of PC-relative jump instructions, and-mno-long-jumpsturns them back on ๐-msoft-float,-mhard-floatโ-msoft-floatturns off hardware floating point instructions, and-mhard-floatturns them back on. This only matters when the target architecture is V850E2V3 or higher ๐ If hardware floating point instructions are being generated, the__FPU_OK__symbol is defined. Otherwise,__NO_FPU__is defined โจ-mloopโ enables the e3v5LOOPinstruction ๐ฅ It's not on by default when the e3v5 architecture is selected, because its use is still experimental ๐-mrh850-abi,-mghsโ enables support for the RH850 version of the V850 ABI. This is the default, and it's giving main character energy ๐ With this version of the ABI, these rules apply:- Integer sized structures and unions are returned via a memory pointer instead of a register.
- Large structures and unions (more than 8 bytes in size) are passed by value.
- Functions are aligned to 16-bit boundaries.
- The
-m8byte-aligncommand-line option is supported. - The
-mdisable-calltcommand-line option is enabled by default. The-mno-disable-calltcommand-line option is not supported.
When this version of the ABI is enabled, the C preprocessor symbol __V850_RH850_ABI__ is defined ๐
-mgcc-abiโ enables support for the old GCC version of the V850 ABI ๐ฐ๏ธ With this version, these rules apply:- Integer sized structures and unions are returned in register
r10. - Large structures and unions (more than 8 bytes in size) are passed by reference.
- Functions are aligned to 32-bit boundaries, unless optimizing for size.
- The
-m8byte-aligncommand-line option is not supported. - The
-mdisable-calltcommand-line option is supported but not enabled by default.
- Integer sized structures and unions are returned in register
When this version of the ABI is enabled, the C preprocessor symbol __V850_GCC_ABI__ is defined ๐
-m8byte-align,-mno-8byte-alignโ enablesdoubleandlong longtypes being aligned on 8-byte boundaries. By default, the alignment of all objects is restricted to at most 4 bytes ๐ฆ When-m8byte-alignis in effect, the C preprocessor symbol__V850_8BYTE_ALIGN__is defined โจ-mbig-switchโ generates code suitable for big switch tables. Only use this one if the assembler or linker complains about out of range branches within a switch table ๐ญ-mapp-regsโ makes r2 and r5 get used in the code the compiler generates. This is the default vibe ๐-mno-app-regsโ makes r2 and r5 get treated as fixed registers ๐ซถ
๐ฆ VAX Options ๐ฆ
These -m options are defined for the VAX ๐ธ
-munixโ doesn't output certain jump instructions (likeaobleqand so on) that the Unix assembler for the VAX can't handle across long ranges ๐-mgnuโ does output those jump instructions, assuming you're using the GNU assembler ๐ง-mgโ outputs code for G-format floating-point numbers instead of D-format ๐ฅ
๐ธ Visium Options ๐ธ
-mdebugโ a program that does file I/O and is destined to run on an MCM target should be linked with this option โจ It causes the librarieslibc.aandlibdebug.ato be linked. The program should be run on the target under the control of the GDB remote debugging stub ๐-msimโ a program that does file I/O and is destined to run on the simulator should be linked with this option ๐ It causes the librarieslibc.aandlibsim.ato be linked ๐-mfpu,-mhard-floatโ generates code containing floating-point instructions. This is the default ๐-mno-fpu,-msoft-floatโ generates code containing library calls for floating-point ๐ซถ
โ ๏ธ-msoft-floatchanges the calling convention in the output file, so it's only useful if you compile all of a program with this option. In particular, you need to compilelibgcc.a, the library that comes with GCC, with-msoft-floatin order for this to work ๐
-mcpu=cpu_typeโ sets the instruction set, register set, and instruction scheduling parameters for machine typecpu_type๐ฆ Supported values forcpu_typearemcm,gr5, andgr6๐mcmis a synonym ofgr5, kept around for backward compatibility.- By default (unless configured otherwise), GCC generates code for the GR5 variant of the Visium architecture.
- With
-mcpu=gr6, GCC generates code for the GR6 variant. The only difference from GR5 code is that the compiler will generate block move instructions ๐ฅ
-mtune=cpu_typeโ sets the instruction scheduling parameters for machine typecpu_type, but doesn't set the instruction set or register set that-mcpu=cpu_typewould ๐ง-msv-modeโ generates code for supervisor mode, where there are no restrictions on access to general registers. This is the default ๐-muser-modeโ generates code for user mode, where access to some general registers is forbidden ๐ On the GR5, registersr24tor31can't be accessed in this mode. On the GR6, only registersr29tor31are affected ๐
๐ VMS Options ๐
These -m options are defined for the VMS implementations โจ
-mvms-return-codesโ returns VMS condition codes frommain. The default is to return POSIX-style condition (e.g. error) codes ๐ธ-mdebug-main=prefixโ flags the first routine whose name starts withprefixas the main routine for the debugger ๐-mmalloc64โ defaults to 64-bit memory allocation routines ๐-mpointer-size=sizeโ sets the default size of pointers ๐ฅ Possible options forsizeare32orshortfor 32-bit pointers,64orlongfor 64-bit pointers, andnofor supporting only 32-bit pointers. The latter option disablespragma pointer_size๐ญ
โญ VxWorks Options โญ
The options in this section are defined for all VxWorks targets. Options specific to the target hardware are listed with the other options for that target ๐ง
-mrtpโ GCC can generate code for both VxWorks kernels and real time processes (RTPs) ๐ฆ This option switches from the former to the latter. It also defines the preprocessor macro__RTP__โจ-non-staticโ links an RTP executable against shared libraries rather than static libraries ๐ซถ The options-staticand-sharedcan also be used for RTPs, and-staticis the default ๐-Bstatic,-Bdynamicโ these options are passed down to the linker. They're defined for compatibility with Diab ๐-Xbind-lazyโ enables lazy binding of function calls ๐ This option is equivalent to-Wl,-z,nowand is defined for compatibility with Diab ๐-Xbind-nowโ disables lazy binding of function calls ๐ This option is the default and is defined for compatibility with Diab ๐
๐ x86 Options ๐
These -m options are defined for the x86 family of computers ๐
-march=cpu-typeโ generates instructions for the machine typecpu-type๐ฅ In contrast to-mtune=cpu-type, which merely tunes the generated code for the specifiedcpu-type,-march=cpu-typeallows GCC to generate code that may not run at all on processors other than the one indicated ๐ญ Specifying-march=cpu-typeimplies-mtune=cpu-type๐ซถ
The choices for cpu-type are:
nativeโ selects the CPU to generate code for at compilation time by determining the processor type of the compiling machine ๐ฆ Using-march=nativeenables all instruction subsets supported by the local machine (so the result might not run on different machines) ๐ Using-mtune=nativeproduces code optimized for the local machine under the constraints of the selected instruction set ๐งx86-64โ a generic CPU with 64-bit extensions ๐i386โ original Intel i386 CPU ๐ฐ๏ธi486โ Intel i486 CPU. (No scheduling is implemented for this chip.) ๐ธi586,pentiumโ Intel Pentium CPU with no MMX support ๐lakemontโ Intel Lakemont MCU, based on Intel Pentium CPU โจpentium-mmxโ Intel Pentium MMX CPU, based on Pentium core with MMX instruction set support ๐pentiumproโ Intel Pentium Pro CPU ๐ฅi686โ when used with-march, the Pentium Pro instruction set is used, so the code runs on all i686 family chips. When used with-mtune, it has the same meaning asgeneric๐pentium2โ Intel Pentium II CPU, based on Pentium Pro core with MMX instruction set support ๐pentium3,pentium3mโ Intel Pentium III CPU, based on Pentium Pro core with MMX and SSE instruction set support ๐pentium-mโ Intel Pentium M, a low-power version of the Intel Pentium III CPU with MMX, SSE, and SSE2 instruction set support. Used by Centrino notebooks ๐ปโจpentium4,pentium4mโ Intel Pentium 4 CPU with MMX, SSE, and SSE2 instruction set support ๐prescottโ improved version of the Intel Pentium 4 CPU with MMX, SSE, SSE2, and SSE3 instruction set support ๐ซถnoconaโ 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 plusMMX,SSE,SSE2,SSE3andSSSE3support. Iconic. ๐nehalemโ โจ Intel Nehalem CPU with 64-bit extensions andMMX,SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2andPOPCNT. The vibe is very structured.westmereโ ๐ฆ Intel Westmere CPU with 64-bit extensions and everything fromnehalem, plusAESandPCLMUL.sandybridgeโ ๐ธ Intel Sandy Bridge CPU with 64-bit extensions,MMX,SSEthroughSSE4.2,POPCNT,AVX,AESandPCLMUL.ivybridgeโ ๐ง Intel Ivy Bridge CPU with 64-bit extensions,MMX,SSEthroughSSE4.2,POPCNT,AVX,AES,PCLMUL,FSGSBASE,RDRNDandF16C.haswellโ ๐ฅ Intel Haswell CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.2,POPCNT,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2andF16C.broadwellโ ๐ Intel Broadwell CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.2,POPCNT,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCXandPREFETCHW.skylakeโ ๐ Intel Skylake CPU with everything frombroadwell, plusCLFLUSHOPT,XSAVECandXSAVES.bonnellโ ๐ Intel Bonnell CPU with 64-bit extensions,MOVBE,MMX,SSE,SSE2,SSE3andSSSE3. Lowkey a chill little starter set.silvermontโ ๐ Intel Silvermont CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.2,POPCNT,AES,PREFETCHW,PCLMULandRDRND.goldmontโ ๐ Intel Goldmont CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.2,POPCNT,AES,PREFETCHW,PCLMUL,RDRND,XSAVE,XSAVEC,XSAVES,XSAVEOPTandFSGSBASE.goldmont-plusโ ๐ธ Intel Goldmont Plus CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.2,POPCNT,AES,PREFETCHW,PCLMUL,RDRND,XSAVE,XSAVEC,XSAVES,XSAVEOPT,FSGSBASE,PTWRITE,RDPID,SGXandUMIP.tremontโ ๐ฆ Intel Tremont CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.2,POPCNT,AES,PREFETCHW,PCLMUL,RDRND,XSAVE,XSAVEC,XSAVES,XSAVEOPT,FSGSBASE,PTWRITE,RDPID,SGX,UMIP,GFNI-SSE,CLWB,MOVDIRI,MOVDIR64B,CLDEMOTEandWAITPKGsupport. That is a LOT of extensions, bestie. ๐ญknlโ ๐ Intel Knight's Landing CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.2,POPCNT,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,PREFETCHWT1,AVX512F,AVX512PF,AVX512ERandAVX512CD.knmโ โญ Intel Knights Mill CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.2,POPCNT,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,PREFETCHWT1,AVX512F,AVX512PF,AVX512ER,AVX512CD,AVX5124VNNIW,AVX5124FMAPSandAVX512VPOPCNTDQ.skylake-avx512โ ๐ฅ Intel Skylake Server CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.2,POPCNT,PKU,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,CLFLUSHOPT,XSAVEC,XSAVES,AVX512F,CLWB,AVX512VL,AVX512BW,AVX512DQandAVX512CD.cannonlakeโ ๐ Intel Cannonlake Server CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.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,SHAandUMIP.icelake-clientโ ๐ซถ Intel Icelake Client CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.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,VPCLMULQDQandVAESsupport.icelake-serverโ ๐ง Intel Icelake Server CPU with everythingicelake-clienthas, plusPCONFIGandWBNOINVD. Same glow-up, server edition. โจcascadelakeโ ๐ Intel Cascadelake CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.2,POPCNT,PKU,AVX,AVX2,AES,PCLMUL,FSGSBASE,RDRND,FMA,BMI,BMI2,F16C,RDSEED,ADCX,PREFETCHW,CLFLUSHOPT,XSAVEC,XSAVES,AVX512F,CLWB,AVX512VL,AVX512BW,AVX512DQ,AVX512CDandAVX512VNNI.tigerlakeโ ๐ Intel Tigerlake CPU with 64-bit extensions,MOVBE,MMX,SSEthroughSSE4.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,MOVDIR64BandCLWBsupport. Note thatCLWBis listed twice in the original, and we're keeping it exactly like that. ๐k6โ ๐ AMD K6 CPU withMMXinstruction set support. A classic, honestly.k6-2,k6-3โ ๐ Improved versions of the AMD K6 CPU withMMXand3DNow!instruction set support.athlon,athlon-tbirdโ ๐ AMD Athlon CPU withMMX,3dNOW!, enhanced3DNow!and SSE prefetch instructions support.athlon-4,athlon-xp,athlon-mpโ โจ Improved AMD Athlon CPU withMMX,3DNow!, enhanced3DNow!and fullSSEinstruction set support. Level up!k8,opteron,athlon64,athlon-fxโ ๐ฆ Processors based on the AMD K8 core withx86-64instruction set support, including the AMD Opteron, Athlon 64 and Athlon 64 FX processors. (This one supersetsMMX,SSE,SSE2,3DNow!, enhanced3DNow!and 64-bit instruction set extensions.)k8-sse3,opteron-sse3,athlon64-sse3โ ๐ธ Improved versions of the AMD K8 cores withSSE3instruction set support.amdfam10,barcelonaโ ๐ฅ CPUs based on AMD Family 10h cores withx86-64instruction set support. (This supersetsMMX,SSE,SSE2,SSE3,SSE4A,3DNow!, enhanced3DNow!,ABMand 64-bit instruction set extensions.)bdver1โ ๐ CPUs based on AMD Family 15h cores withx86-64instruction set support. (This supersetsFMA4,AVX,XOP,LWP,AES,PCL_MUL,CX16,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions.)bdver2โ ๐ AMD Family 15h core based CPUs withx86-64instruction set support. (This supersetsBMI,TBM,F16C,FMA,FMA4,AVX,XOP,LWP,AES,PCL_MUL,CX16,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions.)bdver3โ ๐ง AMD Family 15h core based CPUs withx86-64instruction set support. (This supersetsBMI,TBM,F16C,FMA,FMA4,FSGSBASE,AVX,XOP,LWP,AES,PCL_MUL,CX16,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions.)bdver4โ ๐ AMD Family 15h core based CPUs withx86-64instruction set support. (This supersetsBMI,BMI2,TBM,F16C,FMA,FMA4,FSGSBASE,AVX,AVX2,XOP,LWP,AES,PCL_MUL,CX16,MOVBE,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABMand 64-bit instruction set extensions.)znver1โ ๐ AMD Family 17h core based CPUs withx86-64instruction set support. (This supersetsBMI,BMI2,F16C,FMA,FSGSBASE,AVX,AVX2,ADCX,RDSEED,MWAITX,SHA,CLZERO,AES,PCL_MUL,CX16,MOVBE,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABM,XSAVEC,XSAVES,CLFLUSHOPT,POPCNT, and 64-bit instruction set extensions.)znver2โ ๐ AMD Family 17h core based CPUs withx86-64instruction set support. (This supersetsBMI,BMI2,CLWB,F16C,FMA,FSGSBASE,AVX,AVX2,ADCX,RDSEED,MWAITX,SHA,CLZERO,AES,PCL_MUL,CX16,MOVBE,MMX,SSE,SSE2,SSE3,SSE4A,SSSE3,SSE4.1,SSE4.2,ABM,XSAVEC,XSAVES,CLFLUSHOPT,POPCNTand 64-bit instruction set extensions.)btver1โ ๐ CPUs based on AMD Family 14h cores withx86-64instruction set support. (This supersetsMMX,SSE,SSE2,SSE3,SSSE3,SSE4A,CX16,ABMand 64-bit instruction set extensions.)btver2โ ๐ฆ CPUs based on AMD Family 16h cores withx86-64instruction set support. This includesMOVBE,F16C,BMI,AVX,PCL_MUL,AES,SSE4.2,SSE4.1,CX16,ABM,SSE4A,SSSE3,SSE3,SSE2,SSE,MMXand 64-bit instruction set extensions.winchip-c6โ ๐ IDT WinChip C6 CPU, treated the same way asi486, with additionalMMXinstruction set support.winchip2โ ๐ธ IDT WinChip 2 CPU, treated the same way asi486, with additionalMMXand3DNow!instruction set support.c3โ ๐ง VIA C3 CPU withMMXand3DNow!instruction set support. (No scheduling is implemented for this chip.)c3-2โ ๐ VIA C3-2 (Nehemiah/C5XL) CPU withMMXandSSEinstruction set support. (No scheduling is implemented for this chip.)c7โ โญ VIA C7 (Esther) CPU withMMX,SSE,SSE2andSSE3instruction set support. (No scheduling is implemented for this chip.) ๐ซถsamuel-2โ the VIA Eden Samuel 2 CPU ๐ธ, slaying with MMX and 3DNow! instruction set support. (ngl, no scheduling is implemented for this chip.)nehemiahโ the VIA Eden Nehemiah CPU ๐ฆ, with MMX and SSE instruction set support. (No scheduling is implemented for this chip.)estherโ the VIA Eden Esther CPU ๐ง, with MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.)eden-x2โ the VIA Eden X2 CPU ๐, with x86-64, MMX, SSE, SSE2 and SSE3 instruction set support. (No scheduling is implemented for this chip.)eden-x4โ the VIA Eden X4 CPU ๐, with x86-64, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and AVX2 instruction set support. (No scheduling is implemented for this chip.)nanoโ the generic VIA Nano CPU โจ, with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-1000โ the VIA Nano 1xxx CPU ๐, with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-2000โ the VIA Nano 2xxx CPU ๐, with x86-64, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support. (No scheduling is implemented for this chip.)nano-3000โ the VIA Nano 3xxx CPU ๐, with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.)nano-x2โ the VIA Nano Dual Core CPU ๐ซถ, with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.)nano-x4โ the VIA Nano Quad Core CPU ๐ฅ, with x86-64, MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 instruction set support. (No scheduling is implemented for this chip.)geodeโ the AMD Geode embedded processor ๐ , with MMX and 3DNow! instruction set support.
-mtune=cpu-type ๐
Okay so -mtune is the move when you want the generated code tuned for a specific chip, except for the ABI and the set of available instructions. Picking a specific cpu-type schedules things appropriately for that particular chip, but the compiler won't generate code that can't run on the default machine type unless you also use a -march=cpu-type option. For example, if GCC is configured for i686-pc-linux-gnu, then -mtune=pentium4 generates code tuned for Pentium 4 that still runs on i686 machines. Main character energy ๐.
The choices for cpu-type are the same as for -march. On top of that, -mtune supports 2 extra choices for cpu-type:
genericโ produces code optimized for the most common IA32/AMD64/EM64T processors ๐ธ. If you already know the CPU your code will run on, use the matching-mtuneor-marchoption instead of-mtune=generic. But if you have no idea what CPU your users will have, this is the one to pick.
As new processors hit the market, the behavior of this option will change. So if you upgrade to a newer version of GCC, the code generation controlled by this option will shift to reflect whichever processors are most common when that version of GCC is released.
There is no -march=generic option, because -march indicates the instruction set the compiler can use, and there's no generic instruction set that applies to all processors. -mtune, on the other hand, indicates the processor (or, in this case, collection of processors) the code is optimized for. ๐ง
intelโ produces code optimized for the most current Intel processors, which for this version of GCC are Haswell and Silvermont ๐. If you know the CPU your code will run on, use the matching-mtuneor-marchoption instead of-mtune=intel. But if you want your application to perform better on both Haswell and Silvermont, this is the one.
As new Intel processors get deployed, the behavior of this option will change. So if you upgrade to a newer version of GCC, the code generation controlled by this option will reflect the most current Intel processors at the time that version of GCC is released.
There is no -march=intel option, because -march indicates the instruction set the compiler can use, and there's no common instruction set that applies to all processors. -mtune, in contrast, indicates the processor (or, in this case, collection of processors) the code is optimized for. โจ
-mcpu=cpu-type ๐
This is a deprecated synonym for -mtune. Still works, but it's on its way out, so switch to -mtune ๐ซถ.
-mfpmath=unit ๐ฆ
Generate floating-point arithmetic for the selected unit. The choices for unit are:
387โ uses the standard 387 floating-point coprocessor that's on the majority of chips, and emulates it otherwise ๐. Code compiled with this option runs almost everywhere. The temporary results are computed in 80-bit precision instead of the precision specified by the type, so the results can come out slightly different from most other chips. See-ffloat-storefor a more detailed description.
This is the default choice for non-Darwin x86-32 targets.
sseโ uses the scalar floating-point instructions from the SSE instruction set. This set is supported by Pentium III and newer chips, and on the AMD side by Athlon-4, Athlon XP and Athlon MP chips ๐. The earlier version of the SSE instruction set only supports single-precision arithmetic, so double and extended-precision arithmetic still go through 387. A later version, present only in Pentium 4 and AMD x86-64 chips, supports double-precision arithmetic too.
For the x86-32 compiler, you must use -march=cpu-type, -msse or -msse2 switches to 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 avoids the numerical instability problems of 387 code. But it may break some existing code that expects temporaries to be 80 bits ๐.
This is the default choice for the x86-64 compiler, Darwin x86-32 targets, and the default choice for x86-32 targets with the SSE2 instruction set when -ffast-math is enabled.
sse,387,sse+387,bothโ attempts to use both instruction sets at once ๐ฅ. This effectively doubles the number of available registers, and on chips with separate execution units for 387 and SSE, it doubles the execution resources too. Use this option with care, because it is still experimental: the GCC register allocator doesn't model separate functional units well, which can make performance unstable.
-masm=dialect ๐
Outputs assembly instructions using the selected dialect. This also affects which dialect is used for basic asm and extended asm. The supported choices (in dialect order) are att or intel. The default is att. Darwin does not support intel ๐.
-mieee-fp, -mno-ieee-fp ๐ธ
These 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 โจ
Generates output containing 80387 instructions for floating point ๐.
-mno-80387, -msoft-float ๐
Generates output containing library calls for floating point instead ๐ซถ.
Warning: the requisite libraries are NOT part of GCC ๐ญ. Normally the facilities of the machine's usual C compiler are used, but this can't be done directly in cross-compilation. You must make your own arrangements to provide suitable library functions for cross-compilation.
On machines where a function returns floating-point results in the 80387 register stack, some floating-point opcodes may still be emitted even if -msoft-float is used ๐.
-mno-fp-ret-in-387 ๐ฆ
Do not use the FPU registers for return values of functions.
The usual calling convention has functions return values of types float and double in an FPU register, even if there's no FPU. The idea is that the operating system should emulate an FPU.
-mno-fp-ret-in-387 causes such values to be returned in ordinary CPU registers instead ๐.
-mno-fancy-math-387 ๐ง
Some 387 emulators don't support the sin, cos and sqrt instructions for the 387. Specify this option to avoid generating those instructions. This option is overridden when -march indicates that the target CPU always has an FPU, so the instruction doesn't need emulation. These instructions are not generated unless you also use the -funsafe-math-optimizations switch ๐.
-malign-double, -mno-align-double ๐
These control whether GCC aligns double, long double, and long long variables on a two-word boundary or a one-word boundary. Aligning double variables on a two-word boundary produces code that runs somewhat faster on a Pentium, at the expense of more memory ๐ฅ.
On x86-64, -malign-double is enabled by default.
Warning: if you use the -malign-double switch, structures containing the above types are aligned differently than the published application binary interface specifications for x86-32, and they are not binary compatible with structures in code compiled without that switch ๐ญ.
-m96bit-long-double, -m128bit-long-double ๐
These switches control the size of the long double type ๐
. The x86-32 application binary interface specifies the size as 96 bits, so -m96bit-long-double is the default in 32-bit mode.
Modern architectures (Pentium and newer) prefer long double to be aligned to an 8- or 16-byte boundary. In arrays or structures that conform to the ABI, that isn't possible. So specifying -m128bit-long-double aligns long double to a 16-byte boundary by padding it with an additional 32-bit zero ๐ธ.
On the x86-64 compiler, -m128bit-long-double is the default choice, since its ABI specifies that long double is aligned on a 16-byte boundary ๐ซถ.
Notice that neither of these options enables any extra precision over the x87 standard of 80 bits for a long double ๐.
Okay so this next batch is all about stack alignment and instruction sets ๐ โจ
๐จ Warning: if you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables, as well as modifying the function calling convention for functions takinglong double. Hence they are not binary-compatible with code compiled without that switch. ๐
-mlong-double-64,-mlong-double-80,-mlong-double-128โ ๐ these control the size of thelong doubletype. At 64 bits,long doubleis equivalent todouble, which is the default for the 32-bit Bionic C library. At 128 bits,long doubleis equivalent to__float128, which is the default for the 64-bit Bionic C library.
๐จ Warning: if you override the default value for your target ABI, this changes the size of structures and arrays containinglong doublevariables, as well as modifying the function calling convention for functions takinglong double. Hence they are not binary-compatible with code compiled without that switch. ๐
-malign-data=typeโ ๐ธ controls how GCC aligns variables. The supported values for type are:compatโ uses an increased alignment value that is compatible with GCC 4.8 and earlier. This is the default. ๐abiโ uses the alignment value specified by the psABI. ๐งcachelineโ uses an increased alignment value to match the cache line size. ๐ฆ
-mlarge-data-threshold=thresholdโ ๐ when-mcmodel=mediumis specified, data objects larger than threshold get placed in the large data section. This value has to be the same across every object linked into the binary, and it defaults to65535.-mrtdโ ๐ this swaps in a different function-calling convention. Functions that take a fixed number of arguments return with theret numinstruction, which pops their arguments on the way out. That saves one instruction in the caller, since the caller doesn't have to pop anything. ๐ง
You can make one specific function use this calling sequence with the function attribute stdcall. You can also override -mrtd for a function by using the function attribute cdecl.
โ ๏ธ Warning: this calling convention is incompatible with the one normally used on Unix, so you cannot use it if you need to call libraries compiled with the Unix compiler. ๐ โโ๏ธ
Also, you must provide function prototypes for all functions that take variable numbers of arguments (including printf), otherwise incorrect code gets generated for calls to those functions. ๐ญ
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. This includes the system libraries and startup modules. ๐ซถ
-msseregparmโ โจ uses the 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, then you must build all modules with the same value, including any libraries. This 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 Solaris 8 and 9 and VxWorks, to match the ABI of the Sun Studio compilers until version 12. Later compiler versions (starting with Studio 12 Update 1) follow the ABI used by other x86 targets, which is the default on Solaris 10 and later. Only use this option if you need to stay compatible with existing code produced by those previous compiler versions or older versions of GCC. ๐ฐ๏ธ-mpc32โ ๐ฏ sets the 80387 floating-point precision to 32 bits. The significands of floating-point operation results get rounded to 24 bits (single precision).-mpc64โ ๐ฏ sets the 80387 floating-point precision to 64 bits. The significands of floating-point operation results get rounded to 53 bits (double precision).-mpc80โ ๐ฏ sets the 80387 floating-point precision to 80 bits. The significands of floating-point operation results get rounded to 64 bits (extended double precision). This is the default. ๐
Once this option 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 to less than the default 80 bits can speed some programs up by 2% or more. โก But heads up: some mathematical libraries assume extended-precision (80-bit) floating-point operations are enabled by default. Routines in those libraries could suffer significant loss of accuracy, typically through so-called "catastrophic cancellation", when this option is used to set the precision to less than extended precision. ๐ฑ
-mstackrealignโ ๐ง realigns the stack at entry. On the x86,-mstackrealigngenerates an alternate prologue and epilogue that realigns the run-time stack if necessary. This supports mixing legacy code that keeps 4-byte stack alignment 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โ ๐งฑ attempts to keep the stack boundary aligned to a 2 raised to num byte 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 be used to keep the stack boundary aligned to an 8 byte boundary. Since the x86-64 ABI requires 16 byte stack alignment, this is ABI incompatible and is only intended for a controlled environment where stack space is an important limitation. This option leads to wrong code when functions compiled with 16 byte stack alignment (such as functions from a standard library) are called with a misaligned stack. In this case, SSE instructions may lead to misaligned memory access traps. In addition, variable arguments are handled incorrectly for 16 byte aligned objects (including x87long doubleand__int128), leading to wrong results. You must build all modules with-mpreferred-stack-boundary=3, including any libraries. This includes the system libraries and startup modules. ๐
-mincoming-stack-boundary=numโ ๐ฌ assumes the incoming stack is aligned to a 2 raised to num byte boundary. If-mincoming-stack-boundaryisn't specified, the one specified by-mpreferred-stack-boundaryis used.
On Pentium and Pentium Pro, double and long double values should be aligned to an 8-byte boundary (see -malign-double) or they'll suffer significant run time performance penalties. ๐ข On Pentium III, the Streaming SIMD Extension (SSE) data type __m128 may not work properly if it isn't 16-byte aligned. ๐ฌ
To make sure these values are properly aligned on the stack, the stack boundary must be as aligned as the strictest value stored on the stack requires. Further, every function must be generated so that it keeps the stack aligned. So calling a function compiled with a higher preferred stack boundary from a function compiled with a lower one most likely misaligns the stack. It's recommended that libraries that use callbacks always use the default setting. ๐
This extra alignment does eat up extra stack space and generally increases code size. Code that's sensitive to stack space usage, like embedded systems and operating system kernels, may want to reduce the preferred alignment to -mpreferred-stack-boundary=2. ๐งน
Now for the instruction set switches. โจ These turn on the use of instructions from the following sets, and each one has a matching -mno- option to turn that instruction set off. ๐ง
-mmmxโ ๐ฌ MMX instructions-msseโ ๐ SSE instructions-msse2โ ๐ SSE2 instructions-msse3โ ๐ SSE3 instructions-mssse3โ ๐ SSSE3 instructions-msse4โ ๐ SSE4 instructions-msse4aโ ๐ SSE4A instructions-msse4.1โ ๐ SSE4.1 instructions-msse4.2โ ๐ SSE4.2 instructions-mavxโ ๐ฆ AVX instructions-mavx2โ ๐ฆ AVX2 instructions-mavx512fโ ๐ฅ AVX512F instructions-mavx512pfโ ๐ฅ AVX512PF instructions-mavx512erโ ๐ฅ AVX512ER instructions-mavx512cdโ ๐ฅ AVX512CD instructions-mavx512vlโ ๐ฅ AVX512VL instructions-mavx512bwโ ๐ฅ AVX512BW instructions-mavx512dqโ ๐ฅ AVX512DQ instructions-mavx512ifmaโ ๐ฅ AVX512IFMA instructions-mavx512vbmiโ ๐ฅ AVX512VBMI instructions-mshaโ ๐ SHA instructions-maesโ ๐ AES instructions-mpclmulโ ๐ PCLMUL instructions-mclflushoptโ ๐งฝ CLFLUSHOPT instructions-mclwbโ ๐งฝ CLWB instructions-mfsgsbaseโ ๐งต FSGSBASE instructions-mptwriteโ โ๏ธ PTWRITE instructions-mrdrndโ ๐ฒ RDRND instructions-mf16cโ ๐งฎ F16C instructions-mfmaโ ๐งฎ FMA instructions-mpconfigโ โ๏ธ PCONFIG instructions-mwbnoinvdโ โ๏ธ WBNOINVD instructions-mfma4โ ๐งฎ FMA4 instructions-mprfchwโ ๐โโ๏ธ PREFETCHW instructions-mrdpidโ ๐ชช RDPID instructions-mprefetchwt1โ ๐โโ๏ธ PREFETCHWT1 instructions-mrdseedโ ๐ฒ RDSEED instructions-msgxโ ๐ฐ SGX instructions-mxopโ ๐งฎ XOP instructions-mlwpโ ๐งฎ LWP instructions-m3dnowโ ๐น๏ธ 3DNow! instructions-m3dnowaโ ๐น๏ธ enhanced 3DNow! instructions-mpopcntโ ๐ข POPCNT instructions-mabmโ ๐ข ABM instructions-madxโ โ ADX instructions-mbmiโ ๐ฃ BMI instructions-mbmi2โ ๐ฃ BMI2 instructions-mlzcntโ ๐ข LZCNT instructions-mfxsrโ ๐พ FXSR instructions-mxsaveโ ๐พ XSAVE instructions-mxsaveoptโ ๐พ XSAVEOPT instructions-mxsavecโ ๐พ XSAVEC instructions-mxsavesโ ๐พ XSAVES instructions-mrtmโ ๐ RTM instructions-mhleโ ๐ HLE instructions-mtbmโ ๐ฃ TBM instructions-mmwaitxโ โณ MWAITX instructions-mclzeroโ ๐งน CLZERO instructions-mpkuโ ๐ PKU instructions-mavx512vbmi2โ ๐ฅ AVX512VBMI2 instructions-mgfniโ ๐งฎ GFNI instructions-mvaesโ ๐ VAES instructions-mwaitpkgโ โณ WAITPKG instructions-mvpclmulqdqโ ๐ VPCLMULQDQ instructions-mavx512bitalgโ ๐ฅ AVX512BITALG instructions-mmovdiriโ ๐ MOVDIRI instructions-mmovdir64bโ ๐ MOVDIR64B instructions-mavx512vpopcntdqโ ๐ฅ AVX512VPOPCNTDQ instructions-mavx5124fmapsโ ๐ฅ AVX5124FMAPS instructions-mavx512vnniโ ๐ฅ AVX512VNNI instructions-mavx5124vnniwโ ๐ฅ AVX5124VNNIW instructions-mcldemoteโ ๐งฝ CLDEMOTE instructions
These extensions are also available as built-in functions. ๐งฐ Check out x86 Built-in Functions for the details on which functions get enabled and disabled by these switches. ๐
To generate SSE/SSE2 instructions automatically from floating-point code (as opposed to 387 instructions), use -mfpmath=sse. ๐
๐
Heads up: GCC basically benches the SSEx instructions when -mavx is used. Instead, it generates new AVX instructions, or AVX equivalents for all SSEx instructions, when needed. ๐ฆ
These flags let GCC use the extended instructions in the code it generates even without -mfpmath=sse ๐
Heads up, bestie: if your app does run-time CPU detection, you need to compile a separate file for each supported architecture, each with the right flags ๐ซถ And the file with the CPU detection code specifically has to be compiled without these options ๐ Don't skip this part, no cap.
-mdump-tune-featuresโ this one is giving info ๐ง It tells GCC to dump the names of the x86 performance tuning features along with their default settings โจ You can use those names in-mtune-ctrl=feature-list.-mtune-ctrl=feature-listโ the fine-grain control knob for x86 code generation features ๐ feature-list is a comma-separated list of feature names (see also-mdump-tune-features). A feature gets turned on if its name isn't preceded by^, and turned off if it is. This one is really meant for GCC developers ๐
Real talk: using -mtune-ctrl=feature-list can lead to code paths that aren't covered by testing, and it can potentially result in compiler ICEs or runtime errors ๐ Proceed with caution, bestie.
-mno-defaultโ turns off all tunable features ๐ธ See also-mtune-ctrl=feature-listand-mdump-tune-features.-mcldโ tells GCC to emit acldinstruction in the prologue of functions that use string instructions ๐ Here's the tea: string instructions depend on the DF flag to pick between autoincrement and autodecrement mode. The ABI says DF gets cleared on function entry, but some operating systems don't clear it in their exception dispatchers ๐ญ So the exception handler can be invoked with DF set, which leads to the wrong direction mode when string instructions are used. This option can be enabled by default on 32-bit x86 targets by configuring GCC with the--enable-cldconfigure option. In that case, you can suppress generation ofcldinstructions with the-mno-cldcompiler option.-mvzeroupperโ emits avzeroupperinstruction before control flow transfers out of the function ๐ฆ This minimizes the AVX to SSE transition penalty and also removes unnecessaryzeroupperintrinsics โจ-mprefer-avx128โ uses 128-bit AVX instructions instead of 256-bit AVX instructions in the auto-vectorizer ๐-mprefer-vector-width=optโ uses opt-bit vector width in instructions instead of the default on the selected platform ๐ The values are:noneโ no extra limitations applied to GCC other than what the selected platform defines128โ prefer 128-bit vector width for instructions256โ prefer 256-bit vector width for instructions512โ prefer 512-bit vector width for instructions
-mcx16โ enables GCC to generateCMPXCHG16Binstructions in 64-bit code ๐ฅ These do compare-and-exchange on 16-byte aligned 128-bit objects, which is super useful for atomic updates of data structures bigger than one machine word ๐ GCC 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 ๐ง Quick history moment: early Intel Pentium 4 CPUs with Intel 64 support, before the Pentium 4 G1 step in December 2005, lacked theLAHFandSAHFinstructions that AMD64 supports ๐ These are load and store instructions, respectively, for certain status flags. In 64-bit mode, theSAHFinstruction is used to optimize thefmod,drem, andremainderbuilt-in functions; see Other Builtins for details.-mmovbeโ enables use of themovbeinstruction to implement__builtin_bswap32and__builtin_bswap64๐-mshstkโ enables the shadow stack built-in functions from x86 Control-flow Enforcement Technology (CET) ๐ฅ-mcrc32โ enables the built-in functions__builtin_ia32_crc32qi,__builtin_ia32_crc32hi,__builtin_ia32_crc32siand__builtin_ia32_crc32dito generate thecrc32machine instruction โจ-mrecipโ enables use ofRCPSSandRSQRTSS(and their vectorized variantsRCPPSandRSQRTPS) with an additional Newton-Raphson step for more precision, instead ofDIVSSandSQRTSS(and their vectorized variants) for single-precision floating-point arguments ๐งฎ These instructions are only generated when-funsafe-math-optimizationsis enabled together with-ffinite-math-onlyand-fno-trapping-math.
Heads up: while the throughput of the sequence is higher than the throughput of the non-reciprocal instruction, the precision of the sequence can be decreased by up to 2 ulp (i.e. the inverse of 1.0 equals 0.99999994) ๐ญ
Note that GCC implements 1.0f/sqrtf(x) in terms of RSQRTSS (or RSQRTPS) already with -ffast-math (or the above option combination), so it doesn't need -mrecip ๐ซถ
Also note that GCC emits the above sequence with the additional Newton-Raphson step for vectorized single-float division and vectorized sqrtf(x) already with -ffast-math (or the above option combination), so it doesn't need -mrecip either โจ
-mrecip=optโ controls which reciprocal estimate instructions may be used ๐ opt is a comma-separated list of options, and any of them may be preceded by a!to invert it:allโ enable all estimate instructionsdefaultโ enable the default instructions, equivalent to-mrecipnoneโ disable all estimate instructions, equivalent to-mno-recipdivโ enable the approximation for scalar divisionvec-divโ enable the approximation for vectorized divisionsqrtโ enable the approximation for scalar square rootvec-sqrtโ enable the approximation for vectorized square root
So, for example, -mrecip=all,!sqrt enables all of the reciprocal approximations except for square root ๐
-mveclibabi=typeโ specifies the ABI type to use for vectorizing intrinsics using an external library ๐ฆ Supported values for type aresvml(the Intel short vector math library) andacml(the AMD math core library). To use this option, both-ftree-vectorizeand-funsafe-math-optimizationshave to be enabled, and an SVML or ACML ABI-compatible library must be specified at link time.
GCC currently emits calls to the following functions. With -mveclibabi=svml, you get:
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,vmlsAcosh4andvmlsAcos4for the corresponding function type
And with -mveclibabi=acml, you get:
__vrd2_sin,__vrd2_cos,__vrd2_exp,__vrd2_log,__vrd2_log2,__vrd2_log10,__vrs4_sinf,__vrs4_cosf,__vrs4_expf,__vrs4_logf,__vrs4_log2f,__vrs4_log10fand__vrs4_powffor the corresponding function type
-mabi=nameโ generates code for the specified calling convention ๐ธ Permissible values aresysvfor the ABI used on GNU/Linux and other systems, andmsfor the Microsoft ABI. The default is the Microsoft ABI when targeting Microsoft Windows, and the SysV ABI on all other systems. You can control this behavior for specific functions by using the function attributesms_abiandsysv_abi๐-mforce-indirect-callโ forces all calls to functions to be indirect ๐ฅ This is useful with Intel Processor Trace, where it generates more precise timing information for function calls ๐ง-mmanual-endbrโ inserts anENDBRinstruction at function entry only via thecf_checkfunction attribute ๐ This is useful when used with-fcf-protection=branchto controlENDBRinsertion at the function entry.-mcall-ms2sysv-xloguesโ due to differences in 64-bit ABIs, any Microsoft ABI function that calls a System V ABI function must considerRSI,RDIandXMM6-15as clobbered ๐ By default, the code for saving and restoring these registers is emitted inline, which makes for pretty lengthy prologues and epilogues. Using-mcall-ms2sysv-xloguesemits prologues and epilogues that use stubs in the static portion of libgcc to perform these saves and restores, which reduces function size at the cost of a few extra instructions ๐ซถ-mtls-dialect=typeโ generates code to access thread-local storage using thegnuorgnu2conventions ๐งตgnuis the conservative default.gnu2is more efficient, but it may add compile- and run-time requirements that cannot be satisfied on all systems ๐-mpush-args,-mno-push-argsโ uses PUSH operations to store outgoing parameters ๐ This method is shorter and usually just as fast as the method using SUB/MOV operations, and it's enabled by default. In some cases, disabling it may improve performance because of improved scheduling and reduced dependencies ๐-maccumulate-outgoing-argsโ if enabled, the maximum amount of space required for outgoing arguments is computed in the function prologue โจ This is faster on most modern CPUs because of reduced dependencies, improved scheduling, and reduced stack usage when the preferred stack boundary is not equal to 2. The drawback is a notable increase in code size ๐ญ This switch implies-mno-push-args.-mthreadsโ supports thread-safe exception handling on MinGW ๐งต Programs that rely on thread-safe exception handling must compile and link all code with the-mthreadsoption. When compiling,-mthreadsdefines-D_MT; when linking, it links in a special thread helper library,-lmingwthrd, which cleans up per-thread exception-handling data ๐ฆ-mms-bitfields,-mno-ms-bitfieldsโ enable or disable bit-field layout compatible with the native Microsoft Windows compiler ๐
Okay so, if you use "packed" on a struct or throw bit-fields in there, the Microsoft ABI might lay things out totally differently than GCC does ๐ญ. This matters most when you're passing packed data between GCC code and the native Microsoft compiler, whether through a function call or as data in a file. Sometimes you need to be able to access either format ๐ซถ.
This is on by default for Microsoft Windows targets ๐. You can also control it locally with variable or type attributes. Check out x86 Variable Attributes and x86 Type Attributes for the deets โจ.
The Microsoft struct layout algorithm is pretty chill, except for bit-field packing ๐ง. The padding and alignment of structure members, plus whether a bit-field can straddle a storage-unit boundary, come down to these rules:
- Structure members are stored in the order they're declared ๐. The first member gets the lowest memory address, and the last member gets the highest.
- Every data object has an alignment requirement ๐. For everything except structures, unions, and arrays, it's either the object's size or the current packing size (set with the "aligned" attribute or the "pack" pragma), whichever is smaller. For structures, unions, and arrays, it's the biggest alignment requirement among their members. Every object gets an offset so that:
offset % alignment_requirement == 0
- Adjacent bit-fields get packed into the same 1-, 2-, or 4-byte allocation unit ๐ฆ. This happens when the integral types are the same size and the next bit-field fits in the current allocation unit without crossing the boundary set by the common alignment requirements of the bit-fields.
MSVC handles zero-length bit-fields in these ways, and it's lowkey a lot ๐:
- If a zero-length bit-field sits between two bit-fields that would normally get coalesced, they don't get 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 remove the zero-length bit-field, t1 shrinks to 4 bytes ๐ญ.
- If a zero-length bit-field is inserted after a bit-field,
foo, and the zero-length bit-field's alignment is greater than the member right after 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 lands at offset 2 instead of offset 1, so the size of t2 is 4. For t3, the zero-length bit-field doesn't change the alignment of bar or the size of the structure ๐ธ.
Keeping that in mind, here's what else you need to know:
- If a zero-length bit-field follows a normal bit-field, its type can affect the alignment of the whole structure. For example,
t2is 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 get ignored ๐ซ :
struct
{
char foo;
long : 0;
char bar;
} t5;
Here, t5 takes up 2 bytes โจ.
-mno-align-stringopsโ Don't align the destination of inlined string operations ๐ . This shrinks code size and can boost performance when the destination is already aligned but GCC doesn't know that.-minline-all-stringopsโ By default, GCC only inlines string operations when the destination is known to be aligned to at least a 4-byte boundary. This turns on more inlining, which makes code size bigger, but it might speed up code that leans on fastmemcpy,strlen, andmemsetfor short lengths ๐ฅ.-minline-stringops-dynamicallyโ For string operations of unknown size, GCC uses run-time checks with inline code for small blocks and a library call for large blocks ๐ง .-mstringop-strategy=algโ Overrides the internal heuristic that picks the algorithm used for inlining string operations ๐ฏ. 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โ Overrides the internal heuristic that decides whether__builtin_memcpygets inlined and which inline algorithm it uses when the expected size of the copy is known ๐.strategyis a comma-separated list ofalg:max_size:dest_aligntriplets.algis specified with-mstringop-strategy, andmax_sizeis the largest byte size that inline algorithmalgis allowed to handle. For the last triplet,max_sizemust be-1. Themax_sizevalues in the list must be in increasing order. The minimum byte size foralgis 0 for the first triplet, andmax_size + 1of the preceding range for every triplet after that ๐.-mmemset-strategy=strategyโ Works like-mmemcpy-strategy=except it controls__builtin_memsetexpansion ๐ท.-momit-leaf-frame-pointerโ Doesn't keep the frame pointer in a register for leaf functions ๐. This skips the instructions that save, set up, and restore frame pointers, and it 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 this is valid depends on the operating system and on whether it maps the segment to cover the entire TLS area. For systems that use the GNU C Library, the default is on โ .-msse2avx,-mno-sse2avxโ Tells the assembler to encode SSE instructions with a VEX prefix ๐. The option-mavxturns this on by default.-mfentry,-mno-fentryโ If profiling is active (-pg), puts the profiling counter call before the prologue ๐ธ. Note: on x86 architectures, the attributems_hook_prologueisn't possible at the moment for-mfentryand-pg๐ซ.-mrecord-mcount,-mno-record-mcountโ If profiling is active (-pg), generates a__mcount_locsection containing pointers to each profiling call ๐. This is useful for automatically patching and out calls ๐ช.-mnop-mcount,-mno-nop-mcountโ If profiling is active (-pg), generates the calls to the profiling functions as NOPs ๐ด. This is handy when they should be patched in later dynamically. It's likely only useful together with-mrecord-mcount๐.-minstrument-return=typeโ Instruments function exit in-pg -mfentryinstrumented functions with a call to the specified function ๐ช. This only instruments true returns ending withret, not sibling calls ending with a jump. Valid types arenoneto not instrument,callto generate a call to__return__, ornop5to generate a 5 byte nop ๐ซง.-mrecord-return,-mno-record-returnโ Generates a__return_locsection pointing to all return instrumentation code ๐.-mfentry-name=nameโ Sets the name of the__fentry__symbol that gets called at function entry for-pg -mfentryfunctions ๐ท๏ธ.-mfentry-section=nameโ Sets the name of the section where-mrecord-mcountcalls get recorded (default__mcount_loc) ๐๏ธ.-mskip-rax-setup,-mno-skip-rax-setupโ When generating 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 don't have those issues, regardless of the RAX register value.
-m8bit-idiv,-mno-8bit-idivโ On some processors, like Intel Atom, 8-bit unsigned integer divide is much faster than 32-bit/64-bit integer divide โก. This option generates a run-time check. If both the dividend and divisor are within the range of 0 to 255, 8-bit unsigned integer divide is used instead of 32-bit/64-bit integer divide ๐งฎ.-mavx256-split-unaligned-load,-mavx256-split-unaligned-storeโ Splits 32-byte AVX unaligned loads and stores into smaller pieces ๐ช.-mstack-protector-guard=guard,-mstack-protector-guard-reg=reg,-mstack-protector-guard-offset=offsetโ Generates stack protection code using a canary atguard๐ค. The supported locations areglobalfor a global canary, ortlsfor a per-thread canary in the TLS block (the default). This only has an effect when-fstack-protectoror-fstack-protector-allis specified ๐ก๏ธ.
With that latter choice, the options -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset further specify which segment register (%fs or %gs) to use as the base register for reading the canary, and what offset from that base register to use. The defaults for those are whatever the relevant ABI specifies ๐
โจ.
-mgeneral-regs-only: okay so this one tells GCC to only use the general-purpose registers ๐ No floating-point, vector, mask, or bound registers allowed, so the compiler stays in its lane ๐ธ-mindirect-branch=choice**: convert indirect call and jump with choice โจ The default iskeep, which leaves indirect calls and jumps totally unmodified ๐thunkturns them into call and return thunks ๐งthunk-inlineturns them into inlined call and return thunks ๐ฆ andthunk-externturns them into external call and return thunks that live in a separate object file ๐ฆ You can also control this for one specific function with the function attribute"indirect_branch"๐
bestie, heads up ๐-mcmodel=largeis incompatible with-mindirect-branch=thunkand-mindirect-branch=thunk-extern, since the thunk function may not be reachable in the large code model ๐
ngl this one is giving compatibility ๐ซถ-mindirect-branch=thunk-externworks with-fcf-protection=branch, since the external thunk can be made to enable control-flow check โจ
-mfunction-return=choice**: convert function return with choice ๐ The default iskeep, which keeps function return unmodified ๐thunkconverts function return to call and return thunk ๐งthunk-inlineconverts it to an inlined call and return thunk ๐ฆ andthunk-externconverts it to an external call and return thunk provided in a separate object file ๐ฆ You can control this for a specific function with the function attribute"function_return"๐
Note that-mindirect-return=thunk-externis compatible with-fcf-protection=branchsince the external thunk can be made to enable control-flow check ๐ฅ
Also,-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: force indirect call and jump via register ๐
These -m switches are supported in addition to the above on x86-64 processors in 64-bit environments ๐ธ
Generate code for a 16-bit, 32-bit or 64-bit environment ๐
-m32: sets"int","long", and pointer types to 32 bits, and generates code that runs on any i386 system ๐ฆ-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-m32to be turned on ๐-mno-red-zone: do not use a so-called "red zone" for x86-64 code ๐ The red zone is mandated by the x86-64 ABI, and it's a 128-byte area beyond the stack pointer that signal or interrupt handlers don't modify, so it can be used for temporary data without adjusting the stack pointer ๐ This flag disables that red zone ๐ฅ-mcmodel=small: generate code for the small code model, where the program and its symbols must be linked in the lower 2 GB of the address space ๐ธ Pointers are 64 bits, and programs can be statically or dynamically linked ๐ This is the default code model ๐-mcmodel=kernel: generate code for the kernel code model ๐ฅ The kernel runs in the negative 2 GB of the address space, and this model has to be used for Linux kernel code ๐ง-mcmodel=medium: generate code for the medium model, where the program is linked in the lower 2 GB of the address space ๐ฆ Small symbols are placed there too ๐ Symbols with sizes larger than-mlarge-data-thresholdgo 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 ๐ง This model 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, and 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, and it's the default address mode for 32-bit and x32 environments ๐ซถ
๐ x86 Windows Options ๐
These additional options are available for Microsoft Windows targets ๐ช
-mconsole: this option specifies that a console application is to be generated, by instructing the linker to set the PE header subsystem type required for console applications ๐ฅ๏ธ It's available for Cygwin and MinGW targets and is enabled by default on those targets ๐-mdll: this one's for Cygwin and MinGW targets ๐ง It specifies that a DLL, which is a dynamic link library, is to be generated, enabling the selection of the required runtime startup object and entry point โจ-mnop-fun-dllimport: available for Cygwin and MinGW targets ๐ It specifies that the"dllimport"attribute should be ignored ๐-mthread: available for MinGW targets ๐งต It specifies that MinGW-specific thread support is to be used ๐ฅ-municode: available for MinGW-w64 targets ๐ It causes the"UNICODE"preprocessor macro to be predefined, and chooses Unicode-capable runtime startup code ๐ซถ-mwin32: available for Cygwin and MinGW targets ๐ It specifies that the typical Microsoft Windows predefined macros are set in the preprocessor, but it doesn't influence the choice of runtime library or startup code ๐-mwindows: available for Cygwin and MinGW targets ๐ช It specifies that a GUI application is to be generated by instructing the linker to set the PE header subsystem type appropriately ๐-fno-set-stack-executable: available for MinGW targets ๐ It specifies that 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, since the User32 API (used to set executable privileges) isn't available there ๐ฅ-fwritable-relocated-rdata: available for MinGW and Cygwin targets ๐ธ It specifies that relocated data in a read-only section is put into the".data"section ๐ง This is necessary for older runtimes that don't support modification of".rdata"sections for pseudo-relocation ๐ซถ-mpe-aligned-commons: available for Cygwin and MinGW targets โจ It specifies that the GNU extension to the PE file format, which permits the correct alignment of COMMON variables, should be used when generating code ๐ It's enabled by default if GCC detects that the target assembler found during configuration supports the feature ๐
See also under x86 Options for standard options ๐
๐ธ Xstormy16 Options ๐ธ
These options are defined for Xstormy16 ๐
-msim: choose startup files and linker script suitable for the simulator ๐ง
๐ฆ Xtensa Options ๐ฆ
These options are supported for Xtensa targets ๐
-mconst16,-mno-const16: enable or disable use ofCONST16instructions for loading constant values ๐ TheCONST16instruction is currently not a standard option from Tensilica ๐ When enabled,CONST16instructions are always used in place of the standardL32Rinstructions โจ The use ofCONST16is enabled by default only if theL32Rinstruction 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-mserialize-volatileis enabled, GCC insertsMEMWinstructions beforevolatilememory references to guarantee sequential consistency ๐ The default is-mserialize-volatile๐ Use-mno-serialize-volatileto omit theMEMWinstructions ๐-mforce-no-pic: for targets like GNU/Linux, where all user-mode Xtensa code must be position-independent code (PIC), this option disables PIC for compiling kernel code ๐ง-mtext-section-literals,-mno-text-section-literals: these options control the treatment of literal pools ๐งต The default is-mno-text-section-literals, which places literals in a separate section in the output file ๐ธ That lets the literal pool sit in data RAM/ROM, and it also lets the linker combine literal pools from separate object files to remove redundant literals and improve code size โจ With-mtext-section-literals, the literals are interspersed in the text section so they stay as close as possible to their references ๐ฆ This may be necessary for large assembly files ๐ซถ Literals for each function are placed right before that function ๐-mauto-litpools,-mno-auto-litpoolsโ okay so these two control how literal pools get handled ๐ The default is-mno-auto-litpools, which tosses literals into their own separate section in the output file unless-mtext-section-literalsis used ๐ธ With-mauto-litpools, the assembler mixes literals right into the text section ๐ง The compiler doesn't produce explicit.literaldirectives. It loads literals into registers withMOVIinstructions instead ofL32R, so the assembler can do relaxation and place literals wherever they're needed โจ This lets the assembler create several literal pools per function, so it can assemble really big functions, which might not be possible with-mtext-section-literals๐ญ๐ฅ-mtarget-align,-mno-target-alignโ when this is enabled, GCC tells the assembler to auto-align instructions to cut down on branch penalties, even though the code gets a little less dense ๐ฆ The assembler tries to widen density instructions so that branch targets and the instructions following 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 touch auto-aligned instructions likeLOOP, which the assembler always aligns, 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 the target of a direct call is in range for the call instruction ๐ This usually happens for calls to functions in other source files ๐ซถ Specifically, the assembler turns a directCALLinstruction into anL32Rfollowed by aCALLXinstruction ๐ The default is-mno-longcalls. Use this option in programs where the call target could be out of range ๐ This option lives in the assembler, not the compiler, so the assembly GCC generates still shows direct call instructions. Look at the disassembled object code to see what's actually running ๐ Also, the assembler uses an indirect call for every cross-file call, not just the ones that are really out of range ๐
zSeries Options
These are listed under
โจ ENVIRONMENT โจ
This section covers several environment variables that change how GCC operates ๐ Some of them work by specifying directories or prefixes to search when looking for different kinds of files, and some set other parts of the compilation environment ๐
Quick reminder that you can also specify search places with options like -B, -I and -L ๐ Those take priority over places set using environment variables, and those environment variables in turn take priority over whatever GCC's configuration says โญ
LANG, LC_CTYPE, LC_MESSAGES, LC_ALL
These variables control how GCC uses localization info, which lets it work with different national conventions ๐ GCC checks the locale categories LC_CTYPE and LC_MESSAGES if it's been configured to do so. These categories can be set to any value your installation supports. A typical value is en_GB.UTF-8, which means English in the United Kingdom encoded in UTF-8 ๐ฌ๐ง
The LC_CTYPE variable specifies character classification ๐ค GCC uses it to figure out character boundaries in a string. This matters for some multibyte encodings that contain quote and escape characters, which would otherwise get read as the end of a string or as an escape ๐ญ
The LC_MESSAGES variable specifies which language to use in diagnostic messages ๐ฌ
If LC_ALL is set, it overrides LC_CTYPE and LC_MESSAGES. Otherwise, LC_CTYPE and LC_MESSAGES default to whatever LANG is set to ๐ซถ If none of these variables are set, GCC defaults to traditional C English behaviour ๐งธ
TMPDIR
If TMPDIR is set, it specifies the directory for temporary files ๐๏ธ GCC uses temporary files to hold the output of one stage of compilation that gets used as input for the next stage. For example, the output of the preprocessor is the input to the compiler proper ๐ง
GCC_COMPARE_DEBUG
Setting GCC_COMPARE_DEBUG is nearly the same as passing -fcompare-debug to the compiler driver. Check out the docs for that option for more details ๐
GCC_EXEC_PREFIX
If GCC_EXEC_PREFIX is set, it specifies a prefix to use in the names of the subprograms the compiler runs. No slash gets added when this prefix is combined with a subprogram name, but you can add a trailing slash to your prefix if you want one ๐ฆ
If GCC_EXEC_PREFIX isn't set, GCC tries to figure out a good prefix based on the pathname it was invoked with ๐งญ
If GCC can't find the subprogram using the specified prefix, it looks in the usual places for it ๐
The default value of GCC_EXEC_PREFIX is prefix/lib/gcc/, where prefix is the prefix of the installed compiler. In lots of cases, prefix is the value of prefix you gave when you ran the configure script ๐ท
Other prefixes set with -B take priority over this one ๐
This prefix is also used to find files like crt0.o that get used for linking ๐
The prefix is also used in a kinda unusual way when finding the directories to search for header files ๐ For each standard directory whose name normally begins with /usr/local/lib/gcc (or more precisely, with the value of GCC_INCLUDE_DIR), GCC tries swapping 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 starts with the configured prefix, then the value of prefix gets replaced by GCC_EXEC_PREFIX when GCC looks for header files ๐
COMPILER_PATH
The value of COMPILER_PATH is a colon-separated list of directories, a lot like PATH ๐ฃ๏ธ GCC tries these directories when searching for subprograms, if it can't find them using GCC_EXEC_PREFIX ๐
LIBRARY_PATH
The value of LIBRARY_PATH is also a colon-separated list of directories, just like PATH ๐ When GCC is configured as a native compiler, it tries these directories when searching for special linker files, if it can't find them using GCC_EXEC_PREFIX. Linking with GCC also uses these directories to look for ordinary libraries for the -l option. Directories specified with -L come first though ๐ฅ
LANG
This variable passes locale info to the compiler ๐ One thing this info is used for is figuring out which character set to use when parsing character literals, string literals and comments in C and C++. When the compiler is configured to allow multibyte characters, these values for LANG are recognised:
C-JISโ recognises JIS characters ๐C-SJISโ recognises SJIS characters ๐ฃC-EUCJPโ recognises EUCJP characters ๐
If LANG isn't defined, or has some other value, then the compiler uses mblen and mbtowc as defined by the default locale to recognise and translate multibyte characters ๐ค
Some additional environment variables affect the behaviour of the preprocessor ๐งผ
CPATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH
Each variable's value is a list of directories separated by a special character, a lot like PATH, and they're used to look for header files ๐ That special character, PATH_SEPARATOR, depends on the target and gets set when GCC is built. For Microsoft Windows-based targets it's a semicolon, and for almost every other target it's a colon ๐ป
CPATH specifies a list of directories to search as if they were given with -I, but after any paths given with -I options on the command line. This variable is used no matter which language is being preprocessed ๐
The remaining variables only apply when preprocessing the particular language they name. Each one specifies a list of directories to search as if they were given with -isystem, but after any paths given with -isystem options on the command line ๐ท
In all of these variables, an empty element tells the compiler to search its current working directory. Empty elements can show up at the beginning or end of a path. For instance, if the value of CPATH is ":/special/include", that's the same as -I. -I/special/include ๐ซง
DEPENDENCIES_OUTPUT
If this variable is set, its value specifies how to output dependencies for Make, based on the non-system header files the compiler processes. System header files get ignored in the dependency output ๐ โโ๏ธ
The value of DEPENDENCIES_OUTPUT can be just a file name. In that case the Make rules get written to that file, and the target name gets guessed from the source file name. Or the value can take the form file target, where the rules are written to file using target as the target name ๐ฏ
In other words, this environment variable is the same as combining the options -MM and -MF, with an optional -MT switch too ๐ง
SUNPRO_DEPENDENCIES
This variable is the same as DEPENDENCIES_OUTPUT (see above), except system header files are not ignored, so it implies -M rather than -MM ๐ However, the dependence on the main input file is omitted ๐
SOURCE_DATE_EPOCH
If this variable is set, its value specifies a UNIX timestamp to use instead of the current date and time in the __DATE__ and __TIME__ macros. That way the embedded timestamps are reproducible โฐ
The value of SOURCE_DATE_EPOCH must be a UNIX timestamp, which is the number of seconds (excluding leap seconds) since 01 Jan 1970 00:00:00, written in ASCII. It's identical to the output of date +%s on GNU/Linux and other systems that support the %s extension in the date command ๐ง
The value should be a known timestamp, like the last modification time of the source or package, and the build process should set it ๐ ๏ธ
๐ BUGS ๐
For instructions on reporting bugs, see <file:///usr/share/doc/gcc-9/README.Bugs> ๐๐
โจ FOOTNOTES โจ
okay bestie, there's one footnote and it's a big deal ๐ซถ
- ngl, this one is a whole vibe ๐
On some systems,
gcc -sharedneeds to build supplementary stub code for constructors to work. On multi-libbed systems,gcc -sharedhas to pick the correct support libraries to link against. If you don't supply the correct flags, you can get subtle defects ๐ญ But supplying them when they aren't needed is totally innocuous, so when in doubt, add them ๐ฆ
๐ฆ SEE ALSO ๐ฆ
the vibe check of related reads, all the way from the GNU side of things ๐
gpl(7),gfdl(7),fsf-funding(7),cpp(1),gcov(1),as(1),ld(1),gdb(1),dbx(1), and the Info entries forgcc,cpp,as,ld,binutilsandgdb๐โจ
๐ AUTHOR ๐
the people who built GCC are literally iconic ๐ฅ For the full list of contributors, check the Info entry for gcc, or head to <http://gcc.gnu.org/onlinedocs/gcc/Contributors.html> ๐ธ
๐ COPYRIGHT ๐
okay legal stuff but make it cute ๐ Copyright (c) 1988-2019 Free Software Foundation, Inc.
This document is free for you to copy, distribute, and/or modify under the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation ๐ The Invariant Sections are "GNU General Public License" and "Funding Free Software". The Front-Cover texts are the one in (a) below, and the Back-Cover Texts are the one in (b) below. A copy of the license is included in the gfdl(7) man page ๐ง
(a) The FSF's Front-Cover Text is:
A GNU Manual
(b) The FSF's Back-Cover Text is:
You have freedom to copy and modify this GNU Manual, like GNU
software. Copies published by the Free Software Foundation raise
funds for GNU development.
and that's a wrap on the GCC(1) page, bestie ๐ It's the GCC 9 era, last updated 2022-05-27, and honestly the whole thing is giving main character energy ๐ โจ mwah ๐ซถ๐
๐ฆ where this page comes from
- ubuntu noble: g++-9-mips64el-linux-gnuabi64 9.5.0-6ubuntu2cross1
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms