{
return !string.IsNullOrEmpty(InstructionSetSupport.GetHardwareIntrinsicId(method.Context.Target.Architecture, method.OwningType));
}
-
-#if !READYTORUN
- public static bool IsIsSupportedMethod(MethodDesc method)
- {
- return method.Name == "get_IsSupported";
- }
-
- public static MethodIL GetUnsupportedImplementationIL(MethodDesc method)
- {
- // The implementation of IsSupported for codegen backends that don't support hardware intrinsics
- // at all is to return 0.
- if (IsIsSupportedMethod(method))
- {
- return new ILStubMethodIL(method,
- new byte[] {
- (byte)ILOpcode.ldc_i4_0,
- (byte)ILOpcode.ret
- },
- Array.Empty<LocalVariableDefinition>(), null);
- }
-
- // Other methods throw PlatformNotSupportedException
- MethodDesc throwPnse = method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowPlatformNotSupportedException");
-
- return new ILStubMethodIL(method,
- new byte[] {
- (byte)ILOpcode.call, 1, 0, 0, 0,
- (byte)ILOpcode.br_s, unchecked((byte)-7),
- },
- Array.Empty<LocalVariableDefinition>(),
- new object[] { throwPnse });
- }
-
- /// <summary>
- /// Generates IL for the IsSupported property that reads this information from a field initialized by the runtime
- /// at startup. Returns null for hardware intrinsics whose support level is known at compile time
- /// (i.e. they're known to be always supported or always unsupported).
- /// </summary>
- public static MethodIL EmitIsSupportedIL(MethodDesc method, FieldDesc isSupportedField)
- {
- Debug.Assert(IsIsSupportedMethod(method));
- Debug.Assert(isSupportedField.IsStatic && isSupportedField.FieldType.IsWellKnownType(WellKnownType.Int32));
-
- TargetDetails target = method.Context.Target;
- MetadataType owningType = (MetadataType)method.OwningType;
-
- // Check for case of nested "X64" types
- if (owningType.Name == "X64")
- {
- if (target.Architecture != TargetArchitecture.X64)
- return null;
-
- // Un-nest the type so that we can do a name match
- owningType = (MetadataType)owningType.ContainingType;
- }
-
- int flag;
- if ((target.Architecture == TargetArchitecture.X64 || target.Architecture == TargetArchitecture.X86)
- && owningType.Namespace == "System.Runtime.Intrinsics.X86")
- {
- switch (owningType.Name)
- {
- case "Aes":
- flag = XArchIntrinsicConstants.Aes;
- break;
- case "Pclmulqdq":
- flag = XArchIntrinsicConstants.Pclmulqdq;
- break;
- case "Sse3":
- flag = XArchIntrinsicConstants.Sse3;
- break;
- case "Ssse3":
- flag = XArchIntrinsicConstants.Ssse3;
- break;
- case "Lzcnt":
- flag = XArchIntrinsicConstants.Lzcnt;
- break;
- // NOTE: this switch is complemented by IsKnownSupportedIntrinsicAtCompileTime
- // in the method below.
- default:
- return null;
- }
- }
- else
- {
- return null;
- }
-
- var emit = new ILEmitter();
- ILCodeStream codeStream = emit.NewCodeStream();
-
- codeStream.Emit(ILOpcode.ldsfld, emit.NewToken(isSupportedField));
- codeStream.EmitLdc(flag);
- codeStream.Emit(ILOpcode.and);
- codeStream.EmitLdc(0);
- codeStream.Emit(ILOpcode.cgt_un);
- codeStream.Emit(ILOpcode.ret);
-
- return emit.Link(method);
- }
-
- /// <summary>
- /// Gets a value indicating whether the support for a given intrinsic is known at compile time.
- /// </summary>
- public static bool IsKnownSupportedIntrinsicAtCompileTime(MethodDesc method)
- {
- TargetDetails target = method.Context.Target;
-
- if (target.Architecture == TargetArchitecture.X64
- || target.Architecture == TargetArchitecture.X86)
- {
- var owningType = (MetadataType)method.OwningType;
- if (owningType.Name == "X64")
- {
- if (target.Architecture != TargetArchitecture.X64)
- return true;
- owningType = (MetadataType)owningType.ContainingType;
- }
-
- if (owningType.Namespace != "System.Runtime.Intrinsics.X86")
- return true;
-
- // Sse and Sse2 are baseline required intrinsics.
- // RyuJIT also uses Sse41/Sse42 with the general purpose Vector APIs.
- // RyuJIT only respects Popcnt if Sse41/Sse42 is also enabled.
- // Avx/Avx2/Bmi1/Bmi2 require VEX encoding and RyuJIT currently can't enable them
- // without enabling VEX encoding everywhere. We don't support them.
- // This list complements EmitIsSupportedIL above.
- return owningType.Name == "Sse" || owningType.Name == "Sse2"
- || owningType.Name == "Sse41" || owningType.Name == "Sse42"
- || owningType.Name == "Popcnt"
- || owningType.Name == "Bmi1" || owningType.Name == "Bmi2"
- || owningType.Name == "Avx" || owningType.Name == "Avx2";
- }
-
- return false;
- }
-
- // Keep this enumeration in sync with startup.cpp in the native runtime.
- private static class XArchIntrinsicConstants
- {
- public const int Aes = 0x0001;
- public const int Pclmulqdq = 0x0002;
- public const int Sse3 = 0x0004;
- public const int Ssse3 = 0x0008;
- public const int Sse41 = 0x0010;
- public const int Sse42 = 0x0020;
- public const int Popcnt = 0x0040;
- public const int Lzcnt = 0x0080;
- }
-#endif // !READYTORUN
}
}
public struct InstructionSetInfo
{
public readonly string Name;
+ public readonly string ManagedName;
public readonly InstructionSet InstructionSet;
public readonly bool Specifiable;
- public InstructionSetInfo(string name, InstructionSet instructionSet, bool specifiable)
+ public InstructionSetInfo(string name, string managedName, InstructionSet instructionSet, bool specifiable)
{
Name = name;
+ ManagedName = managedName;
InstructionSet = instructionSet;
Specifiable = specifiable;
}
{
case TargetArchitecture.ARM64:
- yield return new InstructionSetInfo("base", InstructionSet.ARM64_ArmBase, true);
- yield return new InstructionSetInfo("neon", InstructionSet.ARM64_AdvSimd, true);
- yield return new InstructionSetInfo("aes", InstructionSet.ARM64_Aes, true);
- yield return new InstructionSetInfo("crc", InstructionSet.ARM64_Crc32, true);
- yield return new InstructionSetInfo("sha1", InstructionSet.ARM64_Sha1, true);
- yield return new InstructionSetInfo("sha2", InstructionSet.ARM64_Sha256, true);
- yield return new InstructionSetInfo("lse", InstructionSet.ARM64_Atomics, true);
- yield return new InstructionSetInfo("Vector64", InstructionSet.ARM64_Vector64, false);
- yield return new InstructionSetInfo("Vector128", InstructionSet.ARM64_Vector128, false);
+ yield return new InstructionSetInfo("base", "ArmBase", InstructionSet.ARM64_ArmBase, true);
+ yield return new InstructionSetInfo("neon", "AdvSimd", InstructionSet.ARM64_AdvSimd, true);
+ yield return new InstructionSetInfo("aes", "Aes", InstructionSet.ARM64_Aes, true);
+ yield return new InstructionSetInfo("crc", "Crc32", InstructionSet.ARM64_Crc32, true);
+ yield return new InstructionSetInfo("sha1", "Sha1", InstructionSet.ARM64_Sha1, true);
+ yield return new InstructionSetInfo("sha2", "Sha256", InstructionSet.ARM64_Sha256, true);
+ yield return new InstructionSetInfo("lse", "", InstructionSet.ARM64_Atomics, true);
+ yield return new InstructionSetInfo("Vector64", "", InstructionSet.ARM64_Vector64, false);
+ yield return new InstructionSetInfo("Vector128", "", InstructionSet.ARM64_Vector128, false);
break;
case TargetArchitecture.X64:
- yield return new InstructionSetInfo("sse", InstructionSet.X64_SSE, true);
- yield return new InstructionSetInfo("sse2", InstructionSet.X64_SSE2, true);
- yield return new InstructionSetInfo("sse3", InstructionSet.X64_SSE3, true);
- yield return new InstructionSetInfo("ssse3", InstructionSet.X64_SSSE3, true);
- yield return new InstructionSetInfo("sse4.1", InstructionSet.X64_SSE41, true);
- yield return new InstructionSetInfo("sse4.2", InstructionSet.X64_SSE42, true);
- yield return new InstructionSetInfo("avx", InstructionSet.X64_AVX, true);
- yield return new InstructionSetInfo("avx2", InstructionSet.X64_AVX2, true);
- yield return new InstructionSetInfo("aes", InstructionSet.X64_AES, true);
- yield return new InstructionSetInfo("bmi", InstructionSet.X64_BMI1, true);
- yield return new InstructionSetInfo("bmi2", InstructionSet.X64_BMI2, true);
- yield return new InstructionSetInfo("fma", InstructionSet.X64_FMA, true);
- yield return new InstructionSetInfo("lzcnt", InstructionSet.X64_LZCNT, true);
- yield return new InstructionSetInfo("pclmul", InstructionSet.X64_PCLMULQDQ, true);
- yield return new InstructionSetInfo("popcnt", InstructionSet.X64_POPCNT, true);
- yield return new InstructionSetInfo("Vector128", InstructionSet.X64_Vector128, false);
- yield return new InstructionSetInfo("Vector256", InstructionSet.X64_Vector256, false);
+ yield return new InstructionSetInfo("sse", "Sse", InstructionSet.X64_SSE, true);
+ yield return new InstructionSetInfo("sse2", "Sse2", InstructionSet.X64_SSE2, true);
+ yield return new InstructionSetInfo("sse3", "Sse3", InstructionSet.X64_SSE3, true);
+ yield return new InstructionSetInfo("ssse3", "Ssse3", InstructionSet.X64_SSSE3, true);
+ yield return new InstructionSetInfo("sse4.1", "Sse41", InstructionSet.X64_SSE41, true);
+ yield return new InstructionSetInfo("sse4.2", "Sse42", InstructionSet.X64_SSE42, true);
+ yield return new InstructionSetInfo("avx", "Avx", InstructionSet.X64_AVX, true);
+ yield return new InstructionSetInfo("avx2", "Avx2", InstructionSet.X64_AVX2, true);
+ yield return new InstructionSetInfo("aes", "Aes", InstructionSet.X64_AES, true);
+ yield return new InstructionSetInfo("bmi", "Bmi1", InstructionSet.X64_BMI1, true);
+ yield return new InstructionSetInfo("bmi2", "Bmi2", InstructionSet.X64_BMI2, true);
+ yield return new InstructionSetInfo("fma", "Fma", InstructionSet.X64_FMA, true);
+ yield return new InstructionSetInfo("lzcnt", "Lzcnt", InstructionSet.X64_LZCNT, true);
+ yield return new InstructionSetInfo("pclmul", "Pclmulqdq", InstructionSet.X64_PCLMULQDQ, true);
+ yield return new InstructionSetInfo("popcnt", "Popcnt", InstructionSet.X64_POPCNT, true);
+ yield return new InstructionSetInfo("Vector128", "", InstructionSet.X64_Vector128, false);
+ yield return new InstructionSetInfo("Vector256", "", InstructionSet.X64_Vector256, false);
break;
case TargetArchitecture.X86:
- yield return new InstructionSetInfo("sse", InstructionSet.X86_SSE, true);
- yield return new InstructionSetInfo("sse2", InstructionSet.X86_SSE2, true);
- yield return new InstructionSetInfo("sse3", InstructionSet.X86_SSE3, true);
- yield return new InstructionSetInfo("ssse3", InstructionSet.X86_SSSE3, true);
- yield return new InstructionSetInfo("sse4.1", InstructionSet.X86_SSE41, true);
- yield return new InstructionSetInfo("sse4.2", InstructionSet.X86_SSE42, true);
- yield return new InstructionSetInfo("avx", InstructionSet.X86_AVX, true);
- yield return new InstructionSetInfo("avx2", InstructionSet.X86_AVX2, true);
- yield return new InstructionSetInfo("aes", InstructionSet.X86_AES, true);
- yield return new InstructionSetInfo("bmi", InstructionSet.X86_BMI1, true);
- yield return new InstructionSetInfo("bmi2", InstructionSet.X86_BMI2, true);
- yield return new InstructionSetInfo("fma", InstructionSet.X86_FMA, true);
- yield return new InstructionSetInfo("lzcnt", InstructionSet.X86_LZCNT, true);
- yield return new InstructionSetInfo("pclmul", InstructionSet.X86_PCLMULQDQ, true);
- yield return new InstructionSetInfo("popcnt", InstructionSet.X86_POPCNT, true);
- yield return new InstructionSetInfo("Vector128", InstructionSet.X86_Vector128, false);
- yield return new InstructionSetInfo("Vector256", InstructionSet.X86_Vector256, false);
+ yield return new InstructionSetInfo("sse", "Sse", InstructionSet.X86_SSE, true);
+ yield return new InstructionSetInfo("sse2", "Sse2", InstructionSet.X86_SSE2, true);
+ yield return new InstructionSetInfo("sse3", "Sse3", InstructionSet.X86_SSE3, true);
+ yield return new InstructionSetInfo("ssse3", "Ssse3", InstructionSet.X86_SSSE3, true);
+ yield return new InstructionSetInfo("sse4.1", "Sse41", InstructionSet.X86_SSE41, true);
+ yield return new InstructionSetInfo("sse4.2", "Sse42", InstructionSet.X86_SSE42, true);
+ yield return new InstructionSetInfo("avx", "Avx", InstructionSet.X86_AVX, true);
+ yield return new InstructionSetInfo("avx2", "Avx2", InstructionSet.X86_AVX2, true);
+ yield return new InstructionSetInfo("aes", "Aes", InstructionSet.X86_AES, true);
+ yield return new InstructionSetInfo("bmi", "Bmi1", InstructionSet.X86_BMI1, true);
+ yield return new InstructionSetInfo("bmi2", "Bmi2", InstructionSet.X86_BMI2, true);
+ yield return new InstructionSetInfo("fma", "Fma", InstructionSet.X86_FMA, true);
+ yield return new InstructionSetInfo("lzcnt", "Lzcnt", InstructionSet.X86_LZCNT, true);
+ yield return new InstructionSetInfo("pclmul", "Pclmulqdq", InstructionSet.X86_PCLMULQDQ, true);
+ yield return new InstructionSetInfo("popcnt", "Popcnt", InstructionSet.X86_POPCNT, true);
+ yield return new InstructionSetInfo("Vector128", "", InstructionSet.X86_Vector128, false);
+ yield return new InstructionSetInfo("Vector256", "", InstructionSet.X86_Vector256, false);
break;
}