Skip to content

[API Proposal]: Add X86 and ARM hardware intrinsics for RDRAND/RDSEED/RNDR/RNDRRS and AMX/SME/APX #131694

Description

@ahmetenesay

Background and motivation

We propose adding explicit low-level hardware intrinsics for high-performance CPU extensions that are currently missing from System.Runtime.Intrinsics.X86 and System.Runtime.Intrinsics.Arm.

This proposal targets three major CPU instruction domains:

  1. Hardware Entropy / True Random Generation (RDRAND/RDSEED on x86, RNDR/RNDRRS on ARMv8.5-A FEAT_RNG):
    Currently, .NET developers requiring hardware entropy must fallback to RandomNumberGenerator (P/Invoke to BCryptGenRandom or getrandom), which introduces unacceptable syscall and interop overhead in tight simulation loops (e.g., ray tracing, Monte Carlo simulations, or game engine procedural generation). Exposing direct processor hardware entropy registers allows sub-nanosecond random UInt64 generation with zero allocation.

  2. Hardware Matrix Acceleration (AMX on Intel/AMD, SME/SME2 on ARMv9-A):
    Modern high-performance compute workloads (on-device AI inference, 3D skeletal skinning, pathfinding, and physics) rely heavily on matrix multiplication ($A \times B + C$). While vector extensions (AVX-512, AVX10, SVE) process 1D vectors, AMX (x86 Tile registers) and SME (ARM Tile matrices) operate directly on 2D matrix tiles in hardware. Exposing these intrinsics gives C# game engines and native ML runtimes equal footing with C++/CUDA pipelines without native DllImport overhead.

  3. Explicit APX API Exposure (Apx.IsSupported):
    While .NET 10 introduced implicit JIT codegen support for Intel APX, exposing an explicit intrinsic class allows low-level developers to query support (Apx.IsSupported) and perform conditional branching for high-performance data structures.

API Proposal

namespace System.Runtime.Intrinsics.X86
{
// ==========================================
// 1. Hardware Random Number Generation (x86)
// ==========================================
public abstract class Rdrand : X86Base
{
public static new bool IsSupported { get; }

    /// <summary>
    /// Executes the RDRAND instruction to retrieve a hardware-generated random 16-bit value.
    /// Returns false if hardware entropy pool was not ready (CF = 0).
    /// </summary>
    public static bool TryGetUInt16(out ushort result);

    /// <summary>
    /// Executes the RDRAND instruction to retrieve a hardware-generated random 32-bit value.
    /// </summary>
    public static bool TryGetUInt32(out uint result);

    /// <summary>
    /// Executes the RDRAND instruction to retrieve a hardware-generated random 64-bit value.
    /// </summary>
    public static bool TryGetUInt64(out ulong result);
}

public abstract class Rdseed : X86Base
{
    public static new bool IsSupported { get; }

    public static bool TryGetUInt16(out ushort result);
    public static bool TryGetUInt32(out uint result);
    public static bool TryGetUInt64(out ulong result);
}

// ==========================================
// 2. Advanced Matrix Extensions (AMX)
// ==========================================
public abstract class Amx : X86Base
{
    public static new bool IsSupported { get; }

    // Tile Configuration & Control
    public static void TileConfig(ReadOnlySpan<byte> tilecfg);
    public static void TileRelease();

    // Tile Matrix Operations
    public static void MultiplyAndAddBF16(byte dstTile, byte src1Tile, byte src2Tile);
    public static void MultiplyAndAddInt8(byte dstTile, byte src1Tile, byte src2Tile);

    // Tile Load & Store
    public static unsafe void TileLoad(byte tile, void* baseAddress, nint stride);
    public static unsafe void TileStore(byte tile, void* baseAddress, nint stride);
}

// ==========================================
// 3. Advanced Performance Extensions (APX)
// ==========================================
public abstract class Apx : X86Base
{
    /// <summary>
    /// Indicates whether Intel APX (Extended GPRs r16-r31, NDD 3-operand instructions) is supported.
    /// </summary>
    public static new bool IsSupported { get; }
}

}

