Commit b48b82e7 authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[wasm] Fix wasm decoder for multi-byte opcodes

SIMD opcodes consist of the prefix byte, then an LEB128 encoded int. We
were decoding this incorrectly as a fixed uint8. This fixes the decoder
to properly handle multi bytes.

In some cases, the multi byte logic is applied to all prefixed opcodes.
This is not a problem, since for values < 0x80, the LEB encoding is a
single byte, and decodes to the same int. If the prefix opcode has
instructions with index >= 0x80, it would be required to be LEB128
encoded anyway.

There are a bunch of trivial changes to test-run-wasm-simd, to change
the macro from BUILD to BUILD_V, the former only works for single byte
opcodes, the latter is a new template-based macro that correct handles
multi-byte opcodes. The only unchanged test is the shuffle fuzzer test,
which builds its own sequence of bytes without using the BUILD macro.

Bug: v8:10258
Change-Id: Ie7377e899a7eab97ecf28176fd908babc08d0f19
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2118476
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarDeepti Gandluri <gdeepti@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67186}
parent 70b4f28b
...@@ -731,10 +731,8 @@ class LiftoffCompiler { ...@@ -731,10 +731,8 @@ class LiftoffCompiler {
TraceCacheState(decoder); TraceCacheState(decoder);
#ifdef DEBUG #ifdef DEBUG
SLOW_DCHECK(__ ValidateCacheState()); SLOW_DCHECK(__ ValidateCacheState());
if (WasmOpcodes::IsPrefixOpcode(opcode) && if (WasmOpcodes::IsPrefixOpcode(opcode)) {
decoder->pc() + 1 < decoder->end()) { opcode = decoder->read_prefixed_opcode<Decoder::kValidate>(decoder->pc());
byte op_index = *(decoder->pc() + 1);
opcode = static_cast<WasmOpcode>(opcode << 8 | op_index);
} }
DEBUG_CODE_COMMENT(WasmOpcodes::OpcodeName(opcode)); DEBUG_CODE_COMMENT(WasmOpcodes::OpcodeName(opcode));
#endif #endif
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "src/flags/flags.h" #include "src/flags/flags.h"
#include "src/utils/utils.h" #include "src/utils/utils.h"
#include "src/utils/vector.h" #include "src/utils/vector.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-result.h" #include "src/wasm/wasm-result.h"
#include "src/zone/zone-containers.h" #include "src/zone/zone-containers.h"
...@@ -126,6 +127,31 @@ class Decoder { ...@@ -126,6 +127,31 @@ class Decoder {
name); name);
} }
// Reads a prefixed-opcode, possibly with variable-length index.
// The length param is set to the number of bytes this index is encoded with.
// For most cases (non variable-length), it will be 1.
template <ValidateFlag validate>
WasmOpcode read_prefixed_opcode(const byte* pc, uint32_t* length = nullptr,
const char* name = "prefixed opcode") {
uint32_t unused_length;
if (length == nullptr) {
length = &unused_length;
}
DCHECK(WasmOpcodes::IsPrefixOpcode(static_cast<WasmOpcode>(*pc)));
uint32_t index;
if (*pc == WasmOpcode::kSimdPrefix) {
// SIMD opcodes can be multiple bytes (when LEB128 encoded).
index = read_u32v<validate>(pc + 1, length, "prefixed opcode index");
// Only support SIMD opcodes that go up to 0xFF (when decoded). Anything
// bigger will need 1 more byte, and the '<< 8' below will be wrong.
DCHECK_LE(index, 0xff);
} else {
index = *(pc + 1);
*length = 1;
}
return static_cast<WasmOpcode>((*pc) << 8 | index);
}
// Reads a 8-bit unsigned integer (byte) and advances {pc_}. // Reads a 8-bit unsigned integer (byte) and advances {pc_}.
uint8_t consume_u8(const char* name = "uint8_t") { uint8_t consume_u8(const char* name = "uint8_t") {
return consume_little_endian<uint8_t>(name); return consume_little_endian<uint8_t>(name);
......
...@@ -1379,31 +1379,30 @@ class WasmDecoder : public Decoder { ...@@ -1379,31 +1379,30 @@ class WasmDecoder : public Decoder {
} }
} }
case kSimdPrefix: { case kSimdPrefix: {
byte simd_index = decoder->read_u8<validate>(pc + 1, "simd_index"); uint32_t length = 0;
WasmOpcode opcode = opcode = decoder->read_prefixed_opcode<validate>(pc, &length);
static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
switch (opcode) { switch (opcode) {
#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE) FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
#undef DECLARE_OPCODE_CASE #undef DECLARE_OPCODE_CASE
return 2; return 1 + length;
#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
#undef DECLARE_OPCODE_CASE #undef DECLARE_OPCODE_CASE
return 3; return 2 + length;
#define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE) FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE)
#undef DECLARE_OPCODE_CASE #undef DECLARE_OPCODE_CASE
{ {
MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX); MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
return 2 + imm.length; return 1 + length + imm.length;
} }
// Shuffles require a byte per lane, or 16 immediate bytes. // Shuffles require a byte per lane, or 16 immediate bytes.
case kExprS8x16Shuffle: case kExprS8x16Shuffle:
return 2 + kSimd128Size; return 1 + length + kSimd128Size;
default: default:
decoder->error(pc, "invalid SIMD opcode"); decoder->error(pc, "invalid SIMD opcode");
return 2; return 1 + length;
} }
} }
case kAtomicPrefix: { case kAtomicPrefix: {
...@@ -1508,7 +1507,7 @@ class WasmDecoder : public Decoder { ...@@ -1508,7 +1507,7 @@ class WasmDecoder : public Decoder {
case kNumericPrefix: case kNumericPrefix:
case kAtomicPrefix: case kAtomicPrefix:
case kSimdPrefix: { case kSimdPrefix: {
opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1)); opcode = this->read_prefixed_opcode<validate>(pc);
switch (opcode) { switch (opcode) {
FOREACH_SIMD_1_OPERAND_1_PARAM_OPCODE(DECLARE_OPCODE_CASE) FOREACH_SIMD_1_OPERAND_1_PARAM_OPCODE(DECLARE_OPCODE_CASE)
return {1, 1}; return {1, 1};
...@@ -1622,12 +1621,8 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1622,12 +1621,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
if (!WasmOpcodes::IsPrefixOpcode(opcode)) { if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(opcode)); return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(opcode));
} }
// We need one more byte. opcode = this->template read_prefixed_opcode<Decoder::kValidate>(pc);
++pc; return WasmOpcodes::OpcodeName(opcode);
if (pc >= this->end_) return "<end>";
byte sub_opcode = *pc;
opcode = static_cast<WasmOpcode>(opcode << 8 | sub_opcode);
return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(opcode));
} }
inline Zone* zone() const { return zone_; } inline Zone* zone() const { return zone_; }
...@@ -2355,13 +2350,14 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2355,13 +2350,14 @@ class WasmFullDecoder : public WasmDecoder<validate> {
} }
case kSimdPrefix: { case kSimdPrefix: {
CHECK_PROTOTYPE_OPCODE(simd); CHECK_PROTOTYPE_OPCODE(simd);
len++; uint32_t length = 0;
byte simd_index = opcode =
this->template read_u8<validate>(this->pc_ + 1, "simd index"); this->template read_prefixed_opcode<validate>(this->pc_, &length);
opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index); len += length;
TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_), TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
WasmOpcodes::OpcodeName(opcode)); WasmOpcodes::OpcodeName(opcode));
len += DecodeSimdOpcode(opcode); len += DecodeSimdOpcode(opcode, length);
break; break;
} }
case kAtomicPrefix: { case kAtomicPrefix: {
...@@ -2426,7 +2422,8 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2426,7 +2422,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
auto& val = stack_[i]; auto& val = stack_[i];
WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc); WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
if (WasmOpcodes::IsPrefixOpcode(opcode)) { if (WasmOpcodes::IsPrefixOpcode(opcode)) {
opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1)); opcode = this->template read_prefixed_opcode<Decoder::kNoValidate>(
val.pc);
} }
TRACE_PART(" %c@%d:%s", val.type.short_name(), TRACE_PART(" %c@%d:%s", val.type.short_name(),
static_cast<int>(val.pc - this->start_), static_cast<int>(val.pc - this->start_),
...@@ -2546,9 +2543,11 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2546,9 +2543,11 @@ class WasmFullDecoder : public WasmDecoder<validate> {
return imm.length; return imm.length;
} }
int DecodeLoadTransformMem(LoadType type, LoadTransformationKind transform) { int DecodeLoadTransformMem(LoadType type, LoadTransformationKind transform,
uint32_t opcode_length) {
if (!CheckHasMemory()) return 0; if (!CheckHasMemory()) return 0;
MemoryAccessImmediate<validate> imm(this, this->pc_ + 1, type.size_log_2()); MemoryAccessImmediate<validate> imm(this, this->pc_ + opcode_length,
type.size_log_2());
auto index = Pop(0, kWasmI32); auto index = Pop(0, kWasmI32);
auto* result = Push(kWasmS128); auto* result = Push(kWasmS128);
CALL_INTERFACE_IF_REACHABLE(LoadTransform, type, transform, imm, index, CALL_INTERFACE_IF_REACHABLE(LoadTransform, type, transform, imm, index,
...@@ -2686,8 +2685,15 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2686,8 +2685,15 @@ class WasmFullDecoder : public WasmDecoder<validate> {
return 16; return 16;
} }
uint32_t DecodeSimdOpcode(WasmOpcode opcode) { uint32_t DecodeSimdOpcode(WasmOpcode opcode, uint32_t opcode_length) {
// opcode_length is the number of bytes that this SIMD-specific opcode takes
// up in the LEB128 encoded form.
uint32_t len = 0; uint32_t len = 0;
// TODO(v8:10258): Most of the decodings below (like SimdExtractLane) should
// take opcode_length as a parameter, since that will determine where the
// immediate is located. However, for most of these instructions, their
// encoded opcodes take up 2 bytes, so they will not be affected by the
// variable-length encoding, and will still work correctly.
switch (opcode) { switch (opcode) {
case kExprF64x2ExtractLane: { case kExprF64x2ExtractLane: {
len = SimdExtractLane(opcode, kWasmF64); len = SimdExtractLane(opcode, kWasmF64);
...@@ -2739,43 +2745,51 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2739,43 +2745,51 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break; break;
case kExprS8x16LoadSplat: case kExprS8x16LoadSplat:
len = DecodeLoadTransformMem(LoadType::kI32Load8S, len = DecodeLoadTransformMem(LoadType::kI32Load8S,
LoadTransformationKind::kSplat); LoadTransformationKind::kSplat,
opcode_length);
break; break;
case kExprS16x8LoadSplat: case kExprS16x8LoadSplat:
len = DecodeLoadTransformMem(LoadType::kI32Load16S, len = DecodeLoadTransformMem(LoadType::kI32Load16S,
LoadTransformationKind::kSplat); LoadTransformationKind::kSplat,
opcode_length);
break; break;
case kExprS32x4LoadSplat: case kExprS32x4LoadSplat:
len = DecodeLoadTransformMem(LoadType::kI32Load, len = DecodeLoadTransformMem(
LoadTransformationKind::kSplat); LoadType::kI32Load, LoadTransformationKind::kSplat, opcode_length);
break; break;
case kExprS64x2LoadSplat: case kExprS64x2LoadSplat:
len = DecodeLoadTransformMem(LoadType::kI64Load, len = DecodeLoadTransformMem(
LoadTransformationKind::kSplat); LoadType::kI64Load, LoadTransformationKind::kSplat, opcode_length);
break; break;
case kExprI16x8Load8x8S: case kExprI16x8Load8x8S:
len = DecodeLoadTransformMem(LoadType::kI32Load8S, len = DecodeLoadTransformMem(LoadType::kI32Load8S,
LoadTransformationKind::kExtend); LoadTransformationKind::kExtend,
opcode_length);
break; break;
case kExprI16x8Load8x8U: case kExprI16x8Load8x8U:
len = DecodeLoadTransformMem(LoadType::kI32Load8U, len = DecodeLoadTransformMem(LoadType::kI32Load8U,
LoadTransformationKind::kExtend); LoadTransformationKind::kExtend,
opcode_length);
break; break;
case kExprI32x4Load16x4S: case kExprI32x4Load16x4S:
len = DecodeLoadTransformMem(LoadType::kI32Load16S, len = DecodeLoadTransformMem(LoadType::kI32Load16S,
LoadTransformationKind::kExtend); LoadTransformationKind::kExtend,
opcode_length);
break; break;
case kExprI32x4Load16x4U: case kExprI32x4Load16x4U:
len = DecodeLoadTransformMem(LoadType::kI32Load16U, len = DecodeLoadTransformMem(LoadType::kI32Load16U,
LoadTransformationKind::kExtend); LoadTransformationKind::kExtend,
opcode_length);
break; break;
case kExprI64x2Load32x2S: case kExprI64x2Load32x2S:
len = DecodeLoadTransformMem(LoadType::kI64Load32S, len = DecodeLoadTransformMem(LoadType::kI64Load32S,
LoadTransformationKind::kExtend); LoadTransformationKind::kExtend,
opcode_length);
break; break;
case kExprI64x2Load32x2U: case kExprI64x2Load32x2U:
len = DecodeLoadTransformMem(LoadType::kI64Load32U, len = DecodeLoadTransformMem(LoadType::kI64Load32U,
LoadTransformationKind::kExtend); LoadTransformationKind::kExtend,
opcode_length);
break; break;
default: { default: {
if (!FLAG_wasm_simd_post_mvp && if (!FLAG_wasm_simd_post_mvp &&
......
...@@ -173,9 +173,7 @@ class V8_EXPORT_PRIVATE BytecodeIterator : public NON_EXPORTED_BASE(Decoder) { ...@@ -173,9 +173,7 @@ class V8_EXPORT_PRIVATE BytecodeIterator : public NON_EXPORTED_BASE(Decoder) {
bool has_next() { return pc_ < end_; } bool has_next() { return pc_ < end_; }
WasmOpcode prefixed_opcode() { WasmOpcode prefixed_opcode() {
byte prefix = read_u8<Decoder::kNoValidate>(pc_, "expected prefix"); return read_prefixed_opcode<Decoder::kNoValidate>(pc_);
byte index = read_u8<Decoder::kNoValidate>(pc_ + 1, "expected index");
return static_cast<WasmOpcode>(prefix << 8 | index);
} }
}; };
......
...@@ -1748,7 +1748,7 @@ class ThreadImpl { ...@@ -1748,7 +1748,7 @@ class ThreadImpl {
DoTrap(kTrapUnalignedAccess, pc); DoTrap(kTrapUnalignedAccess, pc);
return false; return false;
} }
*len = 2 + imm.length; *len += imm.length;
return true; return true;
} }
...@@ -1777,7 +1777,7 @@ class ThreadImpl { ...@@ -1777,7 +1777,7 @@ class ThreadImpl {
DoTrap(kTrapUnalignedAccess, pc); DoTrap(kTrapUnalignedAccess, pc);
return false; return false;
} }
*len = 2 + imm.length; *len += imm.length;
return true; return true;
} }
...@@ -2167,7 +2167,7 @@ class ThreadImpl { ...@@ -2167,7 +2167,7 @@ class ThreadImpl {
#undef ATOMIC_STORE_CASE #undef ATOMIC_STORE_CASE
case kExprAtomicFence: case kExprAtomicFence:
std::atomic_thread_fence(std::memory_order_seq_cst); std::atomic_thread_fence(std::memory_order_seq_cst);
*len += 2; *len += 1;
break; break;
case kExprI32AtomicWait: { case kExprI32AtomicWait: {
int32_t val; int32_t val;
...@@ -3038,13 +3038,16 @@ class ThreadImpl { ...@@ -3038,13 +3038,16 @@ class ThreadImpl {
byte orig = code->start[pc]; byte orig = code->start[pc];
WasmOpcode opcode = static_cast<WasmOpcode>(orig); WasmOpcode opcode = static_cast<WasmOpcode>(orig);
if (WasmOpcodes::IsPrefixOpcode(opcode)) { if (WasmOpcodes::IsPrefixOpcode(opcode)) {
opcode = static_cast<WasmOpcode>(opcode << 8 | code->start[pc + 1]); uint32_t length;
opcode = decoder.read_prefixed_opcode<Decoder::kNoValidate>(
&code->start[pc], &length);
len += length;
} }
if (V8_UNLIKELY(orig == kInternalBreakpoint)) { if (V8_UNLIKELY(orig == kInternalBreakpoint)) {
orig = code->orig_start[pc]; orig = code->orig_start[pc];
if (WasmOpcodes::IsPrefixOpcode(static_cast<WasmOpcode>(orig))) { if (WasmOpcodes::IsPrefixOpcode(static_cast<WasmOpcode>(orig))) {
opcode = opcode = decoder.read_prefixed_opcode<Decoder::kNoValidate>(
static_cast<WasmOpcode>(orig << 8 | code->orig_start[pc + 1]); &code->start[pc]);
} }
if (SkipBreakpoint(code, pc)) { if (SkipBreakpoint(code, pc)) {
// skip breakpoint by switching on original code. // skip breakpoint by switching on original code.
...@@ -3647,7 +3650,6 @@ class ThreadImpl { ...@@ -3647,7 +3650,6 @@ class ThreadImpl {
break; break;
} }
case kNumericPrefix: { case kNumericPrefix: {
++len;
if (!ExecuteNumericOp(opcode, &decoder, code, pc, &len)) return; if (!ExecuteNumericOp(opcode, &decoder, code, pc, &len)) return;
break; break;
} }
...@@ -3656,7 +3658,6 @@ class ThreadImpl { ...@@ -3656,7 +3658,6 @@ class ThreadImpl {
break; break;
} }
case kSimdPrefix: { case kSimdPrefix: {
++len;
if (!ExecuteSimdOp(opcode, &decoder, code, pc, &len)) return; if (!ExecuteSimdOp(opcode, &decoder, code, pc, &len)) return;
break; break;
} }
......
...@@ -409,10 +409,9 @@ bool ExpectFused(ExecutionTier tier) { ...@@ -409,10 +409,9 @@ bool ExpectFused(ExecutionTier tier) {
WASM_RETURN1(WASM_ZERO)) WASM_RETURN1(WASM_ZERO))
#define TO_BYTE(val) static_cast<byte>(val) #define TO_BYTE(val) static_cast<byte>(val)
// TODO(v8:10258): We have support for emitting multi-byte opcodes now, so this // TODO(v8:10258): Still need this for shuffle test
// can change to simply, op, once the decoder is fixed to decode multi byte #define WASM_SIMD_OP_BYTE(op) kSimdPrefix, TO_BYTE(op)
// opcodes. #define WASM_SIMD_OP(op) op
#define WASM_SIMD_OP(op) kSimdPrefix, TO_BYTE(op)
#define WASM_SIMD_SPLAT(Type, ...) __VA_ARGS__, WASM_SIMD_OP(kExpr##Type##Splat) #define WASM_SIMD_SPLAT(Type, ...) __VA_ARGS__, WASM_SIMD_OP(kExpr##Type##Splat)
#define WASM_SIMD_UNOP(op, x) x, WASM_SIMD_OP(op) #define WASM_SIMD_UNOP(op, x) x, WASM_SIMD_OP(op)
#define WASM_SIMD_BINOP(op, x, y) x, y, WASM_SIMD_OP(op) #define WASM_SIMD_BINOP(op, x, y) x, y, WASM_SIMD_OP(op)
...@@ -568,8 +567,8 @@ WASM_SIMD_TEST(F32x4Splat) { ...@@ -568,8 +567,8 @@ WASM_SIMD_TEST(F32x4Splat) {
// Set up a global to hold output vector. // Set up a global to hold output vector.
float* g = r.builder().AddGlobal<float>(kWasmS128); float* g = r.builder().AddGlobal<float>(kWasmS128);
byte param1 = 0; byte param1 = 0;
BUILD(r, WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(param1))), BUILD_V(r, WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(param1))),
WASM_ONE); WASM_ONE);
FOR_FLOAT32_INPUTS(x) { FOR_FLOAT32_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -591,16 +590,16 @@ WASM_SIMD_TEST(F32x4ReplaceLane) { ...@@ -591,16 +590,16 @@ WASM_SIMD_TEST(F32x4ReplaceLane) {
float* g = r.builder().AddGlobal<float>(kWasmS128); float* g = r.builder().AddGlobal<float>(kWasmS128);
// Build function to replace each lane with its (FP) index. // Build function to replace each lane with its (FP) index.
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_SPLAT(WASM_F32(3.14159f))), BUILD_V(r, WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_SPLAT(WASM_F32(3.14159f))),
WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_REPLACE_LANE(
0, WASM_GET_LOCAL(temp1), WASM_F32(0.0f))), 0, WASM_GET_LOCAL(temp1), WASM_F32(0.0f))),
WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_REPLACE_LANE(
1, WASM_GET_LOCAL(temp1), WASM_F32(1.0f))), 1, WASM_GET_LOCAL(temp1), WASM_F32(1.0f))),
WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_REPLACE_LANE(
2, WASM_GET_LOCAL(temp1), WASM_F32(2.0f))), 2, WASM_GET_LOCAL(temp1), WASM_F32(2.0f))),
WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE( WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(
3, WASM_GET_LOCAL(temp1), WASM_F32(3.0f))), 3, WASM_GET_LOCAL(temp1), WASM_F32(3.0f))),
WASM_ONE); WASM_ONE);
r.Call(); r.Call();
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
...@@ -618,12 +617,13 @@ WASM_SIMD_COMPILED_TEST(F32x4ConvertI32x4) { ...@@ -618,12 +617,13 @@ WASM_SIMD_COMPILED_TEST(F32x4ConvertI32x4) {
// Build fn to splat test value, perform conversions, and write the results. // Build fn to splat test value, perform conversions, and write the results.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(
WASM_SET_GLOBAL( r, WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value))),
0, WASM_SIMD_UNOP(kExprF32x4SConvertI32x4, WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(
WASM_SET_GLOBAL( 0, WASM_SIMD_UNOP(kExprF32x4SConvertI32x4, WASM_GET_LOCAL(temp1))),
1, WASM_SIMD_UNOP(kExprF32x4UConvertI32x4, WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(
WASM_ONE); 1, WASM_SIMD_UNOP(kExprF32x4UConvertI32x4, WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_INT32_INPUTS(x) { FOR_INT32_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -706,9 +706,10 @@ void RunF32x4UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -706,9 +706,10 @@ void RunF32x4UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
// Build fn to splat test value, perform unop, and write the result. // Build fn to splat test value, perform unop, and write the result.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(r,
WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))), WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value))),
WASM_ONE); WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_FLOAT32_INPUTS(x) { FOR_FLOAT32_INPUTS(x) {
if (!PlatformCanRepresent(x)) continue; if (!PlatformCanRepresent(x)) continue;
...@@ -771,11 +772,12 @@ void RunF32x4BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -771,11 +772,12 @@ void RunF32x4BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte value1 = 0, value2 = 1; byte value1 = 0, value2 = 1;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
byte temp2 = r.AllocateLocal(kWasmS128); byte temp2 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value1))), BUILD_V(r,
WASM_SET_LOCAL(temp2, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value2))), WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value1))),
WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1), WASM_SET_LOCAL(temp2, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value2))),
WASM_GET_LOCAL(temp2))), WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1),
WASM_ONE); WASM_GET_LOCAL(temp2))),
WASM_ONE);
FOR_FLOAT32_INPUTS(x) { FOR_FLOAT32_INPUTS(x) {
if (!PlatformCanRepresent(x)) continue; if (!PlatformCanRepresent(x)) continue;
...@@ -838,11 +840,12 @@ void RunF32x4CompareOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -838,11 +840,12 @@ void RunF32x4CompareOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte value1 = 0, value2 = 1; byte value1 = 0, value2 = 1;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
byte temp2 = r.AllocateLocal(kWasmS128); byte temp2 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value1))), BUILD_V(r,
WASM_SET_LOCAL(temp2, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value2))), WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value1))),
WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1), WASM_SET_LOCAL(temp2, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value2))),
WASM_GET_LOCAL(temp2))), WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1),
WASM_ONE); WASM_GET_LOCAL(temp2))),
WASM_ONE);
FOR_FLOAT32_INPUTS(x) { FOR_FLOAT32_INPUTS(x) {
if (!PlatformCanRepresent(x)) continue; if (!PlatformCanRepresent(x)) continue;
...@@ -891,12 +894,13 @@ WASM_SIMD_TEST_NO_LOWERING(F32x4Qfma) { ...@@ -891,12 +894,13 @@ WASM_SIMD_TEST_NO_LOWERING(F32x4Qfma) {
float* g = r.builder().AddGlobal<float>(kWasmS128); float* g = r.builder().AddGlobal<float>(kWasmS128);
// Build fn to splat test values, perform compare op, and write the result. // Build fn to splat test values, perform compare op, and write the result.
byte value1 = 0, value2 = 1, value3 = 2; byte value1 = 0, value2 = 1, value3 = 2;
BUILD(r, BUILD_V(
WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_QFMA( r,
WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value1)), WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_QFMA(
WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value2)), WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value1)),
WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value3)))), WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value2)),
WASM_ONE); WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value3)))),
WASM_ONE);
for (FMOperation<float> x : qfma_vector<float>()) { for (FMOperation<float> x : qfma_vector<float>()) {
r.Call(x.a, x.b, x.c); r.Call(x.a, x.b, x.c);
...@@ -916,12 +920,13 @@ WASM_SIMD_TEST_NO_LOWERING(F32x4Qfms) { ...@@ -916,12 +920,13 @@ WASM_SIMD_TEST_NO_LOWERING(F32x4Qfms) {
float* g = r.builder().AddGlobal<float>(kWasmS128); float* g = r.builder().AddGlobal<float>(kWasmS128);
// Build fn to splat test values, perform compare op, and write the result. // Build fn to splat test values, perform compare op, and write the result.
byte value1 = 0, value2 = 1, value3 = 2; byte value1 = 0, value2 = 1, value3 = 2;
BUILD(r, BUILD_V(
WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_QFMS( r,
WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value1)), WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_QFMS(
WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value2)), WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value1)),
WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value3)))), WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value2)),
WASM_ONE); WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value3)))),
WASM_ONE);
for (FMOperation<float> x : qfms_vector<float>()) { for (FMOperation<float> x : qfms_vector<float>()) {
r.Call(x.a, x.b, x.c); r.Call(x.a, x.b, x.c);
...@@ -957,7 +962,7 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2ExtractLane) { ...@@ -957,7 +962,7 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2ExtractLane) {
WasmRunner<int64_t> r(execution_tier, lower_simd); WasmRunner<int64_t> r(execution_tier, lower_simd);
r.AllocateLocal(kWasmI64); r.AllocateLocal(kWasmI64);
r.AllocateLocal(kWasmS128); r.AllocateLocal(kWasmS128);
BUILD( BUILD_V(
r, r,
WASM_SET_LOCAL(0, WASM_SIMD_I64x2_EXTRACT_LANE( WASM_SET_LOCAL(0, WASM_SIMD_I64x2_EXTRACT_LANE(
0, WASM_SIMD_I64x2_SPLAT(WASM_I64V(0xFFFFFFFFFF)))), 0, WASM_SIMD_I64x2_SPLAT(WASM_I64V(0xFFFFFFFFFF)))),
...@@ -972,12 +977,12 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2ReplaceLane) { ...@@ -972,12 +977,12 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2ReplaceLane) {
int64_t* g = r.builder().AddGlobal<int64_t>(kWasmS128); int64_t* g = r.builder().AddGlobal<int64_t>(kWasmS128);
// Build function to replace each lane with its index. // Build function to replace each lane with its index.
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I64x2_SPLAT(WASM_I64V(-1))), BUILD_V(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I64x2_SPLAT(WASM_I64V(-1))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I64x2_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I64x2_REPLACE_LANE(
0, WASM_GET_LOCAL(temp1), WASM_I64V(0))), 0, WASM_GET_LOCAL(temp1), WASM_I64V(0))),
WASM_SET_GLOBAL(0, WASM_SIMD_I64x2_REPLACE_LANE( WASM_SET_GLOBAL(0, WASM_SIMD_I64x2_REPLACE_LANE(
1, WASM_GET_LOCAL(temp1), WASM_I64V(1))), 1, WASM_GET_LOCAL(temp1), WASM_I64V(1))),
WASM_ONE); WASM_ONE);
r.Call(); r.Call();
for (int64_t i = 0; i < 2; i++) { for (int64_t i = 0; i < 2; i++) {
...@@ -993,9 +998,10 @@ void RunI64x2UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -993,9 +998,10 @@ void RunI64x2UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
// Build fn to splat test value, perform unop, and write the result. // Build fn to splat test value, perform unop, and write the result.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I64x2_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(r,
WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))), WASM_SET_LOCAL(temp1, WASM_SIMD_I64x2_SPLAT(WASM_GET_LOCAL(value))),
WASM_ONE); WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_INT64_INPUTS(x) { FOR_INT64_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -1022,7 +1028,7 @@ void RunI64x2ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -1022,7 +1028,7 @@ void RunI64x2ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte value = 0; byte value = 0;
byte simd = r.AllocateLocal(kWasmS128); byte simd = r.AllocateLocal(kWasmS128);
// Shift using an immediate, and shift using a value loaded from memory. // Shift using an immediate, and shift using a value loaded from memory.
BUILD( BUILD_V(
r, WASM_SET_LOCAL(simd, WASM_SIMD_I64x2_SPLAT(WASM_GET_LOCAL(value))), r, WASM_SET_LOCAL(simd, WASM_SIMD_I64x2_SPLAT(WASM_GET_LOCAL(value))),
WASM_SET_GLOBAL(0, WASM_SIMD_SHIFT_OP(opcode, WASM_GET_LOCAL(simd), WASM_SET_GLOBAL(0, WASM_SIMD_SHIFT_OP(opcode, WASM_GET_LOCAL(simd),
WASM_I32V(shift))), WASM_I32V(shift))),
...@@ -1068,11 +1074,12 @@ void RunI64x2BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -1068,11 +1074,12 @@ void RunI64x2BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte value1 = 0, value2 = 1; byte value1 = 0, value2 = 1;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
byte temp2 = r.AllocateLocal(kWasmS128); byte temp2 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I64x2_SPLAT(WASM_GET_LOCAL(value1))), BUILD_V(r,
WASM_SET_LOCAL(temp2, WASM_SIMD_I64x2_SPLAT(WASM_GET_LOCAL(value2))), WASM_SET_LOCAL(temp1, WASM_SIMD_I64x2_SPLAT(WASM_GET_LOCAL(value1))),
WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1), WASM_SET_LOCAL(temp2, WASM_SIMD_I64x2_SPLAT(WASM_GET_LOCAL(value2))),
WASM_GET_LOCAL(temp2))), WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1),
WASM_ONE); WASM_GET_LOCAL(temp2))),
WASM_ONE);
FOR_INT64_INPUTS(x) { FOR_INT64_INPUTS(x) {
FOR_INT64_INPUTS(y) { FOR_INT64_INPUTS(y) {
...@@ -1144,8 +1151,8 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2Splat) { ...@@ -1144,8 +1151,8 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2Splat) {
// Set up a global to hold output vector. // Set up a global to hold output vector.
double* g = r.builder().AddGlobal<double>(kWasmS128); double* g = r.builder().AddGlobal<double>(kWasmS128);
byte param1 = 0; byte param1 = 0;
BUILD(r, WASM_SET_GLOBAL(0, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(param1))), BUILD_V(r, WASM_SET_GLOBAL(0, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(param1))),
WASM_ONE); WASM_ONE);
FOR_FLOAT64_INPUTS(x) { FOR_FLOAT64_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -1166,12 +1173,12 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2ExtractLane) { ...@@ -1166,12 +1173,12 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2ExtractLane) {
byte param1 = 0; byte param1 = 0;
byte temp1 = r.AllocateLocal(kWasmF64); byte temp1 = r.AllocateLocal(kWasmF64);
byte temp2 = r.AllocateLocal(kWasmS128); byte temp2 = r.AllocateLocal(kWasmS128);
BUILD(r, BUILD_V(r,
WASM_SET_LOCAL(temp1, WASM_SET_LOCAL(temp1,
WASM_SIMD_F64x2_EXTRACT_LANE( WASM_SIMD_F64x2_EXTRACT_LANE(
0, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(param1)))), 0, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(param1)))),
WASM_SET_LOCAL(temp2, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(temp1))), WASM_SET_LOCAL(temp2, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(temp1))),
WASM_SIMD_F64x2_EXTRACT_LANE(1, WASM_GET_LOCAL(temp2))); WASM_SIMD_F64x2_EXTRACT_LANE(1, WASM_GET_LOCAL(temp2)));
FOR_FLOAT64_INPUTS(x) { FOR_FLOAT64_INPUTS(x) {
double actual = r.Call(x); double actual = r.Call(x);
double expected = x; double expected = x;
...@@ -1190,14 +1197,14 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2ReplaceLane) { ...@@ -1190,14 +1197,14 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2ReplaceLane) {
double* g1 = r.builder().AddGlobal<double>(kWasmS128); double* g1 = r.builder().AddGlobal<double>(kWasmS128);
// Build function to replace each lane with its (FP) index. // Build function to replace each lane with its (FP) index.
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_F64x2_SPLAT(WASM_F64(1e100))), BUILD_V(r, WASM_SET_LOCAL(temp1, WASM_SIMD_F64x2_SPLAT(WASM_F64(1e100))),
// Replace lane 0. // Replace lane 0.
WASM_SET_GLOBAL(0, WASM_SIMD_F64x2_REPLACE_LANE( WASM_SET_GLOBAL(0, WASM_SIMD_F64x2_REPLACE_LANE(
0, WASM_GET_LOCAL(temp1), WASM_F64(0.0f))), 0, WASM_GET_LOCAL(temp1), WASM_F64(0.0f))),
// Replace lane 1. // Replace lane 1.
WASM_SET_GLOBAL(1, WASM_SIMD_F64x2_REPLACE_LANE( WASM_SET_GLOBAL(1, WASM_SIMD_F64x2_REPLACE_LANE(
1, WASM_GET_LOCAL(temp1), WASM_F64(1.0f))), 1, WASM_GET_LOCAL(temp1), WASM_F64(1.0f))),
WASM_ONE); WASM_ONE);
r.Call(); r.Call();
CHECK_EQ(0., ReadLittleEndianValue<double>(&g0[0])); CHECK_EQ(0., ReadLittleEndianValue<double>(&g0[0]));
...@@ -1209,21 +1216,21 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2ReplaceLane) { ...@@ -1209,21 +1216,21 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2ReplaceLane) {
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X #if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X
WASM_SIMD_TEST_NO_LOWERING(F64x2ExtractLaneWithI64x2) { WASM_SIMD_TEST_NO_LOWERING(F64x2ExtractLaneWithI64x2) {
WasmRunner<int64_t> r(execution_tier, lower_simd); WasmRunner<int64_t> r(execution_tier, lower_simd);
BUILD(r, WASM_IF_ELSE_L( BUILD_V(r, WASM_IF_ELSE_L(
WASM_F64_EQ(WASM_SIMD_F64x2_EXTRACT_LANE( WASM_F64_EQ(WASM_SIMD_F64x2_EXTRACT_LANE(
0, WASM_SIMD_I64x2_SPLAT(WASM_I64V(1e15))), 0, WASM_SIMD_I64x2_SPLAT(WASM_I64V(1e15))),
WASM_F64_REINTERPRET_I64(WASM_I64V(1e15))), WASM_F64_REINTERPRET_I64(WASM_I64V(1e15))),
WASM_I64V(1), WASM_I64V(0))); WASM_I64V(1), WASM_I64V(0)));
CHECK_EQ(1, r.Call()); CHECK_EQ(1, r.Call());
} }
WASM_SIMD_TEST_NO_LOWERING(I64x2ExtractWithF64x2) { WASM_SIMD_TEST_NO_LOWERING(I64x2ExtractWithF64x2) {
WasmRunner<int64_t> r(execution_tier, lower_simd); WasmRunner<int64_t> r(execution_tier, lower_simd);
BUILD(r, WASM_IF_ELSE_L( BUILD_V(r, WASM_IF_ELSE_L(
WASM_I64_EQ(WASM_SIMD_I64x2_EXTRACT_LANE( WASM_I64_EQ(WASM_SIMD_I64x2_EXTRACT_LANE(
0, WASM_SIMD_F64x2_SPLAT(WASM_F64(1e15))), 0, WASM_SIMD_F64x2_SPLAT(WASM_F64(1e15))),
WASM_I64_REINTERPRET_F64(WASM_F64(1e15))), WASM_I64_REINTERPRET_F64(WASM_F64(1e15))),
WASM_I64V(1), WASM_I64V(0))); WASM_I64V(1), WASM_I64V(0)));
CHECK_EQ(1, r.Call()); CHECK_EQ(1, r.Call());
} }
#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X #endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X
...@@ -1310,9 +1317,10 @@ void RunF64x2UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -1310,9 +1317,10 @@ void RunF64x2UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
// Build fn to splat test value, perform unop, and write the result. // Build fn to splat test value, perform unop, and write the result.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(r,
WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))), WASM_SET_LOCAL(temp1, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value))),
WASM_ONE); WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_FLOAT64_INPUTS(x) { FOR_FLOAT64_INPUTS(x) {
if (!PlatformCanRepresent(x)) continue; if (!PlatformCanRepresent(x)) continue;
...@@ -1363,11 +1371,12 @@ void RunF64x2BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -1363,11 +1371,12 @@ void RunF64x2BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte value1 = 0, value2 = 1; byte value1 = 0, value2 = 1;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
byte temp2 = r.AllocateLocal(kWasmS128); byte temp2 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value1))), BUILD_V(r,
WASM_SET_LOCAL(temp2, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value2))), WASM_SET_LOCAL(temp1, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value1))),
WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1), WASM_SET_LOCAL(temp2, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value2))),
WASM_GET_LOCAL(temp2))), WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1),
WASM_ONE); WASM_GET_LOCAL(temp2))),
WASM_ONE);
FOR_FLOAT64_INPUTS(x) { FOR_FLOAT64_INPUTS(x) {
if (!PlatformCanRepresent(x)) continue; if (!PlatformCanRepresent(x)) continue;
...@@ -1428,14 +1437,15 @@ void RunF64x2CompareOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -1428,14 +1437,15 @@ void RunF64x2CompareOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte temp2 = r.AllocateLocal(kWasmS128); byte temp2 = r.AllocateLocal(kWasmS128);
// Make the lanes of each temp compare differently: // Make the lanes of each temp compare differently:
// temp1 = y, x and temp2 = y, y. // temp1 = y, x and temp2 = y, y.
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value1))), BUILD_V(r,
WASM_SET_LOCAL(temp1, WASM_SET_LOCAL(temp1, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value1))),
WASM_SIMD_F64x2_REPLACE_LANE(1, WASM_GET_LOCAL(temp1), WASM_SET_LOCAL(temp1,
WASM_GET_LOCAL(value2))), WASM_SIMD_F64x2_REPLACE_LANE(1, WASM_GET_LOCAL(temp1),
WASM_SET_LOCAL(temp2, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value2))), WASM_GET_LOCAL(value2))),
WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1), WASM_SET_LOCAL(temp2, WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value2))),
WASM_GET_LOCAL(temp2))), WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1),
WASM_ONE); WASM_GET_LOCAL(temp2))),
WASM_ONE);
FOR_FLOAT64_INPUTS(x) { FOR_FLOAT64_INPUTS(x) {
if (!PlatformCanRepresent(x)) continue; if (!PlatformCanRepresent(x)) continue;
...@@ -1517,12 +1527,13 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2Qfma) { ...@@ -1517,12 +1527,13 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2Qfma) {
double* g = r.builder().AddGlobal<double>(kWasmS128); double* g = r.builder().AddGlobal<double>(kWasmS128);
// Build fn to splat test values, perform compare op, and write the result. // Build fn to splat test values, perform compare op, and write the result.
byte value1 = 0, value2 = 1, value3 = 2; byte value1 = 0, value2 = 1, value3 = 2;
BUILD(r, BUILD_V(
WASM_SET_GLOBAL(0, WASM_SIMD_F64x2_QFMA( r,
WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value1)), WASM_SET_GLOBAL(0, WASM_SIMD_F64x2_QFMA(
WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value2)), WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value1)),
WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value3)))), WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value2)),
WASM_ONE); WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value3)))),
WASM_ONE);
for (FMOperation<double> x : qfma_vector<double>()) { for (FMOperation<double> x : qfma_vector<double>()) {
r.Call(x.a, x.b, x.c); r.Call(x.a, x.b, x.c);
...@@ -1542,12 +1553,13 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2Qfms) { ...@@ -1542,12 +1553,13 @@ WASM_SIMD_TEST_NO_LOWERING(F64x2Qfms) {
double* g = r.builder().AddGlobal<double>(kWasmS128); double* g = r.builder().AddGlobal<double>(kWasmS128);
// Build fn to splat test values, perform compare op, and write the result. // Build fn to splat test values, perform compare op, and write the result.
byte value1 = 0, value2 = 1, value3 = 2; byte value1 = 0, value2 = 1, value3 = 2;
BUILD(r, BUILD_V(
WASM_SET_GLOBAL(0, WASM_SIMD_F64x2_QFMS( r,
WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value1)), WASM_SET_GLOBAL(0, WASM_SIMD_F64x2_QFMS(
WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value2)), WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value1)),
WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value3)))), WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value2)),
WASM_ONE); WASM_SIMD_F64x2_SPLAT(WASM_GET_LOCAL(value3)))),
WASM_ONE);
for (FMOperation<double> x : qfms_vector<double>()) { for (FMOperation<double> x : qfms_vector<double>()) {
r.Call(x.a, x.b, x.c); r.Call(x.a, x.b, x.c);
...@@ -1566,8 +1578,8 @@ WASM_SIMD_TEST(I32x4Splat) { ...@@ -1566,8 +1578,8 @@ WASM_SIMD_TEST(I32x4Splat) {
// Set up a global to hold output vector. // Set up a global to hold output vector.
int32_t* g = r.builder().AddGlobal<int32_t>(kWasmS128); int32_t* g = r.builder().AddGlobal<int32_t>(kWasmS128);
byte param1 = 0; byte param1 = 0;
BUILD(r, WASM_SET_GLOBAL(0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(param1))), BUILD_V(r, WASM_SET_GLOBAL(0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(param1))),
WASM_ONE); WASM_ONE);
FOR_INT32_INPUTS(x) { FOR_INT32_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -1585,16 +1597,16 @@ WASM_SIMD_TEST(I32x4ReplaceLane) { ...@@ -1585,16 +1597,16 @@ WASM_SIMD_TEST(I32x4ReplaceLane) {
int32_t* g = r.builder().AddGlobal<int32_t>(kWasmS128); int32_t* g = r.builder().AddGlobal<int32_t>(kWasmS128);
// Build function to replace each lane with its index. // Build function to replace each lane with its index.
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_SPLAT(WASM_I32V(-1))), BUILD_V(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_SPLAT(WASM_I32V(-1))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_REPLACE_LANE(
0, WASM_GET_LOCAL(temp1), WASM_I32V(0))), 0, WASM_GET_LOCAL(temp1), WASM_I32V(0))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_REPLACE_LANE(
1, WASM_GET_LOCAL(temp1), WASM_I32V(1))), 1, WASM_GET_LOCAL(temp1), WASM_I32V(1))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_REPLACE_LANE(
2, WASM_GET_LOCAL(temp1), WASM_I32V(2))), 2, WASM_GET_LOCAL(temp1), WASM_I32V(2))),
WASM_SET_GLOBAL(0, WASM_SIMD_I32x4_REPLACE_LANE( WASM_SET_GLOBAL(0, WASM_SIMD_I32x4_REPLACE_LANE(
3, WASM_GET_LOCAL(temp1), WASM_I32V(3))), 3, WASM_GET_LOCAL(temp1), WASM_I32V(3))),
WASM_ONE); WASM_ONE);
r.Call(); r.Call();
for (int32_t i = 0; i < 4; i++) { for (int32_t i = 0; i < 4; i++) {
...@@ -1607,8 +1619,8 @@ WASM_SIMD_TEST(I16x8Splat) { ...@@ -1607,8 +1619,8 @@ WASM_SIMD_TEST(I16x8Splat) {
// Set up a global to hold output vector. // Set up a global to hold output vector.
int16_t* g = r.builder().AddGlobal<int16_t>(kWasmS128); int16_t* g = r.builder().AddGlobal<int16_t>(kWasmS128);
byte param1 = 0; byte param1 = 0;
BUILD(r, WASM_SET_GLOBAL(0, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(param1))), BUILD_V(r, WASM_SET_GLOBAL(0, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(param1))),
WASM_ONE); WASM_ONE);
FOR_INT16_INPUTS(x) { FOR_INT16_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -1636,24 +1648,24 @@ WASM_SIMD_TEST(I16x8ReplaceLane) { ...@@ -1636,24 +1648,24 @@ WASM_SIMD_TEST(I16x8ReplaceLane) {
int16_t* g = r.builder().AddGlobal<int16_t>(kWasmS128); int16_t* g = r.builder().AddGlobal<int16_t>(kWasmS128);
// Build function to replace each lane with its index. // Build function to replace each lane with its index.
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_I32V(-1))), BUILD_V(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_I32V(-1))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE(
0, WASM_GET_LOCAL(temp1), WASM_I32V(0))), 0, WASM_GET_LOCAL(temp1), WASM_I32V(0))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE(
1, WASM_GET_LOCAL(temp1), WASM_I32V(1))), 1, WASM_GET_LOCAL(temp1), WASM_I32V(1))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE(
2, WASM_GET_LOCAL(temp1), WASM_I32V(2))), 2, WASM_GET_LOCAL(temp1), WASM_I32V(2))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE(
3, WASM_GET_LOCAL(temp1), WASM_I32V(3))), 3, WASM_GET_LOCAL(temp1), WASM_I32V(3))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE(
4, WASM_GET_LOCAL(temp1), WASM_I32V(4))), 4, WASM_GET_LOCAL(temp1), WASM_I32V(4))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE(
5, WASM_GET_LOCAL(temp1), WASM_I32V(5))), 5, WASM_GET_LOCAL(temp1), WASM_I32V(5))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_REPLACE_LANE(
6, WASM_GET_LOCAL(temp1), WASM_I32V(6))), 6, WASM_GET_LOCAL(temp1), WASM_I32V(6))),
WASM_SET_GLOBAL(0, WASM_SIMD_I16x8_REPLACE_LANE( WASM_SET_GLOBAL(0, WASM_SIMD_I16x8_REPLACE_LANE(
7, WASM_GET_LOCAL(temp1), WASM_I32V(7))), 7, WASM_GET_LOCAL(temp1), WASM_I32V(7))),
WASM_ONE); WASM_ONE);
r.Call(); r.Call();
for (int16_t i = 0; i < 8; i++) { for (int16_t i = 0; i < 8; i++) {
...@@ -1668,12 +1680,12 @@ WASM_SIMD_TEST_NO_LOWERING(I8x16BitMask) { ...@@ -1668,12 +1680,12 @@ WASM_SIMD_TEST_NO_LOWERING(I8x16BitMask) {
WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd);
byte value1 = r.AllocateLocal(kWasmS128); byte value1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(value1, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(0))), BUILD_V(r, WASM_SET_LOCAL(value1, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(0))),
WASM_SET_LOCAL(value1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(value1, WASM_SIMD_I8x16_REPLACE_LANE(
0, WASM_GET_LOCAL(value1), WASM_I32V(0))), 0, WASM_GET_LOCAL(value1), WASM_I32V(0))),
WASM_SET_LOCAL(value1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(value1, WASM_SIMD_I8x16_REPLACE_LANE(
1, WASM_GET_LOCAL(value1), WASM_I32V(-1))), 1, WASM_GET_LOCAL(value1), WASM_I32V(-1))),
WASM_SIMD_UNOP(kExprI8x16BitMask, WASM_GET_LOCAL(value1))); WASM_SIMD_UNOP(kExprI8x16BitMask, WASM_GET_LOCAL(value1)));
FOR_INT8_INPUTS(x) { FOR_INT8_INPUTS(x) {
int32_t actual = r.Call(x); int32_t actual = r.Call(x);
...@@ -1688,12 +1700,12 @@ WASM_SIMD_TEST_NO_LOWERING(I16x8BitMask) { ...@@ -1688,12 +1700,12 @@ WASM_SIMD_TEST_NO_LOWERING(I16x8BitMask) {
WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd);
byte value1 = r.AllocateLocal(kWasmS128); byte value1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(value1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(0))), BUILD_V(r, WASM_SET_LOCAL(value1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(0))),
WASM_SET_LOCAL(value1, WASM_SIMD_I16x8_REPLACE_LANE( WASM_SET_LOCAL(value1, WASM_SIMD_I16x8_REPLACE_LANE(
0, WASM_GET_LOCAL(value1), WASM_I32V(0))), 0, WASM_GET_LOCAL(value1), WASM_I32V(0))),
WASM_SET_LOCAL(value1, WASM_SIMD_I16x8_REPLACE_LANE( WASM_SET_LOCAL(value1, WASM_SIMD_I16x8_REPLACE_LANE(
1, WASM_GET_LOCAL(value1), WASM_I32V(-1))), 1, WASM_GET_LOCAL(value1), WASM_I32V(-1))),
WASM_SIMD_UNOP(kExprI16x8BitMask, WASM_GET_LOCAL(value1))); WASM_SIMD_UNOP(kExprI16x8BitMask, WASM_GET_LOCAL(value1)));
FOR_INT16_INPUTS(x) { FOR_INT16_INPUTS(x) {
int32_t actual = r.Call(x); int32_t actual = r.Call(x);
...@@ -1708,12 +1720,12 @@ WASM_SIMD_TEST_NO_LOWERING(I32x4BitMask) { ...@@ -1708,12 +1720,12 @@ WASM_SIMD_TEST_NO_LOWERING(I32x4BitMask) {
WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd);
byte value1 = r.AllocateLocal(kWasmS128); byte value1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(value1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(0))), BUILD_V(r, WASM_SET_LOCAL(value1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(0))),
WASM_SET_LOCAL(value1, WASM_SIMD_I32x4_REPLACE_LANE( WASM_SET_LOCAL(value1, WASM_SIMD_I32x4_REPLACE_LANE(
0, WASM_GET_LOCAL(value1), WASM_I32V(0))), 0, WASM_GET_LOCAL(value1), WASM_I32V(0))),
WASM_SET_LOCAL(value1, WASM_SIMD_I32x4_REPLACE_LANE( WASM_SET_LOCAL(value1, WASM_SIMD_I32x4_REPLACE_LANE(
1, WASM_GET_LOCAL(value1), WASM_I32V(-1))), 1, WASM_GET_LOCAL(value1), WASM_I32V(-1))),
WASM_SIMD_UNOP(kExprI32x4BitMask, WASM_GET_LOCAL(value1))); WASM_SIMD_UNOP(kExprI32x4BitMask, WASM_GET_LOCAL(value1)));
FOR_INT32_INPUTS(x) { FOR_INT32_INPUTS(x) {
int32_t actual = r.Call(x); int32_t actual = r.Call(x);
...@@ -1730,8 +1742,8 @@ WASM_SIMD_TEST(I8x16Splat) { ...@@ -1730,8 +1742,8 @@ WASM_SIMD_TEST(I8x16Splat) {
// Set up a global to hold output vector. // Set up a global to hold output vector.
int8_t* g = r.builder().AddGlobal<int8_t>(kWasmS128); int8_t* g = r.builder().AddGlobal<int8_t>(kWasmS128);
byte param1 = 0; byte param1 = 0;
BUILD(r, WASM_SET_GLOBAL(0, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(param1))), BUILD_V(r, WASM_SET_GLOBAL(0, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(param1))),
WASM_ONE); WASM_ONE);
FOR_INT8_INPUTS(x) { FOR_INT8_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -1759,40 +1771,40 @@ WASM_SIMD_TEST(I8x16ReplaceLane) { ...@@ -1759,40 +1771,40 @@ WASM_SIMD_TEST(I8x16ReplaceLane) {
int8_t* g = r.builder().AddGlobal<int8_t>(kWasmS128); int8_t* g = r.builder().AddGlobal<int8_t>(kWasmS128);
// Build function to replace each lane with its index. // Build function to replace each lane with its index.
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_SPLAT(WASM_I32V(-1))), BUILD_V(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_SPLAT(WASM_I32V(-1))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
0, WASM_GET_LOCAL(temp1), WASM_I32V(0))), 0, WASM_GET_LOCAL(temp1), WASM_I32V(0))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
1, WASM_GET_LOCAL(temp1), WASM_I32V(1))), 1, WASM_GET_LOCAL(temp1), WASM_I32V(1))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
2, WASM_GET_LOCAL(temp1), WASM_I32V(2))), 2, WASM_GET_LOCAL(temp1), WASM_I32V(2))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
3, WASM_GET_LOCAL(temp1), WASM_I32V(3))), 3, WASM_GET_LOCAL(temp1), WASM_I32V(3))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
4, WASM_GET_LOCAL(temp1), WASM_I32V(4))), 4, WASM_GET_LOCAL(temp1), WASM_I32V(4))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
5, WASM_GET_LOCAL(temp1), WASM_I32V(5))), 5, WASM_GET_LOCAL(temp1), WASM_I32V(5))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
6, WASM_GET_LOCAL(temp1), WASM_I32V(6))), 6, WASM_GET_LOCAL(temp1), WASM_I32V(6))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
7, WASM_GET_LOCAL(temp1), WASM_I32V(7))), 7, WASM_GET_LOCAL(temp1), WASM_I32V(7))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
8, WASM_GET_LOCAL(temp1), WASM_I32V(8))), 8, WASM_GET_LOCAL(temp1), WASM_I32V(8))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
9, WASM_GET_LOCAL(temp1), WASM_I32V(9))), 9, WASM_GET_LOCAL(temp1), WASM_I32V(9))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
10, WASM_GET_LOCAL(temp1), WASM_I32V(10))), 10, WASM_GET_LOCAL(temp1), WASM_I32V(10))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
11, WASM_GET_LOCAL(temp1), WASM_I32V(11))), 11, WASM_GET_LOCAL(temp1), WASM_I32V(11))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
12, WASM_GET_LOCAL(temp1), WASM_I32V(12))), 12, WASM_GET_LOCAL(temp1), WASM_I32V(12))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
13, WASM_GET_LOCAL(temp1), WASM_I32V(13))), 13, WASM_GET_LOCAL(temp1), WASM_I32V(13))),
WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_REPLACE_LANE(
14, WASM_GET_LOCAL(temp1), WASM_I32V(14))), 14, WASM_GET_LOCAL(temp1), WASM_I32V(14))),
WASM_SET_GLOBAL(0, WASM_SIMD_I8x16_REPLACE_LANE( WASM_SET_GLOBAL(0, WASM_SIMD_I8x16_REPLACE_LANE(
15, WASM_GET_LOCAL(temp1), WASM_I32V(15))), 15, WASM_GET_LOCAL(temp1), WASM_I32V(15))),
WASM_ONE); WASM_ONE);
r.Call(); r.Call();
for (int8_t i = 0; i < 16; i++) { for (int8_t i = 0; i < 16; i++) {
...@@ -1823,12 +1835,13 @@ WASM_SIMD_TEST(I32x4ConvertF32x4) { ...@@ -1823,12 +1835,13 @@ WASM_SIMD_TEST(I32x4ConvertF32x4) {
// Build fn to splat test value, perform conversions, and write the results. // Build fn to splat test value, perform conversions, and write the results.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(
WASM_SET_GLOBAL( r, WASM_SET_LOCAL(temp1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(value))),
0, WASM_SIMD_UNOP(kExprI32x4SConvertF32x4, WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(
WASM_SET_GLOBAL( 0, WASM_SIMD_UNOP(kExprI32x4SConvertF32x4, WASM_GET_LOCAL(temp1))),
1, WASM_SIMD_UNOP(kExprI32x4UConvertF32x4, WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(
WASM_ONE); 1, WASM_SIMD_UNOP(kExprI32x4UConvertF32x4, WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_FLOAT32_INPUTS(x) { FOR_FLOAT32_INPUTS(x) {
if (!PlatformCanRepresent(x)) continue; if (!PlatformCanRepresent(x)) continue;
...@@ -1853,16 +1866,17 @@ WASM_SIMD_TEST(I32x4ConvertI16x8) { ...@@ -1853,16 +1866,17 @@ WASM_SIMD_TEST(I32x4ConvertI16x8) {
// Build fn to splat test value, perform conversions, and write the results. // Build fn to splat test value, perform conversions, and write the results.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(
WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(kExprI32x4SConvertI16x8High, r, WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value))),
WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(kExprI32x4SConvertI16x8High,
WASM_SET_GLOBAL(1, WASM_SIMD_UNOP(kExprI32x4SConvertI16x8Low, WASM_GET_LOCAL(temp1))),
WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(
WASM_SET_GLOBAL(2, WASM_SIMD_UNOP(kExprI32x4UConvertI16x8High, 1, WASM_SIMD_UNOP(kExprI32x4SConvertI16x8Low, WASM_GET_LOCAL(temp1))),
WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(2, WASM_SIMD_UNOP(kExprI32x4UConvertI16x8High,
WASM_SET_GLOBAL(3, WASM_SIMD_UNOP(kExprI32x4UConvertI16x8Low, WASM_GET_LOCAL(temp1))),
WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(
WASM_ONE); 3, WASM_SIMD_UNOP(kExprI32x4UConvertI16x8Low, WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_INT16_INPUTS(x) { FOR_INT16_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -1885,9 +1899,10 @@ void RunI32x4UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -1885,9 +1899,10 @@ void RunI32x4UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
// Build fn to splat test value, perform unop, and write the result. // Build fn to splat test value, perform unop, and write the result.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(r,
WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))), WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value))),
WASM_ONE); WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_INT32_INPUTS(x) { FOR_INT32_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -1920,11 +1935,12 @@ void RunI32x4BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -1920,11 +1935,12 @@ void RunI32x4BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte value1 = 0, value2 = 1; byte value1 = 0, value2 = 1;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
byte temp2 = r.AllocateLocal(kWasmS128); byte temp2 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value1))), BUILD_V(r,
WASM_SET_LOCAL(temp2, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value2))), WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value1))),
WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1), WASM_SET_LOCAL(temp2, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value2))),
WASM_GET_LOCAL(temp2))), WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1),
WASM_ONE); WASM_GET_LOCAL(temp2))),
WASM_ONE);
FOR_INT32_INPUTS(x) { FOR_INT32_INPUTS(x) {
FOR_INT32_INPUTS(y) { FOR_INT32_INPUTS(y) {
...@@ -2040,7 +2056,7 @@ void RunI32x4ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -2040,7 +2056,7 @@ void RunI32x4ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte value = 0; byte value = 0;
byte simd = r.AllocateLocal(kWasmS128); byte simd = r.AllocateLocal(kWasmS128);
// Shift using an immediate, and shift using a value loaded from memory. // Shift using an immediate, and shift using a value loaded from memory.
BUILD( BUILD_V(
r, WASM_SET_LOCAL(simd, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value))), r, WASM_SET_LOCAL(simd, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value))),
WASM_SET_GLOBAL(0, WASM_SIMD_SHIFT_OP(opcode, WASM_GET_LOCAL(simd), WASM_SET_GLOBAL(0, WASM_SIMD_SHIFT_OP(opcode, WASM_GET_LOCAL(simd),
WASM_I32V(shift))), WASM_I32V(shift))),
...@@ -2087,16 +2103,17 @@ WASM_SIMD_TEST(I16x8ConvertI8x16) { ...@@ -2087,16 +2103,17 @@ WASM_SIMD_TEST(I16x8ConvertI8x16) {
// Build fn to splat test value, perform conversions, and write the results. // Build fn to splat test value, perform conversions, and write the results.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(
WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(kExprI16x8SConvertI8x16High, r, WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value))),
WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(kExprI16x8SConvertI8x16High,
WASM_SET_GLOBAL(1, WASM_SIMD_UNOP(kExprI16x8SConvertI8x16Low, WASM_GET_LOCAL(temp1))),
WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(
WASM_SET_GLOBAL(2, WASM_SIMD_UNOP(kExprI16x8UConvertI8x16High, 1, WASM_SIMD_UNOP(kExprI16x8SConvertI8x16Low, WASM_GET_LOCAL(temp1))),
WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(2, WASM_SIMD_UNOP(kExprI16x8UConvertI8x16High,
WASM_SET_GLOBAL(3, WASM_SIMD_UNOP(kExprI16x8UConvertI8x16Low, WASM_GET_LOCAL(temp1))),
WASM_GET_LOCAL(temp1))), WASM_SET_GLOBAL(
WASM_ONE); 3, WASM_SIMD_UNOP(kExprI16x8UConvertI8x16Low, WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_INT8_INPUTS(x) { FOR_INT8_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -2120,14 +2137,15 @@ WASM_SIMD_TEST(I16x8ConvertI32x4) { ...@@ -2120,14 +2137,15 @@ WASM_SIMD_TEST(I16x8ConvertI32x4) {
// Build fn to splat test value, perform conversions, and write the results. // Build fn to splat test value, perform conversions, and write the results.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(r,
WASM_SET_GLOBAL( WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value))),
0, WASM_SIMD_BINOP(kExprI16x8SConvertI32x4, WASM_GET_LOCAL(temp1), WASM_SET_GLOBAL(
WASM_GET_LOCAL(temp1))), 0, WASM_SIMD_BINOP(kExprI16x8SConvertI32x4, WASM_GET_LOCAL(temp1),
WASM_SET_GLOBAL( WASM_GET_LOCAL(temp1))),
1, WASM_SIMD_BINOP(kExprI16x8UConvertI32x4, WASM_GET_LOCAL(temp1), WASM_SET_GLOBAL(
WASM_GET_LOCAL(temp1))), 1, WASM_SIMD_BINOP(kExprI16x8UConvertI32x4, WASM_GET_LOCAL(temp1),
WASM_ONE); WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_INT32_INPUTS(x) { FOR_INT32_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -2148,9 +2166,10 @@ void RunI16x8UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -2148,9 +2166,10 @@ void RunI16x8UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
// Build fn to splat test value, perform unop, and write the result. // Build fn to splat test value, perform unop, and write the result.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(r,
WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))), WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value))),
WASM_ONE); WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_INT16_INPUTS(x) { FOR_INT16_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -2180,11 +2199,12 @@ void RunI16x8BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -2180,11 +2199,12 @@ void RunI16x8BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte value1 = 0, value2 = 1; byte value1 = 0, value2 = 1;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
byte temp2 = r.AllocateLocal(kWasmS128); byte temp2 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value1))), BUILD_V(r,
WASM_SET_LOCAL(temp2, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value2))), WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value1))),
WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1), WASM_SET_LOCAL(temp2, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value2))),
WASM_GET_LOCAL(temp2))), WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1),
WASM_ONE); WASM_GET_LOCAL(temp2))),
WASM_ONE);
for (T x : compiler::ValueHelper::GetVector<T>()) { for (T x : compiler::ValueHelper::GetVector<T>()) {
for (T y : compiler::ValueHelper::GetVector<T>()) { for (T y : compiler::ValueHelper::GetVector<T>()) {
...@@ -2309,7 +2329,7 @@ void RunI16x8ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -2309,7 +2329,7 @@ void RunI16x8ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte value = 0; byte value = 0;
byte simd = r.AllocateLocal(kWasmS128); byte simd = r.AllocateLocal(kWasmS128);
// Shift using an immediate, and shift using a value loaded from memory. // Shift using an immediate, and shift using a value loaded from memory.
BUILD( BUILD_V(
r, WASM_SET_LOCAL(simd, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value))), r, WASM_SET_LOCAL(simd, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value))),
WASM_SET_GLOBAL(0, WASM_SIMD_SHIFT_OP(opcode, WASM_GET_LOCAL(simd), WASM_SET_GLOBAL(0, WASM_SIMD_SHIFT_OP(opcode, WASM_GET_LOCAL(simd),
WASM_I32V(shift))), WASM_I32V(shift))),
...@@ -2353,9 +2373,10 @@ void RunI8x16UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -2353,9 +2373,10 @@ void RunI8x16UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
// Build fn to splat test value, perform unop, and write the result. // Build fn to splat test value, perform unop, and write the result.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(r,
WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))), WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value))),
WASM_ONE); WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(opcode, WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_INT8_INPUTS(x) { FOR_INT8_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -2384,14 +2405,15 @@ WASM_SIMD_TEST(I8x16ConvertI16x8) { ...@@ -2384,14 +2405,15 @@ WASM_SIMD_TEST(I8x16ConvertI16x8) {
// Build fn to splat test value, perform conversions, and write the results. // Build fn to splat test value, perform conversions, and write the results.
byte value = 0; byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value))), BUILD_V(r,
WASM_SET_GLOBAL( WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value))),
0, WASM_SIMD_BINOP(kExprI8x16SConvertI16x8, WASM_GET_LOCAL(temp1), WASM_SET_GLOBAL(
WASM_GET_LOCAL(temp1))), 0, WASM_SIMD_BINOP(kExprI8x16SConvertI16x8, WASM_GET_LOCAL(temp1),
WASM_SET_GLOBAL( WASM_GET_LOCAL(temp1))),
1, WASM_SIMD_BINOP(kExprI8x16UConvertI16x8, WASM_GET_LOCAL(temp1), WASM_SET_GLOBAL(
WASM_GET_LOCAL(temp1))), 1, WASM_SIMD_BINOP(kExprI8x16UConvertI16x8, WASM_GET_LOCAL(temp1),
WASM_ONE); WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_INT16_INPUTS(x) { FOR_INT16_INPUTS(x) {
r.Call(x); r.Call(x);
...@@ -2414,11 +2436,12 @@ void RunI8x16BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -2414,11 +2436,12 @@ void RunI8x16BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte value1 = 0, value2 = 1; byte value1 = 0, value2 = 1;
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
byte temp2 = r.AllocateLocal(kWasmS128); byte temp2 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value1))), BUILD_V(r,
WASM_SET_LOCAL(temp2, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value2))), WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value1))),
WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1), WASM_SET_LOCAL(temp2, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value2))),
WASM_GET_LOCAL(temp2))), WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1),
WASM_ONE); WASM_GET_LOCAL(temp2))),
WASM_ONE);
for (T x : compiler::ValueHelper::GetVector<T>()) { for (T x : compiler::ValueHelper::GetVector<T>()) {
for (T y : compiler::ValueHelper::GetVector<T>()) { for (T y : compiler::ValueHelper::GetVector<T>()) {
...@@ -2543,7 +2566,7 @@ void RunI8x16ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -2543,7 +2566,7 @@ void RunI8x16ShiftOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
byte value = 0; byte value = 0;
byte simd = r.AllocateLocal(kWasmS128); byte simd = r.AllocateLocal(kWasmS128);
// Shift using an immediate, and shift using a value loaded from memory. // Shift using an immediate, and shift using a value loaded from memory.
BUILD( BUILD_V(
r, WASM_SET_LOCAL(simd, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value))), r, WASM_SET_LOCAL(simd, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value))),
WASM_SET_GLOBAL(0, WASM_SIMD_SHIFT_OP(opcode, WASM_GET_LOCAL(simd), WASM_SET_GLOBAL(0, WASM_SIMD_SHIFT_OP(opcode, WASM_GET_LOCAL(simd),
WASM_I32V(shift))), WASM_I32V(shift))),
...@@ -2582,37 +2605,37 @@ WASM_SIMD_TEST(I8x16ShrU) { ...@@ -2582,37 +2605,37 @@ WASM_SIMD_TEST(I8x16ShrU) {
// Test Select by making a mask where the 0th and 3rd lanes are true and the // Test Select by making a mask where the 0th and 3rd lanes are true and the
// rest false, and comparing for non-equality with zero to convert to a boolean // rest false, and comparing for non-equality with zero to convert to a boolean
// vector. // vector.
#define WASM_SIMD_SELECT_TEST(format) \ #define WASM_SIMD_SELECT_TEST(format) \
WASM_SIMD_TEST(S##format##Select) { \ WASM_SIMD_TEST(S##format##Select) { \
WasmRunner<int32_t, int32_t, int32_t> r(execution_tier, lower_simd); \ WasmRunner<int32_t, int32_t, int32_t> r(execution_tier, lower_simd); \
byte val1 = 0; \ byte val1 = 0; \
byte val2 = 1; \ byte val2 = 1; \
byte src1 = r.AllocateLocal(kWasmS128); \ byte src1 = r.AllocateLocal(kWasmS128); \
byte src2 = r.AllocateLocal(kWasmS128); \ byte src2 = r.AllocateLocal(kWasmS128); \
byte zero = r.AllocateLocal(kWasmS128); \ byte zero = r.AllocateLocal(kWasmS128); \
byte mask = r.AllocateLocal(kWasmS128); \ byte mask = r.AllocateLocal(kWasmS128); \
BUILD(r, \ BUILD_V(r, \
WASM_SET_LOCAL(src1, \ WASM_SET_LOCAL(src1, \
WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(val1))), \ WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(val1))), \
WASM_SET_LOCAL(src2, \ WASM_SET_LOCAL(src2, \
WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(val2))), \ WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(val2))), \
WASM_SET_LOCAL(zero, WASM_SIMD_I##format##_SPLAT(WASM_ZERO)), \ WASM_SET_LOCAL(zero, WASM_SIMD_I##format##_SPLAT(WASM_ZERO)), \
WASM_SET_LOCAL(mask, WASM_SIMD_I##format##_REPLACE_LANE( \ WASM_SET_LOCAL(mask, WASM_SIMD_I##format##_REPLACE_LANE( \
1, WASM_GET_LOCAL(zero), WASM_I32V(-1))), \ 1, WASM_GET_LOCAL(zero), WASM_I32V(-1))), \
WASM_SET_LOCAL(mask, WASM_SIMD_I##format##_REPLACE_LANE( \ WASM_SET_LOCAL(mask, WASM_SIMD_I##format##_REPLACE_LANE( \
2, WASM_GET_LOCAL(mask), WASM_I32V(-1))), \ 2, WASM_GET_LOCAL(mask), WASM_I32V(-1))), \
WASM_SET_LOCAL( \ WASM_SET_LOCAL( \
mask, \ mask, \
WASM_SIMD_SELECT( \ WASM_SIMD_SELECT( \
format, WASM_GET_LOCAL(src1), WASM_GET_LOCAL(src2), \ format, WASM_GET_LOCAL(src1), WASM_GET_LOCAL(src2), \
WASM_SIMD_BINOP(kExprI##format##Ne, WASM_GET_LOCAL(mask), \ WASM_SIMD_BINOP(kExprI##format##Ne, WASM_GET_LOCAL(mask), \
WASM_GET_LOCAL(zero)))), \ WASM_GET_LOCAL(zero)))), \
WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 0), \ WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 0), \
WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val1, 1), \ WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val1, 1), \
WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val1, 2), \ WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val1, 2), \
WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 3), WASM_ONE); \ WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 3), WASM_ONE); \
\ \
CHECK_EQ(1, r.Call(0x12, 0x34)); \ CHECK_EQ(1, r.Call(0x12, 0x34)); \
} }
WASM_SIMD_SELECT_TEST(32x4) WASM_SIMD_SELECT_TEST(32x4)
...@@ -2621,36 +2644,37 @@ WASM_SIMD_SELECT_TEST(8x16) ...@@ -2621,36 +2644,37 @@ WASM_SIMD_SELECT_TEST(8x16)
// Test Select by making a mask where the 0th and 3rd lanes are non-zero and the // Test Select by making a mask where the 0th and 3rd lanes are non-zero and the
// rest 0. The mask is not the result of a comparison op. // rest 0. The mask is not the result of a comparison op.
#define WASM_SIMD_NON_CANONICAL_SELECT_TEST(format) \ #define WASM_SIMD_NON_CANONICAL_SELECT_TEST(format) \
WASM_SIMD_TEST_NO_LOWERING(S##format##NonCanonicalSelect) { \ WASM_SIMD_TEST_NO_LOWERING(S##format##NonCanonicalSelect) { \
WasmRunner<int32_t, int32_t, int32_t, int32_t> r(execution_tier, \ WasmRunner<int32_t, int32_t, int32_t, int32_t> r(execution_tier, \
lower_simd); \ lower_simd); \
byte val1 = 0; \ byte val1 = 0; \
byte val2 = 1; \ byte val2 = 1; \
byte combined = 2; \ byte combined = 2; \
byte src1 = r.AllocateLocal(kWasmS128); \ byte src1 = r.AllocateLocal(kWasmS128); \
byte src2 = r.AllocateLocal(kWasmS128); \ byte src2 = r.AllocateLocal(kWasmS128); \
byte zero = r.AllocateLocal(kWasmS128); \ byte zero = r.AllocateLocal(kWasmS128); \
byte mask = r.AllocateLocal(kWasmS128); \ byte mask = r.AllocateLocal(kWasmS128); \
BUILD(r, \ BUILD_V( \
WASM_SET_LOCAL(src1, \ r, \
WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(val1))), \ WASM_SET_LOCAL(src1, \
WASM_SET_LOCAL(src2, \ WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(val1))), \
WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(val2))), \ WASM_SET_LOCAL(src2, \
WASM_SET_LOCAL(zero, WASM_SIMD_I##format##_SPLAT(WASM_ZERO)), \ WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(val2))), \
WASM_SET_LOCAL(mask, WASM_SIMD_I##format##_REPLACE_LANE( \ WASM_SET_LOCAL(zero, WASM_SIMD_I##format##_SPLAT(WASM_ZERO)), \
1, WASM_GET_LOCAL(zero), WASM_I32V(0xF))), \ WASM_SET_LOCAL(mask, WASM_SIMD_I##format##_REPLACE_LANE( \
WASM_SET_LOCAL(mask, WASM_SIMD_I##format##_REPLACE_LANE( \ 1, WASM_GET_LOCAL(zero), WASM_I32V(0xF))), \
2, WASM_GET_LOCAL(mask), WASM_I32V(0xF))), \ WASM_SET_LOCAL(mask, WASM_SIMD_I##format##_REPLACE_LANE( \
WASM_SET_LOCAL(mask, WASM_SIMD_SELECT(format, WASM_GET_LOCAL(src1), \ 2, WASM_GET_LOCAL(mask), WASM_I32V(0xF))), \
WASM_GET_LOCAL(src2), \ WASM_SET_LOCAL(mask, WASM_SIMD_SELECT(format, WASM_GET_LOCAL(src1), \
WASM_GET_LOCAL(mask))), \ WASM_GET_LOCAL(src2), \
WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 0), \ WASM_GET_LOCAL(mask))), \
WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, combined, 1), \ WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 0), \
WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, combined, 2), \ WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, combined, 1), \
WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 3), WASM_ONE); \ WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, combined, 2), \
\ WASM_SIMD_CHECK_LANE_S(I##format, mask, I32, val2, 3), WASM_ONE); \
CHECK_EQ(1, r.Call(0x12, 0x34, 0x32)); \ \
CHECK_EQ(1, r.Call(0x12, 0x34, 0x32)); \
} }
WASM_SIMD_NON_CANONICAL_SELECT_TEST(32x4) WASM_SIMD_NON_CANONICAL_SELECT_TEST(32x4)
...@@ -2672,16 +2696,16 @@ void RunBinaryLaneOpTest( ...@@ -2672,16 +2696,16 @@ void RunBinaryLaneOpTest(
WriteLittleEndianValue<T>(&src1[i], kElems + i); WriteLittleEndianValue<T>(&src1[i], kElems + i);
} }
if (simd_op == kExprS8x16Shuffle) { if (simd_op == kExprS8x16Shuffle) {
BUILD(r, BUILD_V(r,
WASM_SET_GLOBAL(0, WASM_SIMD_S8x16_SHUFFLE_OP(simd_op, expected, WASM_SET_GLOBAL(0, WASM_SIMD_S8x16_SHUFFLE_OP(simd_op, expected,
WASM_GET_GLOBAL(0), WASM_GET_GLOBAL(0),
WASM_GET_GLOBAL(1))), WASM_GET_GLOBAL(1))),
WASM_ONE); WASM_ONE);
} else { } else {
BUILD(r, BUILD_V(r,
WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(simd_op, WASM_GET_GLOBAL(0), WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(simd_op, WASM_GET_GLOBAL(0),
WASM_GET_GLOBAL(1))), WASM_GET_GLOBAL(1))),
WASM_ONE); WASM_ONE);
} }
CHECK_EQ(1, r.Call()); CHECK_EQ(1, r.Call());
...@@ -2914,7 +2938,7 @@ WASM_SIMD_TEST(S8x16Swizzle) { ...@@ -2914,7 +2938,7 @@ WASM_SIMD_TEST(S8x16Swizzle) {
uint8_t* dst = r.builder().AddGlobal<uint8_t>(kWasmS128); uint8_t* dst = r.builder().AddGlobal<uint8_t>(kWasmS128);
uint8_t* src0 = r.builder().AddGlobal<uint8_t>(kWasmS128); uint8_t* src0 = r.builder().AddGlobal<uint8_t>(kWasmS128);
uint8_t* src1 = r.builder().AddGlobal<uint8_t>(kWasmS128); uint8_t* src1 = r.builder().AddGlobal<uint8_t>(kWasmS128);
BUILD( BUILD_V(
r, r,
WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(kExprS8x16Swizzle, WASM_GET_GLOBAL(1), WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(kExprS8x16Swizzle, WASM_GET_GLOBAL(1),
WASM_GET_GLOBAL(2))), WASM_GET_GLOBAL(2))),
...@@ -2962,7 +2986,7 @@ WASM_SIMD_TEST(S8x16ShuffleFuzz) { ...@@ -2962,7 +2986,7 @@ WASM_SIMD_TEST(S8x16ShuffleFuzz) {
} }
void AppendShuffle(const Shuffle& shuffle, std::vector<byte>* buffer) { void AppendShuffle(const Shuffle& shuffle, std::vector<byte>* buffer) {
byte opcode[] = {WASM_SIMD_OP(kExprS8x16Shuffle)}; byte opcode[] = {WASM_SIMD_OP_BYTE(kExprS8x16Shuffle)};
for (size_t i = 0; i < arraysize(opcode); ++i) buffer->push_back(opcode[i]); for (size_t i = 0; i < arraysize(opcode); ++i) buffer->push_back(opcode[i]);
for (size_t i = 0; i < kSimd128Size; ++i) buffer->push_back((shuffle[i])); for (size_t i = 0; i < kSimd128Size; ++i) buffer->push_back((shuffle[i]));
} }
...@@ -3041,73 +3065,74 @@ WASM_SIMD_COMPILED_TEST(S8x16MultiShuffleFuzz) { ...@@ -3041,73 +3065,74 @@ WASM_SIMD_COMPILED_TEST(S8x16MultiShuffleFuzz) {
// test inputs. Test inputs with all true, all false, one true, and one false. // test inputs. Test inputs with all true, all false, one true, and one false.
#define WASM_SIMD_BOOL_REDUCTION_TEST(format, lanes, int_type) \ #define WASM_SIMD_BOOL_REDUCTION_TEST(format, lanes, int_type) \
WASM_SIMD_TEST(ReductionTest##lanes) { \ WASM_SIMD_TEST(ReductionTest##lanes) { \
FLAG_SCOPE(wasm_simd_post_mvp); \ FLAG_SCOPE(wasm_simd_post_mvp); \
WasmRunner<int32_t> r(execution_tier, lower_simd); \ WasmRunner<int32_t> r(execution_tier, lower_simd); \
if (lanes == 2 && lower_simd == kLowerSimd) return; \ if (lanes == 2 && lower_simd == kLowerSimd) return; \
byte zero = r.AllocateLocal(kWasmS128); \ byte zero = r.AllocateLocal(kWasmS128); \
byte one_one = r.AllocateLocal(kWasmS128); \ byte one_one = r.AllocateLocal(kWasmS128); \
byte reduced = r.AllocateLocal(kWasmI32); \ byte reduced = r.AllocateLocal(kWasmI32); \
BUILD(r, WASM_SET_LOCAL(zero, WASM_SIMD_I##format##_SPLAT(int_type(0))), \ BUILD_V( \
WASM_SET_LOCAL( \ r, WASM_SET_LOCAL(zero, WASM_SIMD_I##format##_SPLAT(int_type(0))), \
reduced, WASM_SIMD_UNOP(kExprS1x##lanes##AnyTrue, \ WASM_SET_LOCAL(reduced, \
WASM_SIMD_UNOP(kExprS1x##lanes##AnyTrue, \
WASM_SIMD_BINOP(kExprI##format##Eq, \ WASM_SIMD_BINOP(kExprI##format##Eq, \
WASM_GET_LOCAL(zero), \ WASM_GET_LOCAL(zero), \
WASM_GET_LOCAL(zero)))), \ WASM_GET_LOCAL(zero)))), \
WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(reduced), WASM_ZERO), \ WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(reduced), WASM_ZERO), \
WASM_RETURN1(WASM_ZERO)), \ WASM_RETURN1(WASM_ZERO)), \
WASM_SET_LOCAL( \ WASM_SET_LOCAL(reduced, \
reduced, WASM_SIMD_UNOP(kExprS1x##lanes##AnyTrue, \ WASM_SIMD_UNOP(kExprS1x##lanes##AnyTrue, \
WASM_SIMD_BINOP(kExprI##format##Ne, \ WASM_SIMD_BINOP(kExprI##format##Ne, \
WASM_GET_LOCAL(zero), \ WASM_GET_LOCAL(zero), \
WASM_GET_LOCAL(zero)))), \ WASM_GET_LOCAL(zero)))), \
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(reduced), WASM_ZERO), \ WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(reduced), WASM_ZERO), \
WASM_RETURN1(WASM_ZERO)), \ WASM_RETURN1(WASM_ZERO)), \
WASM_SET_LOCAL( \ WASM_SET_LOCAL(reduced, \
reduced, WASM_SIMD_UNOP(kExprS1x##lanes##AllTrue, \ WASM_SIMD_UNOP(kExprS1x##lanes##AllTrue, \
WASM_SIMD_BINOP(kExprI##format##Eq, \ WASM_SIMD_BINOP(kExprI##format##Eq, \
WASM_GET_LOCAL(zero), \ WASM_GET_LOCAL(zero), \
WASM_GET_LOCAL(zero)))), \ WASM_GET_LOCAL(zero)))), \
WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(reduced), WASM_ZERO), \ WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(reduced), WASM_ZERO), \
WASM_RETURN1(WASM_ZERO)), \ WASM_RETURN1(WASM_ZERO)), \
WASM_SET_LOCAL( \ WASM_SET_LOCAL(reduced, \
reduced, WASM_SIMD_UNOP(kExprS1x##lanes##AllTrue, \ WASM_SIMD_UNOP(kExprS1x##lanes##AllTrue, \
WASM_SIMD_BINOP(kExprI##format##Ne, \ WASM_SIMD_BINOP(kExprI##format##Ne, \
WASM_GET_LOCAL(zero), \ WASM_GET_LOCAL(zero), \
WASM_GET_LOCAL(zero)))), \ WASM_GET_LOCAL(zero)))), \
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(reduced), WASM_ZERO), \ WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(reduced), WASM_ZERO), \
WASM_RETURN1(WASM_ZERO)), \ WASM_RETURN1(WASM_ZERO)), \
WASM_SET_LOCAL(one_one, \ WASM_SET_LOCAL(one_one, \
WASM_SIMD_I##format##_REPLACE_LANE( \ WASM_SIMD_I##format##_REPLACE_LANE( \
lanes - 1, WASM_GET_LOCAL(zero), int_type(1))), \ lanes - 1, WASM_GET_LOCAL(zero), int_type(1))), \
WASM_SET_LOCAL( \ WASM_SET_LOCAL(reduced, \
reduced, WASM_SIMD_UNOP(kExprS1x##lanes##AnyTrue, \ WASM_SIMD_UNOP(kExprS1x##lanes##AnyTrue, \
WASM_SIMD_BINOP(kExprI##format##Eq, \ WASM_SIMD_BINOP(kExprI##format##Eq, \
WASM_GET_LOCAL(one_one), \ WASM_GET_LOCAL(one_one), \
WASM_GET_LOCAL(zero)))), \ WASM_GET_LOCAL(zero)))), \
WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(reduced), WASM_ZERO), \ WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(reduced), WASM_ZERO), \
WASM_RETURN1(WASM_ZERO)), \ WASM_RETURN1(WASM_ZERO)), \
WASM_SET_LOCAL( \ WASM_SET_LOCAL(reduced, \
reduced, WASM_SIMD_UNOP(kExprS1x##lanes##AnyTrue, \ WASM_SIMD_UNOP(kExprS1x##lanes##AnyTrue, \
WASM_SIMD_BINOP(kExprI##format##Ne, \ WASM_SIMD_BINOP(kExprI##format##Ne, \
WASM_GET_LOCAL(one_one), \ WASM_GET_LOCAL(one_one), \
WASM_GET_LOCAL(zero)))), \ WASM_GET_LOCAL(zero)))), \
WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(reduced), WASM_ZERO), \ WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(reduced), WASM_ZERO), \
WASM_RETURN1(WASM_ZERO)), \ WASM_RETURN1(WASM_ZERO)), \
WASM_SET_LOCAL( \ WASM_SET_LOCAL(reduced, \
reduced, WASM_SIMD_UNOP(kExprS1x##lanes##AllTrue, \ WASM_SIMD_UNOP(kExprS1x##lanes##AllTrue, \
WASM_SIMD_BINOP(kExprI##format##Eq, \ WASM_SIMD_BINOP(kExprI##format##Eq, \
WASM_GET_LOCAL(one_one), \ WASM_GET_LOCAL(one_one), \
WASM_GET_LOCAL(zero)))), \ WASM_GET_LOCAL(zero)))), \
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(reduced), WASM_ZERO), \ WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(reduced), WASM_ZERO), \
WASM_RETURN1(WASM_ZERO)), \ WASM_RETURN1(WASM_ZERO)), \
WASM_SET_LOCAL( \ WASM_SET_LOCAL(reduced, \
reduced, WASM_SIMD_UNOP(kExprS1x##lanes##AllTrue, \ WASM_SIMD_UNOP(kExprS1x##lanes##AllTrue, \
WASM_SIMD_BINOP(kExprI##format##Ne, \ WASM_SIMD_BINOP(kExprI##format##Ne, \
WASM_GET_LOCAL(one_one), \ WASM_GET_LOCAL(one_one), \
WASM_GET_LOCAL(zero)))), \ WASM_GET_LOCAL(zero)))), \
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(reduced), WASM_ZERO), \ WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(reduced), WASM_ZERO), \
WASM_RETURN1(WASM_ZERO)), \ WASM_RETURN1(WASM_ZERO)), \
WASM_ONE); \ WASM_ONE); \
CHECK_EQ(1, r.Call()); \ CHECK_EQ(1, r.Call()); \
} }
...@@ -3120,21 +3145,21 @@ WASM_SIMD_BOOL_REDUCTION_TEST(8x16, 16, WASM_I32V) ...@@ -3120,21 +3145,21 @@ WASM_SIMD_BOOL_REDUCTION_TEST(8x16, 16, WASM_I32V)
WASM_SIMD_TEST(SimdI32x4ExtractWithF32x4) { WASM_SIMD_TEST(SimdI32x4ExtractWithF32x4) {
WasmRunner<int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t> r(execution_tier, lower_simd);
BUILD(r, WASM_IF_ELSE_I( BUILD_V(r, WASM_IF_ELSE_I(
WASM_I32_EQ(WASM_SIMD_I32x4_EXTRACT_LANE( WASM_I32_EQ(WASM_SIMD_I32x4_EXTRACT_LANE(
0, WASM_SIMD_F32x4_SPLAT(WASM_F32(30.5))), 0, WASM_SIMD_F32x4_SPLAT(WASM_F32(30.5))),
WASM_I32_REINTERPRET_F32(WASM_F32(30.5))), WASM_I32_REINTERPRET_F32(WASM_F32(30.5))),
WASM_I32V(1), WASM_I32V(0))); WASM_I32V(1), WASM_I32V(0)));
CHECK_EQ(1, r.Call()); CHECK_EQ(1, r.Call());
} }
WASM_SIMD_TEST(SimdF32x4ExtractWithI32x4) { WASM_SIMD_TEST(SimdF32x4ExtractWithI32x4) {
WasmRunner<int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t> r(execution_tier, lower_simd);
BUILD(r, BUILD_V(r, WASM_IF_ELSE_I(
WASM_IF_ELSE_I(WASM_F32_EQ(WASM_SIMD_F32x4_EXTRACT_LANE( WASM_F32_EQ(WASM_SIMD_F32x4_EXTRACT_LANE(
0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(15))), 0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(15))),
WASM_F32_REINTERPRET_I32(WASM_I32V(15))), WASM_F32_REINTERPRET_I32(WASM_I32V(15))),
WASM_I32V(1), WASM_I32V(0))); WASM_I32V(1), WASM_I32V(0)));
CHECK_EQ(1, r.Call()); CHECK_EQ(1, r.Call());
} }
...@@ -3142,11 +3167,11 @@ WASM_SIMD_TEST(SimdF32x4ExtractLane) { ...@@ -3142,11 +3167,11 @@ WASM_SIMD_TEST(SimdF32x4ExtractLane) {
WasmRunner<float> r(execution_tier, lower_simd); WasmRunner<float> r(execution_tier, lower_simd);
r.AllocateLocal(kWasmF32); r.AllocateLocal(kWasmF32);
r.AllocateLocal(kWasmS128); r.AllocateLocal(kWasmS128);
BUILD(r, BUILD_V(r,
WASM_SET_LOCAL(0, WASM_SIMD_F32x4_EXTRACT_LANE( WASM_SET_LOCAL(0, WASM_SIMD_F32x4_EXTRACT_LANE(
0, WASM_SIMD_F32x4_SPLAT(WASM_F32(30.5)))), 0, WASM_SIMD_F32x4_SPLAT(WASM_F32(30.5)))),
WASM_SET_LOCAL(1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(0))), WASM_SET_LOCAL(1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(0))),
WASM_SIMD_F32x4_EXTRACT_LANE(1, WASM_GET_LOCAL(1))); WASM_SIMD_F32x4_EXTRACT_LANE(1, WASM_GET_LOCAL(1)));
CHECK_EQ(30.5, r.Call()); CHECK_EQ(30.5, r.Call());
} }
...@@ -3156,40 +3181,41 @@ WASM_SIMD_TEST(SimdF32x4AddWithI32x4) { ...@@ -3156,40 +3181,41 @@ WASM_SIMD_TEST(SimdF32x4AddWithI32x4) {
const int kOne = 0x3F800000; const int kOne = 0x3F800000;
const int kTwo = 0x40000000; const int kTwo = 0x40000000;
WasmRunner<int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t> r(execution_tier, lower_simd);
BUILD(r, BUILD_V(
WASM_IF_ELSE_I( r,
WASM_F32_EQ( WASM_IF_ELSE_I(
WASM_SIMD_F32x4_EXTRACT_LANE( WASM_F32_EQ(
0, WASM_SIMD_BINOP(kExprF32x4Add, WASM_SIMD_F32x4_EXTRACT_LANE(
WASM_SIMD_I32x4_SPLAT(WASM_I32V(kOne)), 0, WASM_SIMD_BINOP(kExprF32x4Add,
WASM_SIMD_I32x4_SPLAT(WASM_I32V(kTwo)))), WASM_SIMD_I32x4_SPLAT(WASM_I32V(kOne)),
WASM_F32_ADD(WASM_F32_REINTERPRET_I32(WASM_I32V(kOne)), WASM_SIMD_I32x4_SPLAT(WASM_I32V(kTwo)))),
WASM_F32_REINTERPRET_I32(WASM_I32V(kTwo)))), WASM_F32_ADD(WASM_F32_REINTERPRET_I32(WASM_I32V(kOne)),
WASM_I32V(1), WASM_I32V(0))); WASM_F32_REINTERPRET_I32(WASM_I32V(kTwo)))),
WASM_I32V(1), WASM_I32V(0)));
CHECK_EQ(1, r.Call()); CHECK_EQ(1, r.Call());
} }
WASM_SIMD_TEST(SimdI32x4AddWithF32x4) { WASM_SIMD_TEST(SimdI32x4AddWithF32x4) {
WasmRunner<int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t> r(execution_tier, lower_simd);
BUILD(r, BUILD_V(
WASM_IF_ELSE_I( r, WASM_IF_ELSE_I(
WASM_I32_EQ( WASM_I32_EQ(
WASM_SIMD_I32x4_EXTRACT_LANE( WASM_SIMD_I32x4_EXTRACT_LANE(
0, WASM_SIMD_BINOP(kExprI32x4Add, 0, WASM_SIMD_BINOP(kExprI32x4Add,
WASM_SIMD_F32x4_SPLAT(WASM_F32(21.25)), WASM_SIMD_F32x4_SPLAT(WASM_F32(21.25)),
WASM_SIMD_F32x4_SPLAT(WASM_F32(31.5)))), WASM_SIMD_F32x4_SPLAT(WASM_F32(31.5)))),
WASM_I32_ADD(WASM_I32_REINTERPRET_F32(WASM_F32(21.25)), WASM_I32_ADD(WASM_I32_REINTERPRET_F32(WASM_F32(21.25)),
WASM_I32_REINTERPRET_F32(WASM_F32(31.5)))), WASM_I32_REINTERPRET_F32(WASM_F32(31.5)))),
WASM_I32V(1), WASM_I32V(0))); WASM_I32V(1), WASM_I32V(0)));
CHECK_EQ(1, r.Call()); CHECK_EQ(1, r.Call());
} }
WASM_SIMD_TEST(SimdI32x4Local) { WASM_SIMD_TEST(SimdI32x4Local) {
WasmRunner<int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t> r(execution_tier, lower_simd);
r.AllocateLocal(kWasmS128); r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(31))), BUILD_V(r, WASM_SET_LOCAL(0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(31))),
WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_GET_LOCAL(0))); WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_GET_LOCAL(0)));
CHECK_EQ(31, r.Call()); CHECK_EQ(31, r.Call());
} }
...@@ -3197,10 +3223,11 @@ WASM_SIMD_TEST(SimdI32x4SplatFromExtract) { ...@@ -3197,10 +3223,11 @@ WASM_SIMD_TEST(SimdI32x4SplatFromExtract) {
WasmRunner<int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t> r(execution_tier, lower_simd);
r.AllocateLocal(kWasmI32); r.AllocateLocal(kWasmI32);
r.AllocateLocal(kWasmS128); r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(0, WASM_SIMD_I32x4_EXTRACT_LANE( BUILD_V(r,
0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(76)))), WASM_SET_LOCAL(0, WASM_SIMD_I32x4_EXTRACT_LANE(
WASM_SET_LOCAL(1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(0))), 0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(76)))),
WASM_SIMD_I32x4_EXTRACT_LANE(1, WASM_GET_LOCAL(1))); WASM_SET_LOCAL(1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(0))),
WASM_SIMD_I32x4_EXTRACT_LANE(1, WASM_GET_LOCAL(1)));
CHECK_EQ(76, r.Call()); CHECK_EQ(76, r.Call());
} }
...@@ -3208,33 +3235,34 @@ WASM_SIMD_TEST(SimdI32x4For) { ...@@ -3208,33 +3235,34 @@ WASM_SIMD_TEST(SimdI32x4For) {
WasmRunner<int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t> r(execution_tier, lower_simd);
r.AllocateLocal(kWasmI32); r.AllocateLocal(kWasmI32);
r.AllocateLocal(kWasmS128); r.AllocateLocal(kWasmS128);
BUILD(r, BUILD_V(
r,
WASM_SET_LOCAL(1, WASM_SIMD_I32x4_SPLAT(WASM_I32V(31))),
WASM_SET_LOCAL(1, WASM_SIMD_I32x4_REPLACE_LANE(1, WASM_GET_LOCAL(1), WASM_SET_LOCAL(1, WASM_SIMD_I32x4_SPLAT(WASM_I32V(31))),
WASM_I32V(53))), WASM_SET_LOCAL(
WASM_SET_LOCAL(1, WASM_SIMD_I32x4_REPLACE_LANE(2, WASM_GET_LOCAL(1), 1, WASM_SIMD_I32x4_REPLACE_LANE(1, WASM_GET_LOCAL(1), WASM_I32V(53))),
WASM_I32V(23))), WASM_SET_LOCAL(
WASM_SET_LOCAL(0, WASM_I32V(0)), 1, WASM_SIMD_I32x4_REPLACE_LANE(2, WASM_GET_LOCAL(1), WASM_I32V(23))),
WASM_LOOP( WASM_SET_LOCAL(0, WASM_I32V(0)),
WASM_SET_LOCAL( WASM_LOOP(
1, WASM_SIMD_BINOP(kExprI32x4Add, WASM_GET_LOCAL(1), WASM_SET_LOCAL(1,
WASM_SIMD_I32x4_SPLAT(WASM_I32V(1)))), WASM_SIMD_BINOP(kExprI32x4Add, WASM_GET_LOCAL(1),
WASM_IF(WASM_I32_NE(WASM_INC_LOCAL(0), WASM_I32V(5)), WASM_BR(1))), WASM_SIMD_I32x4_SPLAT(WASM_I32V(1)))),
WASM_SET_LOCAL(0, WASM_I32V(1)), WASM_IF(WASM_I32_NE(WASM_INC_LOCAL(0), WASM_I32V(5)), WASM_BR(1))),
WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_GET_LOCAL(1)), WASM_SET_LOCAL(0, WASM_I32V(1)),
WASM_I32V(36)), WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_GET_LOCAL(1)),
WASM_SET_LOCAL(0, WASM_I32V(0))), WASM_I32V(36)),
WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(1, WASM_GET_LOCAL(1)), WASM_SET_LOCAL(0, WASM_I32V(0))),
WASM_I32V(58)), WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(1, WASM_GET_LOCAL(1)),
WASM_SET_LOCAL(0, WASM_I32V(0))), WASM_I32V(58)),
WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(2, WASM_GET_LOCAL(1)), WASM_SET_LOCAL(0, WASM_I32V(0))),
WASM_I32V(28)), WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(2, WASM_GET_LOCAL(1)),
WASM_SET_LOCAL(0, WASM_I32V(0))), WASM_I32V(28)),
WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(3, WASM_GET_LOCAL(1)), WASM_SET_LOCAL(0, WASM_I32V(0))),
WASM_I32V(36)), WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(3, WASM_GET_LOCAL(1)),
WASM_SET_LOCAL(0, WASM_I32V(0))), WASM_I32V(36)),
WASM_GET_LOCAL(0)); WASM_SET_LOCAL(0, WASM_I32V(0))),
WASM_GET_LOCAL(0));
CHECK_EQ(1, r.Call()); CHECK_EQ(1, r.Call());
} }
...@@ -3242,23 +3270,24 @@ WASM_SIMD_TEST(SimdF32x4For) { ...@@ -3242,23 +3270,24 @@ WASM_SIMD_TEST(SimdF32x4For) {
WasmRunner<int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t> r(execution_tier, lower_simd);
r.AllocateLocal(kWasmI32); r.AllocateLocal(kWasmI32);
r.AllocateLocal(kWasmS128); r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(1, WASM_SIMD_F32x4_SPLAT(WASM_F32(21.25))), BUILD_V(
WASM_SET_LOCAL(1, WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_LOCAL(1), r, WASM_SET_LOCAL(1, WASM_SIMD_F32x4_SPLAT(WASM_F32(21.25))),
WASM_F32(19.5))), WASM_SET_LOCAL(1, WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_LOCAL(1),
WASM_SET_LOCAL(0, WASM_I32V(0)), WASM_F32(19.5))),
WASM_LOOP( WASM_SET_LOCAL(0, WASM_I32V(0)),
WASM_SET_LOCAL( WASM_LOOP(
1, WASM_SIMD_BINOP(kExprF32x4Add, WASM_GET_LOCAL(1), WASM_SET_LOCAL(1,
WASM_SIMD_F32x4_SPLAT(WASM_F32(2.0)))), WASM_SIMD_BINOP(kExprF32x4Add, WASM_GET_LOCAL(1),
WASM_IF(WASM_I32_NE(WASM_INC_LOCAL(0), WASM_I32V(3)), WASM_BR(1))), WASM_SIMD_F32x4_SPLAT(WASM_F32(2.0)))),
WASM_SET_LOCAL(0, WASM_I32V(1)), WASM_IF(WASM_I32_NE(WASM_INC_LOCAL(0), WASM_I32V(3)), WASM_BR(1))),
WASM_IF(WASM_F32_NE(WASM_SIMD_F32x4_EXTRACT_LANE(0, WASM_GET_LOCAL(1)), WASM_SET_LOCAL(0, WASM_I32V(1)),
WASM_F32(27.25)), WASM_IF(WASM_F32_NE(WASM_SIMD_F32x4_EXTRACT_LANE(0, WASM_GET_LOCAL(1)),
WASM_SET_LOCAL(0, WASM_I32V(0))), WASM_F32(27.25)),
WASM_IF(WASM_F32_NE(WASM_SIMD_F32x4_EXTRACT_LANE(3, WASM_GET_LOCAL(1)), WASM_SET_LOCAL(0, WASM_I32V(0))),
WASM_F32(25.5)), WASM_IF(WASM_F32_NE(WASM_SIMD_F32x4_EXTRACT_LANE(3, WASM_GET_LOCAL(1)),
WASM_SET_LOCAL(0, WASM_I32V(0))), WASM_F32(25.5)),
WASM_GET_LOCAL(0)); WASM_SET_LOCAL(0, WASM_I32V(0))),
WASM_GET_LOCAL(0));
CHECK_EQ(1, r.Call()); CHECK_EQ(1, r.Call());
} }
...@@ -3288,7 +3317,7 @@ WASM_SIMD_TEST(SimdI32x4GetGlobal) { ...@@ -3288,7 +3317,7 @@ WASM_SIMD_TEST(SimdI32x4GetGlobal) {
int32_t* global = r.builder().AddGlobal<int32_t>(kWasmS128); int32_t* global = r.builder().AddGlobal<int32_t>(kWasmS128);
SetVectorByLanes(global, {{0, 1, 2, 3}}); SetVectorByLanes(global, {{0, 1, 2, 3}});
r.AllocateLocal(kWasmI32); r.AllocateLocal(kWasmI32);
BUILD( BUILD_V(
r, WASM_SET_LOCAL(1, WASM_I32V(1)), r, WASM_SET_LOCAL(1, WASM_I32V(1)),
WASM_IF(WASM_I32_NE(WASM_I32V(0), WASM_IF(WASM_I32_NE(WASM_I32V(0),
WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_GET_GLOBAL(4))), WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_GET_GLOBAL(4))),
...@@ -3314,14 +3343,14 @@ WASM_SIMD_TEST(SimdI32x4SetGlobal) { ...@@ -3314,14 +3343,14 @@ WASM_SIMD_TEST(SimdI32x4SetGlobal) {
r.builder().AddGlobal<int32_t>(kWasmI32); // purposefully unused r.builder().AddGlobal<int32_t>(kWasmI32); // purposefully unused
r.builder().AddGlobal<int32_t>(kWasmI32); // purposefully unused r.builder().AddGlobal<int32_t>(kWasmI32); // purposefully unused
int32_t* global = r.builder().AddGlobal<int32_t>(kWasmS128); int32_t* global = r.builder().AddGlobal<int32_t>(kWasmS128);
BUILD(r, WASM_SET_GLOBAL(4, WASM_SIMD_I32x4_SPLAT(WASM_I32V(23))), BUILD_V(r, WASM_SET_GLOBAL(4, WASM_SIMD_I32x4_SPLAT(WASM_I32V(23))),
WASM_SET_GLOBAL(4, WASM_SIMD_I32x4_REPLACE_LANE(1, WASM_GET_GLOBAL(4), WASM_SET_GLOBAL(4, WASM_SIMD_I32x4_REPLACE_LANE(1, WASM_GET_GLOBAL(4),
WASM_I32V(34))), WASM_I32V(34))),
WASM_SET_GLOBAL(4, WASM_SIMD_I32x4_REPLACE_LANE(2, WASM_GET_GLOBAL(4), WASM_SET_GLOBAL(4, WASM_SIMD_I32x4_REPLACE_LANE(2, WASM_GET_GLOBAL(4),
WASM_I32V(45))), WASM_I32V(45))),
WASM_SET_GLOBAL(4, WASM_SIMD_I32x4_REPLACE_LANE(3, WASM_GET_GLOBAL(4), WASM_SET_GLOBAL(4, WASM_SIMD_I32x4_REPLACE_LANE(3, WASM_GET_GLOBAL(4),
WASM_I32V(56))), WASM_I32V(56))),
WASM_I32V(1)); WASM_I32V(1));
CHECK_EQ(1, r.Call(0)); CHECK_EQ(1, r.Call(0));
CHECK_EQ(GetScalar(global, 0), 23); CHECK_EQ(GetScalar(global, 0), 23);
CHECK_EQ(GetScalar(global, 1), 34); CHECK_EQ(GetScalar(global, 1), 34);
...@@ -3334,7 +3363,7 @@ WASM_SIMD_TEST(SimdF32x4GetGlobal) { ...@@ -3334,7 +3363,7 @@ WASM_SIMD_TEST(SimdF32x4GetGlobal) {
float* global = r.builder().AddGlobal<float>(kWasmS128); float* global = r.builder().AddGlobal<float>(kWasmS128);
SetVectorByLanes<float>(global, {{0.0, 1.5, 2.25, 3.5}}); SetVectorByLanes<float>(global, {{0.0, 1.5, 2.25, 3.5}});
r.AllocateLocal(kWasmI32); r.AllocateLocal(kWasmI32);
BUILD( BUILD_V(
r, WASM_SET_LOCAL(1, WASM_I32V(1)), r, WASM_SET_LOCAL(1, WASM_I32V(1)),
WASM_IF(WASM_F32_NE(WASM_F32(0.0), WASM_IF(WASM_F32_NE(WASM_F32(0.0),
WASM_SIMD_F32x4_EXTRACT_LANE(0, WASM_GET_GLOBAL(0))), WASM_SIMD_F32x4_EXTRACT_LANE(0, WASM_GET_GLOBAL(0))),
...@@ -3355,14 +3384,14 @@ WASM_SIMD_TEST(SimdF32x4GetGlobal) { ...@@ -3355,14 +3384,14 @@ WASM_SIMD_TEST(SimdF32x4GetGlobal) {
WASM_SIMD_TEST(SimdF32x4SetGlobal) { WASM_SIMD_TEST(SimdF32x4SetGlobal) {
WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd);
float* global = r.builder().AddGlobal<float>(kWasmS128); float* global = r.builder().AddGlobal<float>(kWasmS128);
BUILD(r, WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_SPLAT(WASM_F32(13.5))), BUILD_V(r, WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_SPLAT(WASM_F32(13.5))),
WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(1, WASM_GET_GLOBAL(0), WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(1, WASM_GET_GLOBAL(0),
WASM_F32(45.5))), WASM_F32(45.5))),
WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(2, WASM_GET_GLOBAL(0), WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(2, WASM_GET_GLOBAL(0),
WASM_F32(32.25))), WASM_F32(32.25))),
WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_GLOBAL(0), WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_GLOBAL(0),
WASM_F32(65.0))), WASM_F32(65.0))),
WASM_I32V(1)); WASM_I32V(1));
CHECK_EQ(1, r.Call(0)); CHECK_EQ(1, r.Call(0));
CHECK_EQ(GetScalar(global, 0), 13.5f); CHECK_EQ(GetScalar(global, 0), 13.5f);
CHECK_EQ(GetScalar(global, 1), 45.5f); CHECK_EQ(GetScalar(global, 1), 45.5f);
...@@ -3376,8 +3405,9 @@ WASM_SIMD_TEST(SimdLoadStoreLoad) { ...@@ -3376,8 +3405,9 @@ WASM_SIMD_TEST(SimdLoadStoreLoad) {
r.builder().AddMemoryElems<int32_t>(kWasmPageSize / sizeof(int32_t)); r.builder().AddMemoryElems<int32_t>(kWasmPageSize / sizeof(int32_t));
// Load memory, store it, then reload it and extract the first lane. Use a // Load memory, store it, then reload it and extract the first lane. Use a
// non-zero offset into the memory of 1 lane (4 bytes) to test indexing. // non-zero offset into the memory of 1 lane (4 bytes) to test indexing.
BUILD(r, WASM_SIMD_STORE_MEM(WASM_I32V(8), WASM_SIMD_LOAD_MEM(WASM_I32V(4))), BUILD_V(r,
WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_SIMD_LOAD_MEM(WASM_I32V(8)))); WASM_SIMD_STORE_MEM(WASM_I32V(8), WASM_SIMD_LOAD_MEM(WASM_I32V(4))),
WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_SIMD_LOAD_MEM(WASM_I32V(8))));
FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(i) {
int32_t expected = i; int32_t expected = i;
...@@ -3394,7 +3424,7 @@ WASM_SIMD_TEST(SimdLoadStoreLoadMemargOffset) { ...@@ -3394,7 +3424,7 @@ WASM_SIMD_TEST(SimdLoadStoreLoadMemargOffset) {
constexpr byte offset_2 = 8; constexpr byte offset_2 = 8;
// Load from memory at offset_1, store to offset_2, load from offset_2, and // Load from memory at offset_1, store to offset_2, load from offset_2, and
// extract first lane. We use non-zero memarg offsets to test offset decoding. // extract first lane. We use non-zero memarg offsets to test offset decoding.
BUILD( BUILD_V(
r, r,
WASM_SIMD_STORE_MEM_OFFSET( WASM_SIMD_STORE_MEM_OFFSET(
offset_2, WASM_ZERO, WASM_SIMD_LOAD_MEM_OFFSET(offset_1, WASM_ZERO)), offset_2, WASM_ZERO, WASM_SIMD_LOAD_MEM_OFFSET(offset_1, WASM_ZERO)),
...@@ -3417,8 +3447,8 @@ void RunLoadSplatTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -3417,8 +3447,8 @@ void RunLoadSplatTest(ExecutionTier execution_tier, LowerSimd lower_simd,
WasmRunner<int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t> r(execution_tier, lower_simd);
T* memory = r.builder().AddMemoryElems<T>(kWasmPageSize / sizeof(T)); T* memory = r.builder().AddMemoryElems<T>(kWasmPageSize / sizeof(T));
T* global = r.builder().AddGlobal<T>(kWasmS128); T* global = r.builder().AddGlobal<T>(kWasmS128);
BUILD(r, WASM_SET_GLOBAL(0, WASM_SIMD_LOAD_SPLAT(op, WASM_I32V(mem_index))), BUILD_V(r, WASM_SET_GLOBAL(0, WASM_SIMD_LOAD_SPLAT(op, WASM_I32V(mem_index))),
WASM_ONE); WASM_ONE);
for (T x : compiler::ValueHelper::GetVector<T>()) { for (T x : compiler::ValueHelper::GetVector<T>()) {
// 16-th byte in memory is lanes-th element (size T) of memory. // 16-th byte in memory is lanes-th element (size T) of memory.
...@@ -3455,8 +3485,9 @@ void RunLoadExtendTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -3455,8 +3485,9 @@ void RunLoadExtendTest(ExecutionTier execution_tier, LowerSimd lower_simd,
WasmRunner<int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t> r(execution_tier, lower_simd);
S* memory = r.builder().AddMemoryElems<S>(kWasmPageSize / sizeof(S)); S* memory = r.builder().AddMemoryElems<S>(kWasmPageSize / sizeof(S));
T* global = r.builder().AddGlobal<T>(kWasmS128); T* global = r.builder().AddGlobal<T>(kWasmS128);
BUILD(r, WASM_SET_GLOBAL(0, WASM_SIMD_LOAD_EXTEND(op, WASM_I32V(mem_index))), BUILD_V(r,
WASM_ONE); WASM_SET_GLOBAL(0, WASM_SIMD_LOAD_EXTEND(op, WASM_I32V(mem_index))),
WASM_ONE);
for (S x : compiler::ValueHelper::GetVector<S>()) { for (S x : compiler::ValueHelper::GetVector<S>()) {
for (int i = 0; i < lanes_s; i++) { for (int i = 0; i < lanes_s; i++) {
...@@ -3503,11 +3534,11 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2Load32x2S) { ...@@ -3503,11 +3534,11 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2Load32x2S) {
V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_S390X V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_S390X
#define WASM_SIMD_ANYTRUE_TEST(format, lanes, max, param_type) \ #define WASM_SIMD_ANYTRUE_TEST(format, lanes, max, param_type) \
WASM_SIMD_TEST(S##format##AnyTrue) { \ WASM_SIMD_TEST(S##format##AnyTrue) { \
FLAG_SCOPE(wasm_simd_post_mvp); \ FLAG_SCOPE(wasm_simd_post_mvp); \
WasmRunner<int32_t, param_type> r(execution_tier, lower_simd); \ WasmRunner<int32_t, param_type> r(execution_tier, lower_simd); \
if (lanes == 2 && lower_simd == kLowerSimd) return; \ if (lanes == 2 && lower_simd == kLowerSimd) return; \
byte simd = r.AllocateLocal(kWasmS128); \ byte simd = r.AllocateLocal(kWasmS128); \
BUILD( \ BUILD_V( \
r, \ r, \
WASM_SET_LOCAL(simd, WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(0))), \ WASM_SET_LOCAL(simd, WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(0))), \
WASM_SIMD_UNOP(kExprS1x##lanes##AnyTrue, WASM_GET_LOCAL(simd))); \ WASM_SIMD_UNOP(kExprS1x##lanes##AnyTrue, WASM_GET_LOCAL(simd))); \
...@@ -3524,11 +3555,11 @@ WASM_SIMD_ANYTRUE_TEST(8x16, 16, 0xff, int32_t) ...@@ -3524,11 +3555,11 @@ WASM_SIMD_ANYTRUE_TEST(8x16, 16, 0xff, int32_t)
#define WASM_SIMD_ALLTRUE_TEST(format, lanes, max, param_type) \ #define WASM_SIMD_ALLTRUE_TEST(format, lanes, max, param_type) \
WASM_SIMD_TEST(S##format##AllTrue) { \ WASM_SIMD_TEST(S##format##AllTrue) { \
FLAG_SCOPE(wasm_simd_post_mvp); \ FLAG_SCOPE(wasm_simd_post_mvp); \
WasmRunner<int32_t, param_type> r(execution_tier, lower_simd); \ WasmRunner<int32_t, param_type> r(execution_tier, lower_simd); \
if (lanes == 2 && lower_simd == kLowerSimd) return; \ if (lanes == 2 && lower_simd == kLowerSimd) return; \
byte simd = r.AllocateLocal(kWasmS128); \ byte simd = r.AllocateLocal(kWasmS128); \
BUILD( \ BUILD_V( \
r, \ r, \
WASM_SET_LOCAL(simd, WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(0))), \ WASM_SET_LOCAL(simd, WASM_SIMD_I##format##_SPLAT(WASM_GET_LOCAL(0))), \
WASM_SIMD_UNOP(kExprS1x##lanes##AllTrue, WASM_GET_LOCAL(simd))); \ WASM_SIMD_UNOP(kExprS1x##lanes##AllTrue, WASM_GET_LOCAL(simd))); \
...@@ -3548,13 +3579,13 @@ WASM_SIMD_ALLTRUE_TEST(8x16, 16, 0xff, int32_t) ...@@ -3548,13 +3579,13 @@ WASM_SIMD_ALLTRUE_TEST(8x16, 16, 0xff, int32_t)
WASM_SIMD_TEST(BitSelect) { WASM_SIMD_TEST(BitSelect) {
WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd);
byte simd = r.AllocateLocal(kWasmS128); byte simd = r.AllocateLocal(kWasmS128);
BUILD(r, BUILD_V(r,
WASM_SET_LOCAL( WASM_SET_LOCAL(simd,
simd, WASM_SIMD_SELECT(
WASM_SIMD_SELECT(32x4, WASM_SIMD_I32x4_SPLAT(WASM_I32V(0x01020304)), 32x4, WASM_SIMD_I32x4_SPLAT(WASM_I32V(0x01020304)),
WASM_SIMD_I32x4_SPLAT(WASM_I32V(0)), WASM_SIMD_I32x4_SPLAT(WASM_I32V(0)),
WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(0)))), WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(0)))),
WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_GET_LOCAL(simd))); WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_GET_LOCAL(simd)));
DCHECK_EQ(0x01020304, r.Call(0xFFFFFFFF)); DCHECK_EQ(0x01020304, r.Call(0xFFFFFFFF));
} }
...@@ -3566,11 +3597,12 @@ void RunI8x16MixedRelationalOpTest(ExecutionTier execution_tier, ...@@ -3566,11 +3597,12 @@ void RunI8x16MixedRelationalOpTest(ExecutionTier execution_tier,
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
byte temp2 = r.AllocateLocal(kWasmS128); byte temp2 = r.AllocateLocal(kWasmS128);
byte temp3 = r.AllocateLocal(kWasmS128); byte temp3 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value1))), BUILD_V(r,
WASM_SET_LOCAL(temp2, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value2))), WASM_SET_LOCAL(temp1, WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(value1))),
WASM_SET_LOCAL(temp3, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1), WASM_SET_LOCAL(temp2, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value2))),
WASM_GET_LOCAL(temp2))), WASM_SET_LOCAL(temp3, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1),
WASM_SIMD_I8x16_EXTRACT_LANE(0, WASM_GET_LOCAL(temp3))); WASM_GET_LOCAL(temp2))),
WASM_SIMD_I8x16_EXTRACT_LANE(0, WASM_GET_LOCAL(temp3)));
DCHECK_EQ(expected_op(0xff, static_cast<uint8_t>(0x7fff)), DCHECK_EQ(expected_op(0xff, static_cast<uint8_t>(0x7fff)),
r.Call(0xff, 0x7fff)); r.Call(0xff, 0x7fff));
...@@ -3605,11 +3637,12 @@ void RunI16x8MixedRelationalOpTest(ExecutionTier execution_tier, ...@@ -3605,11 +3637,12 @@ void RunI16x8MixedRelationalOpTest(ExecutionTier execution_tier,
byte temp1 = r.AllocateLocal(kWasmS128); byte temp1 = r.AllocateLocal(kWasmS128);
byte temp2 = r.AllocateLocal(kWasmS128); byte temp2 = r.AllocateLocal(kWasmS128);
byte temp3 = r.AllocateLocal(kWasmS128); byte temp3 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value1))), BUILD_V(r,
WASM_SET_LOCAL(temp2, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value2))), WASM_SET_LOCAL(temp1, WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(value1))),
WASM_SET_LOCAL(temp3, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1), WASM_SET_LOCAL(temp2, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value2))),
WASM_GET_LOCAL(temp2))), WASM_SET_LOCAL(temp3, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1),
WASM_SIMD_I16x8_EXTRACT_LANE(0, WASM_GET_LOCAL(temp3))); WASM_GET_LOCAL(temp2))),
WASM_SIMD_I16x8_EXTRACT_LANE(0, WASM_GET_LOCAL(temp3)));
DCHECK_EQ(expected_op(0xffff, static_cast<uint16_t>(0x7fffffff)), DCHECK_EQ(expected_op(0xffff, static_cast<uint16_t>(0x7fffffff)),
r.Call(0xffff, 0x7fffffff)); r.Call(0xffff, 0x7fffffff));
...@@ -3636,41 +3669,42 @@ WASM_SIMD_TEST_NO_LOWERING(I16x8GtUMixed) { ...@@ -3636,41 +3669,42 @@ WASM_SIMD_TEST_NO_LOWERING(I16x8GtUMixed) {
UnsignedGreater); UnsignedGreater);
} }
#define WASM_EXTRACT_I16x8_TEST(Sign, Type) \ #define WASM_EXTRACT_I16x8_TEST(Sign, Type) \
WASM_SIMD_TEST(I16X8ExtractLane##Sign) { \ WASM_SIMD_TEST(I16X8ExtractLane##Sign) { \
WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); \ WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); \
byte int_val = r.AllocateLocal(kWasmI32); \ byte int_val = r.AllocateLocal(kWasmI32); \
byte simd_val = r.AllocateLocal(kWasmS128); \ byte simd_val = r.AllocateLocal(kWasmS128); \
BUILD(r, \ BUILD_V(r, \
WASM_SET_LOCAL(simd_val, \ WASM_SET_LOCAL(simd_val, \
WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(int_val))), \ WASM_SIMD_I16x8_SPLAT(WASM_GET_LOCAL(int_val))), \
WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 0), \ WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 0), \
WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 2), \ WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 2), \
WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 4), \ WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 4), \
WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 6), WASM_ONE); \ WASM_SIMD_CHECK_LANE_U(I16x8, simd_val, I32, int_val, 6), \
FOR_##Type##_INPUTS(x) { CHECK_EQ(1, r.Call(x)); } \ WASM_ONE); \
FOR_##Type##_INPUTS(x) { CHECK_EQ(1, r.Call(x)); } \
} }
WASM_EXTRACT_I16x8_TEST(S, UINT16) WASM_EXTRACT_I16x8_TEST(I, INT16) WASM_EXTRACT_I16x8_TEST(S, UINT16) WASM_EXTRACT_I16x8_TEST(I, INT16)
#undef WASM_EXTRACT_I16x8_TEST #undef WASM_EXTRACT_I16x8_TEST
#define WASM_EXTRACT_I8x16_TEST(Sign, Type) \ #define WASM_EXTRACT_I8x16_TEST(Sign, Type) \
WASM_SIMD_TEST(I8x16ExtractLane##Sign) { \ WASM_SIMD_TEST(I8x16ExtractLane##Sign) { \
WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); \ WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd); \
byte int_val = r.AllocateLocal(kWasmI32); \ byte int_val = r.AllocateLocal(kWasmI32); \
byte simd_val = r.AllocateLocal(kWasmS128); \ byte simd_val = r.AllocateLocal(kWasmS128); \
BUILD(r, \ BUILD_V(r, \
WASM_SET_LOCAL(simd_val, \ WASM_SET_LOCAL(simd_val, \
WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(int_val))), \ WASM_SIMD_I8x16_SPLAT(WASM_GET_LOCAL(int_val))), \
WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 1), \ WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 1), \
WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 3), \ WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 3), \
WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 5), \ WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 5), \
WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 7), \ WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 7), \
WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 9), \ WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 9), \
WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 10), \ WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 10), \
WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 11), \ WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 11), \
WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 13), \ WASM_SIMD_CHECK_LANE_U(I8x16, simd_val, I32, int_val, 13), \
WASM_ONE); \ WASM_ONE); \
FOR_##Type##_INPUTS(x) { CHECK_EQ(1, r.Call(x)); } \ FOR_##Type##_INPUTS(x) { CHECK_EQ(1, r.Call(x)); } \
} }
WASM_EXTRACT_I8x16_TEST(S, UINT8) WASM_EXTRACT_I8x16_TEST(I, INT8) WASM_EXTRACT_I8x16_TEST(S, UINT8) WASM_EXTRACT_I8x16_TEST(I, INT8)
#undef WASM_EXTRACT_I8x16_TEST #undef WASM_EXTRACT_I8x16_TEST
......
...@@ -47,6 +47,11 @@ void AppendSingle(std::vector<byte>* code, WasmOpcode op) { ...@@ -47,6 +47,11 @@ void AppendSingle(std::vector<byte>* code, WasmOpcode op) {
} }
} }
template <>
void AppendSingle(std::vector<byte>* code, ValueTypeCode op) {
code->push_back(op);
}
TestingModuleBuilder::TestingModuleBuilder( TestingModuleBuilder::TestingModuleBuilder(
Zone* zone, ManuallyImportedJSFunction* maybe_import, ExecutionTier tier, Zone* zone, ManuallyImportedJSFunction* maybe_import, ExecutionTier tier,
RuntimeExceptionSupport exception_support, LowerSimd lower_simd) RuntimeExceptionSupport exception_support, LowerSimd lower_simd)
......
...@@ -86,6 +86,10 @@ void AppendSingle(std::vector<byte>* code, T t) { ...@@ -86,6 +86,10 @@ void AppendSingle(std::vector<byte>* code, T t) {
template <> template <>
void AppendSingle<WasmOpcode>(std::vector<byte>* code, WasmOpcode op); void AppendSingle<WasmOpcode>(std::vector<byte>* code, WasmOpcode op);
// Specialized for ValueTypeCode.
template <>
void AppendSingle<ValueTypeCode>(std::vector<byte>* code, ValueTypeCode op);
template <typename... T> template <typename... T>
void Append(std::vector<byte>* code, T... ts) { void Append(std::vector<byte>* code, T... ts) {
static_assert(sizeof...(ts) == 0, "Base case for appending bytes to code."); static_assert(sizeof...(ts) == 0, "Base case for appending bytes to code.");
......
...@@ -17,7 +17,7 @@ builder.addFunction(undefined, 0 /* sig */) ...@@ -17,7 +17,7 @@ builder.addFunction(undefined, 0 /* sig */)
kExprI32Const, 0x75, // i32.const kExprI32Const, 0x75, // i32.const
kExprI32Const, 0x74, // i32.const kExprI32Const, 0x74, // i32.const
kExprI32Const, 0x18, // i32.const kExprI32Const, 0x18, // i32.const
kSimdPrefix, kExprS8x16LoadSplat, // s8x16.load_splat kSimdPrefix, ...kExprS8x16LoadSplat, // s8x16.load_splat
kExprUnreachable, // unreachable kExprUnreachable, // unreachable
kExprUnreachable, // unreachable kExprUnreachable, // unreachable
kExprI32Const, 0x6f, // i32.const kExprI32Const, 0x6f, // i32.const
......
...@@ -479,7 +479,7 @@ let kExprI16x8ShrS = 0x66; ...@@ -479,7 +479,7 @@ let kExprI16x8ShrS = 0x66;
let kExprS1x4AllTrue = 0x75; let kExprS1x4AllTrue = 0x75;
let kExprI32x4Add = 0x79; let kExprI32x4Add = 0x79;
let kExprF32x4Min = 0x9e; let kExprF32x4Min = 0x9e;
let kExprS8x16LoadSplat = 0xc2; let kExprS8x16LoadSplat = [0xc2, 0x1];
// Compilation hint constants. // Compilation hint constants.
let kCompilationHintStrategyDefault = 0x00; let kCompilationHintStrategyDefault = 0x00;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "src/wasm/leb-helper.h"
#include "test/unittests/test-utils.h" #include "test/unittests/test-utils.h"
#include "src/init/v8.h" #include "src/init/v8.h"
...@@ -3628,6 +3629,20 @@ class WasmOpcodeLengthTest : public TestWithZone { ...@@ -3628,6 +3629,20 @@ class WasmOpcodeLengthTest : public TestWithZone {
EXPECT_EQ(expected, OpcodeLength(code, code + sizeof(code))) EXPECT_EQ(expected, OpcodeLength(code, code + sizeof(code)))
<< PrintOpcodes{code, code + sizeof...(bytes)}; << PrintOpcodes{code, code + sizeof...(bytes)};
} }
// Helper to check for prefixed opcodes, which can have multiple bytes.
void ExpectLengthPrefixed(unsigned operands, WasmOpcode opcode) {
uint8_t prefix = (opcode >> 8) & 0xff;
DCHECK(WasmOpcodes::IsPrefixOpcode(static_cast<WasmOpcode>(prefix)));
uint8_t index = opcode & 0xff;
uint8_t encoded[2] = {0, 0};
uint8_t* p = encoded;
unsigned len = static_cast<unsigned>(LEBHelper::sizeof_u32v(index));
DCHECK_GE(2, len);
LEBHelper::write_u32v(&p, index);
// length of index, + number of operands + prefix bye
ExpectLength(len + operands + 1, prefix, encoded[0], encoded[1]);
}
}; };
TEST_F(WasmOpcodeLengthTest, Statements) { TEST_F(WasmOpcodeLengthTest, Statements) {
...@@ -3754,17 +3769,15 @@ TEST_F(WasmOpcodeLengthTest, SimpleExpressions) { ...@@ -3754,17 +3769,15 @@ TEST_F(WasmOpcodeLengthTest, SimpleExpressions) {
} }
TEST_F(WasmOpcodeLengthTest, SimdExpressions) { TEST_F(WasmOpcodeLengthTest, SimdExpressions) {
#define TEST_SIMD(name, opcode, sig) \ #define TEST_SIMD(name, opcode, sig) ExpectLengthPrefixed(0, kExpr##name);
ExpectLength(2, kSimdPrefix, static_cast<byte>(kExpr##name & 0xFF));
FOREACH_SIMD_0_OPERAND_OPCODE(TEST_SIMD) FOREACH_SIMD_0_OPERAND_OPCODE(TEST_SIMD)
#undef TEST_SIMD #undef TEST_SIMD
#define TEST_SIMD(name, opcode, sig) \ #define TEST_SIMD(name, opcode, sig) ExpectLengthPrefixed(1, kExpr##name);
ExpectLength(3, kSimdPrefix, static_cast<byte>(kExpr##name & 0xFF));
FOREACH_SIMD_1_OPERAND_OPCODE(TEST_SIMD) FOREACH_SIMD_1_OPERAND_OPCODE(TEST_SIMD)
#undef TEST_SIMD #undef TEST_SIMD
ExpectLength(18, kSimdPrefix, static_cast<byte>(kExprS8x16Shuffle & 0xFF)); ExpectLengthPrefixed(16, kExprS8x16Shuffle);
// test for bad simd opcode // test for bad simd opcode, 0xFF is encoded in two bytes.
ExpectLength(2, kSimdPrefix, 0xFF); ExpectLength(3, kSimdPrefix, 0xFF, 0x1);
} }
using TypesOfLocals = ZoneVector<ValueType>; using TypesOfLocals = ZoneVector<ValueType>;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment