Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

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