1# cpu_features 2 3A cross-platform C library to retrieve CPU features (such as available 4instructions) at runtime. 5 6# GitHub-CI Status 7 8[comment]: <> (The following lines are generated by "scripts/generate_badges.d" that you can run online https://run.dlang.io/) 9 10| | Linux | FreeBSD | MacOS | Windows | 11| :-- | --: | --: | --: | --: | 12| amd64 | [![CMake][i1a0]][l1a0]<br/>[![Bazel][i1a1]][l1a1] | [![CMake][i2a0]][l2a0]<br/>![Bazel][d1] | [![CMake][i3a0]][l3a0]<br/>[![Bazel][i3a1]][l3a1] | [![CMake][i4a0]][l4a0]<br/>![Bazel][d1] | 13| AArch64 | [![CMake][i1b0]][l1b0]<br/>[![Bazel][i1b1]][l1b1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | 14| ARM | [![CMake][i1c0]][l1c0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | 15| MIPS | [![CMake][i1d0]][l1d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | 16| POWER | [![CMake][i1e0]][l1e0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | 17| RISCV | [![CMake][i1f0]][l1f0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | 18| LOONGARCH | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | 19| s390x | [![CMake][i1h0]][l1h0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | 20 21[d0]: https://img.shields.io/badge/n%2Fa-lightgrey?&logo=cmake 22[d1]: https://img.shields.io/badge/n%2Fa-lightgrey?&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4= 23[i1a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_cmake.yml?branch=main&event=push&label=&logo=cmake 24[i1a1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4= 25[i1b0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/aarch64_linux_cmake.yml?branch=main&event=push&label=&logo=cmake 26[i1b1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/aarch64_linux_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4= 27[i1c0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/arm_linux_cmake.yml?branch=main&event=push&label=&logo=cmake 28[i1d0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/mips_linux_cmake.yml?branch=main&event=push&label=&logo=cmake 29[i1e0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/power_linux_cmake.yml?branch=main&event=push&label=&logo=cmake 30[i1f0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/riscv_linux_cmake.yml?branch=main&event=push&label=&logo=cmake 31[i1h0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/s390x_linux_cmake.yml?branch=main&event=push&label=&logo=cmake 32[i2a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_freebsd_cmake.yml?branch=main&event=push&label=&logo=cmake 33[i3a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_macos_cmake.yml?branch=main&event=push&label=&logo=cmake 34[i3a1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_macos_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4= 35[i4a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_windows_cmake.yml?branch=main&event=push&label=&logo=cmake 36[l1a0]: https://github.com/google/cpu_features/actions/workflows/amd64_linux_cmake.yml 37[l1a1]: https://github.com/google/cpu_features/actions/workflows/amd64_linux_bazel.yml 38[l1b0]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux_cmake.yml 39[l1b1]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux_bazel.yml 40[l1c0]: https://github.com/google/cpu_features/actions/workflows/arm_linux_cmake.yml 41[l1d0]: https://github.com/google/cpu_features/actions/workflows/mips_linux_cmake.yml 42[l1e0]: https://github.com/google/cpu_features/actions/workflows/power_linux_cmake.yml 43[l1f0]: https://github.com/google/cpu_features/actions/workflows/riscv_linux_cmake.yml 44[l1h0]: https://github.com/google/cpu_features/actions/workflows/s390x_linux_cmake.yml 45[l2a0]: https://github.com/google/cpu_features/actions/workflows/amd64_freebsd_cmake.yml 46[l3a0]: https://github.com/google/cpu_features/actions/workflows/amd64_macos_cmake.yml 47[l3a1]: https://github.com/google/cpu_features/actions/workflows/amd64_macos_bazel.yml 48[l4a0]: https://github.com/google/cpu_features/actions/workflows/amd64_windows_cmake.yml 49 50## Table of Contents 51 52- [Design Rationale](#rationale) 53- [Code samples](#codesample) 54- [Running sample code](#usagesample) 55- [What's supported](#support) 56- [Android NDK's drop in replacement](#ndk) 57- [License](#license) 58- [Build with cmake](#cmake) 59- [Community Bindings](#bindings) 60 61<a name="rationale"></a> 62## Design Rationale 63 64- **Simple to use.** See the snippets below for examples. 65- **Extensible.** Easy to add missing features or architectures. 66- **Compatible with old compilers** and available on many architectures so it 67 can be used widely. To ensure that cpu_features works on as many platforms 68 as possible, we implemented it in a highly portable version of C: C99. 69- **Sandbox-compatible.** The library uses a variety of strategies to cope 70 with sandboxed environments or when `cpuid` is unavailable. This is useful 71 when running integration tests in hermetic environments. 72- **Thread safe, no memory allocation, and raises no exceptions.** 73 cpu_features is suitable for implementing fundamental libc functions like 74 `malloc`, `memcpy`, and `memcmp`. 75- **Unit tested.** 76 77<a name="codesample"></a> 78## Code samples 79 80**Note:** For C++ code, the library functions are defined in the `cpu_features` namespace. 81 82### Checking features at runtime 83 84Here's a simple example that executes a codepath if the CPU supports both the 85AES and the SSE4.2 instruction sets: 86 87```c 88#include "cpuinfo_x86.h" 89 90// For C++, add `using namespace cpu_features;` 91static const X86Features features = GetX86Info().features; 92 93void Compute(void) { 94 if (features.aes && features.sse4_2) { 95 // Run optimized code. 96 } else { 97 // Run standard code. 98 } 99} 100``` 101 102### Caching for faster evaluation of complex checks 103 104If you wish, you can read all the features at once into a global variable, and 105then query for the specific features you care about. Below, we store all the ARM 106features and then check whether AES and NEON are supported. 107 108```c 109#include <stdbool.h> 110#include "cpuinfo_arm.h" 111 112// For C++, add `using namespace cpu_features;` 113static const ArmFeatures features = GetArmInfo().features; 114static const bool has_aes_and_neon = features.aes && features.neon; 115 116// use has_aes_and_neon. 117``` 118 119This is a good approach to take if you're checking for combinations of features 120when using a compiler that is slow to extract individual bits from bit-packed 121structures. 122 123### Checking compile time flags 124 125The following code determines whether the compiler was told to use the AVX 126instruction set (e.g., `g++ -mavx`) and sets `has_avx` accordingly. 127 128```c 129#include <stdbool.h> 130#include "cpuinfo_x86.h" 131 132// For C++, add `using namespace cpu_features;` 133static const X86Features features = GetX86Info().features; 134static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx; 135 136// use has_avx. 137``` 138 139`CPU_FEATURES_COMPILED_X86_AVX` is set to 1 if the compiler was instructed to 140use AVX and 0 otherwise, combining compile time and runtime knowledge. 141 142### Rejecting poor hardware implementations based on microarchitecture 143 144On x86, the first incarnation of a feature in a microarchitecture might not be 145the most efficient (e.g. AVX on Sandy Bridge). We provide a function to retrieve 146the underlying microarchitecture so you can decide whether to use it. 147 148Below, `has_fast_avx` is set to 1 if the CPU supports the AVX instruction 149set—but only if it's not Sandy Bridge. 150 151```c 152#include <stdbool.h> 153#include "cpuinfo_x86.h" 154 155// For C++, add `using namespace cpu_features;` 156static const X86Info info = GetX86Info(); 157static const X86Microarchitecture uarch = GetX86Microarchitecture(&info); 158static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB; 159 160// use has_fast_avx. 161``` 162 163This feature is currently available only for x86 microarchitectures. 164 165<a name="usagesample"></a> 166### Running sample code 167 168Building `cpu_features` (check [quickstart](#quickstart) below) brings a small executable to test the library. 169 170```shell 171 % ./build/list_cpu_features 172arch : x86 173brand : Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz 174family : 6 (0x06) 175model : 45 (0x2D) 176stepping : 7 (0x07) 177uarch : INTEL_SNB 178flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3 179``` 180 181```shell 182% ./build/list_cpu_features --json 183{"arch":"x86","brand":" Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz","family":6,"model":45,"stepping":7,"uarch":"INTEL_SNB","flags":["aes","avx","cx16","smx","sse4_1","sse4_2","ssse3"]} 184``` 185 186<a name="support"></a> 187## What's supported 188 189| | x86³ | AArch64 | ARM | MIPS⁴ | POWER | RISCV | Loongarch | s390x | 190|---------|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|:---------:|:-------:| 191| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | 192| FreeBSD | yes² | not yet | not yet | not yet | not yet | N/A | not yet | not yet | 193| MacOs | yes² | yes⁵ | N/A | N/A | N/A | N/A | N/A | N/A | 194| Windows | yes² | not yet | not yet | N/A | N/A | N/A | N/A | N/A | 195| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A | N/A | N/A | 196| iOS | N/A | not yet | not yet | N/A | N/A | N/A | N/A | N/A | 197 1981. **Features revealed from Linux.** We gather data from several sources 199 depending on availability: 200 + from glibc's 201 [getauxval](https://www.gnu.org/software/libc/manual/html_node/Auxiliary-Vector.html) 202 + by parsing `/proc/self/auxv` 203 + by parsing `/proc/cpuinfo` 2042. **Features revealed from CPU.** features are retrieved by using the `cpuid` 205 instruction. 2063. **Microarchitecture detection.** On x86 some features are not always 207 implemented efficiently in hardware (e.g. AVX on Sandybridge). Exposing the 208 microarchitecture allows the client to reject particular microarchitectures. 2094. All flavors of Mips are supported, little and big endian as well as 32/64 210 bits. 2115. **Features revealed from sysctl.** features are retrieved by the `sysctl` 212 instruction. 213 214<a name="ndk"></a> 215## Android NDK's drop in replacement 216 217[cpu_features](https://github.com/google/cpu_features) is now officially 218supporting Android and offers a drop in replacement of for the NDK's [cpu-features.h](https://android.googlesource.com/platform/ndk/+/main/sources/android/cpufeatures/cpu-features.h) 219, see [ndk_compat](ndk_compat) folder for details. 220 221<a name="license"></a> 222## License 223 224The cpu_features library is licensed under the terms of the Apache license. 225See [LICENSE](LICENSE) for more information. 226 227<a name="cmake"></a> 228## Build with CMake 229 230Please check the [CMake build instructions](cmake/README.md). 231 232<a name="quickstart"></a> 233### Quickstart 234 235- Run `list_cpu_features` 236 ```sh 237 cmake -S. -Bbuild -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release 238 cmake --build build --config Release -j 239 ./build/list_cpu_features --json 240 ``` 241 242 _Note_: Use `--target ALL_BUILD` on the second line for `Visual Studio` and `XCode`. 243 244- run tests 245 ```sh 246 cmake -S. -Bbuild -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug 247 cmake --build build --config Debug -j 248 cmake --build build --config Debug --target test 249 ``` 250 251 _Note_: Use `--target RUN_TESTS` on the last line for `Visual Studio` and `--target RUN_TEST` for `XCode`. 252 253 254- install `cpu_features` 255 ```sh 256 cmake --build build --config Release --target install -v 257 ``` 258 259 _Note_: Use `--target INSTALL` for `Visual Studio`. 260 261 _Note_: When using `Makefile` or `XCode` generator, you can use 262 [`DESTDIR`](https://www.gnu.org/software/make/manual/html_node/DESTDIR.html) 263 to install on a local repository.<br> 264 e.g. 265 ```sh 266 cmake --build build --config Release --target install -v -- DESTDIR=install 267 ``` 268 269<a name="bindings"></a> 270## Community bindings 271 272Links provided here are not affiliated with Google but are kindly provided by the OSS Community. 273 274 - .Net 275 - https://github.com/toor1245/cpu_features.NET 276 - Python 277 - https://github.com/Narasimha1997/py_cpu 278 - Java 279 - https://github.com/aecsocket/cpu-features-java 280 281 282_Send PR to showcase your wrapper here_ 283