Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wasm] Enable v128 and PackedSimd in the interpreter #85920

Merged
merged 1 commit into from
May 18, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion eng/testing/tests.wasm.targets
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
So, set those parameters explicitly here.
-->
<_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' == 'true' and '$(RunAOTCompilation)' == 'true'">$(_ExtraTrimmerArgs) --substitutions &quot;$(MonoProjectRoot)\wasm\build\ILLink.Substitutions.WasmIntrinsics.xml&quot;</_ExtraTrimmerArgs>
<_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' != 'true' or '$(RunAOTCompilation)' != 'true'">$(_ExtraTrimmerArgs) --substitutions &quot;$(MonoProjectRoot)\wasm\build\ILLink.Substitutions.NoWasmIntrinsics.xml&quot;</_ExtraTrimmerArgs>
<_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' != 'true'">$(_ExtraTrimmerArgs) --substitutions &quot;$(MonoProjectRoot)\wasm\build\ILLink.Substitutions.NoWasmIntrinsics.xml&quot;</_ExtraTrimmerArgs>
</PropertyGroup>

<ItemGroup>
Expand Down
4 changes: 4 additions & 0 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -3802,6 +3802,10 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause
memset (locals + ip [1], 0, ip [2]);
ip += 3;
MINT_IN_BREAK;
MINT_IN_CASE(MINT_NIY)
g_printf ("MONO interpreter: NIY encountered in method %s\n", frame->imethod->method->name);
g_assert_not_reached ();
MINT_IN_BREAK;
MINT_IN_CASE(MINT_BREAK)
++ip;
SAVE_INTERP_STATE (frame);
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/mini/interp/mintops.def
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#define IROPDEF(opsymbol, opstring, oplength, num_dregs, num_sregs, optype) OPDEF(opsymbol, opstring, oplength, num_dregs, num_sregs, optype)
#endif // IROPDEF

OPDEF(MINT_NIY, "niy", 1, 0, 0, MintOpNoArgs)
OPDEF(MINT_BREAK, "break", 1, 0, 0, MintOpNoArgs)
OPDEF(MINT_BREAKPOINT, "breakpoint", 1, 0, 0, MintOpNoArgs)