namespace System.Runtime.Intrinsics.Arm
{
// ==========================================
// 1. Hardware Random Number Generation (ARMv8.5-A FEAT_RNG)
// ==========================================
public abstract class Rng : ArmBase
{
public static new bool IsSupported { get; }

    /// <summary>
    /// Executes 'MRS xt, RNDR' to read true hardware random number.
    /// Returns false if hardware entropy pool was underflowed.
    /// </summary>
    public static bool TryGetUInt64(out ulong result);

    /// <summary>
    /// Executes 'MRS xt, RNDRRS' to read reseeded hardware random entropy source.
    /// </summary>
    public static bool TryGetEntropyUInt64(out ulong result);
}

// ==========================================
// 2. Scalable Matrix Extension (SME / SME2 - ARMv9-A)
// ==========================================
public abstract class Sme : ArmBase
{
    public static new bool IsSupported { get; }

    // Streaming Mode Controls
    public static void EnterStreamingMode();
    public static void ExitStreamingMode();

    // Matrix Tile Operations (Outer Product & Accumulate)
    public static void OuterProductAccumulate(byte tile, Vector128<float> vector1, Vector128<float> vector2);
    public static void OuterProductSubtract(byte tile, Vector128<float> vector1, Vector128<float> vector2);
}

public abstract class Sme2 : Sme
{
    public static new bool IsSupported { get; }
}

}

API Usage

using System;
using System.Runtime.Intrinsics.X86;
using System.Runtime.Intrinsics.Arm;

public static class FastHardwareRandom
{
// Sub-nanosecond Random Generation with hardware cross-platform fallbacks
public static ulong GetNextUInt64()
{
if (Rdrand.IsSupported)
{
if (Rdrand.TryGetUInt64(out ulong val))
return val;
}
else if (Rng.IsSupported)
{
if (Rng.TryGetUInt64(out ulong val))
return val;
}

    // Software Fallback
    return (ulong)Random.Shared.Next64();
}

}

public static class MatrixComputeExample
{
public static void ExecuteMatrixMultiply()
{
if (Amx.IsSupported)
{
// Intel AMX tile multiplication path
// Amx.TileConfig(...);
// Amx.MultiplyAndAddBF16(0, 1, 2);
// Amx.TileRelease();
}
else if (Sme.IsSupported)
{
// ARM SME streaming mode matrix multiplication path
Sme.EnterStreamingMode();
// Sme.OuterProductAccumulate(...);
Sme.ExitStreamingMode();
}
}
}

Alternative Designs

  1. RNG via System.Random / RandomNumberGenerator:
    An alternative is modifying System.Random or RandomNumberGenerator to internally use RDRAND/RNDR when available. However, high-performance engines require fine-grained control over execution failure checking (evaluating returned boolean flags for CF/underflow) without the allocation and abstraction overhead of managed random generators.

  2. Hiding Matrix Extensions behind System.Numerics.Tensors:
    Another design is to only utilize AMX and SME inside high-level APIs like TensorPrimitives. While beneficial for high-level ML, game engine developers writing custom compute shaders, physics engines, or software rasterizers require direct hardware intrinsic access matching C++ intrinsics (<immintrin.h> / <arm_sme.h>).

Risks

  1. Hardware / Microcode Quirks:
    Early hardware implementations of RDRAND (e.g., specific older AMD microcodes) occasionally failed to replenish entropy pools under heavy contention. Returning a bool status (TryGetUInt64) directly mitigates this risk by allowing developers to safely fall back to software generators.

  2. OS Context Switch Support for AMX/SME:
    Both AMX and SME introduce significant new register states (Tile registers) that require OS kernel save/restore support (XSAVE on Windows/Linux for AMX, and streaming mode state management for SME). Amx.IsSupported and Sme.IsSupported must validate both CPUID flags AND OS kernel enablement flags (e.g., XCR0 bits) to prevent access violation crashes during context switches.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions