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 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 | 67 |
68 #define WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3) \ | 68 #define WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3) \ |
69 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \ | 69 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \ |
70 , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \ | 70 , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \ |
71 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \ | 71 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \ |
72 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3) | 72 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3) |
73 | 73 |
74 #define WASM_SIMD_CHECK_SPLAT4(TYPE, value, LANE_TYPE, lv) \ | 74 #define WASM_SIMD_CHECK_SPLAT4(TYPE, value, LANE_TYPE, lv) \ |
75 WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv, lv, lv, lv) | 75 WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv, lv, lv, lv) |
76 | 76 |
77 #define WASM_SIMD_CHECK_F32_LANE(value, lane_value, lane_index) \ | 77 #define WASM_SIMD_CHECK_F32_LANE(TYPE, value, lane_value, lane_index) \ |
78 WASM_IF(WASM_F32_NE(WASM_GET_LOCAL(lane_value), \ | 78 WASM_IF( \ |
79 WASM_SIMD_F32x4_EXTRACT_LANE(lane_index, \ | 79 WASM_I32_NE(WASM_I32_REINTERPRET_F32(WASM_GET_LOCAL(lane_value)), \ |
80 WASM_GET_LOCAL(value))), \ | 80 WASM_I32_REINTERPRET_F32(WASM_SIMD_##TYPE##_EXTRACT_LANE( \ |
81 WASM_RETURN1(WASM_ZERO)) | 81 lane_index, WASM_GET_LOCAL(value)))), \ |
| 82 WASM_RETURN1(WASM_ZERO)) |
82 | 83 |
83 #define WASM_SIMD_CHECK_F32x4(value, lv0, lv1, lv2, lv3) \ | 84 #define WASM_SIMD_CHECK4_F32(TYPE, value, lv0, lv1, lv2, lv3) \ |
84 WASM_SIMD_CHECK_F32_LANE(value, lv0, 0) \ | 85 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv0, 0) \ |
85 , WASM_SIMD_CHECK_F32_LANE(value, lv1, 1), \ | 86 , WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv1, 1), \ |
86 WASM_SIMD_CHECK_F32_LANE(value, lv2, 2), \ | 87 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv2, 2), \ |
87 WASM_SIMD_CHECK_F32_LANE(value, lv3, 3) | 88 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv3, 3) |
88 | 89 |
89 #define WASM_SIMD_CHECK_SPLAT_F32x4(value, lv) \ | 90 #define WASM_SIMD_CHECK_SPLAT4_F32(TYPE, value, lv) \ |
90 WASM_SIMD_CHECK_F32x4(value, lv, lv, lv, lv) | 91 WASM_SIMD_CHECK4_F32(TYPE, value, lv, lv, lv, lv) |
91 | 92 |
92 #if V8_TARGET_ARCH_ARM | 93 #if V8_TARGET_ARCH_ARM |
93 WASM_EXEC_TEST(F32x4Splat) { | 94 WASM_EXEC_TEST(F32x4Splat) { |
94 FLAG_wasm_simd_prototype = true; | 95 FLAG_wasm_simd_prototype = true; |
95 | 96 |
96 WasmRunner<int32_t, float> r(kExecuteCompiled); | 97 WasmRunner<int32_t, float> r(kExecuteCompiled); |
97 byte lane_val = 0; | 98 byte lane_val = 0; |
98 byte simd = r.AllocateLocal(kWasmS128); | 99 byte simd = r.AllocateLocal(kWasmS128); |
99 BUILD( | 100 BUILD(r, WASM_BLOCK(WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT( |
100 r, | 101 WASM_GET_LOCAL(lane_val))), |
101 WASM_BLOCK( | 102 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd, lane_val), |
102 WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(lane_val))), | 103 WASM_RETURN1(WASM_ONE))); |
103 WASM_SIMD_CHECK_SPLAT_F32x4(simd, lane_val), WASM_RETURN1(WASM_ONE))); | |
104 | 104 |
105 FOR_FLOAT32_INPUTS(i) { | 105 FOR_FLOAT32_INPUTS(i) { CHECK_EQ(1, r.Call(*i)); } |
106 if (std::isnan(*i)) continue; | |
107 CHECK_EQ(1, r.Call(*i)); | |
108 } | |
109 } | 106 } |
110 | 107 |
111 WASM_EXEC_TEST(F32x4ReplaceLane) { | 108 WASM_EXEC_TEST(F32x4ReplaceLane) { |
112 FLAG_wasm_simd_prototype = true; | 109 FLAG_wasm_simd_prototype = true; |
113 WasmRunner<int32_t, float, float> r(kExecuteCompiled); | 110 WasmRunner<int32_t, float, float> r(kExecuteCompiled); |
114 byte old_val = 0; | 111 byte old_val = 0; |
115 byte new_val = 1; | 112 byte new_val = 1; |
116 byte simd = r.AllocateLocal(kWasmS128); | 113 byte simd = r.AllocateLocal(kWasmS128); |
117 BUILD(r, WASM_BLOCK( | 114 BUILD(r, WASM_BLOCK( |
118 WASM_SET_LOCAL(simd, | 115 WASM_SET_LOCAL(simd, |
(...skipping 29 matching lines...) Expand all Loading... |
148 byte a = 0; | 145 byte a = 0; |
149 byte expected_signed = 1; | 146 byte expected_signed = 1; |
150 byte expected_unsigned = 2; | 147 byte expected_unsigned = 2; |
151 byte simd0 = r.AllocateLocal(kWasmS128); | 148 byte simd0 = r.AllocateLocal(kWasmS128); |
152 byte simd1 = r.AllocateLocal(kWasmS128); | 149 byte simd1 = r.AllocateLocal(kWasmS128); |
153 byte simd2 = r.AllocateLocal(kWasmS128); | 150 byte simd2 = r.AllocateLocal(kWasmS128); |
154 BUILD(r, WASM_BLOCK( | 151 BUILD(r, WASM_BLOCK( |
155 WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))), | 152 WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))), |
156 WASM_SET_LOCAL( | 153 WASM_SET_LOCAL( |
157 simd1, WASM_SIMD_F32x4_FROM_I32x4(WASM_GET_LOCAL(simd0))), | 154 simd1, WASM_SIMD_F32x4_FROM_I32x4(WASM_GET_LOCAL(simd0))), |
158 WASM_SIMD_CHECK_SPLAT_F32x4(simd1, expected_signed), | 155 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected_signed), |
159 WASM_SET_LOCAL( | 156 WASM_SET_LOCAL( |
160 simd2, WASM_SIMD_F32x4_FROM_U32x4(WASM_GET_LOCAL(simd0))), | 157 simd2, WASM_SIMD_F32x4_FROM_U32x4(WASM_GET_LOCAL(simd0))), |
161 WASM_SIMD_CHECK_SPLAT_F32x4(simd2, expected_unsigned), | 158 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd2, expected_unsigned), |
162 WASM_RETURN1(WASM_ONE))); | 159 WASM_RETURN1(WASM_ONE))); |
163 | 160 |
164 FOR_INT32_INPUTS(i) { | 161 FOR_INT32_INPUTS(i) { |
165 CHECK_EQ(1, r.Call(*i, static_cast<float>(*i), | 162 CHECK_EQ(1, r.Call(*i, static_cast<float>(*i), |
166 static_cast<float>(static_cast<uint32_t>(*i)))); | 163 static_cast<float>(static_cast<uint32_t>(*i)))); |
167 } | 164 } |
168 } | 165 } |
169 | 166 |
170 WASM_EXEC_TEST(S32x4Select) { | 167 WASM_EXEC_TEST(S32x4Select) { |
171 FLAG_wasm_simd_prototype = true; | 168 FLAG_wasm_simd_prototype = true; |
(...skipping 27 matching lines...) Expand all Loading... |
199 void RunF32x4UnOpTest(WasmOpcode simd_op, FloatUnOp expected_op) { | 196 void RunF32x4UnOpTest(WasmOpcode simd_op, FloatUnOp expected_op) { |
200 FLAG_wasm_simd_prototype = true; | 197 FLAG_wasm_simd_prototype = true; |
201 WasmRunner<int32_t, float, float> r(kExecuteCompiled); | 198 WasmRunner<int32_t, float, float> r(kExecuteCompiled); |
202 byte a = 0; | 199 byte a = 0; |
203 byte expected = 1; | 200 byte expected = 1; |
204 byte simd = r.AllocateLocal(kWasmS128); | 201 byte simd = r.AllocateLocal(kWasmS128); |
205 BUILD(r, WASM_BLOCK( | 202 BUILD(r, WASM_BLOCK( |
206 WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), | 203 WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), |
207 WASM_SET_LOCAL( | 204 WASM_SET_LOCAL( |
208 simd, WASM_SIMD_UNOP(simd_op & 0xffu, WASM_GET_LOCAL(simd))), | 205 simd, WASM_SIMD_UNOP(simd_op & 0xffu, WASM_GET_LOCAL(simd))), |
209 WASM_SIMD_CHECK_SPLAT_F32x4(simd, expected), | 206 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd, expected), |
210 WASM_RETURN1(WASM_ONE))); | 207 WASM_RETURN1(WASM_ONE))); |
211 | 208 |
212 FOR_FLOAT32_INPUTS(i) { | 209 FOR_FLOAT32_INPUTS(i) { |
213 if (std::isnan(*i)) continue; | 210 if (std::isnan(*i)) continue; |
214 CHECK_EQ(1, r.Call(*i, expected_op(*i))); | 211 CHECK_EQ(1, r.Call(*i, expected_op(*i))); |
215 } | 212 } |
216 } | 213 } |
217 | 214 |
218 WASM_EXEC_TEST(F32x4Abs) { RunF32x4UnOpTest(kExprF32x4Abs, std::abs); } | 215 WASM_EXEC_TEST(F32x4Abs) { RunF32x4UnOpTest(kExprF32x4Abs, std::abs); } |
219 WASM_EXEC_TEST(F32x4Neg) { RunF32x4UnOpTest(kExprF32x4Neg, Negate); } | 216 WASM_EXEC_TEST(F32x4Neg) { RunF32x4UnOpTest(kExprF32x4Neg, Negate); } |
220 | 217 |
221 void RunF32x4BinOpTest(WasmOpcode simd_op, FloatBinOp expected_op) { | 218 void RunF32x4BinOpTest(WasmOpcode simd_op, FloatBinOp expected_op) { |
222 FLAG_wasm_simd_prototype = true; | 219 FLAG_wasm_simd_prototype = true; |
223 WasmRunner<int32_t, float, float, float> r(kExecuteCompiled); | 220 WasmRunner<int32_t, float, float, float> r(kExecuteCompiled); |
224 byte a = 0; | 221 byte a = 0; |
225 byte b = 1; | 222 byte b = 1; |
226 byte expected = 2; | 223 byte expected = 2; |
227 byte simd0 = r.AllocateLocal(kWasmS128); | 224 byte simd0 = r.AllocateLocal(kWasmS128); |
228 byte simd1 = r.AllocateLocal(kWasmS128); | 225 byte simd1 = r.AllocateLocal(kWasmS128); |
229 BUILD(r, WASM_BLOCK( | 226 BUILD(r, WASM_BLOCK( |
230 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))), |
231 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))), |
232 WASM_SET_LOCAL(simd1, WASM_SIMD_BINOP(simd_op & 0xffu, | 229 WASM_SET_LOCAL(simd1, WASM_SIMD_BINOP(simd_op & 0xffu, |
233 WASM_GET_LOCAL(simd0), | 230 WASM_GET_LOCAL(simd0), |
234 WASM_GET_LOCAL(simd1))), | 231 WASM_GET_LOCAL(simd1))), |
235 WASM_SIMD_CHECK_SPLAT_F32x4(simd1, expected), | 232 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected), |
236 WASM_RETURN1(WASM_ONE))); | 233 WASM_RETURN1(WASM_ONE))); |
237 | 234 |
238 FOR_FLOAT32_INPUTS(i) { | 235 FOR_FLOAT32_INPUTS(i) { |
| 236 if (std::isnan(*i)) continue; |
239 FOR_FLOAT32_INPUTS(j) { | 237 FOR_FLOAT32_INPUTS(j) { |
| 238 if (std::isnan(*j)) continue; |
240 float expected = expected_op(*i, *j); | 239 float expected = expected_op(*i, *j); |
241 int result_type = std::fpclassify(expected); | 240 // SIMD on some platforms may handle denormalized numbers differently. |
242 // Skip arithmetic operations on NaNs or whose expected result is a NaN | 241 // TODO(bbudge) On platforms that flush denorms to zero, test with |
243 // or denormalized. | 242 // expected == 0. |
244 // TODO(bbudge) On platforms where denormals are flushed to zero, test | 243 if (std::fpclassify(expected) == FP_SUBNORMAL) continue; |
245 // with expected = 0. | |
246 if (result_type == FP_NAN || result_type == FP_SUBNORMAL) continue; | |
247 CHECK_EQ(1, r.Call(*i, *j, expected)); | 244 CHECK_EQ(1, r.Call(*i, *j, expected)); |
248 } | 245 } |
249 } | 246 } |
250 } | 247 } |
251 | 248 |
252 WASM_EXEC_TEST(F32x4Add) { RunF32x4BinOpTest(kExprF32x4Add, Add); } | 249 WASM_EXEC_TEST(F32x4Add) { RunF32x4BinOpTest(kExprF32x4Add, Add); } |
253 WASM_EXEC_TEST(F32x4Sub) { RunF32x4BinOpTest(kExprF32x4Sub, Sub); } | 250 WASM_EXEC_TEST(F32x4Sub) { RunF32x4BinOpTest(kExprF32x4Sub, Sub); } |
254 | 251 |
255 void RunF32x4CompareOpTest(WasmOpcode simd_op, FloatCompareOp expected_op) { | 252 void RunF32x4CompareOpTest(WasmOpcode simd_op, FloatCompareOp expected_op) { |
256 FLAG_wasm_simd_prototype = true; | 253 FLAG_wasm_simd_prototype = true; |
257 WasmRunner<int32_t, float, float, int32_t> r(kExecuteCompiled); | 254 WasmRunner<int32_t, float, float, int32_t> r(kExecuteCompiled); |
258 byte a = 0; | 255 byte a = 0; |
259 byte b = 1; | 256 byte b = 1; |
260 byte expected = 2; | 257 byte expected = 2; |
261 byte simd0 = r.AllocateLocal(kWasmS128); | 258 byte simd0 = r.AllocateLocal(kWasmS128); |
262 byte simd1 = r.AllocateLocal(kWasmS128); | 259 byte simd1 = r.AllocateLocal(kWasmS128); |
263 BUILD(r, WASM_BLOCK( | 260 BUILD(r, WASM_BLOCK( |
264 WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), | 261 WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), |
265 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), | 262 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), |
266 WASM_SET_LOCAL(simd1, WASM_SIMD_BINOP(simd_op & 0xffu, | 263 WASM_SET_LOCAL(simd1, WASM_SIMD_BINOP(simd_op & 0xffu, |
267 WASM_GET_LOCAL(simd0), | 264 WASM_GET_LOCAL(simd0), |
268 WASM_GET_LOCAL(simd1))), | 265 WASM_GET_LOCAL(simd1))), |
269 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), | 266 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), |
270 WASM_RETURN1(WASM_ONE))); | 267 WASM_RETURN1(WASM_ONE))); |
271 | 268 |
272 FOR_FLOAT32_INPUTS(i) { | 269 FOR_FLOAT32_INPUTS(i) { |
| 270 if (std::isnan(*i)) continue; |
273 FOR_FLOAT32_INPUTS(j) { | 271 FOR_FLOAT32_INPUTS(j) { |
274 int diff_type = std::fpclassify(*i - *j); | 272 if (std::isnan(*j)) continue; |
275 // Skip comparisons on NaNs or pairs whose difference is a NaN. | 273 // SIMD on some platforms may handle denormalized numbers differently. |
276 // Skip comparisons on pairs whose difference is denormalized. | 274 // Check for number pairs that are very close together. |
277 // On some platforms, SIMD instructions may flush denormals to zero. | 275 if (std::fpclassify(*i - *j) == FP_SUBNORMAL) continue; |
278 if (diff_type == FP_NAN || diff_type == FP_SUBNORMAL) continue; | |
279 CHECK_EQ(1, r.Call(*i, *j, expected_op(*i, *j))); | 276 CHECK_EQ(1, r.Call(*i, *j, expected_op(*i, *j))); |
280 } | 277 } |
281 } | 278 } |
282 } | 279 } |
283 | 280 |
284 WASM_EXEC_TEST(F32x4Equal) { RunF32x4CompareOpTest(kExprF32x4Eq, Equal); } | 281 WASM_EXEC_TEST(F32x4Equal) { RunF32x4CompareOpTest(kExprF32x4Eq, Equal); } |
285 WASM_EXEC_TEST(F32x4NotEqual) { RunF32x4CompareOpTest(kExprF32x4Ne, NotEqual); } | 282 WASM_EXEC_TEST(F32x4NotEqual) { RunF32x4CompareOpTest(kExprF32x4Ne, NotEqual); } |
286 #endif // V8_TARGET_ARCH_ARM | 283 #endif // V8_TARGET_ARCH_ARM |
287 | 284 |
288 WASM_EXEC_TEST(I32x4Splat) { | 285 WASM_EXEC_TEST(I32x4Splat) { |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 | 433 |
437 WASM_EXEC_TEST(I32x4Add) { RunI32x4BinOpTest(kExprI32x4Add, Add); } | 434 WASM_EXEC_TEST(I32x4Add) { RunI32x4BinOpTest(kExprI32x4Add, Add); } |
438 | 435 |
439 WASM_EXEC_TEST(I32x4Sub) { RunI32x4BinOpTest(kExprI32x4Sub, Sub); } | 436 WASM_EXEC_TEST(I32x4Sub) { RunI32x4BinOpTest(kExprI32x4Sub, Sub); } |
440 | 437 |
441 #if V8_TARGET_ARCH_ARM | 438 #if V8_TARGET_ARCH_ARM |
442 WASM_EXEC_TEST(I32x4Equal) { RunI32x4BinOpTest(kExprI32x4Eq, Equal); } | 439 WASM_EXEC_TEST(I32x4Equal) { RunI32x4BinOpTest(kExprI32x4Eq, Equal); } |
443 | 440 |
444 WASM_EXEC_TEST(I32x4NotEqual) { RunI32x4BinOpTest(kExprI32x4Ne, NotEqual); } | 441 WASM_EXEC_TEST(I32x4NotEqual) { RunI32x4BinOpTest(kExprI32x4Ne, NotEqual); } |
445 #endif // V8_TARGET_ARCH_ARM | 442 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |