Lists the ISA extensions the running CPU actually has, and the compiler flags that enable each one. x86-64 and AArch64.
$ cpuck
Intel(R) Xeon(R) Processor @ 2.80GHz
x86_64 GenuineIntel
family/model/stepping: 6 / 85 (0x55) / 7
xcr0: 0x00000000000000e7
feature support gcc/clang rustc description
AVX-512
avx512f yes -mavx512f +avx512f AVX-512 foundation
avx512dq yes -mavx512dq +avx512dq doubleword/quadword
avx512vnni yes -mavx512vnni +avx512vnni vector neural-net instructions
...
61 absent features not shown; run with --all to list them
Suggested flags
native -march=native
portable baseline -march=x86-64-v4
microarchitecture -march=cascadelake
OS state, not just CPUID. On x86 a CPUID bit does not mean you may emit the
instruction. AVX, AVX-512, AMX and APX keep architectural state the OS must
enable in XCR0; if it hasn't — a hypervisor masking AVX-512, an old kernel,
a noxsave boot arg — the instructions #UD regardless of what CPUID says.
Those features are reported as cpu-only and excluded from every flag list.
On AArch64 the equivalent is handled by reading AT_HWCAP, which the kernel
sets only when it can also support the state.
Flag spellings verified against your actual compiler. GCC 13 has no
-msha512 and has never heard of armv8.9-a; Clang 18 has no -mhle; GCC
rejects +jscvt, +fcma, +dit and +bti as -march modifiers because it
treats them as implied by the architecture level. A static table cannot be
right across compiler versions, so --cc asks:
$ cpuck --cc gcc --flags | xargs gcc -c foo.c # always compiles
$ cpuck --cc clang --flags
... Verified against `clang`: 39 of 40 feature flags accepted.
Not supported by this compiler: -mhle
The probe compiles an empty translation unit with -fsyntax-only. It tries
the whole set in one invocation and only bisects on failure, so the usual cost
is one process (~50 ms); a set with rejects costs O(k log n) (~300 ms). On
AArch64 the base -march= level is settled first and walked down until the
compiler recognises it, because otherwise every extension gets rejected for a
reason unrelated to the extension.
AArch64 base + extensions, not a guess. The architecture level is inferred
from the features each revision makes mandatory, giving a lower bound, and
every extension is then appended explicitly — so the result stays correct even
when the inferred level is conservative. Cores are identified from MIDR_EL1
across all of /sys/devices/system/cpu/*, so heterogeneous parts get GCC's
fused form:
big.LITTLE -mcpu=cortex-a73.cortex-a53+simd+aes+sha2+crc
cpuck grouped table of present features
cpuck --all include absent features
cpuck --flags CFLAGS for everything usable
cpuck --rustflags -C target-feature=+...
cpuck --march just the -march/-mcpu suggestions
cpuck --json machine-readable
cpuck --check avx512vnni exit 0 if present and usable
cpuck --cc gcc verify flags against a compiler
cpuck --cc clang --cc-arg --target=aarch64-linux-gnu
cpuck --hwcap 0x8ff --hwcap2 0x0 decode HWCAP captured on another machine
--check accepts kernel (asimddp), architectural (FEAT_DotProd) or rustc
(dotprod) spellings.
--hwcap is for cross-inspection: grab AT_HWCAP/AT_HWCAP2 off an embedded
board or a remote host and decode them anywhere, including on x86. The
decoding table and the level inference are architecture-independent code, so
they run and are unit-tested on any host.
Scriptable:
cpuck --check avx2 && make SIMD=avx2
export RUSTFLAGS="$(cpuck --rustflags)"
CFLAGS="$(cpuck --cc "${CC:-cc}" --flags)"| x86-64 | AArch64 | |
|---|---|---|
| features | CPUID leaves 1, 7:0, 7:1, 0xD:1, 0x8000_0001, 0x8000_0008 |
AT_HWCAP/AT_HWCAP2 from /proc/self/auxv; hw.optional.arm.FEAT_* sysctls on macOS |
| usability | XGETBV(0) → XCR0 |
implied by HWCAP |
| identity | vendor string, brand string, family/model/stepping | MIDR_EL1 via sysfs; machdep.cpu.brand_string on macOS |
| level | psABI x86-64-v1..v4 |
mandatory-feature inference, armv8.N-a / armv9.N-a |
/proc/self/auxv is read directly rather than calling getauxval, so there is
no glibc version floor and the binary works against musl unchanged.
The family/model → -march=znver5-style microarchitecture name is best effort;
it returns nothing rather than guessing, since -march=native and the psABI
level are always offered as well. The AArch64 macOS backend covers fewer
features than Linux because Apple exposes fewer sysctls than the kernel exposes
HWCAP bits — absent entries there may simply be unqueryable.
Windows on ARM is not supported (no auxv, no sysctl); --hwcap still works for
decoding values from elsewhere.
cargo build --release
cargo test
Copyright © 2026 Necessary Innovations AB
Licensed under the EUPL, version 1.2. See LICENSE.