Low-Level Systems Programming

CPU Architecture Awareness

CPU architecture awareness allows systems programs to take advantage of hardware-specific SIMD vector units, bit-manipulation instructions, cryptographic accelerators, and inline assembly (core::arch) while maintaining a portable scalar fallback so the same crate compiles and runs cleanly on x86_64, aarch64, riscv64, and wasm32.

Architecture-Aware Dispatch in Rust:

  1. Portable Bit Intrinsics (`u64::count_ones`, `leading_zeros`, `rotate_left`)
     ---> Automatically lowers to `popcnt` / `lzcnt` / `rbit` on target CPU!

  2. Compile-Time Selection (`#[cfg(target_arch = "...")]` + `#[target_feature]`)
     ---> Specialized path selected when compiled with `-C target-cpu=native`

  3. Runtime CPU Feature Detection (`std::arch::is_x86_feature_detected!("avx2")`)
     ---> Queries CPUID / OS auxiliary vector at runtime and dispatches dynamically!

1. Portable Hardware Intrinsics on Primitive Integers

Before reaching for architecture-specific core::arch modules, note that Rust's primitive integer types (u8..u128, usize) expose methods that compile directly into single-cycle CPU instructions when available:

Rust Integer Method x86_64 Instruction aarch64 (ARM64) Instruction Purpose
x.count_ones() popcnt cnt + addv Counts set 1 bits (Hamming weight).
x.leading_zeros() lzcnt / bsr clz Counts leading 0 bits from MSB (used for fast $\lfloor\log_2(x)\rfloor$).
x.trailing_zeros() tzcnt / bsf rbit + clz Counts trailing 0 bits from LSB (fast bitset iteration).
x.swap_bytes() bswap rev Reverses byte order (endianness conversion).
x.reverse_bits() Bitwise mask sequence rbit Reverses bit order within the integer.
x.rotate_left(k) rol ror Circular bit rotation (cryptographic hashes/ciphers).

2. Compile-Time vs Runtime CPU Feature Dispatch (core::arch)

When writing SIMD or hardware-accelerated routines using core::arch::x86_64 or core::arch::aarch64, you can combine #[target_feature(enable = "...")] with runtime feature detection macros (is_x86_feature_detected! or std::arch::is_aarch64_feature_detected!) so binaries built for baseline targets still use hardware acceleration on modern CPUs:

pub fn dot_product_u32(a: &[u32], b: &[u32]) -> u64 {
    assert_eq!(a.len(), b.len());

    #[cfg(target_arch = "x86_64")]
    {
        if std::arch::is_x86_feature_detected!("avx2") {
            // SAFETY: Verified `avx2` is supported on the current CPU at runtime.
            return unsafe { dot_product_avx2_enabled(a, b) };
        }
    }

    #[cfg(target_arch = "aarch64")]
    {
        if std::arch::is_aarch64_feature_detected!("neon") {
            // SAFETY: Verified `neon` is supported on the current ARM64 CPU.
            return unsafe { dot_product_neon_enabled(a, b) };
        }
    }

    dot_product_scalar(a, b)
}

#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "avx2")]
unsafe fn dot_product_avx2_enabled(a: &[u32], b: &[u32]) -> u64 {
    // Compiled by LLVM with AVX2 vectorization enabled specifically for this function!
    dot_product_scalar(a, b)
}

#[cfg(target_arch = "aarch64")]
#[target_feature(enable = "neon")]
unsafe fn dot_product_neon_enabled(a: &[u32], b: &[u32]) -> u64 {
    // Compiled by LLVM with ARMv8 NEON vectorization enabled!
    dot_product_scalar(a, b)
}

fn dot_product_scalar(a: &[u32], b: &[u32]) -> u64 {
    a.iter()
        .zip(b.iter())
        .map(|(&x, &y)| u64::from(x) * u64::from(y))
        .sum()
}

fn main() {
    let left = [10u32, 20, 30, 40];
    let right = [2u32, 3, 4, 5];

    let total = dot_product_u32(&left, &right);
    assert_eq!(total, 20 + 60 + 120 + 200);
    println!(
        "Dot product on {} = {total} (popcnt={})",
        std::env::consts::ARCH,
        total.count_ones()
    );
}
Dot product on aarch64 = 400 (popcnt=3)

3. Inline Assembly (core::arch::asm!)

For low-level OS kernels, bootloaders, or reading CPU control/cycle registers (rdtsc on x86_64, cntvct_el0 on ARM64), Rust provides stable inline assembly via core::arch::asm! with explicit register constraints and clobber tracking.