gcc(1)

CLI

  • -v verbose, outputs exact compiler/linker invocations made by the gcc driver
  • -### dry-run, outputting exact compiler/linker invocations
  • -print-multi-lib print available multilib configurations
  • --help=<class> print description of cmdline options for given class, eg warnings, optimizers, target, c, c++
  • -Wl,<opt> additional option passed to the linker invocation (can be specified multiple times)
  • -Wl,--trace trace each file the linker touches

Preprocessing

While debugging can be helpful to just pre-process files.

gcc -E [-dM] ...
  • -E run only preprocessor
  • -dM list only #define statements

Target options

# List all target options with their description.
gcc --help=target

# Configure for current cpu arch and query (-Q) value of options.
gcc -march=native -Q --help=target

Warnings / optimizations

# List available warnings with short description.
gcc --help=warnings
# List available optimizations with short description.
gcc --help=optimizers

# Prepend --help with `-Q` to print wheter options are enabled or disabled
# instead showing their description.

Sanitizer

# Enable address sanitizer, a memory error checker (out of bounds, use after free, ..).
gcc -fsanitize=address ...

# Enable leak sanitizer, a memory leak detector.
gcc -fsanitize=leak

# Enable undefined behavior sanitizer, detects various UBs (integer overflow, ..).
gcc -fsanitize=undefined ...

# Enable thread sanitizer, a data race detector.
gcc -fsanitize=thread

Builtins

__builtin_expect(expr, cond)

Give the compiler a hint which branch is hot, so it can lay out the code accordingly to reduce number of jump instructions. See on compiler explorer.

The semantics of this hint are as follows, the compiler prioritises expr == cond. So __builtin_expect(expr, 0) means that we expect the expr to be 0 most of the time.

echo "
extern void foo();
extern void bar();
void run0(int x) {
  if (__builtin_expect(x,0)) { foo(); }
  else { bar(); }
}
void run1(int x) {
  if (__builtin_expect(x,1)) { foo(); }
  else { bar(); }
}
" | gcc -O2 -S -masm=intel -o /dev/stdout -xc -

Will generate something similar to the following.

  • run0: bar is on the path without branch
  • run1: foo is on the path without branch
run0:
        test    edi, edi
        jne     .L4
        xor     eax, eax
        jmp     bar
.L4:
        xor     eax, eax
        jmp     foo
run1:
        test    edi, edi
        je      .L6
        xor     eax, eax
        jmp     foo
.L6:
        xor     eax, eax
        jmp     bar

ABI (Linux)