1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5#include "jitpch.h"
6
7#ifdef FEATURE_HW_INTRINSICS
8
9//------------------------------------------------------------------------
10// impUnsupportedHWIntrinsic: returns a node for an unsupported HWIntrinsic
11//
12// Arguments:
13// helper - JIT helper ID for the exception to be thrown
14// method - method handle of the intrinsic function.
15// sig - signature of the intrinsic call
16// mustExpand - true if the intrinsic must return a GenTree*; otherwise, false
17//
18// Return Value:
19// a gtNewMustThrowException if mustExpand is true; otherwise, nullptr
20//
21GenTree* Compiler::impUnsupportedHWIntrinsic(unsigned helper,
22 CORINFO_METHOD_HANDLE method,
23 CORINFO_SIG_INFO* sig,
24 bool mustExpand)
25{
26 // We've hit some error case and may need to return a node for the given error.
27 //
28 // When `mustExpand=false`, we are attempting to inline the intrinsic directly into another method. In this
29 // scenario, we need to return `nullptr` so that a GT_CALL to the intrinsic is emitted instead. This is to
30 // ensure that everything continues to behave correctly when optimizations are enabled (e.g. things like the
31 // inliner may expect the node we return to have a certain signature, and the `MustThrowException` node won't
32 // match that).
33 //
34 // When `mustExpand=true`, we are in a GT_CALL to the intrinsic and are attempting to JIT it. This will generally
35 // be in response to an indirect call (e.g. done via reflection) or in response to an earlier attempt returning
36 // `nullptr` (under `mustExpand=false`). In that scenario, we are safe to return the `MustThrowException` node.
37
38 if (mustExpand)
39 {
40 for (unsigned i = 0; i < sig->numArgs; i++)
41 {
42 impPopStack();
43 }
44
45 return gtNewMustThrowException(helper, JITtype2varType(sig->retType), sig->retTypeClass);
46 }
47 else
48 {
49 return nullptr;
50 }
51}
52
53CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleForHWSIMD(var_types simdType, var_types simdBaseType)
54{
55 if (simdType == TYP_SIMD16)
56 {
57 switch (simdBaseType)
58 {
59 case TYP_FLOAT:
60 return m_simdHandleCache->Vector128FloatHandle;
61 case TYP_DOUBLE:
62 return m_simdHandleCache->Vector128DoubleHandle;
63 case TYP_INT:
64 return m_simdHandleCache->Vector128IntHandle;
65 case TYP_USHORT:
66 return m_simdHandleCache->Vector128UShortHandle;
67 case TYP_UBYTE:
68 return m_simdHandleCache->Vector128UByteHandle;
69 case TYP_SHORT:
70 return m_simdHandleCache->Vector128ShortHandle;
71 case TYP_BYTE:
72 return m_simdHandleCache->Vector128ByteHandle;
73 case TYP_LONG:
74 return m_simdHandleCache->Vector128LongHandle;
75 case TYP_UINT:
76 return m_simdHandleCache->Vector128UIntHandle;
77 case TYP_ULONG:
78 return m_simdHandleCache->Vector128ULongHandle;
79 default:
80 assert(!"Didn't find a class handle for simdType");
81 }
82 }
83#ifdef _TARGET_XARCH_
84 else if (simdType == TYP_SIMD32)
85 {
86 switch (simdBaseType)
87 {
88 case TYP_FLOAT:
89 return m_simdHandleCache->Vector256FloatHandle;
90 case TYP_DOUBLE:
91 return m_simdHandleCache->Vector256DoubleHandle;
92 case TYP_INT:
93 return m_simdHandleCache->Vector256IntHandle;
94 case TYP_USHORT:
95 return m_simdHandleCache->Vector256UShortHandle;
96 case TYP_UBYTE:
97 return m_simdHandleCache->Vector256UByteHandle;
98 case TYP_SHORT:
99 return m_simdHandleCache->Vector256ShortHandle;
100 case TYP_BYTE:
101 return m_simdHandleCache->Vector256ByteHandle;
102 case TYP_LONG:
103 return m_simdHandleCache->Vector256LongHandle;
104 case TYP_UINT:
105 return m_simdHandleCache->Vector256UIntHandle;
106 case TYP_ULONG:
107 return m_simdHandleCache->Vector256ULongHandle;
108 default:
109 assert(!"Didn't find a class handle for simdType");
110 }
111 }
112#endif // _TARGET_XARCH_
113#ifdef _TARGET_ARM64_
114 else if (simdType == TYP_SIMD8)
115 {
116 switch (simdBaseType)
117 {
118 case TYP_FLOAT:
119 return m_simdHandleCache->Vector64FloatHandle;
120 case TYP_INT:
121 return m_simdHandleCache->Vector64IntHandle;
122 case TYP_USHORT:
123 return m_simdHandleCache->Vector64UShortHandle;
124 case TYP_UBYTE:
125 return m_simdHandleCache->Vector64UByteHandle;
126 case TYP_SHORT:
127 return m_simdHandleCache->Vector64ShortHandle;
128 case TYP_BYTE:
129 return m_simdHandleCache->Vector64ByteHandle;
130 case TYP_UINT:
131 return m_simdHandleCache->Vector64UIntHandle;
132 default:
133 assert(!"Didn't find a class handle for simdType");
134 }
135 }
136#endif // _TARGET_ARM64_
137
138 return NO_CLASS_HANDLE;
139}
140
141#endif // FEATURE_HW_INTRINSICS
142