Skip to content

Commit 326aea2

Browse files
authored
Implement the first few SIMD opcodes for fast interpreter (v128.const, v128.any_true) (#3818)
Tested on the following code: ``` (module (import "wasi_snapshot_preview1" "proc_exit" (func $proc_exit (param i32))) (memory (export "memory") 1) ;; WASI entry point (func $main (export "_start") v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 v128.any_true if unreachable end v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 v128.any_true i32.const 0 i32.eq if unreachable end i32.const 0 call $proc_exit ) ) ```
1 parent 2133099 commit 326aea2

4 files changed

Lines changed: 107 additions & 16 deletions

File tree

core/iwasm/common/wasm_runtime_common.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ extern "C" {
3737
do { \
3838
*(int64 *)(addr) = (int64)(value); \
3939
} while (0)
40+
#define PUT_V128_TO_ADDR(addr, value) \
41+
do { \
42+
*(V128 *)(addr) = (value); \
43+
} while (0)
4044
#define PUT_F64_TO_ADDR(addr, value) \
4145
do { \
4246
*(float64 *)(addr) = (float64)(value); \
@@ -49,6 +53,7 @@ extern "C" {
4953
#define GET_I64_FROM_ADDR(addr) (*(int64 *)(addr))
5054
#define GET_F64_FROM_ADDR(addr) (*(float64 *)(addr))
5155
#define GET_REF_FROM_ADDR(addr) (*(void **)(addr))
56+
#define GET_V128_FROM_ADDR(addr) (*(V128 *)(addr))
5257

5358
/* For STORE opcodes */
5459
#define STORE_I64 PUT_I64_TO_ADDR
@@ -83,6 +88,15 @@ STORE_U8(void *addr, uint8_t value)
8388

8489
#else /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */
8590

91+
#define PUT_V128_TO_ADDR(addr, value) \
92+
do { \
93+
uint32 *addr_u32 = (uint32 *)(addr); \
94+
addr_u32[0] = (value).i32x4[0]; \
95+
addr_u32[1] = (value).i32x4[1]; \
96+
addr_u32[2] = (value).i32x4[2]; \
97+
addr_u32[3] = (value).i32x4[3]; \
98+
} while (0)
99+
86100
#define PUT_I64_TO_ADDR(addr, value) \
87101
do { \
88102
uint32 *addr_u32 = (uint32 *)(addr); \
@@ -124,6 +138,17 @@ STORE_U8(void *addr, uint8_t value)
124138
} while (0)
125139
#endif
126140

141+
static inline V128
142+
GET_V128_FROM_ADDR(uint32 *addr)
143+
{
144+
V128 ret;
145+
ret.i32x4[0] = addr[0];
146+
ret.i32x4[1] = addr[1];
147+
ret.i32x4[2] = addr[2];
148+
ret.i32x4[3] = addr[3];
149+
return ret;
150+
}
151+
127152
static inline int64
128153
GET_I64_FROM_ADDR(uint32 *addr)
129154
{

core/iwasm/interpreter/wasm_interp_fast.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
433433
(type) GET_I64_FROM_ADDR(frame_lp + *(int16 *)(frame_ip + off))
434434
#define GET_OPERAND_F64(type, off) \
435435
(type) GET_F64_FROM_ADDR(frame_lp + *(int16 *)(frame_ip + off))
436+
#define GET_OPERAND_V128(off) \
437+
GET_V128_FROM_ADDR(frame_lp + *(int16 *)(frame_ip + off))
436438
#define GET_OPERAND_REF(type, off) \
437439
(type) GET_REF_FROM_ADDR(frame_lp + *(int16 *)(frame_ip + off))
438440

@@ -5642,7 +5644,37 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
56425644
#endif
56435645
goto call_func_from_entry;
56445646
}
5647+
#if WASM_ENABLE_SIMD != 0
5648+
HANDLE_OP(WASM_OP_SIMD_PREFIX)
5649+
{
5650+
GET_OPCODE();
5651+
5652+
switch (opcode) {
5653+
case SIMD_v128_const:
5654+
{
5655+
uint8 *orig_ip = frame_ip;
5656+
5657+
frame_ip += sizeof(V128);
5658+
addr_ret = GET_OFFSET();
56455659

5660+
PUT_V128_TO_ADDR(frame_lp + addr_ret, *(V128 *)orig_ip);
5661+
break;
5662+
}
5663+
case SIMD_v128_any_true:
5664+
{
5665+
V128 value = GET_OPERAND_V128(0);
5666+
frame_ip += 2;
5667+
addr_ret = GET_OFFSET();
5668+
frame_lp[addr_ret] =
5669+
value.i64x2[0] != 0 || value.i64x2[1] != 0;
5670+
break;
5671+
}
5672+
default:
5673+
wasm_set_exception(module, "unsupported SIMD opcode");
5674+
}
5675+
HANDLE_OP_END();
5676+
}
5677+
#endif
56465678
HANDLE_OP(WASM_OP_CALL)
56475679
{
56485680
#if WASM_ENABLE_THREAD_MGR != 0

core/iwasm/interpreter/wasm_loader.c

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,8 @@ is_byte_a_type(uint8 type)
307307
}
308308

309309
#if WASM_ENABLE_SIMD != 0
310-
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
310+
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) \
311+
|| (WASM_ENABLE_FAST_INTERP != 0)
311312
static V128
312313
read_i8x16(uint8 *p_buf, char *error_buf, uint32 error_buf_size)
313314
{
@@ -320,7 +321,8 @@ read_i8x16(uint8 *p_buf, char *error_buf, uint32 error_buf_size)
320321

321322
return result;
322323
}
323-
#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */
324+
#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) || \
325+
(WASM_ENABLE_FAST_INTERP != 0) */
324326
#endif /* end of WASM_ENABLE_SIMD */
325327

326328
static void *
@@ -707,7 +709,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
707709
goto fail;
708710
break;
709711
#if WASM_ENABLE_SIMD != 0
710-
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
712+
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) \
713+
|| (WASM_ENABLE_FAST_INTERP != 0)
711714
/* v128.const */
712715
case INIT_EXPR_TYPE_V128_CONST:
713716
{
@@ -736,7 +739,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
736739
#endif
737740
break;
738741
}
739-
#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */
742+
#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) || \
743+
(WASM_ENABLE_FAST_INTERP != 0) */
740744
#endif /* end of WASM_ENABLE_SIMD */
741745

742746
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
@@ -4105,7 +4109,8 @@ load_export_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
41054109
return false;
41064110
}
41074111
#if WASM_ENABLE_SIMD != 0
4108-
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
4112+
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) \
4113+
|| (WASM_ENABLE_FAST_INTERP != 0)
41094114
/* TODO: check func type, if it has v128 param or result,
41104115
report error */
41114116
#endif
@@ -7566,7 +7571,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
75667571
}
75677572

