On this page
GCC and Clang Internals
Coverage: Compilation Pipeline (frontend/middle-end/backend) → IR (GIMPLE/LLVM IR) → LTO → PGO → Sanitizers → Compiler Optimization Overview Applicable to: GCC 12+, Clang 15+, User-space compilation
Compilation Pipeline
flowchart TD
SRC["📄 C Source Code"]
SRC --> FRONTEND["🔍 Frontend (Language-specific)<br/>Preprocessing + Lexical Analysis + Syntax Analysis + Semantic Analysis"]
FRONTEND --> AST["🌳 Abstract Syntax Tree (AST)"]
AST --> MIDDLE["⚙️ Middle-end (Language-independent, Architecture-independent)<br/>GIMPLE (GCC) or LLVM IR (Clang)<br/>→ Optimization Passes: Dead Code Elimination, Loop Optimization, Vectorization, ..."]
MIDDLE --> BACKEND["🔧 Backend (Architecture-specific)<br/>Register Allocation + Instruction Selection + Instruction Scheduling"]
BACKEND --> ASM["📝 Target Assembly (.s)"]
ASM --> ASSEMBLER["🔗 Assembler"]
ASSEMBLER --> OBJ["📦 Object File (.o)"]
classDef src fill:#e3f2fd,stroke:#1565c0
classDef step fill:#f3e5f5,stroke:#7b1fa2
classDef ir fill:#fff3e0,stroke:#ef6c00
classDef out fill:#e8f5e9,stroke:#2e7d32
class SRC,OBJ src
class FRONTEND,BACKEND,ASSEMBLER step
class MIDDLE ir
class AST,ASM out
GCC GIMPLE vs LLVM IR
GCC GIMPLE (GNU Compiler Collection):
3-address code form → ~200 optimization passes
Format: Function → basic blocks → GIMPLE statements
Use -fdump-tree-all to observe output from each optimization pass
LLVM IR (Clang):
SSA form → closer to high-level languages
-emit-llvm → outputs .ll text → human-readable
opt → standalone optimizer tool (independent of clang)
llc → standalone code generator
LTO: Link-Time Optimization
# GCC LTO:
# Thin LTO (Clang, faster incremental LTO):
# Typical benefits of LTO:
# - Inlining of small functions across files (cost model can see thousands of functions)
# - Dead code elimination (analyzes the entire program → removes un-called functions)
# - Constant propagation (tracks constants across files)
# Binary size: ↓5-15%, Performance: ↑2-5%
PGO: Profile-Guided Optimization
# 1. Instrument:
# 2. Recompile (using profile to guide):
# Typical benefits of PGO:
# - Branch prediction optimization (rearranging code on hot paths)
# - More accurate inlining decisions (frequently called functions → inlined)
# - Better register allocation (hot variables get higher priority)
# Performance: ↑5-15%
Sanitizers: Runtime Error Detection
# Address Sanitizer (ASAN): heap out-of-bounds, UAF, stack overflow
# Undefined Behavior Sanitizer (UBSAN):
# Detects: integer overflow, shift out of bounds, null dereference, type alignment
# Thread Sanitizer (TSAN): data races
# Memory Sanitizer (MSAN): uninitialized reads (Clang only)
# Overhead:
# ASAN: ~2x slower, ~2x memory usage
# TSAN: ~5-10x slower, ~5-10x memory usage
# UBSAN: ~1.2x slower (lightest weight, production-safe)
Common Optimization Flags
# Specific optimizations:
-march=native # Optimize for the local CPU (uses AVX2/BMI/...)
Analyzing Compilation Artifacts
# Observe optimization results:
|
# Binary analysis:
| |
References
- Documentation: GCC Internals Manual, LLVM Language Reference
- LWN: "LTO and PGO", "Sanitizers in GCC and Clang"
Keywords: GCC, Clang, GIMPLE, LLVM IR, LTO, ThinLTO, PGO, ASAN, UBSAN, TSAN, optimization flags