gentree.cpp
gschecks.cpp
hashbv.cpp
+ hwintrinsic.cpp
hostallocator.cpp
importer.cpp
inline.cpp
NamedIntrinsic lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method);
#ifdef FEATURE_HW_INTRINSICS
+ GenTree* impHWIntrinsic(NamedIntrinsic intrinsic,
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_SIG_INFO* sig,
+ bool mustExpand);
+ GenTree* impUnsupportedHWIntrinsic(unsigned helper,
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_SIG_INFO* sig,
+ bool mustExpand);
#ifdef _TARGET_XARCH_
static InstructionSet lookupHWIntrinsicISA(const char* className);
static NamedIntrinsic lookupHWIntrinsic(const char* methodName, InstructionSet isa);
static InstructionSet isaOfHWIntrinsic(NamedIntrinsic intrinsic);
static bool isIntrinsicAnIsSupportedPropertyGetter(NamedIntrinsic intrinsic);
static bool isFullyImplmentedISAClass(InstructionSet isa);
- GenTree* impUnsupportedHWIntrinsic(unsigned helper,
- CORINFO_METHOD_HANDLE method,
- CORINFO_SIG_INFO* sig,
- bool mustExpand);
- GenTree* impX86HWIntrinsic(NamedIntrinsic intrinsic,
- CORINFO_METHOD_HANDLE method,
- CORINFO_SIG_INFO* sig,
- bool mustExpand);
GenTree* impSSEIntrinsic(NamedIntrinsic intrinsic,
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
#ifdef _TARGET_ARM64_
InstructionSet lookupHWIntrinsicISA(const char* className);
NamedIntrinsic lookupHWIntrinsic(const char* className, const char* methodName);
- GenTree* impHWIntrinsic(NamedIntrinsic intrinsic,
- CORINFO_METHOD_HANDLE method,
- CORINFO_SIG_INFO* sig,
- bool mustExpand);
- GenTree* impUnsupportedHWIntrinsic(unsigned helper,
- CORINFO_METHOD_HANDLE method,
- CORINFO_SIG_INFO* sig,
- bool mustExpand);
const HWIntrinsicInfo& getHWIntrinsicInfo(NamedIntrinsic);
#endif // _TARGET_ARM64_
#endif // FEATURE_HW_INTRINSICS
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "jitpch.h"
+
+#ifdef FEATURE_HW_INTRINSICS
+
+//------------------------------------------------------------------------
+// impUnsupportedHWIntrinsic: returns a node for an unsupported HWIntrinsic
+//
+// Arguments:
+// helper - JIT helper ID for the exception to be thrown
+// method - method handle of the intrinsic function.
+// sig - signature of the intrinsic call
+// mustExpand - true if the intrinsic must return a GenTree*; otherwise, false
+//
+// Return Value:
+// a gtNewMustThrowException if mustExpand is true; otherwise, nullptr
+//
+GenTree* Compiler::impUnsupportedHWIntrinsic(unsigned helper,
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_SIG_INFO* sig,
+ bool mustExpand)
+{
+ // We've hit some error case and may need to return a node for the given error.
+ //
+ // When `mustExpand=false`, we are attempting to inline the intrinsic directly into another method. In this
+ // scenario, we need to return `nullptr` so that a GT_CALL to the intrinsic is emitted instead. This is to
+ // ensure that everything continues to behave correctly when optimizations are enabled (e.g. things like the
+ // inliner may expect the node we return to have a certain signature, and the `MustThrowException` node won't
+ // match that).
+ //
+ // When `mustExpand=true`, we are in a GT_CALL to the intrinsic and are attempting to JIT it. This will generally
+ // be in response to an indirect call (e.g. done via reflection) or in response to an earlier attempt returning
+ // `nullptr` (under `mustExpand=false`). In that scenario, we are safe to return the `MustThrowException` node.
+
+ if (mustExpand)
+ {
+ for (unsigned i = 0; i < sig->numArgs; i++)
+ {
+ impPopStack();
+ }
+
+ return gtNewMustThrowException(helper, JITtype2varType(sig->retType), sig->retTypeClass);
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleForHWSIMD(var_types simdType, var_types simdBaseType)
+{
+ if (simdType == TYP_SIMD16)
+ {
+ switch (simdBaseType)
+ {
+ case TYP_FLOAT:
+ return Vector128FloatHandle;
+ case TYP_DOUBLE:
+ return Vector128DoubleHandle;
+ case TYP_INT:
+ return Vector128IntHandle;
+ case TYP_USHORT:
+ return Vector128UShortHandle;
+ case TYP_UBYTE:
+ return Vector128UByteHandle;
+ case TYP_SHORT:
+ return Vector128ShortHandle;
+ case TYP_BYTE:
+ return Vector128ByteHandle;
+ case TYP_LONG:
+ return Vector128LongHandle;
+ case TYP_UINT:
+ return Vector128UIntHandle;
+ case TYP_ULONG:
+ return Vector128ULongHandle;
+ default:
+ assert(!"Didn't find a class handle for simdType");
+ }
+ }
+#ifdef _TARGET_XARCH_
+ else if (simdType == TYP_SIMD32)
+ {
+ switch (simdBaseType)
+ {
+ case TYP_FLOAT:
+ return Vector256FloatHandle;
+ case TYP_DOUBLE:
+ return Vector256DoubleHandle;
+ case TYP_INT:
+ return Vector256IntHandle;
+ case TYP_USHORT:
+ return Vector256UShortHandle;
+ case TYP_UBYTE:
+ return Vector256UByteHandle;
+ case TYP_SHORT:
+ return Vector256ShortHandle;
+ case TYP_BYTE:
+ return Vector256ByteHandle;
+ case TYP_LONG:
+ return Vector256LongHandle;
+ case TYP_UINT:
+ return Vector256UIntHandle;
+ case TYP_ULONG:
+ return Vector256ULongHandle;
+ default:
+ assert(!"Didn't find a class handle for simdType");
+ }
+ }
+#endif // _TARGET_XARCH_
+#ifdef _TARGET_ARM64_
+ else if (simdType == TYP_SIMD8)
+ {
+ switch (simdBaseType)
+ {
+ case TYP_FLOAT:
+ return Vector64FloatHandle;
+ case TYP_UINT:
+ return Vector64UIntHandle;
+ case TYP_USHORT:
+ return Vector64UShortHandle;
+ case TYP_UBYTE:
+ return Vector64UByteHandle;
+ case TYP_SHORT:
+ return Vector64ShortHandle;
+ case TYP_BYTE:
+ return Vector64ByteHandle;
+ case TYP_INT:
+ return Vector64IntHandle;
+ default:
+ assert(!"Didn't find a class handle for simdType");
+ }
+ }
+#endif // _TARGET_ARM64_
+
+ return NO_CLASS_HANDLE;
+}
+
+#endif // FEATURE_HW_INTRINSICS
}
//------------------------------------------------------------------------
-// impUnsupportedHWIntrinsic: returns a node for an unsupported HWIntrinsic
-//
-// Arguments:
-// helper - JIT helper ID for the exception to be thrown
-// method - method handle of the intrinsic function.
-// sig - signature of the intrinsic call
-// mustExpand - true if the intrinsic must return a GenTree*; otherwise, false
-//
-// Return Value:
-// a gtNewMustThrowException if mustExpand is true; otherwise, nullptr
-//
-GenTree* Compiler::impUnsupportedHWIntrinsic(unsigned helper,
- CORINFO_METHOD_HANDLE method,
- CORINFO_SIG_INFO* sig,
- bool mustExpand)
-{
- // We've hit some error case and may need to return a node for the given error.
- //
- // When `mustExpand=false`, we are attempting to inline the intrinsic directly into another method. In this
- // scenario, we need to return `nullptr` so that a GT_CALL to the intrinsic is emitted instead. This is to
- // ensure that everything continues to behave correctly when optimizations are enabled (e.g. things like the
- // inliner may expect the node we return to have a certain signature, and the `MustThrowException` node won't
- // match that).
- //
- // When `mustExpand=true`, we are in a GT_CALL to the intrinsic and are attempting to JIT it. This will generally
- // be in response to an indirect call (e.g. done via reflection) or in response to an earlier attempt returning
- // `nullptr` (under `mustExpand=false`). In that scenario, we are safe to return the `MustThrowException` node.
-
- if (mustExpand)
- {
- for (unsigned i = 0; i < sig->numArgs; i++)
- {
- impPopStack();
- }
-
- return gtNewMustThrowException(helper, JITtype2varType(sig->retType), sig->retTypeClass);
- }
- else
- {
- return nullptr;
- }
-}
-
-//------------------------------------------------------------------------
// impHWIntrinsic: dispatch hardware intrinsics to their own implementation
// function
//
return retNode;
}
-CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleForHWSIMD(var_types simdType, var_types simdBaseType)
-{
- if (simdType == TYP_SIMD16)
- {
- switch (simdBaseType)
- {
- case TYP_FLOAT:
- return Vector128FloatHandle;
- case TYP_DOUBLE:
- return Vector128DoubleHandle;
- case TYP_INT:
- return Vector128IntHandle;
- case TYP_USHORT:
- return Vector128UShortHandle;
- case TYP_UBYTE:
- return Vector128UByteHandle;
- case TYP_SHORT:
- return Vector128ShortHandle;
- case TYP_BYTE:
- return Vector128ByteHandle;
- case TYP_LONG:
- return Vector128LongHandle;
- case TYP_UINT:
- return Vector128UIntHandle;
- case TYP_ULONG:
- return Vector128ULongHandle;
- default:
- assert(!"Didn't find a class handle for simdType");
- }
- }
- else if (simdType == TYP_SIMD8)
- {
- switch (simdBaseType)
- {
- case TYP_FLOAT:
- return Vector64FloatHandle;
- case TYP_UINT:
- return Vector64UIntHandle;
- case TYP_USHORT:
- return Vector64UShortHandle;
- case TYP_UBYTE:
- return Vector64UByteHandle;
- case TYP_SHORT:
- return Vector64ShortHandle;
- case TYP_BYTE:
- return Vector64ByteHandle;
- case TYP_INT:
- return Vector64IntHandle;
- default:
- assert(!"Didn't find a class handle for simdType");
- }
- }
-
- return NO_CLASS_HANDLE;
-}
-
#endif // FEATURE_HW_INTRINSICS
}
//------------------------------------------------------------------------
-// impUnsupportedHWIntrinsic: returns a node for an unsupported HWIntrinsic
-//
-// Arguments:
-// helper - JIT helper ID for the exception to be thrown
-// method - method handle of the intrinsic function.
-// sig - signature of the intrinsic call
-// mustExpand - true if the intrinsic must return a GenTree*; otherwise, false
-//
-// Return Value:
-// a gtNewMustThrowException if mustExpand is true; otherwise, nullptr
-//
-GenTree* Compiler::impUnsupportedHWIntrinsic(unsigned helper,
- CORINFO_METHOD_HANDLE method,
- CORINFO_SIG_INFO* sig,
- bool mustExpand)
-{
- // We've hit some error case and may need to return a node for the given error.
- //
- // When `mustExpand=false`, we are attempting to inline the intrinsic directly into another method. In this
- // scenario, we need to return `nullptr` so that a GT_CALL to the intrinsic is emitted instead. This is to
- // ensure that everything continues to behave correctly when optimizations are enabled (e.g. things like the
- // inliner may expect the node we return to have a certain signature, and the `MustThrowException` node won't
- // match that).
- //
- // When `mustExpand=true`, we are in a GT_CALL to the intrinsic and are attempting to JIT it. This will generally
- // be in response to an indirect call (e.g. done via reflection) or in response to an earlier attempt returning
- // `nullptr` (under `mustExpand=false`). In that scenario, we are safe to return the `MustThrowException` node.
-
- if (mustExpand)
- {
- for (unsigned i = 0; i < sig->numArgs; i++)
- {
- impPopStack();
- }
-
- return gtNewMustThrowException(helper, JITtype2varType(sig->retType), sig->retTypeClass);
- }
- else
- {
- return nullptr;
- }
-}
-
-//------------------------------------------------------------------------
// impIsTableDrivenHWIntrinsic:
//
// Arguments:
}
//------------------------------------------------------------------------
-// impX86HWIntrinsic: dispatch hardware intrinsics to their own implementation
+// impHWIntrinsic: dispatch hardware intrinsics to their own implementation
//
// Arguments:
// intrinsic -- id of the intrinsic function.
// Return Value:
// the expanded intrinsic.
//
-GenTree* Compiler::impX86HWIntrinsic(NamedIntrinsic intrinsic,
- CORINFO_METHOD_HANDLE method,
- CORINFO_SIG_INFO* sig,
- bool mustExpand)
+GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_SIG_INFO* sig,
+ bool mustExpand)
{
InstructionSet isa = isaOfHWIntrinsic(intrinsic);
HWIntrinsicCategory category = categoryOfHWIntrinsic(intrinsic);
}
}
-CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleForHWSIMD(var_types simdType, var_types simdBaseType)
-{
- if (simdType == TYP_SIMD16)
- {
- switch (simdBaseType)
- {
- case TYP_FLOAT:
- return Vector128FloatHandle;
- case TYP_DOUBLE:
- return Vector128DoubleHandle;
- case TYP_INT:
- return Vector128IntHandle;
- case TYP_USHORT:
- return Vector128UShortHandle;
- case TYP_UBYTE:
- return Vector128UByteHandle;
- case TYP_SHORT:
- return Vector128ShortHandle;
- case TYP_BYTE:
- return Vector128ByteHandle;
- case TYP_LONG:
- return Vector128LongHandle;
- case TYP_UINT:
- return Vector128UIntHandle;
- case TYP_ULONG:
- return Vector128ULongHandle;
- default:
- assert(!"Didn't find a class handle for simdType");
- }
- }
- else if (simdType == TYP_SIMD32)
- {
- switch (simdBaseType)
- {
- case TYP_FLOAT:
- return Vector256FloatHandle;
- case TYP_DOUBLE:
- return Vector256DoubleHandle;
- case TYP_INT:
- return Vector256IntHandle;
- case TYP_USHORT:
- return Vector256UShortHandle;
- case TYP_UBYTE:
- return Vector256UByteHandle;
- case TYP_SHORT:
- return Vector256ShortHandle;
- case TYP_BYTE:
- return Vector256ByteHandle;
- case TYP_LONG:
- return Vector256LongHandle;
- case TYP_UINT:
- return Vector256UIntHandle;
- case TYP_ULONG:
- return Vector256ULongHandle;
- default:
- assert(!"Didn't find a class handle for simdType");
- }
- }
-
- return NO_CLASS_HANDLE;
-}
-
GenTree* Compiler::impSSEIntrinsic(NamedIntrinsic intrinsic,
CORINFO_METHOD_HANDLE method,
CORINFO_SIG_INFO* sig,
ni = lookupNamedIntrinsic(method);
#ifdef FEATURE_HW_INTRINSICS
-#ifdef _TARGET_XARCH_
- if (ni > NI_HW_INTRINSIC_START && ni < NI_HW_INTRINSIC_END)
- {
- return impX86HWIntrinsic(ni, method, sig, mustExpand);
- }
-#endif // _TARGET_XARCH_
-#ifdef _TARGET_ARM64_
if (ni > NI_HW_INTRINSIC_START && ni < NI_HW_INTRINSIC_END)
{
return impHWIntrinsic(ni, method, sig, mustExpand);
}
-#endif // _TARGET_XARCH_
#endif // FEATURE_HW_INTRINSICS
}
}