Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions eng/pipelines/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -818,15 +818,15 @@ extends:
#
# WebAssembly legs
#
- template: /eng/pipelines/common/templates/wasm-library-tests.yml
parameters:
platforms:
- browser_wasm
alwaysRun: ${{ variables.isRollingBuild }}
extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS)
scenarios:
- WasmTestOnChrome
- WasmTestOnFirefox
#- template: /eng/pipelines/common/templates/wasm-library-tests.yml
# parameters:
# platforms:
# - browser_wasm
# alwaysRun: ${{ variables.isRollingBuild }}
# extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS)
# scenarios:
# - WasmTestOnChrome
# - WasmTestOnFirefox

- template: /eng/pipelines/common/templates/wasm-library-tests.yml
parameters:
Expand Down
4 changes: 4 additions & 0 deletions src/mono/mono/mini/interp/simd-methods.def
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ SIMD_METHOD(op_Division)
SIMD_METHOD(op_Equality)
SIMD_METHOD(op_ExclusiveOr)
SIMD_METHOD(op_Explicit)
SIMD_METHOD(op_GreaterThan)
SIMD_METHOD(op_GreaterThanOrEqual)
SIMD_METHOD(op_Inequality)
SIMD_METHOD(op_LeftShift)
SIMD_METHOD(op_LessThan)
SIMD_METHOD(op_LessThanOrEqual)
SIMD_METHOD(op_Multiply)
SIMD_METHOD(op_OnesComplement)
SIMD_METHOD(op_RightShift)
Expand Down
156 changes: 114 additions & 42 deletions src/mono/mono/mini/interp/transform-simd.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ static guint16 sri_packedsimd_methods [] = {
SN_get_IsSupported,
};

static guint16 packed_simd_alias_methods [] = {
static guint16 packedsimd_alias_methods [] = {
SN_Abs,
SN_Add,
SN_AndNot,
Expand Down Expand Up @@ -174,6 +174,23 @@ static guint16 packed_simd_alias_methods [] = {
SN_WidenLower,
SN_WidenUpper,
SN_Xor,
// operators
SN_op_Addition,
SN_op_BitwiseAnd,
SN_op_BitwiseOr,
SN_op_Division,
SN_op_ExclusiveOr,
SN_op_GreaterThan,
SN_op_GreaterThanOrEqual,
SN_op_LeftShift,
SN_op_LessThan,
SN_op_LessThanOrEqual,
SN_op_Multiply,
SN_op_OnesComplement,
SN_op_RightShift,
SN_op_Subtraction,
SN_op_UnaryNegation,
SN_op_UnsignedRightShift,
};

static MonoTypeEnum
Expand All @@ -192,8 +209,31 @@ resolve_native_size (MonoTypeEnum type)
return MONO_TYPE_U8;
#endif
return type;
}

static const char *
strip_explicit_isimd_prefix (const char *cmethod_name)
{
if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector<System.", 45) == 0) {
if (strncmp (cmethod_name + 45, "Runtime.Intrinsics.Vector", 25) == 0) {
// We want explicitly implemented ISimdVector<TSelf, T> APIs to still be expanded where possible
// but, they all prefix the qualified name of the interface first, so we'll check for that and
// skip the prefix before trying to resolve the method.

if (strncmp(cmethod_name + 70, "64<T>,T>.", 9) == 0) {
cmethod_name += 79;
} else if ((strncmp(cmethod_name + 70, "128<T>,T>.", 10) == 0) ||
(strncmp(cmethod_name + 70, "256<T>,T>.", 10) == 0) ||
(strncmp(cmethod_name + 70, "512<T>,T>.", 10) == 0)) {
cmethod_name += 80;
}
} else if (strncmp(cmethod_name + 45, "Numerics.Vector<T>,T>.", 22) == 0) {
cmethod_name += 67;
}
}
return cmethod_name;
}

// Returns if opcode was added
static gboolean
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)
Expand Down Expand Up @@ -475,22 +515,11 @@ emit_vector_create (TransformData *td, MonoMethodSignature *csignature, MonoClas
static gboolean
emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature)
{
const char *cmethod_name = cmethod->name;

if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector<System.Runtime.Intrinsics.Vector", 70) == 0) {
// We want explicitly implemented ISimdVector<TSelf, T> APIs to still be expanded where possible
// but, they all prefix the qualified name of the interface first, so we'll check for that and
// skip the prefix before trying to resolve the method.

if (strncmp(cmethod_name + 70, "128<T>,T>.", 10) == 0) {
cmethod_name += 80;
}
}

#ifdef HOST_BROWSER
if (emit_sri_packedsimd (td, cmethod, csignature))
return TRUE;
#endif
const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name);

int id = lookup_intrins (sri_vector128_methods, sizeof (sri_vector128_methods), cmethod_name);
if (id == -1)
Expand Down Expand Up @@ -699,19 +728,12 @@ emit_sri_vector128 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature
static gboolean
emit_sri_vector128_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature)
{
const char *cmethod_name = cmethod->name;
bool explicitly_implemented = false;

if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector<System.Runtime.Intrinsics.Vector", 70) == 0) {
// We want explicitly implemented ISimdVector<TSelf, T> APIs to still be expanded where possible
// but, they all prefix the qualified name of the interface first, so we'll check for that and
// skip the prefix before trying to resolve the method.

if ((strncmp(cmethod_name + 70, "128<T>,T>.", 10) == 0)) {
cmethod_name += 80;
explicitly_implemented = true;
}
}
#ifdef HOST_BROWSER
if (emit_sri_packedsimd (td, cmethod, csignature))
return TRUE;
#endif
const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name);
bool explicitly_implemented = cmethod_name != cmethod->name;

