OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/wasm/wasm-macro-gen.h" | 5 #include "src/wasm/wasm-macro-gen.h" |
6 | 6 |
7 #include "test/cctest/cctest.h" | 7 #include "test/cctest/cctest.h" |
8 #include "test/cctest/compiler/value-helper.h" | 8 #include "test/cctest/compiler/value-helper.h" |
9 #include "test/cctest/wasm/wasm-run-utils.h" | 9 #include "test/cctest/wasm/wasm-run-utils.h" |
10 | 10 |
11 using namespace v8::base; | 11 using namespace v8::base; |
12 using namespace v8::internal; | 12 using namespace v8::internal; |
13 using namespace v8::internal::compiler; | 13 using namespace v8::internal::compiler; |
14 using namespace v8::internal::wasm; | 14 using namespace v8::internal::wasm; |
15 | 15 |
16 namespace { | 16 namespace { |
17 | 17 |
| 18 typedef float (*FloatUnOp)(float); |
18 typedef float (*FloatBinOp)(float, float); | 19 typedef float (*FloatBinOp)(float, float); |
| 20 typedef int32_t (*FloatCompareOp)(float, float); |
19 typedef int32_t (*Int32BinOp)(int32_t, int32_t); | 21 typedef int32_t (*Int32BinOp)(int32_t, int32_t); |
20 | 22 |
21 template <typename T> | 23 template <typename T> |
| 24 T Negate(T a) { |
| 25 return -a; |
| 26 } |
| 27 |
| 28 template <typename T> |
22 T Add(T a, T b) { | 29 T Add(T a, T b) { |
23 return a + b; | 30 return a + b; |
24 } | 31 } |
25 | 32 |
26 template <typename T> | 33 template <typename T> |
27 T Sub(T a, T b) { | 34 T Sub(T a, T b) { |
28 return a - b; | 35 return a - b; |
29 } | 36 } |
30 | 37 |
31 template <typename T> | 38 template <typename T> |
32 int32_t Equal(T a, T b) { | 39 int32_t Equal(T a, T b) { |
33 return a == b ? 0xFFFFFFFF : 0; | 40 return a == b ? 0xFFFFFFFF : 0; |
34 } | 41 } |
35 | 42 |
36 template <typename T> | 43 template <typename T> |
37 int32_t NotEqual(T a, T b) { | 44 int32_t NotEqual(T a, T b) { |
38 return a != b ? 0xFFFFFFFF : 0; | 45 return a != b ? 0xFFFFFFFF : 0; |
39 } | 46 } |
40 | 47 |
| 48 #if V8_TARGET_ARCH_ARM |
| 49 int32_t Equal(float a, float b) { return a == b ? 0xFFFFFFFF : 0; } |
| 50 |
| 51 int32_t NotEqual(float a, float b) { return a != b ? 0xFFFFFFFF : 0; } |
| 52 #endif // V8_TARGET_ARCH_ARM |
| 53 |
41 } // namespace | 54 } // namespace |
42 | 55 |
43 // TODO(gdeepti): These are tests using sample values to verify functional | 56 // TODO(gdeepti): These are tests using sample values to verify functional |
44 // correctness of opcodes, add more tests for a range of values and macroize | 57 // correctness of opcodes, add more tests for a range of values and macroize |
45 // tests. | 58 // tests. |
46 | 59 |
47 // TODO(bbudge) Figure out how to compare floats in Wasm code that can handle | 60 // TODO(bbudge) Figure out how to compare floats in Wasm code that can handle |
48 // NaNs. For now, our tests avoid using NaNs. | 61 // NaNs. For now, our tests avoid using NaNs. |
49 #define WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lane_value, lane_index) \ | 62 #define WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lane_value, lane_index) \ |
50 WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \ | 63 WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \ |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 WASM_GET_LOCAL(src2))), | 186 WASM_GET_LOCAL(src2))), |
174 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val2, 0), | 187 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val2, 0), |
175 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val1, 1), | 188 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val1, 1), |
176 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val1, 2), | 189 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val1, 2), |
177 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val2, 3), | 190 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val2, 3), |
178 WASM_RETURN1(WASM_ONE))); | 191 WASM_RETURN1(WASM_ONE))); |
179 | 192 |
180 CHECK_EQ(1, r.Call(0x1234, 0x5678)); | 193 CHECK_EQ(1, r.Call(0x1234, 0x5678)); |
181 } | 194 } |
182 | 195 |
183 static void RunF32x4BinopTest(WasmOpcode simd_op, FloatBinOp expected_op) { | 196 void RunF32x4UnOpTest(WasmOpcode simd_op, FloatUnOp expected_op) { |
| 197 FLAG_wasm_simd_prototype = true; |
| 198 WasmRunner<int32_t, float, float> r(kExecuteCompiled); |
| 199 byte a = 0; |
| 200 byte expected = 1; |
| 201 byte simd = r.AllocateLocal(kAstS128); |
| 202 BUILD(r, WASM_BLOCK( |
| 203 WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), |
| 204 WASM_SET_LOCAL( |
| 205 simd, WASM_SIMD_UNOP(simd_op & 0xffu, WASM_GET_LOCAL(simd))), |
| 206 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd, expected), |
| 207 WASM_RETURN1(WASM_ONE))); |
| 208 |
| 209 FOR_FLOAT32_INPUTS(i) { |
| 210 if (std::isnan(*i)) continue; |
| 211 CHECK_EQ(1, r.Call(*i, expected_op(*i))); |
| 212 } |
| 213 } |
| 214 |
| 215 WASM_EXEC_TEST(F32x4Abs) { RunF32x4UnOpTest(kExprF32x4Abs, std::abs); } |
| 216 WASM_EXEC_TEST(F32x4Neg) { RunF32x4UnOpTest(kExprF32x4Neg, Negate); } |
| 217 |
| 218 void RunF32x4BinOpTest(WasmOpcode simd_op, FloatBinOp expected_op) { |
184 FLAG_wasm_simd_prototype = true; | 219 FLAG_wasm_simd_prototype = true; |
185 WasmRunner<int32_t, float, float, float> r(kExecuteCompiled); | 220 WasmRunner<int32_t, float, float, float> r(kExecuteCompiled); |
186 byte a = 0; | 221 byte a = 0; |
187 byte b = 1; | 222 byte b = 1; |
188 byte expected = 2; | 223 byte expected = 2; |
189 byte simd0 = r.AllocateLocal(kAstS128); | 224 byte simd0 = r.AllocateLocal(kAstS128); |
190 byte simd1 = r.AllocateLocal(kAstS128); | 225 byte simd1 = r.AllocateLocal(kAstS128); |
191 BUILD(r, WASM_BLOCK( | 226 BUILD(r, WASM_BLOCK( |
192 WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), | 227 WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), |
193 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), | 228 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), |
194 WASM_SET_LOCAL(simd1, WASM_SIMD_BINOP(simd_op & 0xffu, | 229 WASM_SET_LOCAL(simd1, WASM_SIMD_BINOP(simd_op & 0xffu, |
195 WASM_GET_LOCAL(simd0), | 230 WASM_GET_LOCAL(simd0), |
196 WASM_GET_LOCAL(simd1))), | 231 WASM_GET_LOCAL(simd1))), |
197 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected), | 232 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected), |
198 WASM_RETURN1(WASM_ONE))); | 233 WASM_RETURN1(WASM_ONE))); |
199 | 234 |
200 FOR_FLOAT32_INPUTS(i) { | 235 FOR_FLOAT32_INPUTS(i) { |
201 if (std::isnan(*i)) continue; | 236 if (std::isnan(*i)) continue; |
202 FOR_FLOAT32_INPUTS(j) { | 237 FOR_FLOAT32_INPUTS(j) { |
203 if (std::isnan(*j)) continue; | 238 if (std::isnan(*j)) continue; |
204 CHECK_EQ(1, r.Call(*i, *j, expected_op(*i, *j))); | 239 CHECK_EQ(1, r.Call(*i, *j, expected_op(*i, *j))); |
205 } | 240 } |
206 } | 241 } |
207 } | 242 } |
208 | 243 |
209 WASM_EXEC_TEST(F32x4Add) { RunF32x4BinopTest(kExprF32x4Add, Add); } | 244 WASM_EXEC_TEST(F32x4Add) { RunF32x4BinOpTest(kExprF32x4Add, Add); } |
210 WASM_EXEC_TEST(F32x4Sub) { RunF32x4BinopTest(kExprF32x4Sub, Sub); } | 245 WASM_EXEC_TEST(F32x4Sub) { RunF32x4BinOpTest(kExprF32x4Sub, Sub); } |
| 246 |
| 247 void RunF32x4CompareOpTest(WasmOpcode simd_op, FloatCompareOp expected_op) { |
| 248 FLAG_wasm_simd_prototype = true; |
| 249 WasmRunner<int32_t, float, float, int32_t> r(kExecuteCompiled); |
| 250 byte a = 0; |
| 251 byte b = 1; |
| 252 byte expected = 2; |
| 253 byte simd0 = r.AllocateLocal(kAstS128); |
| 254 byte simd1 = r.AllocateLocal(kAstS128); |
| 255 BUILD(r, WASM_BLOCK( |
| 256 WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), |
| 257 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), |
| 258 WASM_SET_LOCAL(simd1, WASM_SIMD_BINOP(simd_op & 0xffu, |
| 259 WASM_GET_LOCAL(simd0), |
| 260 WASM_GET_LOCAL(simd1))), |
| 261 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), |
| 262 WASM_RETURN1(WASM_ONE))); |
| 263 |
| 264 FOR_FLOAT32_INPUTS(i) { |
| 265 if (std::isnan(*i)) continue; |
| 266 FOR_FLOAT32_INPUTS(j) { |
| 267 if (std::isnan(*j)) continue; |
| 268 CHECK_EQ(1, r.Call(*i, *j, expected_op(*i, *j))); |
| 269 } |
| 270 } |
| 271 } |
| 272 |
| 273 WASM_EXEC_TEST(F32x4Equal) { RunF32x4CompareOpTest(kExprF32x4Eq, Equal); } |
| 274 WASM_EXEC_TEST(F32x4NotEqual) { RunF32x4CompareOpTest(kExprF32x4Ne, NotEqual); } |
211 #endif // V8_TARGET_ARCH_ARM | 275 #endif // V8_TARGET_ARCH_ARM |
212 | 276 |
213 WASM_EXEC_TEST(I32x4Splat) { | 277 WASM_EXEC_TEST(I32x4Splat) { |
214 FLAG_wasm_simd_prototype = true; | 278 FLAG_wasm_simd_prototype = true; |
215 | 279 |
216 // Store SIMD value in a local variable, use extract lane to check lane values | 280 // Store SIMD value in a local variable, use extract lane to check lane values |
217 // This test is not a test for ExtractLane as Splat does not create | 281 // This test is not a test for ExtractLane as Splat does not create |
218 // interesting SIMD values. | 282 // interesting SIMD values. |
219 // | 283 // |
220 // SetLocal(1, I32x4Splat(Local(0))); | 284 // SetLocal(1, I32x4Splat(Local(0))); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 WASM_RETURN1(WASM_ONE))); | 394 WASM_RETURN1(WASM_ONE))); |
331 | 395 |
332 FOR_FLOAT32_INPUTS(i) { | 396 FOR_FLOAT32_INPUTS(i) { |
333 int32_t signed_value = ConvertToInt(*i, false); | 397 int32_t signed_value = ConvertToInt(*i, false); |
334 int32_t unsigned_value = ConvertToInt(*i, true); | 398 int32_t unsigned_value = ConvertToInt(*i, true); |
335 CHECK_EQ(1, r.Call(*i, signed_value, unsigned_value)); | 399 CHECK_EQ(1, r.Call(*i, signed_value, unsigned_value)); |
336 } | 400 } |
337 } | 401 } |
338 #endif // V8_TARGET_ARCH_ARM | 402 #endif // V8_TARGET_ARCH_ARM |
339 | 403 |
340 static void RunI32x4BinopTest(WasmOpcode simd_op, Int32BinOp expected_op) { | 404 void RunI32x4BinOpTest(WasmOpcode simd_op, Int32BinOp expected_op) { |
341 FLAG_wasm_simd_prototype = true; | 405 FLAG_wasm_simd_prototype = true; |
342 WasmRunner<int32_t, int32_t, int32_t, int32_t> r(kExecuteCompiled); | 406 WasmRunner<int32_t, int32_t, int32_t, int32_t> r(kExecuteCompiled); |
343 byte a = 0; | 407 byte a = 0; |
344 byte b = 1; | 408 byte b = 1; |
345 byte expected = 2; | 409 byte expected = 2; |
346 byte simd0 = r.AllocateLocal(kAstS128); | 410 byte simd0 = r.AllocateLocal(kAstS128); |
347 byte simd1 = r.AllocateLocal(kAstS128); | 411 byte simd1 = r.AllocateLocal(kAstS128); |
348 BUILD(r, WASM_BLOCK( | 412 BUILD(r, WASM_BLOCK( |
349 WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))), | 413 WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))), |
350 WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(b))), | 414 WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(b))), |
351 WASM_SET_LOCAL(simd1, WASM_SIMD_BINOP(simd_op & 0xffu, | 415 WASM_SET_LOCAL(simd1, WASM_SIMD_BINOP(simd_op & 0xffu, |
352 WASM_GET_LOCAL(simd0), | 416 WASM_GET_LOCAL(simd0), |
353 WASM_GET_LOCAL(simd1))), | 417 WASM_GET_LOCAL(simd1))), |
354 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), | 418 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), |
355 WASM_RETURN1(WASM_ONE))); | 419 WASM_RETURN1(WASM_ONE))); |
356 | 420 |
357 FOR_INT32_INPUTS(i) { | 421 FOR_INT32_INPUTS(i) { |
358 FOR_INT32_INPUTS(j) { CHECK_EQ(1, r.Call(*i, *j, expected_op(*i, *j))); } | 422 FOR_INT32_INPUTS(j) { CHECK_EQ(1, r.Call(*i, *j, expected_op(*i, *j))); } |
359 } | 423 } |
360 } | 424 } |
361 | 425 |
362 WASM_EXEC_TEST(I32x4Add) { RunI32x4BinopTest(kExprI32x4Add, Add); } | 426 WASM_EXEC_TEST(I32x4Add) { RunI32x4BinOpTest(kExprI32x4Add, Add); } |
363 | 427 |
364 WASM_EXEC_TEST(I32x4Sub) { RunI32x4BinopTest(kExprI32x4Sub, Sub); } | 428 WASM_EXEC_TEST(I32x4Sub) { RunI32x4BinOpTest(kExprI32x4Sub, Sub); } |
365 | 429 |
366 #if V8_TARGET_ARCH_ARM | 430 #if V8_TARGET_ARCH_ARM |
367 WASM_EXEC_TEST(I32x4Equal) { RunI32x4BinopTest(kExprI32x4Eq, Equal); } | 431 WASM_EXEC_TEST(I32x4Equal) { RunI32x4BinOpTest(kExprI32x4Eq, Equal); } |
368 | 432 |
369 WASM_EXEC_TEST(I32x4NotEqual) { RunI32x4BinopTest(kExprI32x4Ne, NotEqual); } | 433 WASM_EXEC_TEST(I32x4NotEqual) { RunI32x4BinOpTest(kExprI32x4Ne, NotEqual); } |
370 #endif // V8_TARGET_ARCH_ARM | 434 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |