Skip to content

Commit 4e9627e

Browse files
authored
[wasm][interp] alias Vector operators to PackedSimd (#114293)
1 parent 4ef4f90 commit 4e9627e

File tree

1 file changed

+99
-42
lines changed

1 file changed

+99
-42
lines changed

src/mono/mono/mini/interp/transform-simd.c

Lines changed: 99 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ static guint16 sri_packedsimd_methods [] = {
145145
SN_get_IsSupported,
146146
};
147147

148-
static guint16 packed_simd_alias_methods [] = {
148+
static guint16 packedsimd_alias_methods [] = {
149149
SN_Abs,
150150
SN_Add,
151151
SN_AndNot,
@@ -174,6 +174,19 @@ static guint16 packed_simd_alias_methods [] = {
174174
SN_WidenLower,
175175
SN_WidenUpper,
176176
SN_Xor,
177+
// operators
178+
SN_op_Addition,
179+
SN_op_BitwiseAnd,
180+
SN_op_BitwiseOr,
181+
SN_op_Division,
182+
SN_op_ExclusiveOr,
183+
SN_op_LeftShift,
184+
SN_op_Multiply,
185+
SN_op_OnesComplement,
186+
SN_op_RightShift,
187+
SN_op_Subtraction,
188+
SN_op_UnaryNegation,
189+
SN_op_UnsignedRightShift,
177190
};
178191

179192
static MonoTypeEnum
@@ -192,8 +205,24 @@ resolve_native_size (MonoTypeEnum type)
192205
return MONO_TYPE_U8;
193206
#endif
194207
return type;
208+
}
195209

210+
static const char *
211+
strip_explicit_isimd_prefix (const char *cmethod_name)
212+
{
213+
if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector<System.", 45) == 0) {
214+
// We want explicitly implemented ISimdVector<TSelf, T> APIs to still be expanded where possible
215+
// but, they all prefix the qualified name of the interface first, so we'll check for that and
216+
// skip the prefix before trying to resolve the method.
217+
if (strncmp (cmethod_name + 45, "Runtime.Intrinsics.Vector128<T>,T>.", 35) == 0) {
218+
cmethod_name += 80;
219+
} else if (strncmp(cmethod_name + 45, "Numerics.Vector<T>,T>.", 22) == 0) {
220+
cmethod_name += 67;
221+
}
222+
}
223+
return cmethod_name;
196224
}
225+
197226
// Returns if opcode was added
198227
static gboolean
199228
emit_common_simd_operations (TransformData *td, int id, int atype, int vector_size, int arg_size, int scalar_arg, gint16 *simd_opcode, gint16 *simd_intrins)
@@ -475,22 +504,11 @@ emit_vector_create (TransformData *td, MonoMethodSignature *csignature, MonoClas
475504
static gboolean
476505
emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature)
477506
{
478-
const char *cmethod_name = cmethod->name;
479-
480-
if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector<System.Runtime.Intrinsics.Vector", 70) == 0) {
481-
// We want explicitly implemented ISimdVector<TSelf, T> APIs to still be expanded where possible
482-
// but, they all prefix the qualified name of the interface first, so we'll check for that and
483-
// skip the prefix before trying to resolve the method.
484-
485-
if (strncmp(cmethod_name + 70, "128<T>,T>.", 10) == 0) {
486-
cmethod_name += 80;
487-
}
488-
}
489-
490507
#ifdef HOST_BROWSER
491508
if (emit_sri_packedsimd (td, cmethod, csignature))
492509
return TRUE;
493510
#endif
511+
const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name);
494512

495513
int id = lookup_intrins (sri_vector128_methods, sizeof (sri_vector128_methods), cmethod_name);
496514
if (id == -1)
@@ -699,19 +717,12 @@ emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature
699717
static gboolean
700718
emit_sri_vector128_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature)
701719
{
702-
const char *cmethod_name = cmethod->name;
703-
bool explicitly_implemented = false;
704-
705-
if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector<System.Runtime.Intrinsics.Vector", 70) == 0) {
706-
// We want explicitly implemented ISimdVector<TSelf, T> APIs to still be expanded where possible
707-
// but, they all prefix the qualified name of the interface first, so we'll check for that and
708-
// skip the prefix before trying to resolve the method.
709-
710-
if ((strncmp(cmethod_name + 70, "128<T>,T>.", 10) == 0)) {
711-
cmethod_name += 80;
712-
explicitly_implemented = true;
713-
}
714-
}
720+
#ifdef HOST_BROWSER
721+
if (emit_sri_packedsimd (td, cmethod, csignature))
722+
return TRUE;
723+
#endif
724+
const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name);
725+
bool explicitly_implemented = cmethod_name != cmethod->name;
715726

716727
int id = lookup_intrins (sri_vector128_t_methods, sizeof (sri_vector128_t_methods), cmethod->name);
717728
if (id == -1) {
@@ -750,17 +761,12 @@ emit_sri_vector128_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignatur
750761
static gboolean
751762
emit_sn_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature, gboolean newobj)
752763
{
753-
const char *cmethod_name = cmethod->name;
754-
bool explicitly_implemented = false;
755-
756-
if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector<System.Numerics.Vector<T>,T>.", 67) == 0) {
757-
// We want explicitly implemented ISimdVector<TSelf, T> APIs to still be expanded where possible
758-
// but, they all prefix the qualified name of the interface first, so we'll check for that and
759-
// skip the prefix before trying to resolve the method.
760-
761-
cmethod_name += 67;
762-
explicitly_implemented = true;
763-
}
764+
#ifdef HOST_BROWSER
765+
if (emit_sri_packedsimd (td, cmethod, csignature))
766+
return TRUE;
767+
#endif
768+
const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name);
769+
bool explicitly_implemented = cmethod_name != cmethod->name;
764770

765771
int id = lookup_intrins (sn_vector_t_methods, sizeof (sn_vector_t_methods), cmethod_name);
766772
if (id == -1) {
@@ -1112,10 +1118,23 @@ emit_sri_packedsimd (TransformData *td, MonoMethod *cmethod, MonoMethodSignature
11121118
if (!is_packedsimd) {
11131119
// transform the method name from the Vector(128|) name to the packed simd name
11141120
// FIXME: This is a hack, but it works for now.
1115-
id = lookup_intrins (packed_simd_alias_methods, sizeof (packed_simd_alias_methods), cmethod_name);
1121+
if (csignature->hasthis) {
1122+
return FALSE;
1123+
}
1124+
int scalar_arg = -1;
1125+
for (int i = 0; i < csignature->param_count; i++) {
1126+
if (csignature->params [i]->type != MONO_TYPE_GENERICINST)
1127+
scalar_arg = i;
1128+
}
1129+
cmethod_name = strip_explicit_isimd_prefix (cmethod_name);
1130+
id = lookup_intrins (packedsimd_alias_methods, sizeof (packedsimd_alias_methods), cmethod_name);
11161131
gboolean is_unsigned = (atype == MONO_TYPE_U1 || atype == MONO_TYPE_U2 || atype == MONO_TYPE_U4 || atype == MONO_TYPE_U8 || atype == MONO_TYPE_U);
11171132

1118-
// cmethod_name = must be a packed simd intrinsic, so we can just use the name directly
1133+
// cmethod_name must match a packed simd intrinsic name, so use an alias when needed.
1134+
// If a match with the aliased name and matching arguments is found, we use it,
1135+
// so be careful not to overmatch if the implementations differ (e.g. Dot.)
1136+
// Failing to find a match is expected in some cases for specific types of T, we simply
1137+
// fall back to the regular intrinsics, then to managed looking for an implementation.
11191138
switch (id) {
11201139
case SN_LessThan:
11211140
cmethod_name = "CompareLessThan";
@@ -1133,23 +1152,61 @@ emit_sri_packedsimd (TransformData *td, MonoMethod *cmethod, MonoMethodSignature
11331152
cmethod_name = "CompareEqual";
11341153
break;
11351154
case SN_BitwiseAnd:
1155+
case SN_op_BitwiseAnd:
11361156
cmethod_name = "And";
11371157
break;
11381158
case SN_BitwiseOr:
1159+
case SN_op_BitwiseOr:
11391160
cmethod_name = "Or";
11401161
break;
11411162
case SN_OnesComplement:
1163+
case SN_op_OnesComplement:
11421164
cmethod_name = "Not";
11431165
break;
1166+
case SN_Load:
1167+
case SN_LoadUnsafe:
1168+
cmethod_name = "LoadVector128";
1169+
break;
11441170
case SN_WidenLower:
11451171
cmethod_name = is_unsigned ? "ZeroExtendWideningLower" : "SignExtendWideningLower";
11461172
break;
11471173
case SN_WidenUpper:
11481174
cmethod_name = is_unsigned ? "ZeroExtendWideningUpper" : "SignExtendWideningUpper";
11491175
break;
1150-
case SN_Load:
1151-
case SN_LoadUnsafe:
1152-
cmethod_name = "LoadVector128";
1176+
case SN_op_Addition:
1177+
cmethod_name = "Add";
1178+
break;
1179+
case SN_op_Division:
1180+
if (scalar_arg != -1)
1181+
return FALSE;
1182+
cmethod_name = "Divide";
1183+
break;
1184+
case SN_op_ExclusiveOr:
1185+
cmethod_name = "Xor";
1186+
break;
1187+
case SN_op_LeftShift:
1188+
if (scalar_arg != 1)
1189+
return FALSE;
1190+
cmethod_name = "ShiftLeft";
1191+
break;
1192+
case SN_op_Multiply:
1193+
if (scalar_arg != -1)
1194+
return FALSE;
1195+
cmethod_name = "Multiply";
1196+
break;
1197+
case SN_op_RightShift:
1198+
if (scalar_arg != 1)
1199+
return FALSE;
1200+
cmethod_name = is_unsigned ? "ShiftRightLogical" : "ShiftRightArithmetic";
1201+
break;
1202+
case SN_op_Subtraction:
1203+
cmethod_name = "Subtract";
1204+
break;
1205+
case SN_op_UnaryNegation:
1206+
cmethod_name = "Negate";
1207+
break;
1208+
case SN_op_UnsignedRightShift:
1209+
cmethod_name = "ShiftRightLogical";
11531210
break;
11541211
case SN_Add:
11551212
case SN_AndNot:

0 commit comments

Comments
 (0)