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/assembler-inl.h" | 5 #include "src/assembler-inl.h" |
6 #include "src/wasm/wasm-macro-gen.h" | 6 #include "src/wasm/wasm-macro-gen.h" |
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 |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 } | 218 } |
219 | 219 |
220 } // namespace | 220 } // namespace |
221 | 221 |
222 #if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_X64 | 222 #if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_X64 |
223 #define SIMD_LOWERING_TARGET 1 | 223 #define SIMD_LOWERING_TARGET 1 |
224 #else | 224 #else |
225 #define SIMD_LOWERING_TARGET 0 | 225 #define SIMD_LOWERING_TARGET 0 |
226 #endif // !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_X64 | 226 #endif // !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_X64 |
227 | 227 |
228 // TODO(gdeepti): These are tests using sample values to verify functional | |
229 // correctness of opcodes, add more tests for a range of values and macroize | |
230 // tests. | |
231 | |
232 // TODO(bbudge) Figure out how to compare floats in Wasm code that can handle | |
233 // NaNs. For now, our tests avoid using NaNs. | |
234 #define WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lane_value, lane_index) \ | 228 #define WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lane_value, lane_index) \ |
235 WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \ | 229 WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \ |
236 WASM_SIMD_##TYPE##_EXTRACT_LANE( \ | 230 WASM_SIMD_##TYPE##_EXTRACT_LANE( \ |
237 lane_index, WASM_GET_LOCAL(value))), \ | 231 lane_index, WASM_GET_LOCAL(value))), \ |
238 WASM_RETURN1(WASM_ZERO)) | 232 WASM_RETURN1(WASM_ZERO)) |
239 | 233 |
| 234 #define WASM_SIMD_CHECK_F32_LANE(value, lane_value, lane_index) \ |
| 235 WASM_IF(WASM_F32_NE(WASM_GET_LOCAL(lane_value), \ |
| 236 WASM_SIMD_F32x4_EXTRACT_LANE(lane_index, \ |
| 237 WASM_GET_LOCAL(value))), \ |
| 238 WASM_RETURN1(WASM_ZERO)) |
| 239 |
240 #define WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3) \ | 240 #define WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3) \ |
241 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \ | 241 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \ |
242 , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \ | 242 , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \ |
243 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \ | 243 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \ |
244 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3) | 244 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3) |
245 | 245 |
246 #define WASM_SIMD_CHECK_SPLAT4(TYPE, value, LANE_TYPE, lv) \ | 246 #define WASM_SIMD_CHECK_SPLAT4(TYPE, value, LANE_TYPE, lv) \ |
247 WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv, lv, lv, lv) | 247 WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv, lv, lv, lv) |
248 | 248 |
249 #define WASM_SIMD_CHECK8(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3, lv4, lv5, \ | 249 #define WASM_SIMD_CHECK8(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3, lv4, lv5, \ |
(...skipping 27 matching lines...) Expand all Loading... |
277 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv11, 11), \ | 277 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv11, 11), \ |
278 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv12, 12), \ | 278 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv12, 12), \ |
279 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv13, 13), \ | 279 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv13, 13), \ |
280 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv14, 14), \ | 280 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv14, 14), \ |
281 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv15, 15) | 281 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv15, 15) |
282 | 282 |
283 #define WASM_SIMD_CHECK_SPLAT16(TYPE, value, LANE_TYPE, lv) \ | 283 #define WASM_SIMD_CHECK_SPLAT16(TYPE, value, LANE_TYPE, lv) \ |
284 WASM_SIMD_CHECK16(TYPE, value, LANE_TYPE, lv, lv, lv, lv, lv, lv, lv, lv, \ | 284 WASM_SIMD_CHECK16(TYPE, value, LANE_TYPE, lv, lv, lv, lv, lv, lv, lv, lv, \ |
285 lv, lv, lv, lv, lv, lv, lv, lv) | 285 lv, lv, lv, lv, lv, lv, lv, lv) |
286 | 286 |
287 #define WASM_SIMD_CHECK_F32_LANE(TYPE, value, lane_value, lane_index) \ | 287 #define WASM_SIMD_CHECK_F32x4(value, lv0, lv1, lv2, lv3) \ |
288 WASM_IF( \ | 288 WASM_SIMD_CHECK_F32_LANE(value, lv0, 0) \ |
289 WASM_I32_NE(WASM_I32_REINTERPRET_F32(WASM_GET_LOCAL(lane_value)), \ | 289 , WASM_SIMD_CHECK_F32_LANE(value, lv1, 1), \ |
290 WASM_I32_REINTERPRET_F32(WASM_SIMD_##TYPE##_EXTRACT_LANE( \ | 290 WASM_SIMD_CHECK_F32_LANE(value, lv2, 2), \ |
291 lane_index, WASM_GET_LOCAL(value)))), \ | 291 WASM_SIMD_CHECK_F32_LANE(value, lv3, 3) |
292 WASM_RETURN1(WASM_ZERO)) | |
293 | 292 |
294 #define WASM_SIMD_CHECK4_F32(TYPE, value, lv0, lv1, lv2, lv3) \ | 293 #define WASM_SIMD_CHECK_SPLAT_F32x4(value, lv) \ |
295 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv0, 0) \ | 294 WASM_SIMD_CHECK_F32x4(value, lv, lv, lv, lv) |
296 , WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv1, 1), \ | |
297 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv2, 2), \ | |
298 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv3, 3) | |
299 | |
300 #define WASM_SIMD_CHECK_SPLAT4_F32(TYPE, value, lv) \ | |
301 WASM_SIMD_CHECK4_F32(TYPE, value, lv, lv, lv, lv) | |
302 | 295 |
303 #define TO_BYTE(val) static_cast<byte>(val) | 296 #define TO_BYTE(val) static_cast<byte>(val) |
304 #define WASM_SIMD_OP(op) kSimdPrefix, TO_BYTE(op) | 297 #define WASM_SIMD_OP(op) kSimdPrefix, TO_BYTE(op) |
305 #define WASM_SIMD_SPLAT(Type, x) x, WASM_SIMD_OP(kExpr##Type##Splat) | 298 #define WASM_SIMD_SPLAT(Type, x) x, WASM_SIMD_OP(kExpr##Type##Splat) |
306 #define WASM_SIMD_UNOP(op, x) x, WASM_SIMD_OP(op) | 299 #define WASM_SIMD_UNOP(op, x) x, WASM_SIMD_OP(op) |
307 #define WASM_SIMD_BINOP(op, x, y) x, y, WASM_SIMD_OP(op) | 300 #define WASM_SIMD_BINOP(op, x, y) x, y, WASM_SIMD_OP(op) |
308 #define WASM_SIMD_SHIFT_OP(op, shift, x) x, WASM_SIMD_OP(op), TO_BYTE(shift) | 301 #define WASM_SIMD_SHIFT_OP(op, shift, x) x, WASM_SIMD_OP(op), TO_BYTE(shift) |
309 #define WASM_SIMD_SELECT(format, x, y, z) \ | 302 #define WASM_SIMD_SELECT(format, x, y, z) \ |
310 x, y, z, WASM_SIMD_OP(kExprS##format##Select) | 303 x, y, z, WASM_SIMD_OP(kExprS##format##Select) |
311 // Since boolean vectors can't be checked directly, materialize them into | 304 // Since boolean vectors can't be checked directly, materialize them into |
(...skipping 25 matching lines...) Expand all Loading... |
337 #define WASM_SIMD_I8x16_EXTRACT_LANE(lane, x) \ | 330 #define WASM_SIMD_I8x16_EXTRACT_LANE(lane, x) \ |
338 x, WASM_SIMD_OP(kExprI8x16ExtractLane), TO_BYTE(lane) | 331 x, WASM_SIMD_OP(kExprI8x16ExtractLane), TO_BYTE(lane) |
339 #define WASM_SIMD_I8x16_REPLACE_LANE(lane, x, y) \ | 332 #define WASM_SIMD_I8x16_REPLACE_LANE(lane, x, y) \ |
340 x, y, WASM_SIMD_OP(kExprI8x16ReplaceLane), TO_BYTE(lane) | 333 x, y, WASM_SIMD_OP(kExprI8x16ReplaceLane), TO_BYTE(lane) |
341 | 334 |
342 #define WASM_SIMD_F32x4_FROM_I32x4(x) x, WASM_SIMD_OP(kExprF32x4SConvertI32x4) | 335 #define WASM_SIMD_F32x4_FROM_I32x4(x) x, WASM_SIMD_OP(kExprF32x4SConvertI32x4) |
343 #define WASM_SIMD_F32x4_FROM_U32x4(x) x, WASM_SIMD_OP(kExprF32x4UConvertI32x4) | 336 #define WASM_SIMD_F32x4_FROM_U32x4(x) x, WASM_SIMD_OP(kExprF32x4UConvertI32x4) |
344 #define WASM_SIMD_I32x4_FROM_F32x4(x) x, WASM_SIMD_OP(kExprI32x4SConvertF32x4) | 337 #define WASM_SIMD_I32x4_FROM_F32x4(x) x, WASM_SIMD_OP(kExprI32x4SConvertF32x4) |
345 #define WASM_SIMD_U32x4_FROM_F32x4(x) x, WASM_SIMD_OP(kExprI32x4UConvertF32x4) | 338 #define WASM_SIMD_U32x4_FROM_F32x4(x) x, WASM_SIMD_OP(kExprI32x4UConvertF32x4) |
346 | 339 |
| 340 // Skip FP operations on NaNs or whose expected result is a NaN or so small |
| 341 // that denormalized numbers may flush to zero and cause exact FP comparisons |
| 342 // to fail. |
| 343 // TODO(bbudge) Switch FP comparisons in WASM code to WASM code that handles |
| 344 // NaNs and results with limited precision. |
| 345 bool SkipFPTestInput(float x) { return std::isnan(x); } |
| 346 |
| 347 bool SkipFPTestResult(float x) { |
| 348 if (std::isnan(x)) return true; |
| 349 // Constant empirically determined so existing tests pass on ARM hardware. |
| 350 const float kSmallFloatThreshold = 1.0e-32f; |
| 351 float abs_x = std::fabs(x); |
| 352 return abs_x != 0 && abs_x < kSmallFloatThreshold; |
| 353 } |
| 354 |
347 #if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET | 355 #if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET |
348 WASM_EXEC_COMPILED_TEST(F32x4Splat) { | 356 WASM_EXEC_COMPILED_TEST(F32x4Splat) { |
349 FLAG_wasm_simd_prototype = true; | 357 FLAG_wasm_simd_prototype = true; |
350 | 358 |
351 WasmRunner<int32_t, float> r(kExecuteCompiled); | 359 WasmRunner<int32_t, float> r(kExecuteCompiled); |
352 byte lane_val = 0; | 360 byte lane_val = 0; |
353 byte simd = r.AllocateLocal(kWasmS128); | 361 byte simd = r.AllocateLocal(kWasmS128); |
354 BUILD(r, | 362 BUILD(r, |
355 WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(lane_val))), | 363 WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(lane_val))), |
356 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd, lane_val), WASM_ONE); | 364 WASM_SIMD_CHECK_SPLAT_F32x4(simd, lane_val), WASM_RETURN1(WASM_ONE)); |
357 | 365 |
358 FOR_FLOAT32_INPUTS(i) { CHECK_EQ(1, r.Call(*i)); } | 366 FOR_FLOAT32_INPUTS(i) { |
| 367 if (SkipFPTestInput(*i)) continue; |
| 368 CHECK_EQ(1, r.Call(*i)); |
| 369 } |
359 } | 370 } |
360 | 371 |
361 WASM_EXEC_COMPILED_TEST(F32x4ReplaceLane) { | 372 WASM_EXEC_COMPILED_TEST(F32x4ReplaceLane) { |
362 FLAG_wasm_simd_prototype = true; | 373 FLAG_wasm_simd_prototype = true; |
363 WasmRunner<int32_t, float, float> r(kExecuteCompiled); | 374 WasmRunner<int32_t, float, float> r(kExecuteCompiled); |
364 byte old_val = 0; | 375 byte old_val = 0; |
365 byte new_val = 1; | 376 byte new_val = 1; |
366 byte simd = r.AllocateLocal(kWasmS128); | 377 byte simd = r.AllocateLocal(kWasmS128); |
367 BUILD(r, WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(old_val))), | 378 BUILD(r, WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(old_val))), |
368 WASM_SET_LOCAL(simd, | 379 WASM_SET_LOCAL(simd, |
369 WASM_SIMD_F32x4_REPLACE_LANE(0, WASM_GET_LOCAL(simd), | 380 WASM_SIMD_F32x4_REPLACE_LANE(0, WASM_GET_LOCAL(simd), |
370 WASM_GET_LOCAL(new_val))), | 381 WASM_GET_LOCAL(new_val))), |
371 WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, old_val, old_val, old_val), | 382 WASM_SIMD_CHECK_F32x4(simd, new_val, old_val, old_val, old_val), |
372 WASM_SET_LOCAL(simd, | 383 WASM_SET_LOCAL(simd, |
373 WASM_SIMD_F32x4_REPLACE_LANE(1, WASM_GET_LOCAL(simd), | 384 WASM_SIMD_F32x4_REPLACE_LANE(1, WASM_GET_LOCAL(simd), |
374 WASM_GET_LOCAL(new_val))), | 385 WASM_GET_LOCAL(new_val))), |
375 WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, new_val, old_val, old_val), | 386 WASM_SIMD_CHECK_F32x4(simd, new_val, new_val, old_val, old_val), |
376 WASM_SET_LOCAL(simd, | 387 WASM_SET_LOCAL(simd, |
377 WASM_SIMD_F32x4_REPLACE_LANE(2, WASM_GET_LOCAL(simd), | 388 WASM_SIMD_F32x4_REPLACE_LANE(2, WASM_GET_LOCAL(simd), |
378 WASM_GET_LOCAL(new_val))), | 389 WASM_GET_LOCAL(new_val))), |
379 WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, new_val, new_val, old_val), | 390 WASM_SIMD_CHECK_F32x4(simd, new_val, new_val, new_val, old_val), |
380 WASM_SET_LOCAL(simd, | 391 WASM_SET_LOCAL(simd, |
381 WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_LOCAL(simd), | 392 WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_LOCAL(simd), |
382 WASM_GET_LOCAL(new_val))), | 393 WASM_GET_LOCAL(new_val))), |
383 WASM_SIMD_CHECK_SPLAT4(F32x4, simd, F32, new_val), WASM_ONE); | 394 WASM_SIMD_CHECK_SPLAT_F32x4(simd, new_val), WASM_RETURN1(WASM_ONE)); |
384 | 395 |
385 CHECK_EQ(1, r.Call(3.14159f, -1.5f)); | 396 CHECK_EQ(1, r.Call(3.14159f, -1.5f)); |
386 } | 397 } |
387 | 398 |
388 // Tests both signed and unsigned conversion. | 399 // Tests both signed and unsigned conversion. |
389 WASM_EXEC_COMPILED_TEST(F32x4FromInt32x4) { | 400 WASM_EXEC_COMPILED_TEST(F32x4FromInt32x4) { |
390 FLAG_wasm_simd_prototype = true; | 401 FLAG_wasm_simd_prototype = true; |
391 WasmRunner<int32_t, int32_t, float, float> r(kExecuteCompiled); | 402 WasmRunner<int32_t, int32_t, float, float> r(kExecuteCompiled); |
392 byte a = 0; | 403 byte a = 0; |
393 byte expected_signed = 1; | 404 byte expected_signed = 1; |
394 byte expected_unsigned = 2; | 405 byte expected_unsigned = 2; |
395 byte simd0 = r.AllocateLocal(kWasmS128); | 406 byte simd0 = r.AllocateLocal(kWasmS128); |
396 byte simd1 = r.AllocateLocal(kWasmS128); | 407 byte simd1 = r.AllocateLocal(kWasmS128); |
397 byte simd2 = r.AllocateLocal(kWasmS128); | 408 byte simd2 = r.AllocateLocal(kWasmS128); |
398 BUILD( | 409 BUILD( |
399 r, WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))), | 410 r, WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))), |
400 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_FROM_I32x4(WASM_GET_LOCAL(simd0))), | 411 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_FROM_I32x4(WASM_GET_LOCAL(simd0))), |
401 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected_signed), | 412 WASM_SIMD_CHECK_SPLAT_F32x4(simd1, expected_signed), |
402 WASM_SET_LOCAL(simd2, WASM_SIMD_F32x4_FROM_U32x4(WASM_GET_LOCAL(simd0))), | 413 WASM_SET_LOCAL(simd2, WASM_SIMD_F32x4_FROM_U32x4(WASM_GET_LOCAL(simd0))), |
403 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd2, expected_unsigned), WASM_ONE); | 414 WASM_SIMD_CHECK_SPLAT_F32x4(simd2, expected_unsigned), |
| 415 WASM_RETURN1(WASM_ONE)); |
404 | 416 |
405 FOR_INT32_INPUTS(i) { | 417 FOR_INT32_INPUTS(i) { |
406 CHECK_EQ(1, r.Call(*i, static_cast<float>(*i), | 418 CHECK_EQ(1, r.Call(*i, static_cast<float>(*i), |
407 static_cast<float>(static_cast<uint32_t>(*i)))); | 419 static_cast<float>(static_cast<uint32_t>(*i)))); |
408 } | 420 } |
409 } | 421 } |
410 | 422 |
411 void RunF32x4UnOpTest(WasmOpcode simd_op, FloatUnOp expected_op) { | 423 void RunF32x4UnOpTest(WasmOpcode simd_op, FloatUnOp expected_op) { |
412 FLAG_wasm_simd_prototype = true; | 424 FLAG_wasm_simd_prototype = true; |
413 WasmRunner<int32_t, float, float> r(kExecuteCompiled); | 425 WasmRunner<int32_t, float, float> r(kExecuteCompiled); |
414 byte a = 0; | 426 byte a = 0; |
415 byte expected = 1; | 427 byte expected = 1; |
416 byte simd = r.AllocateLocal(kWasmS128); | 428 byte simd = r.AllocateLocal(kWasmS128); |
417 BUILD(r, WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), | 429 BUILD(r, WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), |
418 WASM_SET_LOCAL(simd, WASM_SIMD_UNOP(simd_op, WASM_GET_LOCAL(simd))), | 430 WASM_SET_LOCAL(simd, WASM_SIMD_UNOP(simd_op, WASM_GET_LOCAL(simd))), |
419 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd, expected), WASM_ONE); | 431 WASM_SIMD_CHECK_SPLAT_F32x4(simd, expected), WASM_RETURN1(WASM_ONE)); |
420 | 432 |
421 FOR_FLOAT32_INPUTS(i) { | 433 FOR_FLOAT32_INPUTS(i) { |
422 if (std::isnan(*i)) continue; | 434 if (SkipFPTestInput(*i)) continue; |
423 if (std::isnan(expected_op(*i))) continue; | 435 float expected = expected_op(*i); |
424 CHECK_EQ(1, r.Call(*i, expected_op(*i))); | 436 if (SkipFPTestResult(expected)) continue; |
| 437 CHECK_EQ(1, r.Call(*i, expected)); |
425 } | 438 } |
426 } | 439 } |
427 | 440 |
428 WASM_EXEC_COMPILED_TEST(F32x4Abs) { RunF32x4UnOpTest(kExprF32x4Abs, std::abs); } | 441 WASM_EXEC_COMPILED_TEST(F32x4Abs) { RunF32x4UnOpTest(kExprF32x4Abs, std::abs); } |
429 WASM_EXEC_COMPILED_TEST(F32x4Neg) { RunF32x4UnOpTest(kExprF32x4Neg, Negate); } | 442 WASM_EXEC_COMPILED_TEST(F32x4Neg) { RunF32x4UnOpTest(kExprF32x4Neg, Negate); } |
430 #endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET | 443 #endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET |
431 | 444 |
432 #if SIMD_LOWERING_TARGET | 445 #if SIMD_LOWERING_TARGET |
433 WASM_EXEC_COMPILED_TEST(F32x4Sqrt) { RunF32x4UnOpTest(kExprF32x4Sqrt, Sqrt); } | 446 WASM_EXEC_COMPILED_TEST(F32x4Sqrt) { RunF32x4UnOpTest(kExprF32x4Sqrt, Sqrt); } |
434 #endif // SIMD_LOWERING_TARGET | 447 #endif // SIMD_LOWERING_TARGET |
435 | 448 |
436 #if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET | 449 #if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET |
437 void RunF32x4BinOpTest(WasmOpcode simd_op, FloatBinOp expected_op, | 450 void RunF32x4BinOpTest(WasmOpcode simd_op, FloatBinOp expected_op) { |
438 bool skip_zero_inputs = false) { | |
439 FLAG_wasm_simd_prototype = true; | 451 FLAG_wasm_simd_prototype = true; |
440 WasmRunner<int32_t, float, float, float> r(kExecuteCompiled); | 452 WasmRunner<int32_t, float, float, float> r(kExecuteCompiled); |
441 byte a = 0; | 453 byte a = 0; |
442 byte b = 1; | 454 byte b = 1; |
443 byte expected = 2; | 455 byte expected = 2; |
444 byte simd0 = r.AllocateLocal(kWasmS128); | 456 byte simd0 = r.AllocateLocal(kWasmS128); |
445 byte simd1 = r.AllocateLocal(kWasmS128); | 457 byte simd1 = r.AllocateLocal(kWasmS128); |
446 BUILD(r, WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), | 458 BUILD(r, WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), |
447 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), | 459 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), |
448 WASM_SET_LOCAL(simd1, WASM_SIMD_BINOP(simd_op, WASM_GET_LOCAL(simd0), | 460 WASM_SET_LOCAL(simd1, WASM_SIMD_BINOP(simd_op, WASM_GET_LOCAL(simd0), |
449 WASM_GET_LOCAL(simd1))), | 461 WASM_GET_LOCAL(simd1))), |
450 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected), WASM_ONE); | 462 WASM_SIMD_CHECK_SPLAT_F32x4(simd1, expected), WASM_RETURN1(WASM_ONE)); |
451 | 463 |
452 FOR_FLOAT32_INPUTS(i) { | 464 FOR_FLOAT32_INPUTS(i) { |
453 if (std::isnan(*i)) continue; | 465 if (SkipFPTestInput(*i)) continue; |
454 FOR_FLOAT32_INPUTS(j) { | 466 FOR_FLOAT32_INPUTS(j) { |
455 if (std::isnan(*j)) continue; | 467 if (SkipFPTestInput(*j)) continue; |
456 if (skip_zero_inputs && std::fpclassify(*i) == FP_ZERO && | |
457 std::fpclassify(*j) == FP_ZERO) | |
458 continue; | |
459 float expected = expected_op(*i, *j); | 468 float expected = expected_op(*i, *j); |
460 // SIMD on some platforms may handle denormalized numbers differently. | 469 if (SkipFPTestResult(expected)) continue; |
461 // TODO(bbudge) On platforms that flush denorms to zero, test with | |
462 // expected == 0. | |
463 if (std::fpclassify(expected) == FP_SUBNORMAL) continue; | |
464 if (std::isnan(expected)) continue; | |
465 CHECK_EQ(1, r.Call(*i, *j, expected)); | 470 CHECK_EQ(1, r.Call(*i, *j, expected)); |
466 } | 471 } |
467 } | 472 } |
468 } | 473 } |
469 | 474 |
470 WASM_EXEC_COMPILED_TEST(F32x4Add) { RunF32x4BinOpTest(kExprF32x4Add, Add); } | 475 WASM_EXEC_COMPILED_TEST(F32x4Add) { RunF32x4BinOpTest(kExprF32x4Add, Add); } |
471 WASM_EXEC_COMPILED_TEST(F32x4Sub) { RunF32x4BinOpTest(kExprF32x4Sub, Sub); } | 476 WASM_EXEC_COMPILED_TEST(F32x4Sub) { RunF32x4BinOpTest(kExprF32x4Sub, Sub); } |
472 #endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET | 477 #endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET |
473 | 478 |
474 #if SIMD_LOWERING_TARGET | 479 #if SIMD_LOWERING_TARGET |
475 WASM_EXEC_COMPILED_TEST(F32x4Mul) { RunF32x4BinOpTest(kExprF32x4Mul, Mul); } | 480 WASM_EXEC_COMPILED_TEST(F32x4Mul) { RunF32x4BinOpTest(kExprF32x4Mul, Mul); } |
476 WASM_EXEC_COMPILED_TEST(F32x4Div) { RunF32x4BinOpTest(kExprF32x4Div, Div); } | 481 WASM_EXEC_COMPILED_TEST(F32x4Div) { RunF32x4BinOpTest(kExprF32x4Div, Div); } |
477 WASM_EXEC_COMPILED_TEST(Simd_F32x4_Min) { | 482 WASM_EXEC_COMPILED_TEST(Simd_F32x4_Min) { |
478 RunF32x4BinOpTest(kExprF32x4Min, Minimum, true); | 483 RunF32x4BinOpTest(kExprF32x4Min, Minimum); |
479 } | 484 } |
480 WASM_EXEC_COMPILED_TEST(Simd_F32x4_Max) { | 485 WASM_EXEC_COMPILED_TEST(Simd_F32x4_Max) { |
481 RunF32x4BinOpTest(kExprF32x4Max, Maximum, true); | 486 RunF32x4BinOpTest(kExprF32x4Max, Maximum); |
482 } | 487 } |
483 #endif // SIMD_LOWERING_TARGET | 488 #endif // SIMD_LOWERING_TARGET |
484 | 489 |
485 #if V8_TARGET_ARCH_ARM | 490 #if V8_TARGET_ARCH_ARM |
486 void RunF32x4CompareOpTest(WasmOpcode simd_op, FloatCompareOp expected_op) { | 491 void RunF32x4CompareOpTest(WasmOpcode simd_op, FloatCompareOp expected_op) { |
487 FLAG_wasm_simd_prototype = true; | 492 FLAG_wasm_simd_prototype = true; |
488 WasmRunner<int32_t, float, float, int32_t> r(kExecuteCompiled); | 493 WasmRunner<int32_t, float, float, int32_t> r(kExecuteCompiled); |
489 byte a = 0; | 494 byte a = 0; |
490 byte b = 1; | 495 byte b = 1; |
491 byte expected = 2; | 496 byte expected = 2; |
492 byte simd0 = r.AllocateLocal(kWasmS128); | 497 byte simd0 = r.AllocateLocal(kWasmS128); |
493 byte simd1 = r.AllocateLocal(kWasmS128); | 498 byte simd1 = r.AllocateLocal(kWasmS128); |
494 BUILD(r, WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), | 499 BUILD(r, WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), |
495 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), | 500 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), |
496 WASM_SET_LOCAL(simd1, | 501 WASM_SET_LOCAL(simd1, |
497 WASM_SIMD_MATERIALIZE_BOOLS( | 502 WASM_SIMD_MATERIALIZE_BOOLS( |
498 32x4, WASM_SIMD_BINOP(simd_op, WASM_GET_LOCAL(simd0), | 503 32x4, WASM_SIMD_BINOP(simd_op, WASM_GET_LOCAL(simd0), |
499 WASM_GET_LOCAL(simd1)))), | 504 WASM_GET_LOCAL(simd1)))), |
500 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), WASM_ONE); | 505 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), WASM_ONE); |
501 | 506 |
502 FOR_FLOAT32_INPUTS(i) { | 507 FOR_FLOAT32_INPUTS(i) { |
503 if (std::isnan(*i)) continue; | 508 if (SkipFPTestInput(*i)) continue; |
504 FOR_FLOAT32_INPUTS(j) { | 509 FOR_FLOAT32_INPUTS(j) { |
505 if (std::isnan(*j)) continue; | 510 if (SkipFPTestInput(*j)) continue; |
506 // SIMD on some platforms may handle denormalized numbers differently. | 511 int diff = *i - *j; |
507 // Check for number pairs that are very close together. | 512 if (SkipFPTestResult(diff)) continue; |
508 if (std::fpclassify(*i - *j) == FP_SUBNORMAL) continue; | |
509 CHECK_EQ(1, r.Call(*i, *j, expected_op(*i, *j))); | 513 CHECK_EQ(1, r.Call(*i, *j, expected_op(*i, *j))); |
510 } | 514 } |
511 } | 515 } |
512 } | 516 } |
513 | 517 |
514 WASM_EXEC_COMPILED_TEST(F32x4Equal) { | 518 WASM_EXEC_COMPILED_TEST(F32x4Equal) { |
515 RunF32x4CompareOpTest(kExprF32x4Eq, Equal); | 519 RunF32x4CompareOpTest(kExprF32x4Eq, Equal); |
516 } | 520 } |
517 | 521 |
518 WASM_EXEC_COMPILED_TEST(F32x4NotEqual) { | 522 WASM_EXEC_COMPILED_TEST(F32x4NotEqual) { |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
804 byte simd1 = r.AllocateLocal(kWasmS128); | 808 byte simd1 = r.AllocateLocal(kWasmS128); |
805 byte simd2 = r.AllocateLocal(kWasmS128); | 809 byte simd2 = r.AllocateLocal(kWasmS128); |
806 BUILD( | 810 BUILD( |
807 r, WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), | 811 r, WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), |
808 WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_FROM_F32x4(WASM_GET_LOCAL(simd0))), | 812 WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_FROM_F32x4(WASM_GET_LOCAL(simd0))), |
809 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected_signed), | 813 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected_signed), |
810 WASM_SET_LOCAL(simd2, WASM_SIMD_U32x4_FROM_F32x4(WASM_GET_LOCAL(simd0))), | 814 WASM_SET_LOCAL(simd2, WASM_SIMD_U32x4_FROM_F32x4(WASM_GET_LOCAL(simd0))), |
811 WASM_SIMD_CHECK_SPLAT4(I32x4, simd2, I32, expected_unsigned), WASM_ONE); | 815 WASM_SIMD_CHECK_SPLAT4(I32x4, simd2, I32, expected_unsigned), WASM_ONE); |
812 | 816 |
813 FOR_FLOAT32_INPUTS(i) { | 817 FOR_FLOAT32_INPUTS(i) { |
| 818 if (SkipFPTestInput(*i)) continue; |
814 int32_t signed_value = ConvertToInt(*i, false); | 819 int32_t signed_value = ConvertToInt(*i, false); |
815 int32_t unsigned_value = ConvertToInt(*i, true); | 820 int32_t unsigned_value = ConvertToInt(*i, true); |
816 CHECK_EQ(1, r.Call(*i, signed_value, unsigned_value)); | 821 CHECK_EQ(1, r.Call(*i, signed_value, unsigned_value)); |
817 } | 822 } |
818 } | 823 } |
819 #endif // V8_TARGET_ARCH_ARM | 824 #endif // V8_TARGET_ARCH_ARM |
820 | 825 |
821 #if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET | 826 #if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET |
822 void RunI32x4UnOpTest(WasmOpcode simd_op, Int32UnOp expected_op) { | 827 void RunI32x4UnOpTest(WasmOpcode simd_op, Int32UnOp expected_op) { |
823 FLAG_wasm_simd_prototype = true; | 828 FLAG_wasm_simd_prototype = true; |
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1563 WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_GLOBAL(0), | 1568 WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_GLOBAL(0), |
1564 WASM_F32(65.0))), | 1569 WASM_F32(65.0))), |
1565 WASM_I32V(1)); | 1570 WASM_I32V(1)); |
1566 FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call(0)); } | 1571 FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call(0)); } |
1567 CHECK_EQ(*global, 13.5); | 1572 CHECK_EQ(*global, 13.5); |
1568 CHECK_EQ(*(global + 1), 45.5); | 1573 CHECK_EQ(*(global + 1), 45.5); |
1569 CHECK_EQ(*(global + 2), 32.25); | 1574 CHECK_EQ(*(global + 2), 32.25); |
1570 CHECK_EQ(*(global + 3), 65.0); | 1575 CHECK_EQ(*(global + 3), 65.0); |
1571 } | 1576 } |
1572 #endif // SIMD_LOWERING_TARGET | 1577 #endif // SIMD_LOWERING_TARGET |
OLD | NEW |