Expand Down Expand Up @@ -843,7 +844,6 @@ OPDEF(MINT_TIER_MONITOR_JITERPRETER, "tier_monitor_jiterpreter", 3, 0, 0, MintOp
#endif // HOST_BROWSER

IROPDEF(MINT_NOP, "nop", 1, 0, 0, MintOpNoArgs)
IROPDEF(MINT_NIY, "niy", 1, 0, 0, MintOpNoArgs)
IROPDEF(MINT_DEF, "def", 2, 1, 0, MintOpNoArgs)
IROPDEF(MINT_IL_SEQ_POINT, "il_seq_point", 1, 0, 0, MintOpNoArgs)
IROPDEF(MINT_DUMMY_USE, "dummy_use", 2, 0, 1, MintOpNoArgs)
Expand Down
59 changes: 41 additions & 18 deletions src/mono/mono/mini/interp/transform-simd.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,6 @@ static guint16 sri_vector128_methods [] = {
};

static guint16 sri_vector128_t_methods [] = {
SN_get_AllBitsSet,
SN_get_Count,
SN_get_One,
SN_get_Zero,
SN_op_Addition,
SN_op_BitwiseAnd,
SN_op_BitwiseOr,
Expand All @@ -84,12 +80,29 @@ static guint16 sri_vector128_t_methods [] = {
SN_op_RightShift,
SN_op_Subtraction,
SN_op_UnaryNegation,
SN_op_UnsignedRightShift
SN_op_UnsignedRightShift,
SN_get_AllBitsSet,
SN_get_Count,
SN_get_One,
SN_get_Zero,
};

static guint16 sri_packedsimd_methods [] = {
SN_Add,
SN_And,
SN_Bitmask,
SN_CompareEqual,
SN_CompareNotEqual,
SN_ConvertNarrowingSignedSaturate,
SN_ConvertNarrowingUnsignedSaturate,
SN_Dot,
SN_Multiply,
SN_Negate,
SN_ShiftLeft,
SN_ShiftRightArithmetic,
SN_ShiftRightLogical,
SN_Splat,
SN_Subtract,
SN_Swizzle,
SN_get_IsHardwareAccelerated,
SN_get_IsSupported,
Expand Down Expand Up @@ -534,12 +547,12 @@ static gboolean
emit_sri_packedsimd (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *csignature)
{
int id = lookup_intrins (sri_packedsimd_methods, sizeof (sri_packedsimd_methods), cmethod);
if (id == -1)
return FALSE;
// We don't early-out for an unrecognized method, we will generate an NIY later

MonoClass *vector_klass = mono_class_from_mono_type_internal (csignature->ret);
int vector_size = -1;

// NOTE: Linker substitutions (used in AOT) will prevent this from running.
if ((id == SN_get_IsSupported) || (id == SN_get_IsHardwareAccelerated)) {
#if HOST_BROWSER
interp_add_ins (td, MINT_LDC_I4_1);
Expand All @@ -550,6 +563,23 @@ emit_sri_packedsimd (TransformData *td, MonoMethod *cmethod, MonoMethodSignature
}

#if HOST_BROWSER
if (id < 0) {
g_print ("MONO interpreter: Unimplemented method: System.Runtime.Intrinsics.Wasm.PackedSimd.%s\n", cmethod->name);

// If we're missing a packedsimd method but the packedsimd method was AOT'd, we can
// just let the interpreter generate a native call to the AOT method instead of
// generating an NIY that will halt execution
ERROR_DECL (error);
gpointer addr = mono_aot_get_method (cmethod, error);
if (addr)
return FALSE;

// The packedsimd method implementations recurse infinitely and cause a stack overflow,
// so replace them with a NIY opcode instead that will assert
interp_add_ins (td, MINT_NIY);
goto opcode_added;
}

gint16 simd_opcode = -1;
gint16 simd_intrins = -1;
if (!m_class_is_simd_type (vector_klass))
Expand Down Expand Up @@ -705,21 +735,14 @@ interp_emit_simd_intrinsics (TransformData *td, MonoMethod *cmethod, MonoMethodS
class_ns = m_class_get_name_space (cmethod->klass);
class_name = m_class_get_name (cmethod->klass);

if (mono_opt_interp_simd_v128 && !strcmp (class_ns, "System.Runtime.Intrinsics")) {
if (!strcmp (class_ns, "System.Runtime.Intrinsics")) {
if (!strcmp (class_name, "Vector128"))
return emit_sri_vector128 (td, cmethod, csignature);
else if (!strcmp (class_name, "Vector128`1"))
return emit_sri_vector128_t (td, cmethod, csignature);
} else if (mono_opt_interp_simd_packedsimd && !strcmp (class_ns, "System.Runtime.Intrinsics.Wasm")) {
if (!strcmp (class_name, "PackedSimd")) {
gboolean res = emit_sri_packedsimd (td, cmethod, csignature);
#if HOST_BROWSER
if (!res)
g_print ("MONO interpreter: Unsupported method: System.Runtime.Intrinsics.Wasm.PackedSimd.%s\n", cmethod->name);
g_assert (res);
#endif
return res;
}
} else if (!strcmp (class_ns, "System.Runtime.Intrinsics.Wasm")) {
if (!strcmp (class_name, "PackedSimd"))
return emit_sri_packedsimd (td, cmethod, csignature);
}
return FALSE;
}
6 changes: 0 additions & 6 deletions src/mono/mono/utils/options-def.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,6 @@ DEFINE_BOOL_READONLY(readonly_flag, "readonly-flag", FALSE, "Example")
DEFINE_BOOL(wasm_exceptions, "wasm-exceptions", FALSE, "Enable codegen for WASM exceptions")
DEFINE_BOOL(wasm_gc_safepoints, "wasm-gc-safepoints", FALSE, "Use GC safepoints on WASM")
DEFINE_BOOL(aot_lazy_assembly_load, "aot-lazy-assembly-load", FALSE, "Load assemblies referenced by AOT images lazily")
#if HOST_BROWSER
DEFINE_BOOL(interp_simd_v128, "interp-simd-v128", FALSE, "Enable interpreter Vector128 support")
#else
DEFINE_BOOL(interp_simd_v128, "interp-simd-v128", TRUE, "Enable interpreter Vector128 support")
#endif
DEFINE_BOOL(interp_simd_packedsimd, "interp-simd-packedsimd", FALSE, "Enable interpreter WASM PackedSimd support")

#if HOST_BROWSER

Expand Down
2 changes: 1 addition & 1 deletion src/mono/wasm/build/WasmApp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
<UseAppHost>false</UseAppHost>
<TrimMode Condition="'$(TrimMode)' == ''">full</TrimMode>
<_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' == 'true' and '$(RunAOTCompilation)' == 'true'">$(_ExtraTrimmerArgs) --substitutions &quot;$(MSBuildThisFileDirectory)ILLink.Substitutions.WasmIntrinsics.xml&quot;</_ExtraTrimmerArgs>
<_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' != 'true' or '$(RunAOTCompilation)' != 'true'">$(_ExtraTrimmerArgs) --substitutions &quot;$(MSBuildThisFileDirectory)ILLink.Substitutions.NoWasmIntrinsics.xml&quot;</_ExtraTrimmerArgs>
<_ExtraTrimmerArgs Condition="'$(WasmEnableSIMD)' != 'true'">$(_ExtraTrimmerArgs) --substitutions &quot;$(MSBuildThisFileDirectory)ILLink.Substitutions.NoWasmIntrinsics.xml&quot;</_ExtraTrimmerArgs>
<_ExtraTrimmerArgs Condition="'$(WasmEnableLegacyJsInterop)' == 'false'">$(_ExtraTrimmerArgs) --substitutions &quot;$(MSBuildThisFileDirectory)ILLink.Substitutions.LegacyJsInterop.xml&quot;</_ExtraTrimmerArgs>

<!-- Temporarily `false`, till sdk gets a fix for supporting the new file -->
Expand Down
18 changes: 16 additions & 2 deletions src/mono/wasm/runtime/jiterpreter-tables.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
WasmOpcode, JiterpSpecialOpcode
WasmOpcode, WasmSimdOpcode, JiterpSpecialOpcode
} from "./jiterpreter-opcodes";
import {
MintOpcode, SimdIntrinsic3
MintOpcode, SimdIntrinsic2, SimdIntrinsic3
} from "./mintops";

export const ldcTable: { [opcode: number]: [WasmOpcode, number] } = {
Expand Down Expand Up @@ -356,3 +356,17 @@ export const simdShiftTable = new Set<SimdIntrinsic3>([
SimdIntrinsic3.V128_I4_URIGHT_SHIFT,
SimdIntrinsic3.V128_I8_URIGHT_SHIFT,
]);

export const bitmaskTable : { [intrinsic: number]: WasmSimdOpcode } = {
[SimdIntrinsic2.V128_I1_EXTRACT_MSB]: WasmSimdOpcode.i8x16_bitmask,
[SimdIntrinsic2.V128_I2_EXTRACT_MSB]: WasmSimdOpcode.i16x8_bitmask,
[SimdIntrinsic2.V128_I4_EXTRACT_MSB]: WasmSimdOpcode.i32x4_bitmask,
[SimdIntrinsic2.V128_I8_EXTRACT_MSB]: WasmSimdOpcode.i64x2_bitmask,
};

export const createScalarTable : { [intrinsic: number]: [WasmOpcode, WasmSimdOpcode] } = {
[SimdIntrinsic2.V128_I1_CREATE_SCALAR]: [WasmOpcode.i32_load8_s, WasmSimdOpcode.i8x16_replace_lane],
[SimdIntrinsic2.V128_I2_CREATE_SCALAR]: [WasmOpcode.i32_load16_s, WasmSimdOpcode.i16x8_replace_lane],
[SimdIntrinsic2.V128_I4_CREATE_SCALAR]: [WasmOpcode.i32_load, WasmSimdOpcode.i32x4_replace_lane],
[SimdIntrinsic2.V128_I8_CREATE_SCALAR]: [WasmOpcode.i64_load, WasmSimdOpcode.i64x2_replace_lane],
};
52 changes: 22 additions & 30 deletions src/mono/wasm/runtime/jiterpreter-trace-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
relopbranchTable, mathIntrinsicTable,
simdCreateLoadOps, simdCreateSizes,
simdCreateStoreOps, simdShiftTable,
bitmaskTable, createScalarTable,
} from "./jiterpreter-tables";
import { mono_log_error, mono_log_info } from "./logging";

Expand Down Expand Up @@ -3156,13 +3157,6 @@ function append_simd_4_load(builder: WasmBuilder, ip: MintOpcodePtr) {
append_ldloc(builder, getArgU16(ip, 4), WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_load);
}

function append_stloc_simd_zero(builder: WasmBuilder, offset: number) {
builder.local("pLocals");
builder.appendSimd(WasmSimdOpcode.v128_const);
builder.appendBytes(new Uint8Array(sizeOfV128));
append_stloc_tail(builder, offset, WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_store);
}

function emit_simd_2(builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrinsic2): boolean {
const simple = <WasmSimdOpcode>cwraps.mono_jiterp_get_simd_opcode(1, index);
if (simple) {
Expand All @@ -3172,35 +3166,33 @@ function emit_simd_2(builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrins
return true;
}

const bitmask = bitmaskTable[index];
if (bitmask) {
append_simd_2_load(builder, ip);
builder.appendSimd(bitmask);
append_stloc_tail(builder, getArgU16(ip, 1), WasmOpcode.i32_store);
return true;
}

switch (index) {
case SimdIntrinsic2.V128_I1_CREATE_SCALAR:
// Zero then write scalar component
builder.local("pLocals");
append_stloc_simd_zero(builder, getArgU16(ip, 1));
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load8_s);
append_stloc_tail(builder, getArgU16(ip, 1), WasmOpcode.i32_store8);
return true;
case SimdIntrinsic2.V128_I2_CREATE_SCALAR:
// Zero then write scalar component
builder.local("pLocals");
append_stloc_simd_zero(builder, getArgU16(ip, 1));
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load16_s);
append_stloc_tail(builder, getArgU16(ip, 1), WasmOpcode.i32_store16);
return true;
case SimdIntrinsic2.V128_I4_CREATE_SCALAR:
// Zero then write scalar component
case SimdIntrinsic2.V128_I8_CREATE_SCALAR: {
const tableEntry = createScalarTable[index];
builder.local("pLocals");
append_stloc_simd_zero(builder, getArgU16(ip, 1));
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load);
append_stloc_tail(builder, getArgU16(ip, 1), WasmOpcode.i32_store);
return true;
case SimdIntrinsic2.V128_I8_CREATE_SCALAR:
// Zero then write scalar component
builder.local("pLocals");
append_stloc_simd_zero(builder, getArgU16(ip, 1));
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i64_load);
append_stloc_tail(builder, getArgU16(ip, 1), WasmOpcode.i64_store);
// Make a zero vector
builder.i52_const(0);
builder.appendSimd(WasmSimdOpcode.i64x2_splat);
// Load the scalar value
append_ldloc(builder, getArgU16(ip, 2), tableEntry[0]);
// Replace the first lane
builder.appendSimd(tableEntry[1]);
builder.appendU8(0);
// Store result
append_stloc_tail(builder, getArgU16(ip, 1), WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_store);
return true;
}

case SimdIntrinsic2.V128_I1_CREATE:
append_simd_2_load(builder, ip, WasmSimdOpcode.v128_load8_splat);
Expand Down