75687573
#if WASM_ENABLE_SIMD != 0
7569-
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
7574+
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) \
7575+
|| (WASM_ENABLE_FAST_INTERP != 0)
75707576
case WASM_OP_SIMD_PREFIX:
75717577
{
75727578
uint32 opcode1;
@@ -7659,7 +7665,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
76597665
}
76607666
break;
76617667
}
7662-
#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */
7668+
#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) || \
7669+
(WASM_ENABLE_FAST_INTERP != 0) */
76637670
#endif /* end of WASM_ENABLE_SIMD */
76647671

76657672
#if WASM_ENABLE_SHARED_MEMORY != 0
@@ -9903,7 +9910,8 @@ check_memory_access_align(uint8 opcode, uint32 align, char *error_buf,
99039910
}
99049911

99059912
#if WASM_ENABLE_SIMD != 0
9906-
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
9913+
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) \
9914+
|| (WASM_ENABLE_FAST_INTERP != 0)
99079915
static bool
99089916
check_simd_memory_access_align(uint8 opcode, uint32 align, char *error_buf,
99099917
uint32 error_buf_size)
@@ -12120,10 +12128,20 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
1212012128
#endif
1212112129
}
1212212130
#if WASM_ENABLE_SIMD != 0
12123-
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
12131+
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) \
12132+
|| (WASM_ENABLE_FAST_INTERP != 0)
1212412133
else if (*(loader_ctx->frame_ref - 1) == VALUE_TYPE_V128) {
1212512134
loader_ctx->frame_ref -= 4;
1212612135
loader_ctx->stack_cell_num -= 4;
12136+
#if WASM_ENABLE_FAST_INTERP != 0
12137+
skip_label();
12138+
loader_ctx->frame_offset -= 4;
12139+
if ((*(loader_ctx->frame_offset)
12140+
> loader_ctx->start_dynamic_offset)
12141+
&& (*(loader_ctx->frame_offset)
12142+
< loader_ctx->max_dynamic_offset))
12143+
loader_ctx->dynamic_offset -= 4;
12144+
#endif
1212712145
}
1212812146
#endif
1212912147
#endif
@@ -12210,10 +12228,12 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
1221012228
#endif /* end of WASM_ENABLE_FAST_INTERP */
1221112229
break;
1221212230
#if WASM_ENABLE_SIMD != 0
12213-
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
12231+
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) \
12232+
|| (WASM_ENABLE_FAST_INTERP != 0)
1221412233
case VALUE_TYPE_V128:
1221512234
break;
12216-
#endif /* (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */
12235+
#endif /* (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) || \
12236+
(WASM_ENABLE_FAST_INTERP != 0) */
1221712237
#endif /* WASM_ENABLE_SIMD != 0 */
1221812238
default:
1221912239
{
@@ -12308,8 +12328,9 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
1230812328
uint8 opcode_tmp = WASM_OP_SELECT;
1230912329

1231012330
if (type == VALUE_TYPE_V128) {
12311-
#if (WASM_ENABLE_SIMD == 0) \
12312-
|| ((WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0))
12331+
#if (WASM_ENABLE_SIMD == 0) \
12332+
|| ((WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_JIT == 0) \
12333+
&& (WASM_ENABLE_FAST_INTERP == 0))
1231312334
set_error_buf(error_buf, error_buf_size,
1231412335
"SIMD v128 type isn't supported");
1231512336
goto fail;
@@ -14870,7 +14891,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
1487014891
}
1487114892

1487214893
#if WASM_ENABLE_SIMD != 0
14873-
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
14894+
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) \
14895+
|| (WASM_ENABLE_FAST_INTERP != 0)
1487414896
case WASM_OP_SIMD_PREFIX:
1487514897
{
1487614898
uint32 opcode1;
@@ -14882,6 +14904,10 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
1488214904

1488314905
read_leb_uint32(p, p_end, opcode1);
1488414906

14907+
#if WASM_ENABLE_FAST_INTERP != 0
14908+
emit_byte(loader_ctx, opcode1);
14909+
#endif
14910+
1488514911
/* follow the order of enum WASMSimdEXTOpcode in wasm_opcode.h
1488614912
*/
1488714913
switch (opcode1) {
@@ -14938,7 +14964,13 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
1493814964
/* basic operation */
1493914965
case SIMD_v128_const:
1494014966
{
14967+
uint64 high, low;
1494114968
CHECK_BUF1(p, p_end, 16);
14969+
#if WASM_ENABLE_FAST_INTERP != 0
14970+
wasm_runtime_read_v128(p, &high, &low);
14971+
emit_uint64(loader_ctx, high);
14972+
emit_uint64(loader_ctx, low);
14973+
#endif
1494214974
p += 16;
1494314975
PUSH_V128();
1494414976
break;
@@ -15524,7 +15556,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
1552415556
}
1552515557
break;
1552615558
}
15527-
#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) */
15559+
#endif /* end of (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) || \
15560+
(WASM_ENABLE_FAST_INTERP != 0) */
1552815561
#endif /* end of WASM_ENABLE_SIMD */
1552915562

1553015563
#if WASM_ENABLE_SHARED_MEMORY != 0

core/iwasm/interpreter/wasm_opcode.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,8 @@ typedef enum WASMAtomicEXTOpcode {
782782

783783
#define SET_GOTO_TABLE_ELEM(opcode) [opcode] = HANDLE_OPCODE(opcode)
784784

785-
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_SIMD != 0
785+
#if (WASM_ENABLE_JIT != 0 || WASM_ENABLE_FAST_INTERP != 0) \
786+
&& WASM_ENABLE_SIMD != 0
786787
#define SET_GOTO_TABLE_SIMD_PREFIX_ELEM() \
787788
SET_GOTO_TABLE_ELEM(WASM_OP_SIMD_PREFIX),
788789
#else

0 commit comments

Comments
 (0)