Commit 5603f5c9 authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[wasm-simd] Prototype double precision conversions

Add interpreter implementation and tests.

Bug: v8:11265
Change-Id: Iddb33f2d2fe0badc0a5ee4a950a65b4caf5d289f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2636846Reviewed-by: 's avatarDeepti Gandluri <gdeepti@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72208}
parent 810eaab3
...@@ -368,6 +368,13 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) { ...@@ -368,6 +368,13 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
CASE_I32x4_OP(WidenI8x16S, "widen_i8x16_s") CASE_I32x4_OP(WidenI8x16S, "widen_i8x16_s")
CASE_I32x4_OP(WidenI8x16U, "widen_i8x16_u") CASE_I32x4_OP(WidenI8x16U, "widen_i8x16_u")
CASE_F64x2_OP(ConvertLowI32x4S, "convert_low_i32x4_s")
CASE_F64x2_OP(ConvertLowI32x4U, "convert_low_i32x4_u")
CASE_I32x4_OP(TruncSatF64x2SZero, "trunc_sat_f64x2_s_zero")
CASE_I32x4_OP(TruncSatF64x2UZero, "trunc_sat_f64x2_u_zero")
CASE_F32x4_OP(DemoteF64x2Zero, "demote_f64x2_zero")
CASE_F64x2_OP(PromoteLowF32x4, "promote_low_f32x4")
// Atomic operations. // Atomic operations.
CASE_OP(AtomicNotify, "atomic.notify") CASE_OP(AtomicNotify, "atomic.notify")
CASE_INT_OP(AtomicWait, "atomic.wait") CASE_INT_OP(AtomicWait, "atomic.wait")
......
...@@ -514,7 +514,13 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig, ...@@ -514,7 +514,13 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
V(I32x4AddHoriz, 0xfdb0, s_ss) \ V(I32x4AddHoriz, 0xfdb0, s_ss) \
V(F32x4AddHoriz, 0xfdb2, s_ss) \ V(F32x4AddHoriz, 0xfdb2, s_ss) \
V(F32x4RecipApprox, 0xfdb3, s_s) \ V(F32x4RecipApprox, 0xfdb3, s_s) \
V(F32x4RecipSqrtApprox, 0xfdbc, s_s) V(F32x4RecipSqrtApprox, 0xfdbc, s_s) \
V(F64x2ConvertLowI32x4S, 0xfd53, s_s) \
V(F64x2ConvertLowI32x4U, 0xfd54, s_s) \
V(I32x4TruncSatF64x2SZero, 0xfd55, s_s) \
V(I32x4TruncSatF64x2UZero, 0xfd56, s_s) \
V(F32x4DemoteF64x2Zero, 0xfd57, s_s) \
V(F64x2PromoteLowF32x4, 0xfd69, s_s)
#define FOREACH_SIMD_POST_MVP_ONE_OPERAND_OPCODE(V) \ #define FOREACH_SIMD_POST_MVP_ONE_OPERAND_OPCODE(V) \
V(I32x4WidenI8x16S, 0xfd67, s_s) \ V(I32x4WidenI8x16S, 0xfd67, s_s) \
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/base/memory.h" #include "src/base/memory.h"
#include "src/base/overflowing-math.h" #include "src/base/overflowing-math.h"
#include "src/base/safe_conversions.h"
#include "src/base/utils/random-number-generator.h" #include "src/base/utils/random-number-generator.h"
#include "src/codegen/assembler-inl.h" #include "src/codegen/assembler-inl.h"
#include "src/codegen/cpu-features.h" #include "src/codegen/cpu-features.h"
...@@ -1282,6 +1283,140 @@ WASM_SIMD_TEST(F64x2NearestInt) { ...@@ -1282,6 +1283,140 @@ WASM_SIMD_TEST(F64x2NearestInt) {
true); true);
} }
// TODO(v8:11265): Prototyping double precision conversions.
template <typename SrcType>
void RunF64x2ConvertLowI32x4Test(TestExecutionTier execution_tier,
LowerSimd lower_simd, WasmOpcode opcode) {
if (TestExecutionTier::kInterpreter != execution_tier) {
return;
}
FLAG_SCOPE(wasm_simd_post_mvp);
WasmRunner<int32_t, SrcType> r(execution_tier, lower_simd);
double* g = r.builder().template AddGlobal<double>(kWasmS128);
// TODO(zhin): set top lanes to 0 to assert conversion happens on low lanes.
BUILD(
r,
WASM_GLOBAL_SET(
0, WASM_SIMD_UNOP(opcode, WASM_SIMD_I32x4_SPLAT(WASM_LOCAL_GET(0)))),
WASM_ONE);
for (SrcType x : compiler::ValueHelper::GetVector<SrcType>()) {
r.Call(x);
double expected = static_cast<double>(x);
for (int i = 0; i < 2; i++) {
double actual = ReadLittleEndianValue<double>(&g[i]);
CheckDoubleResult(x, x, expected, actual, true);
}
}
}
WASM_SIMD_TEST_NO_LOWERING(F64x2ConvertLowI32x4S) {
RunF64x2ConvertLowI32x4Test<int32_t>(execution_tier, lower_simd,
kExprF64x2ConvertLowI32x4S);
}
WASM_SIMD_TEST_NO_LOWERING(F64x2ConvertLowI32x4U) {
RunF64x2ConvertLowI32x4Test<uint32_t>(execution_tier, lower_simd,
kExprF64x2ConvertLowI32x4U);
}
template <typename SrcType>
void RunI32x4TruncSatF64x2Test(TestExecutionTier execution_tier,
LowerSimd lower_simd, WasmOpcode opcode) {
if (TestExecutionTier::kInterpreter != execution_tier) {
return;
}
FLAG_SCOPE(wasm_simd_post_mvp);
WasmRunner<int32_t, double> r(execution_tier, lower_simd);
SrcType* g = r.builder().AddGlobal<SrcType>(kWasmS128);
BUILD(
r,
WASM_GLOBAL_SET(
0, WASM_SIMD_UNOP(opcode, WASM_SIMD_F64x2_SPLAT(WASM_LOCAL_GET(0)))),
WASM_ONE);
FOR_FLOAT64_INPUTS(x) {
r.Call(x);
SrcType expected = base::saturated_cast<SrcType>(x);
for (int i = 0; i < 2; i++) {
SrcType actual = ReadLittleEndianValue<SrcType>(&g[i]);
CHECK_EQ(expected, actual);
}
// Top lanes are zero-ed.
for (int i = 2; i < 4; i++) {
CHECK_EQ(0, ReadLittleEndianValue<SrcType>(&g[i]));
}
}
}
WASM_SIMD_TEST_NO_LOWERING(I32x4TruncSatF64x2SZero) {
RunI32x4TruncSatF64x2Test<int32_t>(execution_tier, lower_simd,
kExprI32x4TruncSatF64x2SZero);
}
WASM_SIMD_TEST_NO_LOWERING(I32x4TruncSatF64x2UZero) {
RunI32x4TruncSatF64x2Test<uint32_t>(execution_tier, lower_simd,
kExprI32x4TruncSatF64x2UZero);
}
WASM_SIMD_TEST_NO_LOWERING(F32x4DemoteF64x2Zero) {
if (TestExecutionTier::kInterpreter != execution_tier) {
return;
}
FLAG_SCOPE(wasm_simd_post_mvp);
WasmRunner<int32_t, double> r(execution_tier, lower_simd);
float* g = r.builder().AddGlobal<float>(kWasmS128);
BUILD(r,
WASM_GLOBAL_SET(
0, WASM_SIMD_UNOP(kExprF32x4DemoteF64x2Zero,
WASM_SIMD_F64x2_SPLAT(WASM_LOCAL_GET(0)))),
WASM_ONE);
FOR_FLOAT64_INPUTS(x) {
r.Call(x);
float expected = DoubleToFloat32(x);
for (int i = 0; i < 2; i++) {
float actual = ReadLittleEndianValue<float>(&g[i]);
CheckFloatResult(x, x, expected, actual, true);
}
for (int i = 2; i < 4; i++) {
float actual = ReadLittleEndianValue<float>(&g[i]);
CheckFloatResult(x, x, 0, actual, true);
}
}
}
WASM_SIMD_TEST_NO_LOWERING(F64x2PromoteLowF32x4) {
if (TestExecutionTier::kInterpreter != execution_tier) {
return;
}
FLAG_SCOPE(wasm_simd_post_mvp);
WasmRunner<int32_t, float> r(execution_tier, lower_simd);
double* g = r.builder().AddGlobal<double>(kWasmS128);
BUILD(r,
WASM_GLOBAL_SET(
0, WASM_SIMD_UNOP(kExprF64x2PromoteLowF32x4,
WASM_SIMD_F32x4_SPLAT(WASM_LOCAL_GET(0)))),
WASM_ONE);
FOR_FLOAT32_INPUTS(x) {
r.Call(x);
double expected = static_cast<double>(x);
for (int i = 0; i < 2; i++) {
double actual = ReadLittleEndianValue<double>(&g[i]);
CheckDoubleResult(x, x, expected, actual, true);
}
for (int i = 2; i < 4; i++) {
double actual = ReadLittleEndianValue<double>(&g[i]);
CheckDoubleResult(x, x, 0, actual, true);
}
}
}
void RunF64x2BinOpTest(TestExecutionTier execution_tier, LowerSimd lower_simd, void RunF64x2BinOpTest(TestExecutionTier execution_tier, LowerSimd lower_simd,
WasmOpcode opcode, DoubleBinOp expected_op) { WasmOpcode opcode, DoubleBinOp expected_op) {
WasmRunner<int32_t, double, double> r(execution_tier, lower_simd); WasmRunner<int32_t, double, double> r(execution_tier, lower_simd);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <type_traits> #include <type_traits>
#include "src/base/overflowing-math.h" #include "src/base/overflowing-math.h"
#include "src/base/safe_conversions.h"
#include "src/codegen/assembler-inl.h" #include "src/codegen/assembler-inl.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/compiler/wasm-compiler.h" #include "src/compiler/wasm-compiler.h"
...@@ -2509,7 +2510,7 @@ class WasmInterpreterInternals { ...@@ -2509,7 +2510,7 @@ class WasmInterpreterInternals {
case kExpr##op: { \ case kExpr##op: { \
WasmValue v = Pop(); \ WasmValue v = Pop(); \
src_type s = v.to_s128().to_##name(); \ src_type s = v.to_s128().to_##name(); \
dst_type res; \ dst_type res = {0}; \
for (size_t i = 0; i < count; ++i) { \ for (size_t i = 0; i < count; ++i) { \
ctype a = s.val[LANE(start_index + i, s)]; \ ctype a = s.val[LANE(start_index + i, s)]; \
auto result = expr; \ auto result = expr; \
...@@ -2554,6 +2555,18 @@ class WasmInterpreterInternals { ...@@ -2554,6 +2555,18 @@ class WasmInterpreterInternals {
CONVERT_CASE(I16x8SConvertI8x16Low, int16, i8x16, int8, 8, 0, int8_t, a) CONVERT_CASE(I16x8SConvertI8x16Low, int16, i8x16, int8, 8, 0, int8_t, a)
CONVERT_CASE(I16x8UConvertI8x16Low, int16, i8x16, int8, 8, 0, uint8_t, CONVERT_CASE(I16x8UConvertI8x16Low, int16, i8x16, int8, 8, 0, uint8_t,
a) a)
CONVERT_CASE(F64x2ConvertLowI32x4S, int4, i32x4, float2, 2, 0, int32_t,
static_cast<double>(a))
CONVERT_CASE(F64x2ConvertLowI32x4U, int4, i32x4, float2, 2, 0, uint32_t,
static_cast<double>(a))
CONVERT_CASE(I32x4TruncSatF64x2SZero, float2, f64x2, int4, 2, 0, double,
base::saturated_cast<int32_t>(a))
CONVERT_CASE(I32x4TruncSatF64x2UZero, float2, f64x2, int4, 2, 0, double,
base::saturated_cast<uint32_t>(a))
CONVERT_CASE(F32x4DemoteF64x2Zero, float2, f64x2, float4, 2, 0, float,
DoubleToFloat32(a))
CONVERT_CASE(F64x2PromoteLowF32x4, float4, f32x4, float2, 2, 0, float,
static_cast<double>(a))
#undef CONVERT_CASE #undef CONVERT_CASE
#define PACK_CASE(op, src_type, name, dst_type, count, ctype, dst_ctype) \ #define PACK_CASE(op, src_type, name, dst_type, count, ctype, dst_ctype) \
case kExpr##op: { \ case kExpr##op: { \
......
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