target-cpu key, so a build can use the instructions of the machine it runs onOpen and answer this issue on GitHub.
decision · opened 2026-10-18 · updated 2026-10-18 · 0 comments
A compiled program is machine code for a processor family: x86_64-linux code by default runs on every 64-bit x86 processor since 2003, so it may only use the instructions all of them have. Newer processors have wider vector instructions (AVX2, AVX-512 on x86; SVE on some ARM), popcnt, lzcnt, bmi2 and more. A compiler told the exact processor (“target-cpu”) may use them: a loop over bytes can handle 32 at a time instead of 16, a bit count is one instruction instead of a dozen.
[build.x86_64-linux]
opt-level = 3
target-cpu = "native" # proposed: use everything the build machine has
The owner asked for the website to say that Nikaia is fast and hardware-optimised (facec91 rewrote the lead). Today it can honestly say optimised native machine code, not tuned to your processor: no build sets a target-cpu. crates/nikaia/src/sysroot.rs (Codegen) already names target-cpu as “the obvious next” key of [build.<target>] and makes any such key a dimension of the compiled std’s cache key by construction (ADR-021 D13’s obligation).
[build.<target>] holds opt-level, lto, incremental, debug; a key it does not know fails the build. The table becomes the generated Cargo.toml’s profile.-C target-cpu is passed anywhere (nikaia build, the fast nikaia run path of 0.0.1016, or the compiled std). Every binary is baseline x86-64 / aarch64 (generic).benches/brc, crates/nikaia/tests/measure.rs) compare against Rust built the same way, so they are fair either way.target-cpu = "native" on a new machine and run on an older one dies with an illegal-instruction signal at the first unsupported instruction. No wrong value, but a crash with no message a user understands. This is the main argument against making native the default.std is compiled once per machine and cached (Part III 13.1); each distinct target-cpu is one more cached std (at most eight entries per kind are kept).native retires fewer, wider instructions. A table must say which CPU level it was counted at, or it compares unlike things.-C target-cpu=native / -march=native opt-in; named levels x86-64-v2, x86-64-v3 (AVX2), x86-64-v4 (AVX-512) for a portable-but-newer binary.GOAMD64=v1..v4, v1 by default.zig build defaults to native for a build for the host, baseline for a cross build.target_clones, Rust’s is_x86_feature_detected!): one binary with several variants of a hot function, chosen at start. A library technique, not a build key.A — a target-cpu key in [build.<target>], absent = baseline. Values as rustc spells them (native, x86-64-v3, neoverse-n1, …). Portable by default, opt-in speed; same as Rust, Go, C. nikaia build --target-cpu overrides it for one build, as --target does.
B — A, and absent = native for a build for the host machine (Zig’s choice), baseline for a cross build (--target differs from the host). The fastest program for someone who builds and runs on one machine, which is the script-like use the language aims at; a program copied to an older machine crashes.
C — A, and nikaia run uses native (it builds and runs on the same machine by definition, so it cannot hit the crash), while nikaia build stays baseline unless the key says otherwise.
benches/brc (1brc.nika against tuned.rs, both at the same level) at baseline, x86-64-v3 and native: instructions and mispredicts per row, the same output byte for byte.crates/nikaia/tests/measure.rs’s template and sparse-row workloads at baseline and x86-64-v3.std built with native differs per machine in a way the cache key must capture (it should key on the resolved CPU name, not the word native).C: it gives nikaia run the full machine with no risk, keeps a built binary portable like every ahead-of-time toolchain except Zig, and the key (A) lets a deployment that knows its machines opt in. B’s crash on another machine is a bad first experience for exactly the user the language invites.
target-cpu in [build.<target>], its values, absent = baseline for nikaia build, the machine’s own CPU for nikaia run; --target-cpu on build. ADR: a new record or a D of ADR-002/ADR-037, with the options above.sysroot::Codegen carries it; native is resolved to the CPU name (rustc --print target-cpus / -C target-cpu=native resolution) before it enters the cache key. Test: two builds with different values get two std entries; native on one machine reuses one entry.Cargo.toml / RUSTFLAGS path and the fast-run rustc line both pass -C target-cpu. Test: nikaia run of a probe whose lowered binary uses popcnt for count_ones on a machine that has it (check the disassembly), and a nikaia build binary without the key does not.benches/brc/README.md and measure.rs, each row naming its CPU level.nikaia run and for a build that asks for it.