summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFei Peng <fei.peng@intel.com>2017-12-20 14:13:47 -0800
committerFei Peng <fei.peng@intel.com>2017-12-20 14:13:47 -0800
commit95c6e74fc8d8b40c883ed373c3ef2335dc23d967 (patch)
treeb2ba3389456b349e722f13e18a2e984fdcc70ca0
parent698264b3683e28aa25dc4061e136fc9d58af2beb (diff)
downloadcoreclr-95c6e74fc8d8b40c883ed373c3ef2335dc23d967.tar.gz
coreclr-95c6e74fc8d8b40c883ed373c3ef2335dc23d967.tar.bz2
coreclr-95c6e74fc8d8b40c883ed373c3ef2335dc23d967.zip
Add COMPlus_EnableIncompleteISAClass and streamline IsSupported
-rw-r--r--src/jit/compiler.h3
-rw-r--r--src/jit/hwintrinsicxarch.cpp251
-rw-r--r--src/jit/jitconfigvalues.h4
-rw-r--r--tests/src/JIT/HardwareIntrinsics/X86/IsSupported.cs61
4 files changed, 119 insertions, 200 deletions
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 813f34460f..904d993f32 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -3026,6 +3026,7 @@ protected:
NamedIntrinsic lookupHWIntrinsic(const char* methodName, InstructionSet isa);
InstructionSet isaOfHWIntrinsic(NamedIntrinsic intrinsic);
bool isIntrinsicAnIsSupportedPropertyGetter(NamedIntrinsic intrinsic);
+ bool isFullyImplmentedISAClass(InstructionSet isa);
#ifdef _TARGET_XARCH_
GenTree* impX86HWIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
GenTree* impSSEIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
@@ -3043,6 +3044,8 @@ protected:
GenTree* impLZCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
GenTree* impPCLMULQDQIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
GenTree* impPOPCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig);
+ bool compSupportsHWIntrinsic(InstructionSet isa);
+ bool isScalarISA(InstructionSet isa);
#endif // _TARGET_XARCH_
#endif // FEATURE_HW_INTRINSICS
GenTreePtr impArrayAccessIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
diff --git a/src/jit/hwintrinsicxarch.cpp b/src/jit/hwintrinsicxarch.cpp
index f2f98b41ff..719ac458ec 100644
--- a/src/jit/hwintrinsicxarch.cpp
+++ b/src/jit/hwintrinsicxarch.cpp
@@ -187,6 +187,85 @@ bool Compiler::isIntrinsicAnIsSupportedPropertyGetter(NamedIntrinsic intrinsic)
}
//------------------------------------------------------------------------
+// isFullyImplmentedISAClass: return true if all the hardware intrinsics
+// of this ISA are implemented in RyuJIT.
+//
+// Arguments:
+// isa - Instruction set
+// Return Value:
+// true - all the hardware intrinsics of "isa" are implemented in RyuJIT.
+//
+bool Compiler::isFullyImplmentedISAClass(InstructionSet isa)
+{
+ switch (isa)
+ {
+ case InstructionSet_SSE:
+ case InstructionSet_SSE2:
+ case InstructionSet_SSE3:
+ case InstructionSet_SSSE3:
+ case InstructionSet_SSE41:
+ case InstructionSet_SSE42:
+ case InstructionSet_AVX:
+ case InstructionSet_AVX2:
+ case InstructionSet_AES:
+ case InstructionSet_BMI1:
+ case InstructionSet_BMI2:
+ case InstructionSet_FMA:
+ case InstructionSet_PCLMULQDQ:
+ return false;
+
+ case InstructionSet_LZCNT:
+ case InstructionSet_POPCNT:
+ return true;
+
+ default:
+ unreached();
+ }
+}
+
+//------------------------------------------------------------------------
+// isScalarISA:
+//
+// Arguments:
+// isa - Instruction set
+// Return Value:
+// true - if "isa" only contains scalar instructions
+//
+bool Compiler::isScalarISA(InstructionSet isa)
+{
+ switch (isa)
+ {
+ case InstructionSet_BMI1:
+ case InstructionSet_BMI2:
+ case InstructionSet_LZCNT:
+ case InstructionSet_POPCNT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+//------------------------------------------------------------------------
+// compSupportsHWIntrinsic: compiler support of hardware intrinsics
+//
+// Arguments:
+// isa - Instruction set
+// Return Value:
+// true if
+// - isa is a scalar ISA
+// - isa is a SIMD ISA and featureSIMD=true
+// - isa is fully implemented or EnableIncompleteISAClass=true
+bool Compiler::compSupportsHWIntrinsic(InstructionSet isa)
+{
+ return (featureSIMD || isScalarISA(isa)) && (
+#ifdef DEBUG
+ JitConfig.EnableIncompleteISAClass() ||
+#endif
+ isFullyImplmentedISAClass(isa));
+}
+
+//------------------------------------------------------------------------
// impX86HWIntrinsic: dispatch hardware intrinsics to their own implementation
// function
//
@@ -201,12 +280,17 @@ bool Compiler::isIntrinsicAnIsSupportedPropertyGetter(NamedIntrinsic intrinsic)
GenTree* Compiler::impX86HWIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
{
InstructionSet isa = isaOfHWIntrinsic(intrinsic);
- // Will throw PlatformNotSupportedException if
- // - calling hardware intrinsics on unsupported hardware
- // - calling SIMD hardware intrinsics with featureSIMD=false
- if ((!compSupports(isa) || (!featureSIMD && isa != InstructionSet_BMI1 && isa != InstructionSet_BMI2 &&
- isa != InstructionSet_LZCNT && isa != InstructionSet_POPCNT)) &&
- !isIntrinsicAnIsSupportedPropertyGetter(intrinsic))
+
+ // This intrinsic is supported if
+ // - the ISA is available on the underlying hardware (compSupports returns true)
+ // - the compiler supports this hardware intrinsics (compSupportsHWIntrinsic returns true)
+ bool issupported = compSupports(isa) && compSupportsHWIntrinsic(isa);
+
+ if (isIntrinsicAnIsSupportedPropertyGetter(intrinsic))
+ {
+ return gtNewIconNode(issupported);
+ }
+ else if (!issupported)
{
for (unsigned i = 0; i < sig->numArgs; i++)
{
@@ -215,6 +299,7 @@ GenTree* Compiler::impX86HWIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HA
return gtNewMustThrowException(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, JITtype2varType(sig->retType),
sig->retTypeClass);
}
+
switch (isa)
{
case InstructionSet_SSE:
@@ -322,10 +407,6 @@ GenTree* Compiler::impSSEIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HAND
GenTree* op2 = nullptr;
switch (intrinsic)
{
- case NI_SSE_IsSupported:
- retNode = gtNewIconNode(featureSIMD && compSupports(InstructionSet_SSE));
- break;
-
case NI_SSE_Add:
assert(sig->numArgs == 2);
op2 = impSIMDPopStack(TYP_SIMD16);
@@ -348,10 +429,6 @@ GenTree* Compiler::impSSE2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HAN
var_types baseType = TYP_UNKNOWN;
switch (intrinsic)
{
- case NI_SSE2_IsSupported:
- retNode = gtNewIconNode(featureSIMD && compSupports(InstructionSet_SSE2));
- break;
-
case NI_SSE2_Add:
assert(sig->numArgs == 2);
op2 = impSIMDPopStack(TYP_SIMD16);
@@ -369,38 +446,17 @@ GenTree* Compiler::impSSE2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HAN
GenTree* Compiler::impSSE3Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
{
- switch (intrinsic)
- {
- case NI_SSE3_IsSupported:
- return gtNewIconNode(featureSIMD && compSupports(InstructionSet_SSE3));
-
- default:
- return nullptr;
- }
+ return nullptr;
}
GenTree* Compiler::impSSSE3Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
{
- switch (intrinsic)
- {
- case NI_SSSE3_IsSupported:
- return gtNewIconNode(featureSIMD && compSupports(InstructionSet_SSSE3));
-
- default:
- return nullptr;
- }
+ return nullptr;
}
GenTree* Compiler::impSSE41Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
{
- switch (intrinsic)
- {
- case NI_SSE41_IsSupported:
- return gtNewIconNode(featureSIMD && compSupports(InstructionSet_SSE41));
-
- default:
- return nullptr;
- }
+ return nullptr;
}
GenTree* Compiler::impSSE42Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
@@ -415,10 +471,6 @@ GenTree* Compiler::impSSE42Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HA
CorInfoType corType;
switch (intrinsic)
{
- case NI_SSE42_IsSupported:
- retNode = gtNewIconNode(featureSIMD && compSupports(InstructionSet_SSE42));
- break;
-
case NI_SSE42_Crc32:
assert(sig->numArgs == 2);
op2 = impPopStack().val;
@@ -454,10 +506,6 @@ GenTree* Compiler::impAVXIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HAND
var_types baseType = TYP_UNKNOWN;
switch (intrinsic)
{
- case NI_AVX_IsSupported:
- retNode = gtNewIconNode(featureSIMD && compSupports(InstructionSet_AVX));
- break;
-
case NI_AVX_Add:
assert(sig->numArgs == 2);
op2 = impSIMDPopStack(TYP_SIMD32);
@@ -481,10 +529,6 @@ GenTree* Compiler::impAVX2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HAN
var_types baseType = TYP_UNKNOWN;
switch (intrinsic)
{
- case NI_AVX2_IsSupported:
- retNode = gtNewIconNode(featureSIMD && compSupports(InstructionSet_AVX2));
- break;
-
case NI_AVX2_Add:
assert(sig->numArgs == 2);
op2 = impSIMDPopStack(TYP_SIMD32);
@@ -502,124 +546,55 @@ GenTree* Compiler::impAVX2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HAN
GenTree* Compiler::impAESIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
{
- switch (intrinsic)
- {
- case NI_AES_IsSupported:
- return gtNewIconNode(featureSIMD && compSupports(InstructionSet_AES));
-
- default:
- return nullptr;
- }
+ return nullptr;
}
GenTree* Compiler::impBMI1Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
{
- switch (intrinsic)
- {
- case NI_BMI1_IsSupported:
- return gtNewIconNode(compSupports(InstructionSet_BMI1));
-
- default:
- return nullptr;
- }
+ return nullptr;
}
GenTree* Compiler::impBMI2Intrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
{
- switch (intrinsic)
- {
- case NI_BMI2_IsSupported:
- return gtNewIconNode(compSupports(InstructionSet_BMI2));
-
- default:
- return nullptr;
- }
+ return nullptr;
}
GenTree* Compiler::impFMAIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
{
- switch (intrinsic)
- {
- case NI_FMA_IsSupported:
- return gtNewIconNode(featureSIMD && compSupports(InstructionSet_FMA));
-
- default:
- return nullptr;
- }
+ return nullptr;
}
GenTree* Compiler::impLZCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
{
- GenTree* retNode = nullptr;
- GenTree* op1 = nullptr;
+ assert(sig->numArgs == 1);
+ GenTree* op = impPopStack().val;
var_types callType = JITtype2varType(sig->retType);
-
- switch (intrinsic)
- {
- case NI_LZCNT_IsSupported:
- retNode = gtNewIconNode(compSupports(InstructionSet_LZCNT));
- break;
-
- case NI_LZCNT_LeadingZeroCount:
- assert(sig->numArgs == 1);
- op1 = impPopStack().val;
#ifdef _TARGET_X86_
- if (varTypeIsLong(callType))
- {
- return gtNewMustThrowException(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, callType, sig->retTypeClass);
- }
-#endif
- retNode = gtNewScalarHWIntrinsicNode(callType, op1, NI_LZCNT_LeadingZeroCount);
- break;
-
- default:
- JITDUMP("Not implemented hardware intrinsic");
- break;
+ if (varTypeIsLong(callType))
+ {
+ return gtNewMustThrowException(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, callType, sig->retTypeClass);
}
- return retNode;
+#endif
+ return gtNewScalarHWIntrinsicNode(callType, op, NI_LZCNT_LeadingZeroCount);
}
GenTree* Compiler::impPCLMULQDQIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
{
- switch (intrinsic)
- {
- case NI_PCLMULQDQ_IsSupported:
- return gtNewIconNode(featureSIMD && compSupports(InstructionSet_PCLMULQDQ));
-
- default:
- return nullptr;
- }
+ return nullptr;
}
GenTree* Compiler::impPOPCNTIntrinsic(NamedIntrinsic intrinsic, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig)
{
- GenTree* retNode = nullptr;
- GenTree* op1 = nullptr;
+ assert(sig->numArgs == 1);
+ GenTree* op = impPopStack().val;
var_types callType = JITtype2varType(sig->retType);
-
- switch (intrinsic)
- {
- case NI_POPCNT_IsSupported:
- retNode = gtNewIconNode(compSupports(InstructionSet_POPCNT));
- break;
-
- case NI_POPCNT_PopCount:
- assert(sig->numArgs == 1);
- op1 = impPopStack().val;
#ifdef _TARGET_X86_
- if (varTypeIsLong(callType))
- {
- return gtNewMustThrowException(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, callType, sig->retTypeClass);
- }
-#endif
- retNode = gtNewScalarHWIntrinsicNode(callType, op1, NI_POPCNT_PopCount);
- break;
-
- default:
- JITDUMP("Not implemented hardware intrinsic");
- break;
+ if (varTypeIsLong(callType))
+ {
+ return gtNewMustThrowException(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, callType, sig->retTypeClass);
}
- return retNode;
+#endif
+ return gtNewScalarHWIntrinsicNode(callType, op, NI_POPCNT_PopCount);
}
#endif // FEATURE_HW_INTRINSICS
diff --git a/src/jit/jitconfigvalues.h b/src/jit/jitconfigvalues.h
index e9b9f0d275..64dfe9ce60 100644
--- a/src/jit/jitconfigvalues.h
+++ b/src/jit/jitconfigvalues.h
@@ -206,7 +206,9 @@ CONFIG_INTEGER(EnableLZCNT, W("EnableLZCNT"), 1) // Enable AES
CONFIG_INTEGER(EnablePCLMULQDQ, W("EnablePCLMULQDQ"), 1) // Enable PCLMULQDQ
CONFIG_INTEGER(EnablePOPCNT, W("EnablePOPCNT"), 1) // Enable POPCNT
#endif // defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
-#endif // defined(DEBUG)
+CONFIG_INTEGER(EnableIncompleteISAClass, W("EnableIncompleteISAClass"), 0) // Enable testing not-yet-implemented
+ // intrinsic classes
+#endif // defined(DEBUG)
#ifdef FEATURE_ENABLE_NO_RANGE_CHECKS
CONFIG_INTEGER(JitNoRangeChks, W("JitNoRngChks"), 0) // If 1, don't generate range checks
diff --git a/tests/src/JIT/HardwareIntrinsics/X86/IsSupported.cs b/tests/src/JIT/HardwareIntrinsics/X86/IsSupported.cs
index e828a4461e..bca38030cd 100644
--- a/tests/src/JIT/HardwareIntrinsics/X86/IsSupported.cs
+++ b/tests/src/JIT/HardwareIntrinsics/X86/IsSupported.cs
@@ -13,46 +13,6 @@ namespace IntelHardwareIntrinsicTest
static int Main(string[] args)
{
bool result = true;
- if (Avx2.IsSupported)
- {
- if (Avx.IsSupported)
- {
- if (!Sse42.IsSupported)
- {
- result = false;
- }
-
- if (Sse41.IsSupported)
- {
- if (Ssse3.IsSupported)
- {
- if (Sse3.IsSupported)
- {
- if (Sse2.IsSupported && Sse.IsSupported)
- {
- result = result && true;
- }
- else
- {
- result = false;
- }
- }
- else
- {
- result = false;
- }
- }
- else
- {
- result = false;
- }
- }
- else
- {
- result = false;
- }
- }
- }
if (Sse.IsSupported)
{
@@ -67,27 +27,6 @@ namespace IntelHardwareIntrinsicTest
result = false;
}
}
- else
- {
- // Non-X86 platforms
- if (Sse2.IsSupported ||
- Sse3.IsSupported ||
- Ssse3.IsSupported ||
- Sse41.IsSupported ||
- Sse42.IsSupported ||
- Avx.IsSupported ||
- Avx2.IsSupported ||
- Aes.IsSupported ||
- Bmi1.IsSupported ||
- Bmi2.IsSupported ||
- Fma.IsSupported ||
- Lzcnt.IsSupported ||
- Popcnt.IsSupported||
- Pclmulqdq.IsSupported)
- {
- result = false;
- }
- }
// Reflection call
var issupported = "get_IsSupported";