From 42ac3d30b1d8310e13eab6f42cc754fa53c5a01d Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 28 Nov 2018 03:52:43 -0800 Subject: [PATCH] Implement the S.R.I.VectorXXX `get_Zero` and `As` helper methods as JIT intrinsics (#21198) * Remove ARM64_SIMD_StaticCast intrinsic and the x86 TwoTypeGeneric flag * Implementing the `S.R.Intrinsic.VectorXXX.As` methods as runtime intrinsics * Implementing the get_Zero method on the S.R.Intrinsic.VectorXXX types as runtime intrinsics --- .../System/Runtime/Intrinsics/Vector128_1.cs | 12 + .../System/Runtime/Intrinsics/Vector256_1.cs | 12 + .../System/Runtime/Intrinsics/Vector64_1.cs | 11 + src/jit/codegen.h | 1 + src/jit/compiler.cpp | 12 +- src/jit/compiler.h | 1 + src/jit/hwintrinsiccodegenxarch.cpp | 53 +++ src/jit/hwintrinsiclistArm64.h | 19 +- src/jit/hwintrinsiclistxarch.h | 29 ++ src/jit/hwintrinsicxarch.cpp | 14 +- src/jit/hwintrinsicxarch.h | 9 - src/jit/importer.cpp | 372 +++++++++++++++++- src/jit/instr.h | 33 +- src/jit/jitconfigvalues.h | 35 +- src/jit/namedintrinsiclist.h | 1 + 15 files changed, 546 insertions(+), 68 deletions(-) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128_1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128_1.cs index 3f8523a257..f3599a9842 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128_1.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128_1.cs @@ -24,6 +24,7 @@ namespace System.Runtime.Intrinsics /// The type of the current instance () is not supported. public static Vector128 Zero { + [Intrinsic] get { ThrowIfUnsupportedType(); @@ -88,6 +89,7 @@ namespace System.Runtime.Intrinsics /// The type of the vector the current instance should be reinterpreted as. /// The current instance reinterpreted as a new . /// The type of the current instance () or the type of the target () is not supported. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector128 As() where U : struct { @@ -99,54 +101,64 @@ namespace System.Runtime.Intrinsics /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector128 AsByte() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector128 AsDouble() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector128 AsInt16() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector128 AsInt32() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector128 AsInt64() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector128 AsSByte() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector128 AsSingle() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector128 AsUInt16() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector128 AsUInt32() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector128 AsUInt64() => As(); diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs index d040ce9989..a86ffb5db0 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs @@ -26,6 +26,7 @@ namespace System.Runtime.Intrinsics /// The type of the current instance () is not supported. public static Vector256 Zero { + [Intrinsic] get { ThrowIfUnsupportedType(); @@ -90,6 +91,7 @@ namespace System.Runtime.Intrinsics /// The type of the vector the current instance should be reinterpreted as. /// The current instance reinterpreted as a new . /// The type of the current instance () or the type of the target () is not supported. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector256 As() where U : struct { @@ -101,54 +103,64 @@ namespace System.Runtime.Intrinsics /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector256 AsByte() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector256 AsDouble() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector256 AsInt16() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector256 AsInt32() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector256 AsInt64() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector256 AsSByte() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector256 AsSingle() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector256 AsUInt16() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector256 AsUInt32() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector256 AsUInt64() => As(); diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64_1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64_1.cs index 99a1e9ec17..0bb028602a 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64_1.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64_1.cs @@ -87,6 +87,7 @@ namespace System.Runtime.Intrinsics /// The type of the vector the current instance should be reinterpreted as. /// The current instance reinterpreted as a new . /// The type of the current instance () or the type of the target () is not supported. + [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector64 As() where U : struct { @@ -98,54 +99,64 @@ namespace System.Runtime.Intrinsics /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector64 AsByte() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector64 AsDouble() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector64 AsInt16() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector64 AsInt32() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector64 AsInt64() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector64 AsSByte() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] public Vector64 AsSingle() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector64 AsUInt16() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector64 AsUInt32() => As(); /// Reinterprets the current instance as a new . /// The current instance reinterpreted as a new . /// The type of the current instance () is not supported. + [Intrinsic] [CLSCompliant(false)] public Vector64 AsUInt64() => As(); diff --git a/src/jit/codegen.h b/src/jit/codegen.h index 06670aaac6..e17633e286 100644 --- a/src/jit/codegen.h +++ b/src/jit/codegen.h @@ -935,6 +935,7 @@ protected: void genHWIntrinsic_R_R_RM_R(GenTreeHWIntrinsic* node, instruction ins); void genHWIntrinsic_R_R_R_RM( instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg, GenTree* op3); + void genBaseIntrinsic(GenTreeHWIntrinsic* node); void genSSEIntrinsic(GenTreeHWIntrinsic* node); void genSSE2Intrinsic(GenTreeHWIntrinsic* node); void genSSE41Intrinsic(GenTreeHWIntrinsic* node); diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp index f394e02aea..fe42bb0dee 100644 --- a/src/jit/compiler.cpp +++ b/src/jit/compiler.cpp @@ -2366,7 +2366,13 @@ static bool configEnableISA(InstructionSet isa) } __fallthrough; case InstructionSet_SSE: - return JitConfig.EnableSSE() != 0; + if (JitConfig.EnableSSE() == 0) + { + return false; + } + __fallthrough; + case InstructionSet_Base: + return (JitConfig.EnableHWIntrinsic() != 0); // TODO: BMI1/BMI2 actually don't depend on AVX, they depend on the VEX encoding; which is currently controlled // by InstructionSet_AVX @@ -2434,6 +2440,10 @@ void Compiler::compSetProcessor() if (!jitFlags.IsSet(JitFlags::JIT_FLAG_PREJIT)) { + if (configEnableISA(InstructionSet_Base)) + { + opts.setSupportedISA(InstructionSet_Base); + } if (configEnableISA(InstructionSet_SSE)) { opts.setSupportedISA(InstructionSet_SSE); diff --git a/src/jit/compiler.h b/src/jit/compiler.h index b973e11105..3ac8b9c9d3 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -3407,6 +3407,7 @@ protected: NamedIntrinsic lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method); #ifdef FEATURE_HW_INTRINSICS + GenTree* impBaseIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig); GenTree* impHWIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, diff --git a/src/jit/hwintrinsiccodegenxarch.cpp b/src/jit/hwintrinsiccodegenxarch.cpp index 67d8c5228b..919b4e84ea 100644 --- a/src/jit/hwintrinsiccodegenxarch.cpp +++ b/src/jit/hwintrinsiccodegenxarch.cpp @@ -302,6 +302,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) switch (isa) { + case InstructionSet_Base: + genBaseIntrinsic(node); + break; case InstructionSet_SSE: genSSEIntrinsic(node); break; @@ -1230,6 +1233,56 @@ void CodeGen::genHWIntrinsicJumpTableFallback(NamedIntrinsic intrinsi genDefineTempLabel(switchTableEnd); } +//------------------------------------------------------------------------ +// genBaseIntrinsic: Generates the code for a base hardware intrinsic node +// +// Arguments: +// node - The hardware intrinsic node +// +void CodeGen::genBaseIntrinsic(GenTreeHWIntrinsic* node) +{ + NamedIntrinsic intrinsicId = node->gtHWIntrinsicId; + regNumber targetReg = node->gtRegNum; + var_types targetType = node->TypeGet(); + var_types baseType = node->gtSIMDBaseType; + + assert(node->gtGetOp1() == nullptr); + assert(node->gtGetOp2() == nullptr); + assert(baseType >= TYP_BYTE && baseType <= TYP_DOUBLE); + + emitter* emit = getEmitter(); + emitAttr attr = EA_ATTR(node->gtSIMDSize); + + switch (intrinsicId) + { + case NI_Base_Vector128_Zero: + { + // When SSE2 is supported, we generate pxor for integral types otherwise just use xorps + instruction ins = + (compiler->compSupports(InstructionSet_SSE2) && varTypeIsIntegral(baseType)) ? INS_pxor : INS_xorps; + emit->emitIns_SIMD_R_R_R(ins, attr, targetReg, targetReg, targetReg); + break; + } + + case NI_Base_Vector256_Zero: + { + // When AVX2 is supported, we generate pxor for integral types otherwise just use xorps + instruction ins = + (compiler->compSupports(InstructionSet_AVX2) && varTypeIsIntegral(baseType)) ? INS_pxor : INS_xorps; + emit->emitIns_SIMD_R_R_R(ins, attr, targetReg, targetReg, targetReg); + break; + } + + default: + { + unreached(); + break; + } + } + + genProduceReg(node); +} + //------------------------------------------------------------------------ // genSSEIntrinsic: Generates the code for an SSE hardware intrinsic node // diff --git a/src/jit/hwintrinsiclistArm64.h b/src/jit/hwintrinsiclistArm64.h index ffc8d39c52..3a2ae3afab 100644 --- a/src/jit/hwintrinsiclistArm64.h +++ b/src/jit/hwintrinsiclistArm64.h @@ -41,6 +41,24 @@ HARDWARE_INTRINSIC(NI_ARM64_NONE_MOV, None, None, // Base HARDWARE_INTRINSIC(NI_ARM64_BASE_CLS, Base, LeadingSignCount, UnaryOp, INS_invalid, INS_cls, INS_cls, None ) HARDWARE_INTRINSIC(NI_ARM64_BASE_CLZ, Base, LeadingZeroCount, UnaryOp, INS_invalid, INS_clz, INS_clz, None ) +HARDWARE_INTRINSIC(NI_Base_Vector64_AsByte, Base, AsByte, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector64_AsInt16, Base, AsInt16, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector64_AsInt32, Base, AsInt32, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector64_AsSByte, Base, AsSByte, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector64_AsSingle, Base, AsSingle, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector64_AsUInt16, Base, AsUInt16, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector64_AsUInt32, Base, AsUInt32, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector128_As, Base, As, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector128_AsByte, Base, AsByte, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector128_AsDouble, Base, AsDouble, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector128_AsInt16, Base, AsInt16, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector128_AsInt32, Base, AsInt32, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector128_AsInt64, Base, AsInt64, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector128_AsSByte, Base, AsSByte, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector128_AsSingle, Base, AsSingle, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector128_AsUInt16, Base, AsUInt16, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector128_AsUInt32, Base, AsUInt32, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) +HARDWARE_INTRINSIC(NI_Base_Vector128_AsUInt64, Base, AsUInt64, UnaryOp, INS_invalid, INS_invalid, INS_invalid, None ) #if NYI // Crc32 HARDWARE_INTRINSIC(NI_ARM64_CRC32_CRC32, Crc32, Crc32, CrcOp, INS_invalid, INS_invalid, INS_crc32, None ) @@ -74,7 +92,6 @@ HARDWARE_INTRINSIC(NI_ARM64_SIMD_Max, Simd, Max, HARDWARE_INTRINSIC(NI_ARM64_SIMD_Min, Simd, Min, SimdBinaryOp, INS_fmin, INS_smin, INS_umin, None ) HARDWARE_INTRINSIC(NI_ARM64_SIMD_Mul, Simd, Multiply, SimdBinaryOp, INS_fmul, INS_mul, INS_mul, None ) HARDWARE_INTRINSIC(NI_ARM64_SIMD_Sqrt, Simd, Sqrt, SimdUnaryOp, INS_fsqrt, INS_invalid, INS_invalid, None ) -HARDWARE_INTRINSIC(NI_ARM64_SIMD_StaticCast, Simd, StaticCast, SimdUnaryOp, INS_mov, INS_mov, INS_mov, None ) HARDWARE_INTRINSIC(NI_ARM64_SIMD_Sub, Simd, Subtract, SimdBinaryOp, INS_fsub, INS_sub, INS_sub, None ) HARDWARE_INTRINSIC(NI_ARM64_SIMD_GetItem, Simd, Extract, SimdExtractOp, INS_mov, INS_mov, INS_mov, None ) HARDWARE_INTRINSIC(NI_ARM64_SIMD_SetItem, Simd, Insert, SimdInsertOp, INS_mov, INS_mov, INS_mov, None ) diff --git a/src/jit/hwintrinsiclistxarch.h b/src/jit/hwintrinsiclistxarch.h index 28678984e3..08fc125d5c 100644 --- a/src/jit/hwintrinsiclistxarch.h +++ b/src/jit/hwintrinsiclistxarch.h @@ -22,6 +22,35 @@ 8) Each intrinsic has one category with type of `enum HWIntrinsicCategory`, please see the definition of HWIntrinsicCategory for details 9) Each intrinsic has one or more flags with type of `enum HWIntrinsicFlag` */ +// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +// Intrinsic ID Function name ISA ival SIMD size NumArg instructions Category Flags +// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +// Base Intrinsics +HARDWARE_INTRINSIC(Base_Vector128_As, "As`1", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector128_AsByte, "AsByte", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector128_AsDouble, "AsDouble", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector128_AsInt16, "AsInt16", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector128_AsInt32, "AsInt32", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector128_AsInt64, "AsInt64", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector128_AsSByte, "AsSByte", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector128_AsSingle, "AsSingle", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector128_AsUInt16, "AsUInt16", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector128_AsUInt32, "AsUInt32", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector128_AsUInt64, "AsUInt64", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector128_Zero, "get_Zero", Base, -1, 16, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_As, "As`1", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_AsByte, "AsByte", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_AsDouble, "AsDouble", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_AsInt16, "AsInt16", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_AsInt32, "AsInt32", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_AsInt64, "AsInt64", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_AsSByte, "AsSByte", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_AsSingle, "AsSingle", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_AsUInt16, "AsUInt16", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_AsUInt32, "AsUInt32", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_AsUInt64, "AsUInt64", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(Base_Vector256_Zero, "get_Zero", Base, -1, 32, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Intrinsic ID Function name ISA ival SIMD size NumArg instructions Category Flags diff --git a/src/jit/hwintrinsicxarch.cpp b/src/jit/hwintrinsicxarch.cpp index 09ae92feda..7a7c689477 100644 --- a/src/jit/hwintrinsicxarch.cpp +++ b/src/jit/hwintrinsicxarch.cpp @@ -788,24 +788,12 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic, } } - if ((HWIntrinsicInfo::IsOneTypeGeneric(intrinsic) || HWIntrinsicInfo::IsTwoTypeGeneric(intrinsic)) && - !HWIntrinsicInfo::HasSpecialImport(intrinsic)) + if (HWIntrinsicInfo::IsOneTypeGeneric(intrinsic) && !HWIntrinsicInfo::HasSpecialImport(intrinsic)) { if (!varTypeIsArithmetic(baseType)) { return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, method, sig, mustExpand); } - - if (HWIntrinsicInfo::IsTwoTypeGeneric(intrinsic)) - { - // StaticCast has two type parameters. - assert(numArgs == 1); - var_types srcType = getBaseTypeOfSIMDType(info.compCompHnd->getArgClass(sig, sig->args)); - if (!varTypeIsArithmetic(srcType)) - { - return impUnsupportedHWIntrinsic(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, method, sig, mustExpand); - } - } } if (HWIntrinsicInfo::IsFloatingPointUsed(intrinsic)) diff --git a/src/jit/hwintrinsicxarch.h b/src/jit/hwintrinsicxarch.h index 039543f1fa..19d2d22773 100644 --- a/src/jit/hwintrinsicxarch.h +++ b/src/jit/hwintrinsicxarch.h @@ -60,9 +60,6 @@ enum HWIntrinsicFlag : unsigned int // Generic // - must throw NotSupportException if the type argument is not numeric type HW_Flag_OneTypeGeneric = 0x4, - // Two-type Generic - // - the intrinsic has two type parameters - HW_Flag_TwoTypeGeneric = 0x8, // NoCodeGen // - should be transformed in the compiler front-end, cannot reach CodeGen @@ -225,12 +222,6 @@ struct HWIntrinsicInfo return (flags & HW_Flag_OneTypeGeneric) != 0; } - static bool IsTwoTypeGeneric(NamedIntrinsic id) - { - HWIntrinsicFlag flags = lookupFlags(id); - return (flags & HW_Flag_TwoTypeGeneric) != 0; - } - static bool RequiresCodegen(NamedIntrinsic id) { HWIntrinsicFlag flags = lookupFlags(id); diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index 6062511ce1..371d277174 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -3422,7 +3422,54 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, ni = lookupNamedIntrinsic(method); #ifdef FEATURE_HW_INTRINSICS - if (ni > NI_HW_INTRINSIC_START && ni < NI_HW_INTRINSIC_END) + switch (ni) + { +#if defined(_TARGET_ARM64_) + case NI_Base_Vector64_AsByte: + case NI_Base_Vector64_AsInt16: + case NI_Base_Vector64_AsInt32: + case NI_Base_Vector64_AsSByte: + case NI_Base_Vector64_AsSingle: + case NI_Base_Vector64_AsUInt16: + case NI_Base_Vector64_AsUInt32: +#endif // _TARGET_ARM64_ + case NI_Base_Vector128_As: + case NI_Base_Vector128_AsByte: + case NI_Base_Vector128_AsDouble: + case NI_Base_Vector128_AsInt16: + case NI_Base_Vector128_AsInt32: + case NI_Base_Vector128_AsInt64: + case NI_Base_Vector128_AsSByte: + case NI_Base_Vector128_AsSingle: + case NI_Base_Vector128_AsUInt16: + case NI_Base_Vector128_AsUInt32: + case NI_Base_Vector128_AsUInt64: +#if defined(_TARGET_XARCH_) + case NI_Base_Vector128_Zero: + case NI_Base_Vector256_As: + case NI_Base_Vector256_AsByte: + case NI_Base_Vector256_AsDouble: + case NI_Base_Vector256_AsInt16: + case NI_Base_Vector256_AsInt32: + case NI_Base_Vector256_AsInt64: + case NI_Base_Vector256_AsSByte: + case NI_Base_Vector256_AsSingle: + case NI_Base_Vector256_AsUInt16: + case NI_Base_Vector256_AsUInt32: + case NI_Base_Vector256_AsUInt64: + case NI_Base_Vector256_Zero: +#endif // _TARGET_XARCH_ + { + return impBaseIntrinsic(ni, method, sig); + } + + default: + { + break; + } + } + + if ((ni > NI_HW_INTRINSIC_START) && (ni < NI_HW_INTRINSIC_END)) { GenTree* hwintrinsic = impHWIntrinsic(ni, method, sig, mustExpand); @@ -4045,6 +4092,125 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, return retNode; } +#ifdef FEATURE_HW_INTRINSICS +//------------------------------------------------------------------------ +// impBaseIntrinsic: dispatch intrinsics to their own implementation +// +// Arguments: +// intrinsic -- id of the intrinsic function. +// method -- method handle of the intrinsic function. +// sig -- signature of the intrinsic call +// +// Return Value: +// the expanded intrinsic. +// +GenTree* Compiler::impBaseIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig) +{ + GenTree* retNode = nullptr; + unsigned simdSize = 0; + var_types baseType = getBaseTypeAndSizeOfSIMDType(sig->retTypeClass, &simdSize); + var_types retType = getSIMDTypeForSize(simdSize); + + if (sig->hasThis()) + { + CORINFO_CLASS_HANDLE thisClass = info.compCompHnd->getArgClass(sig, sig->args); + var_types thisType = getBaseTypeOfSIMDType(thisClass); + + if (!varTypeIsArithmetic(thisType)) + { + return nullptr; + } + } + + if (!varTypeIsArithmetic(baseType)) + { + return nullptr; + } + + switch (intrinsic) + { +#if defined(_TARGET_ARM64_) + case NI_Base_Vector64_AsByte: + case NI_Base_Vector64_AsInt16: + case NI_Base_Vector64_AsInt32: + case NI_Base_Vector64_AsSByte: + case NI_Base_Vector64_AsSingle: + case NI_Base_Vector64_AsUInt16: + case NI_Base_Vector64_AsUInt32: +#endif // _TARGET_ARM64_ + case NI_Base_Vector128_As: + case NI_Base_Vector128_AsByte: + case NI_Base_Vector128_AsDouble: + case NI_Base_Vector128_AsInt16: + case NI_Base_Vector128_AsInt32: + case NI_Base_Vector128_AsInt64: + case NI_Base_Vector128_AsSByte: + case NI_Base_Vector128_AsSingle: + case NI_Base_Vector128_AsUInt16: + case NI_Base_Vector128_AsUInt32: + case NI_Base_Vector128_AsUInt64: +#if defined(_TARGET_XARCH_) + case NI_Base_Vector256_As: + case NI_Base_Vector256_AsByte: + case NI_Base_Vector256_AsDouble: + case NI_Base_Vector256_AsInt16: + case NI_Base_Vector256_AsInt32: + case NI_Base_Vector256_AsInt64: + case NI_Base_Vector256_AsSByte: + case NI_Base_Vector256_AsSingle: + case NI_Base_Vector256_AsUInt16: + case NI_Base_Vector256_AsUInt32: + case NI_Base_Vector256_AsUInt64: +#endif // _TARGET_XARCH_ + { + // We fold away the cast here, as it only exists to satisfy + // the type system. It is safe to do this here since the retNode type + // and the signature return type are both the same TYP_SIMD. + + assert(sig->numArgs == 0); + assert(sig->hasThis()); + + retNode = impSIMDPopStack(retType, true, sig->retTypeClass); + SetOpLclRelatedToSIMDIntrinsic(retNode); + assert(retNode->gtType == getSIMDTypeForSize(getSIMDTypeSizeInBytes(sig->retTypeSigClass))); + break; + } + +#ifdef _TARGET_XARCH_ + case NI_Base_Vector128_Zero: + { + assert(sig->numArgs == 0); + + if (compSupports(InstructionSet_SSE)) + { + retNode = gtNewSimdHWIntrinsicNode(retType, intrinsic, baseType, simdSize); + } + break; + } + + case NI_Base_Vector256_Zero: + { + assert(sig->numArgs == 0); + + if (compSupports(InstructionSet_AVX)) + { + retNode = gtNewSimdHWIntrinsicNode(retType, intrinsic, baseType, simdSize); + } + break; + } +#endif // _TARGET_XARCH_ + + default: + { + unreached(); + break; + } + } + + return retNode; +} +#endif // FEATURE_HW_INTRINSICS + GenTree* Compiler::impMathIntrinsic(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, var_types callType, @@ -4179,21 +4345,207 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) result = NI_System_Collections_Generic_EqualityComparer_get_Default; } } - #ifdef FEATURE_HW_INTRINSICS -#if defined(_TARGET_XARCH_) - if (strcmp(namespaceName, "System.Runtime.Intrinsics.X86") == 0) + else if (strncmp(namespaceName, "System.Runtime.Intrinsics", 25) == 0) { - result = HWIntrinsicInfo::lookupId(className, methodName); - } + namespaceName += 25; + + if (namespaceName[0] == '\0') + { + if (strncmp(className, "Vector", 6) == 0) + { + className += 6; + +#if defined(_TARGET_ARM64_) + if (strncmp(className, "64", 2) == 0) + { + className += 2; + + if (strcmp(className, "`1") == 0) + { + if (strncmp(methodName, "As", 2) == 0) + { + methodName += 2; + + // Vector64_As, Vector64_AsDouble, Vector64_AsInt64, and Vector64_AsUInt64 + // are not currently supported as they require additional plumbing to be + // supported by the JIT as TYP_SIMD8. + + if (strcmp(methodName, "Byte") == 0) + { + result = NI_Base_Vector64_AsByte; + } + else if (strcmp(methodName, "Int16") == 0) + { + result = NI_Base_Vector64_AsInt16; + } + else if (strcmp(methodName, "Int32") == 0) + { + result = NI_Base_Vector64_AsInt32; + } + else if (strcmp(methodName, "SByte") == 0) + { + result = NI_Base_Vector64_AsSByte; + } + else if (strcmp(methodName, "Single") == 0) + { + result = NI_Base_Vector64_AsSingle; + } + else if (strcmp(methodName, "UInt16") == 0) + { + result = NI_Base_Vector64_AsUInt16; + } + else if (strcmp(methodName, "UInt32") == 0) + { + result = NI_Base_Vector64_AsUInt32; + } + } + } + } + else +#endif // _TARGET_ARM64_ + if (strncmp(className, "128", 3) == 0) + { + className += 3; + + if (strcmp(className, "`1") == 0) + { + if (strncmp(methodName, "As", 2) == 0) + { + methodName += 2; + + if (strcmp(methodName, "`1") == 0) + { + result = NI_Base_Vector128_As; + } + else if (strcmp(methodName, "Byte") == 0) + { + result = NI_Base_Vector128_AsByte; + } + else if (strcmp(methodName, "Double") == 0) + { + result = NI_Base_Vector128_AsDouble; + } + else if (strcmp(methodName, "Int16") == 0) + { + result = NI_Base_Vector128_AsInt16; + } + else if (strcmp(methodName, "Int32") == 0) + { + result = NI_Base_Vector128_AsInt32; + } + else if (strcmp(methodName, "Int64") == 0) + { + result = NI_Base_Vector128_AsInt64; + } + else if (strcmp(methodName, "SByte") == 0) + { + result = NI_Base_Vector128_AsSByte; + } + else if (strcmp(methodName, "Single") == 0) + { + result = NI_Base_Vector128_AsSingle; + } + else if (strcmp(methodName, "UInt16") == 0) + { + result = NI_Base_Vector128_AsUInt16; + } + else if (strcmp(methodName, "UInt32") == 0) + { + result = NI_Base_Vector128_AsUInt32; + } + else if (strcmp(methodName, "UInt64") == 0) + { + result = NI_Base_Vector128_AsUInt64; + } + } +#if defined(_TARGET_XARCH_) + else if (strcmp(methodName, "get_Zero") == 0) + { + result = NI_Base_Vector128_Zero; + } +#endif // _TARGET_XARCH_ + } + } +#if defined(_TARGET_XARCH_) + else if (strncmp(className, "256", 3) == 0) + { + className += 3; + + if (strcmp(className, "`1") == 0) + { + if (strncmp(methodName, "As", 2) == 0) + { + methodName += 2; + + if (strcmp(methodName, "`1") == 0) + { + result = NI_Base_Vector256_As; + } + else if (strcmp(methodName, "Byte") == 0) + { + result = NI_Base_Vector256_AsByte; + } + else if (strcmp(methodName, "Double") == 0) + { + result = NI_Base_Vector256_AsDouble; + } + else if (strcmp(methodName, "Int16") == 0) + { + result = NI_Base_Vector256_AsInt16; + } + else if (strcmp(methodName, "Int32") == 0) + { + result = NI_Base_Vector256_AsInt32; + } + else if (strcmp(methodName, "Int64") == 0) + { + result = NI_Base_Vector256_AsInt64; + } + else if (strcmp(methodName, "SByte") == 0) + { + result = NI_Base_Vector256_AsSByte; + } + else if (strcmp(methodName, "Single") == 0) + { + result = NI_Base_Vector256_AsSingle; + } + else if (strcmp(methodName, "UInt16") == 0) + { + result = NI_Base_Vector256_AsUInt16; + } + else if (strcmp(methodName, "UInt32") == 0) + { + result = NI_Base_Vector256_AsUInt32; + } + else if (strcmp(methodName, "UInt64") == 0) + { + result = NI_Base_Vector256_AsUInt64; + } + } + else if (strcmp(methodName, "get_Zero") == 0) + { + result = NI_Base_Vector256_Zero; + } + } + } +#endif // _TARGET_XARCH_ + } + } +#if defined(_TARGET_XARCH_) + else if (strcmp(namespaceName, ".X86") == 0) + { + result = HWIntrinsicInfo::lookupId(className, methodName); + } #elif defined(_TARGET_ARM64_) - if (strcmp(namespaceName, "System.Runtime.Intrinsics.Arm.Arm64") == 0) - { - result = lookupHWIntrinsic(className, methodName); - } + else if (strcmp(namespaceName, ".Arm.Arm64") == 0) + { + result = lookupHWIntrinsic(className, methodName); + } #else // !defined(_TARGET_XARCH_) && !defined(_TARGET_ARM64_) #error Unsupported platform #endif // !defined(_TARGET_XARCH_) && !defined(_TARGET_ARM64_) + } #endif // FEATURE_HW_INTRINSICS return result; diff --git a/src/jit/instr.h b/src/jit/instr.h index 8d1c2215dd..058bec1b65 100644 --- a/src/jit/instr.h +++ b/src/jit/instr.h @@ -296,26 +296,25 @@ enum InstructionSet { InstructionSet_ILLEGAL = 0, #ifdef _TARGET_XARCH_ + InstructionSet_Base, // Start linear order SIMD instruction sets // These ISAs have strictly generation to generation order. - InstructionSet_SSE = 1, - InstructionSet_SSE2 = 2, - InstructionSet_SSE3 = 3, - InstructionSet_SSSE3 = 4, - InstructionSet_SSE41 = 5, - InstructionSet_SSE42 = 6, - InstructionSet_AVX = 7, - InstructionSet_AVX2 = 8, - // Reserve values <32 for future SIMD instruction sets (i.e., AVX512), + InstructionSet_SSE, + InstructionSet_SSE2, + InstructionSet_SSE3, + InstructionSet_SSSE3, + InstructionSet_SSE41, + InstructionSet_SSE42, + InstructionSet_AVX, + InstructionSet_AVX2, // End linear order SIMD instruction sets. - - InstructionSet_AES = 32, - InstructionSet_BMI1 = 33, - InstructionSet_BMI2 = 34, - InstructionSet_FMA = 35, - InstructionSet_LZCNT = 36, - InstructionSet_PCLMULQDQ = 37, - InstructionSet_POPCNT = 38, + InstructionSet_AES, + InstructionSet_BMI1, + InstructionSet_BMI2, + InstructionSet_FMA, + InstructionSet_LZCNT, + InstructionSet_PCLMULQDQ, + InstructionSet_POPCNT, #elif defined(_TARGET_ARM_) InstructionSet_NEON, #elif defined(_TARGET_ARM64_) diff --git a/src/jit/jitconfigvalues.h b/src/jit/jitconfigvalues.h index f238feeb68..383264e6a3 100644 --- a/src/jit/jitconfigvalues.h +++ b/src/jit/jitconfigvalues.h @@ -234,25 +234,26 @@ CONFIG_INTEGER(EnableSSE3_4, W("EnableSSE3_4"), 1) // Enable SSE3, SSSE3, SSE 4. #if defined(_TARGET_AMD64_) || defined(_TARGET_X86_) // Enable AVX instruction set for wide operations as default. When both AVX and SSE3_4 are set, we will use the most // capable instruction set available which will prefer AVX over SSE3/4. -CONFIG_INTEGER(EnableSSE, W("EnableSSE"), 1) // Enable SSE -CONFIG_INTEGER(EnableSSE2, W("EnableSSE2"), 1) // Enable SSE2 -CONFIG_INTEGER(EnableSSE3, W("EnableSSE3"), 1) // Enable SSE3 -CONFIG_INTEGER(EnableSSSE3, W("EnableSSSE3"), 1) // Enable SSSE3 -CONFIG_INTEGER(EnableSSE41, W("EnableSSE41"), 1) // Enable SSE41 -CONFIG_INTEGER(EnableSSE42, W("EnableSSE42"), 1) // Enable SSE42 -CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 1) // Enable AVX -CONFIG_INTEGER(EnableAVX2, W("EnableAVX2"), 1) // Enable AVX2 -CONFIG_INTEGER(EnableFMA, W("EnableFMA"), 1) // Enable FMA -CONFIG_INTEGER(EnableAES, W("EnableAES"), 1) // Enable AES -CONFIG_INTEGER(EnableBMI1, W("EnableBMI1"), 1) // Enable BMI1 -CONFIG_INTEGER(EnableBMI2, W("EnableBMI2"), 1) // Enable BMI2 -CONFIG_INTEGER(EnableLZCNT, W("EnableLZCNT"), 1) // Enable AES -CONFIG_INTEGER(EnablePCLMULQDQ, W("EnablePCLMULQDQ"), 1) // Enable PCLMULQDQ -CONFIG_INTEGER(EnablePOPCNT, W("EnablePOPCNT"), 1) // Enable POPCNT -#else // !defined(_TARGET_AMD64_) && !defined(_TARGET_X86_) +CONFIG_INTEGER(EnableHWIntrinsic, W("EnableHWIntrinsic"), 1) // Enable Base +CONFIG_INTEGER(EnableSSE, W("EnableSSE"), 1) // Enable SSE +CONFIG_INTEGER(EnableSSE2, W("EnableSSE2"), 1) // Enable SSE2 +CONFIG_INTEGER(EnableSSE3, W("EnableSSE3"), 1) // Enable SSE3 +CONFIG_INTEGER(EnableSSSE3, W("EnableSSSE3"), 1) // Enable SSSE3 +CONFIG_INTEGER(EnableSSE41, W("EnableSSE41"), 1) // Enable SSE41 +CONFIG_INTEGER(EnableSSE42, W("EnableSSE42"), 1) // Enable SSE42 +CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 1) // Enable AVX +CONFIG_INTEGER(EnableAVX2, W("EnableAVX2"), 1) // Enable AVX2 +CONFIG_INTEGER(EnableFMA, W("EnableFMA"), 1) // Enable FMA +CONFIG_INTEGER(EnableAES, W("EnableAES"), 1) // Enable AES +CONFIG_INTEGER(EnableBMI1, W("EnableBMI1"), 1) // Enable BMI1 +CONFIG_INTEGER(EnableBMI2, W("EnableBMI2"), 1) // Enable BMI2 +CONFIG_INTEGER(EnableLZCNT, W("EnableLZCNT"), 1) // Enable AES +CONFIG_INTEGER(EnablePCLMULQDQ, W("EnablePCLMULQDQ"), 1) // Enable PCLMULQDQ +CONFIG_INTEGER(EnablePOPCNT, W("EnablePOPCNT"), 1) // Enable POPCNT +#else // !defined(_TARGET_AMD64_) && !defined(_TARGET_X86_) // Enable AVX instruction set for wide operations as default CONFIG_INTEGER(EnableAVX, W("EnableAVX"), 0) -#endif // !defined(_TARGET_AMD64_) && !defined(_TARGET_X86_) +#endif // !defined(_TARGET_AMD64_) && !defined(_TARGET_X86_) /// /// JIT /// diff --git a/src/jit/namedintrinsiclist.h b/src/jit/namedintrinsiclist.h index edf006fe6f..6644a7291a 100644 --- a/src/jit/namedintrinsiclist.h +++ b/src/jit/namedintrinsiclist.h @@ -15,6 +15,7 @@ enum NamedIntrinsic : unsigned short NI_Math_Round = 3, NI_System_Collections_Generic_EqualityComparer_get_Default = 4, NI_System_Buffers_Binary_BinaryPrimitives_ReverseEndianness = 5, + #ifdef FEATURE_HW_INTRINSICS NI_HW_INTRINSIC_START, #if defined(_TARGET_XARCH_) -- 2.34.1