Chromium Code Reviews| Index: test/cctest/wasm/test-wasm-simd-common.h |
| diff --git a/test/cctest/wasm/test-wasm-simd-common.h b/test/cctest/wasm/test-wasm-simd-common.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..053990d23f4cc36111ae969559dd324f03b0e7fc |
| --- /dev/null |
| +++ b/test/cctest/wasm/test-wasm-simd-common.h |
| @@ -0,0 +1,310 @@ |
| +// Copyright 2017 the V8 project authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "src/assembler-inl.h" |
| +#include "src/wasm/wasm-macro-gen.h" |
| +#include "test/cctest/cctest.h" |
| +#include "test/cctest/compiler/value-helper.h" |
| +#include "test/cctest/wasm/wasm-run-utils.h" |
| + |
| +namespace test_wasm_simd_common { |
| + |
| +typedef float (*FloatUnOp)(float); |
| +typedef float (*FloatBinOp)(float, float); |
| +typedef int32_t (*FloatCompareOp)(float, float); |
| +typedef int32_t (*Int32UnOp)(int32_t); |
| +typedef int32_t (*Int32BinOp)(int32_t, int32_t); |
| +typedef int32_t (*Int32ShiftOp)(int32_t, int); |
| +typedef int16_t (*Int16UnOp)(int16_t); |
| +typedef int16_t (*Int16BinOp)(int16_t, int16_t); |
| +typedef int16_t (*Int16ShiftOp)(int16_t, int); |
| +typedef int8_t (*Int8UnOp)(int8_t); |
| +typedef int8_t (*Int8BinOp)(int8_t, int8_t); |
| +typedef int8_t (*Int8ShiftOp)(int8_t, int); |
| + |
| +// Generic expected value functions. |
| +template <typename T> |
| +T Negate(T a) { |
| + return -a; |
| +} |
| + |
| +template <typename T> |
| +T Add(T a, T b) { |
| + return a + b; |
| +} |
| + |
| +template <typename T> |
| +T Sub(T a, T b) { |
| + return a - b; |
| +} |
| + |
| +template <typename T> |
| +T Mul(T a, T b) { |
| + return a * b; |
| +} |
| + |
| +template <typename T> |
| +T Div(T a, T b) { |
| + return a / b; |
| +} |
| + |
| +template <typename T> |
| +T Minimum(T a, T b) { |
| + return a <= b ? a : b; |
| +} |
| + |
| +template <typename T> |
| +T Maximum(T a, T b) { |
| + return a >= b ? a : b; |
| +} |
| + |
| +template <typename T> |
| +T UnsignedMinimum(T a, T b) { |
| + using UnsignedT = typename std::make_unsigned<T>::type; |
| + return static_cast<UnsignedT>(a) <= static_cast<UnsignedT>(b) ? a : b; |
| +} |
| + |
| +template <typename T> |
| +T UnsignedMaximum(T a, T b) { |
| + using UnsignedT = typename std::make_unsigned<T>::type; |
| + return static_cast<UnsignedT>(a) >= static_cast<UnsignedT>(b) ? a : b; |
| +} |
| + |
| +template <typename T> |
| +T Equal(T a, T b) { |
| + return a == b ? 1 : 0; |
| +} |
| + |
| +template <typename T> |
| +T NotEqual(T a, T b) { |
| + return a != b ? 1 : 0; |
| +} |
| + |
| +template <typename T> |
| +T Greater(T a, T b) { |
| + return a > b ? 1 : 0; |
| +} |
| + |
| +template <typename T> |
| +T GreaterEqual(T a, T b) { |
| + return a >= b ? 1 : 0; |
| +} |
| + |
| +template <typename T> |
| +T Less(T a, T b) { |
| + return a < b ? 1 : 0; |
| +} |
| + |
| +template <typename T> |
| +T LessEqual(T a, T b) { |
| + return a <= b ? 1 : 0; |
| +} |
| + |
| +template <typename T> |
| +T UnsignedGreater(T a, T b) { |
| + using UnsignedT = typename std::make_unsigned<T>::type; |
| + return static_cast<UnsignedT>(a) > static_cast<UnsignedT>(b) ? 1 : 0; |
| +} |
| + |
| +template <typename T> |
| +T UnsignedGreaterEqual(T a, T b) { |
| + using UnsignedT = typename std::make_unsigned<T>::type; |
| + return static_cast<UnsignedT>(a) >= static_cast<UnsignedT>(b) ? 1 : 0; |
| +} |
| + |
| +template <typename T> |
| +T UnsignedLess(T a, T b) { |
| + using UnsignedT = typename std::make_unsigned<T>::type; |
| + return static_cast<UnsignedT>(a) < static_cast<UnsignedT>(b) ? 1 : 0; |
| +} |
| + |
| +template <typename T> |
| +T UnsignedLessEqual(T a, T b) { |
| + using UnsignedT = typename std::make_unsigned<T>::type; |
| + return static_cast<UnsignedT>(a) <= static_cast<UnsignedT>(b) ? 1 : 0; |
| +} |
| + |
| +template <typename T> |
| +T LogicalShiftLeft(T a, int shift) { |
| + return a << shift; |
| +} |
| + |
| +template <typename T> |
| +T LogicalShiftRight(T a, int shift) { |
| + using UnsignedT = typename std::make_unsigned<T>::type; |
| + return static_cast<UnsignedT>(a) >> shift; |
| +} |
| + |
| +template <typename T> |
| +int64_t Widen(T value) { |
| + static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller"); |
| + return static_cast<int64_t>(value); |
| +} |
| + |
| +template <typename T> |
| +int64_t UnsignedWiden(T value) { |
| + static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller"); |
| + using UnsignedT = typename std::make_unsigned<T>::type; |
| + return static_cast<int64_t>(static_cast<UnsignedT>(value)); |
| +} |
| + |
| +template <typename T> |
| +T Clamp(int64_t value) { |
| + static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller"); |
| + int64_t min = static_cast<int64_t>(std::numeric_limits<T>::min()); |
| + int64_t max = static_cast<int64_t>(std::numeric_limits<T>::max()); |
| + int64_t clamped = std::max(min, std::min(max, value)); |
| + return static_cast<T>(clamped); |
| +} |
| + |
| +template <typename T> |
| +T AddSaturate(T a, T b) { |
| + return Clamp<T>(Widen(a) + Widen(b)); |
| +} |
| + |
| +template <typename T> |
| +T SubSaturate(T a, T b) { |
| + return Clamp<T>(Widen(a) - Widen(b)); |
| +} |
| + |
| +template <typename T> |
| +T UnsignedAddSaturate(T a, T b) { |
| + using UnsignedT = typename std::make_unsigned<T>::type; |
| + return Clamp<UnsignedT>(UnsignedWiden(a) + UnsignedWiden(b)); |
| +} |
| + |
| +template <typename T> |
| +T UnsignedSubSaturate(T a, T b) { |
| + using UnsignedT = typename std::make_unsigned<T>::type; |
| + return Clamp<UnsignedT>(UnsignedWiden(a) - UnsignedWiden(b)); |
| +} |
| + |
| +template <typename T> |
| +T And(T a, T b) { |
| + return a & b; |
| +} |
| + |
| +template <typename T> |
| +T Or(T a, T b) { |
| + return a | b; |
| +} |
| + |
| +template <typename T> |
| +T Xor(T a, T b) { |
| + return a ^ b; |
| +} |
| + |
| +template <typename T> |
| +T Not(T a) { |
| + return ~a; |
| +} |
| + |
| +#define WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lane_value, lane_index) \ |
| + WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \ |
| + WASM_SIMD_##TYPE##_EXTRACT_LANE( \ |
| + lane_index, WASM_GET_LOCAL(value))), \ |
| + WASM_RETURN1(WASM_ZERO)) |
| + |
| +#define WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3) \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \ |
| + , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3) |
| + |
| +#define WASM_SIMD_CHECK_SPLAT4(TYPE, value, LANE_TYPE, lv) \ |
| + WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv, lv, lv, lv) |
| + |
| +#define WASM_SIMD_CHECK8(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3, lv4, lv5, \ |
| + lv6, lv7) \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \ |
| + , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv4, 4), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv5, 5), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv6, 6), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv7, 7) |
| + |
| +#define WASM_SIMD_CHECK_SPLAT8(TYPE, value, LANE_TYPE, lv) \ |
| + WASM_SIMD_CHECK8(TYPE, value, LANE_TYPE, lv, lv, lv, lv, lv, lv, lv, lv) |
| + |
| +#define WASM_SIMD_CHECK16(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3, lv4, \ |
| + lv5, lv6, lv7, lv8, lv9, lv10, lv11, lv12, lv13, \ |
| + lv14, lv15) \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \ |
| + , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv4, 4), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv5, 5), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv6, 6), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv7, 7), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv8, 8), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv9, 9), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv10, 10), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv11, 11), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv12, 12), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv13, 13), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv14, 14), \ |
| + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv15, 15) |
| + |
| +#define WASM_SIMD_CHECK_SPLAT16(TYPE, value, LANE_TYPE, lv) \ |
| + WASM_SIMD_CHECK16(TYPE, value, LANE_TYPE, lv, lv, lv, lv, lv, lv, lv, lv, \ |
| + lv, lv, lv, lv, lv, lv, lv, lv) |
| + |
| +#define WASM_SIMD_CHECK_F32_LANE(TYPE, value, lane_value, lane_index) \ |
| + WASM_IF( \ |
| + WASM_I32_NE(WASM_I32_REINTERPRET_F32(WASM_GET_LOCAL(lane_value)), \ |
| + WASM_I32_REINTERPRET_F32(WASM_SIMD_##TYPE##_EXTRACT_LANE( \ |
| + lane_index, WASM_GET_LOCAL(value)))), \ |
| + WASM_RETURN1(WASM_ZERO)) |
| + |
| +#define WASM_SIMD_CHECK4_F32(TYPE, value, lv0, lv1, lv2, lv3) \ |
| + WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv0, 0) \ |
| + , WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv1, 1), \ |
| + WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv2, 2), \ |
| + WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv3, 3) |
| + |
| +#define WASM_SIMD_CHECK_SPLAT4_F32(TYPE, value, lv) \ |
| + WASM_SIMD_CHECK4_F32(TYPE, value, lv, lv, lv, lv) |
| + |
| +#define TO_BYTE(val) static_cast<byte>(val) |
| +#define WASM_SIMD_OP(op) kSimdPrefix, TO_BYTE(op) |
| +#define WASM_SIMD_SPLAT(Type, x) x, WASM_SIMD_OP(kExpr##Type##Splat) |
| +#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_SHIFT_OP(op, shift, x) x, WASM_SIMD_OP(op), TO_BYTE(shift) |
| +#define WASM_SIMD_SELECT(format, x, y, z) \ |
| + x, y, z, WASM_SIMD_OP(kExprS##format##Select) |
| +// Since boolean vectors can't be checked directly, materialize them into |
| +// integer vectors using a Select operation. |
| +#define WASM_SIMD_MATERIALIZE_BOOLS(format, x) \ |
| + x, WASM_SIMD_I##format##_SPLAT(WASM_ONE), \ |
| + WASM_SIMD_I##format##_SPLAT(WASM_ZERO), \ |
| + WASM_SIMD_OP(kExprS##format##Select) |
| + |
|
bbudge
2017/02/24 20:53:36
Could you also move the SIMD macros from wasm-macr
aseemgarg
2017/02/25 03:25:16
Done.
|
| +#define WASM_SIMD_I16x8_SPLAT(x) x, WASM_SIMD_OP(kExprI16x8Splat) |
| +#define WASM_SIMD_I16x8_EXTRACT_LANE(lane, x) \ |
| + x, WASM_SIMD_OP(kExprI16x8ExtractLane), TO_BYTE(lane) |
| +#define WASM_SIMD_I16x8_REPLACE_LANE(lane, x, y) \ |
| + x, y, WASM_SIMD_OP(kExprI16x8ReplaceLane), TO_BYTE(lane) |
| +#define WASM_SIMD_I8x16_SPLAT(x) x, WASM_SIMD_OP(kExprI8x16Splat) |
| +#define WASM_SIMD_I8x16_EXTRACT_LANE(lane, x) \ |
| + x, WASM_SIMD_OP(kExprI8x16ExtractLane), TO_BYTE(lane) |
| +#define WASM_SIMD_I8x16_REPLACE_LANE(lane, x, y) \ |
| + x, y, WASM_SIMD_OP(kExprI8x16ReplaceLane), TO_BYTE(lane) |
| + |
| +#define WASM_SIMD_F32x4_FROM_I32x4(x) x, WASM_SIMD_OP(kExprF32x4SConvertI32x4) |
| +#define WASM_SIMD_F32x4_FROM_U32x4(x) x, WASM_SIMD_OP(kExprF32x4UConvertI32x4) |
| +#define WASM_SIMD_I32x4_FROM_F32x4(x) x, WASM_SIMD_OP(kExprI32x4SConvertF32x4) |
| +#define WASM_SIMD_U32x4_FROM_F32x4(x) x, WASM_SIMD_OP(kExprI32x4UConvertF32x4) |
| + |
| +void RunF32x4SplatTest(); |
| +void RunF32x4ReplaceLaneTest(); |
| +void RunF32x4BinOpTest(WasmOpcode simd_op, FloatBinOp expected_op, |
| + bool skip_zero_inputs = false); |
| +void RunI32x4SplatTest(); |
| +void RunI32x4ReplaceLaneTest(); |
| +void RunI32x4BinOpTest(WasmOpcode simd_op, Int32BinOp expected_op); |
| +} // namespace test_wasm_simd_common |