Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Expose the x86 HWIntrinsics via a set of class hierarchies matching the underlying ISA hierarchies #19186

Merged
merged 1 commit into from
Jul 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ namespace System.Runtime.Intrinsics.X86
/// This class provides access to Intel AES hardware instructions via intrinsics
/// </summary>
[CLSCompliant(false)]
public static class Aes
public abstract class Aes : Sse2
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

12.13.4 Checking for AESNI Support

Before an application attempts to use AESNI instructions or PCLMULQDQ, the application should follow the steps
illustrated in Section 11.6.2, “Checking for SSE/SSE2 Support.” Next, use the additional step provided below:

Check that the processor supports AESNI (if CPUID.01H:ECX.AESNI[bit 25] = 1); check that the processor
supports PCLMULQDQ (if CPUID.01H:ECX.PCLMULQDQ[bit 1] = 1).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed with Intel that there is not a co-dependency between AESNI and PCLMULQDQ.

CC. @fiigii

{
public static bool IsSupported { get { return false; } }

internal Aes() { }

public new static bool IsSupported { get { return false; } }

/// <summary>
/// __m128i _mm_aesdec_si128 (__m128i a, __m128i RoundKey)
/// AESDEC xmm, xmm/m128
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ namespace System.Runtime.Intrinsics.X86
/// This class provides access to Intel AES hardware instructions via intrinsics
/// </summary>
[CLSCompliant(false)]
public static class Aes
public abstract class Aes : Sse2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make private or internal constructors on all of them as well? That way no one tries creating the class, or a class inheriting from this class.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

{
public static bool IsSupported { get => IsSupported; }

internal Aes() { }

public new static bool IsSupported { get => IsSupported; }

/// <summary>
/// __m128i _mm_aesdec_si128 (__m128i a, __m128i RoundKey)
/// AESDEC xmm, xmm/m128
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ namespace System.Runtime.Intrinsics.X86
/// This class provides access to Intel AVX hardware instructions via intrinsics
/// </summary>
[CLSCompliant(false)]
public static class Avx
public abstract class Avx : Sse42
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

14.3 DETECTION OF AVX INSTRUCTIONS

Intel AVX instructions operate on the 256-bit YMM register state. Application detection of new instruction extensions
operating on the YMM state follows the general procedural flow in Figure 14-2.

Prior to using AVX, the application must identify that the operating system supports the XGETBV instruction, the
YMM register state, in addition to processor’s support for YMM state management using XSAVE/XRSTOR and AVX
instructions. The following simplified sequence accomplishes both and is strongly recommended.

  1. Detect CPUID.1:ECX.OSXSAVE[bit 27] = 1 (XGETBV enabled for application use1)
  2. Issue XGETBV and verify that XCR0[2:1] = ‘11b’ (XMM state and YMM state are enabled by OS).
  3. detect CPUID.1:ECX.AVX[bit 28] = 1 (AVX instructions supported).

Copy link
Member Author

@tannergooding tannergooding Jul 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed with Intel that AVX has an implicit dependency on Sse42 (and prior) due to extending the existing instructions.

CC. @fiigii

{
public static bool IsSupported { get { return false; } }

internal Avx() { }

public new static bool IsSupported { get { return false; } }

/// <summary>
/// __m256 _mm256_add_ps (__m256 a, __m256 b)
/// VADDPS ymm, ymm, ymm/m256
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ namespace System.Runtime.Intrinsics.X86
/// This class provides access to Intel AVX hardware instructions via intrinsics
/// </summary>
[CLSCompliant(false)]
public static class Avx
public abstract class Avx : Sse42
{
public static bool IsSupported { get => IsSupported; }
internal Avx() { }

public new static bool IsSupported { get => IsSupported; }

/// <summary>
/// __m256 _mm256_add_ps (__m256 a, __m256 b)
Expand Down Expand Up @@ -468,7 +470,7 @@ public static Vector256<byte> Insert(Vector256<byte> value, byte data, byte inde
return LoadVector256(buffer);
}
}

/// <summary>
/// __m256i _mm256_insert_epi16 (__m256i a, __int16 i, const int index)
/// HELPER
Expand Down Expand Up @@ -516,7 +518,7 @@ public static Vector256<int> Insert(Vector256<int> value, int data, byte index)
return LoadVector256(buffer);
}
}

/// <summary>
/// __m256i _mm256_insert_epi32 (__m256i a, __int32 i, const int index)
/// HELPER
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ namespace System.Runtime.Intrinsics.X86
/// This class provides access to Intel AVX2 hardware instructions via intrinsics
/// </summary>
[CLSCompliant(false)]
public static class Avx2
public abstract class Avx2 : Avx
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

14.7.1 Detection of AVX2

Hardware support for AVX2 is indicated by CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]=1.

Application Software must identify that hardware supports AVX, after that it must also detect support for AVX2 by
checking CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5].