int id = lookup_intrins (sri_vector128_t_methods, sizeof (sri_vector128_t_methods), cmethod->name);
if (id == -1) {
Expand Down Expand Up @@ -750,17 +772,12 @@ emit_sri_vector128_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignatur
static gboolean
emit_sn_vector_t (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature, gboolean newobj)
{
const char *cmethod_name = cmethod->name;
bool explicitly_implemented = false;

if (strncmp(cmethod_name, "System.Runtime.Intrinsics.ISimdVector<System.Numerics.Vector<T>,T>.", 67) == 0) {
// We want explicitly implemented ISimdVector<TSelf, T> APIs to still be expanded where possible
// but, they all prefix the qualified name of the interface first, so we'll check for that and
// skip the prefix before trying to resolve the method.

cmethod_name += 67;
explicitly_implemented = true;
}
#ifdef HOST_BROWSER
if (emit_sri_packedsimd (td, cmethod, csignature))
return TRUE;
#endif
const char *cmethod_name = strip_explicit_isimd_prefix (cmethod->name);
bool explicitly_implemented = cmethod_name != cmethod->name;

int id = lookup_intrins (sn_vector_t_methods, sizeof (sn_vector_t_methods), cmethod_name);
if (id == -1) {
Expand Down Expand Up @@ -1112,44 +1129,99 @@ emit_sri_packedsimd (TransformData *td, MonoMethod *cmethod, MonoMethodSignature
if (!is_packedsimd) {
// transform the method name from the Vector(128|) name to the packed simd name
// FIXME: This is a hack, but it works for now.
id = lookup_intrins (packed_simd_alias_methods, sizeof (packed_simd_alias_methods), cmethod_name);
if (csignature->hasthis) {
return FALSE;
}
int scalar_arg = -1;
for (int i = 0; i < csignature->param_count; i++) {
if (csignature->params [i]->type != MONO_TYPE_GENERICINST)
scalar_arg = i;
}
cmethod_name = strip_explicit_isimd_prefix (cmethod_name);
id = lookup_intrins (packedsimd_alias_methods, sizeof (packedsimd_alias_methods), cmethod_name);
gboolean is_unsigned = (atype == MONO_TYPE_U1 || atype == MONO_TYPE_U2 || atype == MONO_TYPE_U4 || atype == MONO_TYPE_U8 || atype == MONO_TYPE_U);

// cmethod_name = must be a packed simd intrinsic, so we can just use the name directly
// cmethod_name must match a packed simd intrinsic name, so use an alias when needed.
// If a match with the aliased name and matching arguments is found, we use it,
// so be careful not to overmatch if the implementations differ (e.g. Dot.)
// Failing to find a match is expected in some cases for specific types of T, we simply
// fall back to the regular intrinsics, then to managed looking for an implementation.
switch (id) {
case SN_LessThan:
case SN_op_LessThan:
cmethod_name = "CompareLessThan";
break;
case SN_LessThanOrEqual:
case SN_op_LessThanOrEqual:
cmethod_name = "CompareLessThanOrEqual";
break;
case SN_GreaterThan:
case SN_op_GreaterThan:
cmethod_name = "CompareGreaterThan";
break;
case SN_GreaterThanOrEqual:
case SN_op_GreaterThanOrEqual:
cmethod_name = "CompareGreaterThanOrEqual";
break;
case SN_Equals:
cmethod_name = "CompareEqual";
break;
case SN_BitwiseAnd:
case SN_op_BitwiseAnd:
cmethod_name = "And";
break;
case SN_BitwiseOr:
case SN_op_BitwiseOr:
cmethod_name = "Or";
break;
case SN_OnesComplement:
case SN_op_OnesComplement:
cmethod_name = "Not";
break;
case SN_Load:
case SN_LoadUnsafe:
cmethod_name = "LoadVector128";
break;
case SN_WidenLower:
cmethod_name = is_unsigned ? "ZeroExtendWideningLower" : "SignExtendWideningLower";
break;
case SN_WidenUpper:
cmethod_name = is_unsigned ? "ZeroExtendWideningUpper" : "SignExtendWideningUpper";
break;
case SN_Load:
case SN_LoadUnsafe:
cmethod_name = "LoadVector128";
case SN_op_Addition:
cmethod_name = "Add";
break;
case SN_op_Division:
if (scalar_arg != -1)
return FALSE;
cmethod_name = "Divide";
break;
case SN_op_ExclusiveOr:
cmethod_name = "Xor";
break;
case SN_op_LeftShift:
if (scalar_arg != 1)
return FALSE;
cmethod_name = "ShiftLeft";
break;
case SN_op_Multiply:
if (scalar_arg != -1)
return FALSE;
cmethod_name = "Multiply";
break;
case SN_op_RightShift:
if (scalar_arg != 1)
return FALSE;
cmethod_name = is_unsigned ? "ShiftRightLogical" : "ShiftRightArithmetic";
break;
case SN_op_Subtraction:
cmethod_name = "Subtract";
break;
case SN_op_UnaryNegation:
cmethod_name = "Negate";
break;
case SN_op_UnsignedRightShift:
cmethod_name = "ShiftRightLogical";
break;
case SN_Add:
case SN_AndNot:
Expand Down
Loading