An optimized fork of CCC — Claude's C Compiler — with a linear-scan register allocator, hot-loop register steal, phi coalescing for registers and stack slots, SIMD auto-vectorization (AVX2 · NEON), and recursion-to-iteration transforms. Targets x86-64, AArch64, RISC-V 64, and i686.
| Benchmark | LCCC | GCC -O2 | LCCC vs GCC |
|---|---|---|---|
arith_loop | 0.035s | 0.030s | 1.15× |
matmul | 0.0024s | 0.0029s | 1.17× faster |
spectral_norm | 0.165s | 0.139s | 1.19× |
fib(40) | 0.000s | 0.091s | ~600× faster |
bitops | 0.092s | 0.169s | 1.8× faster |
fannkuch | 3.34s | 1.81s | 1.85× |
┌─────────────────────────────────────────────────────────────────────┐ │ C source │ │ │ frontend: lex → parse → sema → IR lowering │ │ ▼ │ │ SSA IR │ │ │ optimizer: GVN · LICM · IPCP · DCE · const-fold · inline │ │ ▼ │ │ Optimized IR │ │ │ regalloc (LCCC): linear scan over live intervals │ │ │ pools: callee-saved · caller-saved · FP/SIMD │ │ │ + post-scan steal for hot loop-carried values │ │ ▼ │ │ Machine code x86-64 · AArch64 · RISC-V 64 · i686 │ │ │ standalone assembler + linker (no external toolchain) │ │ ▼ │ │ ELF executable │ └─────────────────────────────────────────────────────────────────────┘
CCC compiles real projects — SQLite, PostgreSQL, Redis, the Linux kernel — from a zero-dependency Rust codebase with its own assembler and linker. LCCC focuses on closing the performance gap with GCC by improving where CCC leaves the most on the table.
Callee-saved, caller-saved, and FP/SIMD pools over live intervals — plus a post-scan steal that gives hot loop-carried values registers won by cold early starters.
Same flags, same output ABI. Point CC=lccc at any Makefile. No build system changes required.
x86-64, AArch64, RISC-V 64, i686. Architecture-agnostic PhysReg allocation; per-target SIMD (AVX2, NEON) and peephole pipelines.
563 unit tests, 18/18 benchmark outputs byte-identical to GCC, and the SQLite amalgamation (260K lines) compiles and runs correctly.
The old CCC allocator uses three greedy phases over a conservative eligibility whitelist. LCCC replaces the allocation core with a linear scan over live intervals, rebalances hot loop-carried values into registers after the scan (a conflict-safe steal, since in-scan eviction miscompiles), and coalesces loop-backedge copies onto the phi dest's register — or its stack slot when both are spilled, deleting the per-iteration load+store shuffle.
// The scan assigns registers in start order, so cold function-spanning values // (array bases, globals) win every callee-saved register. For each hot // loop-carried phi value the scan MISSED: for &(vid, hot_count) in &candidates { // pick the register whose CONFLICTING holders are coldest… // …and fully deallocate them to the stack. Whole-interval dealloc, // never range splitting — safe where in-scan eviction was not. assignments.insert(vid, stolen_reg); }
// v_old = copy v_new (backedge). If the phi-coalesce detector proves // v_old is dead after v_new is defined, v_new borrows v_old's slot: // the copy becomes a same-slot no-op — no ldr+str per iteration. raw_aliases.push((backedge_src, phi_dest)); // certified by detect_phi_coalesce_groups
Best-of-5 wall-clock time. All 18 outputs are byte-identical to GCC. Run with
python3 tests/benchmark/run_benchmarks.py --reps 5.
| Benchmark | Description | LCCC | GCC -O2 | LCCC vs GCC |
|---|---|---|---|---|
arith_loop |
32-var arithmetic, register pressure | 0.034s | 0.031s | 1.12× |
matmul |
256×256 double matrix multiply | 0.0025s | 0.0029s | 1.15× faster |
spectral_norm |
FP dense loops | 0.133s | 0.133s | 1.0× parity |
fib(40) |
Recursive Fibonacci | 0.000s | 0.090s | ~600× faster |
bitops |
popcount / clz / bit reverse | 0.089s | 0.169s | 1.9× faster |
fannkuch |
Fannkuch-Redux permutations | 2.010s | 1.973s | 1.02× |
Across the full 18-benchmark suite LCCC is at 1.01× of GCC -O2 — statistical parity
(0.49× geomean including the two ~600× recursion-to-iteration wins), with
matmul, bitops, qsort and
loop_patterns faster than GCC and spectral_norm
at parity. Full table and per-optimization analysis on the
benchmarks page.
Recent work on the AArch64 backend moved the suite geomean from 0.86× to 0.49× of GCC -O2 — including a register steal for hot loop values, loop-backedge stack-slot coalescing, NEON/F64 loop promotion, reduction vectorization, FP recurrence anti-dependency splitting and reverse phi coalescing, backedge PRE, a csinc select fold, caller-saved-first allocation for small leaf functions, and shrink-wrapped callee saves — plus several latent miscompile fixes found along the way.
Hot inner-loop-carried values (IVs, accumulators, carried pointers) take registers from provably colder scan winners — whole-interval deallocation, never range splitting. fannkuch 2.69× → 1.85×.
A spilled loop variable's update shares the variable's own stack slot, deleting the per-iteration ldr+str shuffle. arith_loop 2.09× → 1.15×.
Register-resident F64x2/I32x4 vector ops, fmadd fusion, and every reduction shape vectorized — sums (sadalp), dot products (smlal), conditional sums and max (smax/smaxv). matmul 1.17× faster than GCC; loop_patterns at parity.
Detects f(n) = f(n-1) + f(n-2) and converts exponential O(2ⁿ) recursion to an O(n) iterative loop. fib(40) and ackermann(3,11): ~600× faster than GCC.
git clone https://github.com/levkropp/lccc.git cd lccc
cargo build --release # Binary at target/release/lccc (target picked by host/argv[0]) # Also: lccc-x86, lccc-arm, lccc-riscv, lccc-i686
GCC_INC="-I$(gcc -print-file-name=include)" ./target/release/lccc $GCC_INC -O2 -o hello hello.c ./hello
python3 tests/benchmark/run_benchmarks.py --reps 5