{
public static bool IsSupported { get { return false; } }
internal Avx2() { }

public new static bool IsSupported { get { return false; } }

/// <summary>
/// __m256i _mm256_abs_epi8 (__m256i a)
Expand Down Expand Up @@ -455,7 +457,7 @@ public static class Avx2
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
/// VEXTRACTI128 m128, ymm, imm8
/// </summary>
public static unsafe void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
Expand All @@ -466,7 +468,7 @@ public static class Avx2
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
/// VEXTRACTI128 m128, ymm, imm8
/// </summary>
public static unsafe void ExtractVector128(byte* address, Vector256<byte> value, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe void ExtractVector128(byte* address, Vector256<byte> value, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
Expand All @@ -477,7 +479,7 @@ public static class Avx2
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
/// VEXTRACTI128 m128, ymm, imm8
/// </summary>
public static unsafe void ExtractVector128(short* address, Vector256<short> value, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe void ExtractVector128(short* address, Vector256<short> value, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
Expand All @@ -488,7 +490,7 @@ public static class Avx2
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
/// VEXTRACTI128 m128, ymm, imm8
/// </summary>
public static unsafe void ExtractVector128(ushort* address, Vector256<ushort> value, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe void ExtractVector128(ushort* address, Vector256<ushort> value, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
Expand All @@ -499,7 +501,7 @@ public static class Avx2
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
/// VEXTRACTI128 m128, ymm, imm8
/// </summary>
public static unsafe void ExtractVector128(int* address, Vector256<int> value, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe void ExtractVector128(int* address, Vector256<int> value, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
Expand All @@ -510,7 +512,7 @@ public static class Avx2
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
/// VEXTRACTI128 m128, ymm, imm8
/// </summary>
public static unsafe void ExtractVector128(uint* address, Vector256<uint> value, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe void ExtractVector128(uint* address, Vector256<uint> value, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
Expand All @@ -521,7 +523,7 @@ public static class Avx2
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
/// VEXTRACTI128 m128, ymm, imm8
/// </summary>
public static unsafe void ExtractVector128(long* address, Vector256<long> value, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe void ExtractVector128(long* address, Vector256<long> value, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
Expand All @@ -532,7 +534,7 @@ public static class Avx2
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
/// VEXTRACTI128 m128, ymm, imm8
/// </summary>
public static unsafe void ExtractVector128(ulong* address, Vector256<ulong> value, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe void ExtractVector128(ulong* address, Vector256<ulong> value, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m128i _mm_i32gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
Expand Down Expand Up @@ -819,7 +821,7 @@ public static class Avx2
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
/// VINSERTI128 ymm, ymm, xm128, imm8
/// </summary>
public static unsafe Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
Expand All @@ -830,7 +832,7 @@ public static class Avx2
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
/// VINSERTI128 ymm, ymm, m128, imm8
/// </summary>
public static unsafe Vector256<byte> InsertVector128(Vector256<byte> value, byte* address, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe Vector256<byte> InsertVector128(Vector256<byte> value, byte* address, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
Expand All @@ -841,7 +843,7 @@ public static class Avx2
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
/// VINSERTI128 ymm, ymm, m128, imm8
/// </summary>
public static unsafe Vector256<short> InsertVector128(Vector256<short> value, short* address, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe Vector256<short> InsertVector128(Vector256<short> value, short* address, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
Expand All @@ -852,7 +854,7 @@ public static class Avx2
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
/// VINSERTI128 ymm, ymm, m128, imm8
/// </summary>
public static unsafe Vector256<ushort> InsertVector128(Vector256<ushort> value, ushort* address, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe Vector256<ushort> InsertVector128(Vector256<ushort> value, ushort* address, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
Expand All @@ -863,7 +865,7 @@ public static class Avx2
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
/// VINSERTI128 ymm, ymm, m128, imm8
/// </summary>
public static unsafe Vector256<int> InsertVector128(Vector256<int> value, int* address, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe Vector256<int> InsertVector128(Vector256<int> value, int* address, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
Expand All @@ -874,7 +876,7 @@ public static class Avx2
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
/// VINSERTI128 ymm, ymm, m128, imm8
/// </summary>
public static unsafe Vector256<uint> InsertVector128(Vector256<uint> value, uint* address, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe Vector256<uint> InsertVector128(Vector256<uint> value, uint* address, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
Expand All @@ -885,7 +887,7 @@ public static class Avx2
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
/// VINSERTI128 ymm, ymm, m128, imm8
/// </summary>
public static unsafe Vector256<long> InsertVector128(Vector256<long> value, long* address, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe Vector256<long> InsertVector128(Vector256<long> value, long* address, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
Expand All @@ -896,7 +898,7 @@ public static class Avx2
/// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
/// VINSERTI128 ymm, ymm, m128, imm8
/// </summary>
public static unsafe Vector256<ulong> InsertVector128(Vector256<ulong> value, ulong* address, byte index) { throw new PlatformNotSupportedException(); }
public new static unsafe Vector256<ulong> InsertVector128(Vector256<ulong> value, ulong* address, byte index) { throw new PlatformNotSupportedException(); }

/// <summary>
/// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
Expand Down
Loading