CodeBlanks Logo Icon CodeBlanks

CPUID

Invoke special instructions like CPUID.

CPUID

x86's cpuid instruction gives information about the processor: the vendor name, supported instruction sets (SSE, AVX, AVX-512...). A "leaf" number is written to eax, and the result comes back in eax, ebx, ecx, edx. Instead of hand-written assembly, the standard library offers ready tools:

use std::arch::x86_64::__cpuid;

let r = unsafe { __cpuid(0) };      // leaf 0: vendor
// r.ebx, r.edx, r.ecx → "GenuineIntel" or "AuthenticAMD"

if is_x86_feature_detected!("avx2") {
    // the AVX2 path
}

is_x86_feature_detected! caches the result; it's ideal for picking the best implementation at runtime.

Runtime selection

Several versions of the same function are written for different instruction sets and the best one is chosen at runtime:

fn toplam(v: &[f32]) -> f32 {
    #[cfg(target_arch = "x86_64")]
    if is_x86_feature_detected!("avx2") {
        return unsafe { toplam_avx2(v) };
    }
    v.iter().sum()
}

#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "avx2")]
unsafe fn toplam_avx2(v: &[f32]) -> f32 { v.iter().sum() }

#[target_feature] recompiles the function with AVX2 enabled; the compiler can use wide vectors in it.

Practice Processor features

On x86-64, print the results of __cpuid(0).eax > 0 (the highest supported leaf) and is_x86_feature_detected!("sse2") separated by a space; on other architectures print true true. (Every x86-64 processor has SSE2.)

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
#[cfg(target_arch = "x86_64")]
fn islemci_bilgisi() -> (bool, bool) {
    // SAFETY: cpuid her x86-64 işlemcide vardır.
    let r = unsafe { std::arch::x86_64::__cpuid(0) };
    (r.eax > 0, is_x86_feature_detected!("sse2"))
}

#[cfg(not(target_arch = "x86_64"))]
fn islemci_bilgisi() -> (bool, bool) {
    (true, true)
}

fn main() {
    let (a, b) = islemci_bilgisi();
    println!("{} {}", a, b);
}

Expected output

true true

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Why is writing <code>cpuid</code> by hand with <code>asm!</code> tricky?

  • It's very slow
  • It isn't tricky
  • LLVM reserves rbx, so it can't be an operand; it must be saved and restored Correct answer
  • cpuid doesn't exist

Explanation: std::arch::__cpuid handles this detail correctly; in most cases intrinsics are safer than raw assembly.

2 Feature check

Question
if ____!("avx2") {
    // AVX2'li yol
}
Answer
if is_x86_feature_detected!("avx2") {
    // AVX2'li yol
}

Explanation: is_x86_feature_detected! checks at runtime whether the processor supports the feature.

3 Tool and timing

Term Meaning
#[cfg(target_feature)] Compile time
is_x86_feature_detected! Runtime
__cpuid(0) Vendor info
#[target_feature(enable)] Per-function feature

All lessons in Expert