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 |