Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cpuck

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

The three things it gets right

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

Usage

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)"

Where the data comes from

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.

Caveats

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.

Build

cargo build --release
cargo test

Licence

Copyright © 2026 Necessary Innovations AB

Licensed under the EUPL, version 1.2. See LICENSE.

About

List the ISA extensions of the running CPU and the compiler flags that enable them

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages