Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(497)

Side by Side Diff: test/cctest/wasm/test-run-wasm-simd.cc

Issue 2584863002: [Turbofan] Add native ARM support for basic SIMD 32x4 operations. (Closed)
Patch Set: Update tests to convert float to int correctly, fix bug in ARM simulator. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/wasm/wasm-macro-gen.h ('K') | « test/cctest/BUILD.gn ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 {
17
18 template <typename T>
19 T Add(T a, T b) {
20 return a + b;
21 }
22
23 template <typename T>
24 T Sub(T a, T b) {
25 return a - b;
26 }
27
28 template <typename T>
29 int32_t Equal(T a, T b) {
30 return a == b ? 0xFFFFFFFF : 0;
31 }
32
33 template <typename T>
34 int32_t NotEqual(T a, T b) {
35 return a != b ? 0xFFFFFFFF : 0;
36 }
37
38 } // namespace
39
16 // TODO(gdeepti): These are tests using sample values to verify functional 40 // TODO(gdeepti): These are tests using sample values to verify functional
17 // correctness of opcodes, add more tests for a range of values and macroize 41 // correctness of opcodes, add more tests for a range of values and macroize
18 // tests. 42 // tests.
19 43
20 #define WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lane_value, lane_index) \ 44 #define WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lane_value, lane_index) \
21 WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \ 45 WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \
22 WASM_SIMD_##TYPE##_EXTRACT_LANE( \ 46 WASM_SIMD_##TYPE##_EXTRACT_LANE( \
23 lane_index, WASM_GET_LOCAL(value))), \ 47 lane_index, WASM_GET_LOCAL(value))), \
24 WASM_RETURN1(WASM_ZERO)) 48 WASM_RETURN1(WASM_ZERO))
25 49
26 #define WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3) \ 50 #define WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3) \
27 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \ 51 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \
28 , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \ 52 , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \
29 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \ 53 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \
30 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3) 54 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3)
31 55
32 #define WASM_SIMD_CHECK_SPLAT4(TYPE, value, LANE_TYPE, lv) \ 56 #define WASM_SIMD_CHECK_SPLAT4(TYPE, value, LANE_TYPE, lv) \
33 WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv, lv, lv, lv) 57 WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv, lv, lv, lv)
34 58
59 #define WASM_SIMD_CHECK_F32_LANE(TYPE, value, lane_value, lane_index) \
60 WASM_IF( \
61 WASM_I32_NE(WASM_I32_REINTERPRET_F32(WASM_GET_LOCAL(lane_value)), \
62 WASM_I32_REINTERPRET_F32(WASM_SIMD_##TYPE##_EXTRACT_LANE( \
63 lane_index, WASM_GET_LOCAL(value)))), \
64 WASM_RETURN1(WASM_ZERO))
65
66 #define WASM_SIMD_CHECK4_F32(TYPE, value, lv0, lv1, lv2, lv3) \
67 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv0, 0) \
68 , WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv1, 1), \
69 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv2, 2), \
70 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv3, 3)
71
72 #define WASM_SIMD_CHECK_SPLAT4_F32(TYPE, value, lv) \
73 WASM_SIMD_CHECK4_F32(TYPE, value, lv, lv, lv, lv)
74
75 #if V8_TARGET_ARCH_ARM
76 WASM_EXEC_TEST(F32x4Splat) {
77 FLAG_wasm_simd_prototype = true;
78
79 WasmRunner<int32_t, float> r(kExecuteCompiled);
80 byte lane_val = 0;
81 byte simd = r.AllocateLocal(kAstS128);
82 BUILD(r, WASM_BLOCK(WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(
83 WASM_GET_LOCAL(lane_val))),
84 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd, lane_val),
85 WASM_RETURN1(WASM_ONE)));
86
87 FOR_FLOAT32_INPUTS(i) { CHECK_EQ(1, r.Call(*i)); }
88 }
89
90 WASM_EXEC_TEST(F32x4ReplaceLane) {
91 FLAG_wasm_simd_prototype = true;
92 WasmRunner<int32_t, float, float> r(kExecuteCompiled);
93 byte old_val = 0;
94 byte new_val = 1;
95 byte simd = r.AllocateLocal(kAstS128);
96 BUILD(r, WASM_BLOCK(
97 WASM_SET_LOCAL(simd,
98 WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(old_val))),
99 WASM_SET_LOCAL(
100 simd, WASM_SIMD_F32x4_REPLACE_LANE(0, WASM_GET_LOCAL(simd),
101 WASM_GET_LOCAL(new_val))),
102 WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, old_val, old_val,
103 old_val),
104 WASM_SET_LOCAL(
105 simd, WASM_SIMD_F32x4_REPLACE_LANE(1, WASM_GET_LOCAL(simd),
106 WASM_GET_LOCAL(new_val))),
107 WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, new_val, old_val,
108 old_val),
109 WASM_SET_LOCAL(
110 simd, WASM_SIMD_F32x4_REPLACE_LANE(2, WASM_GET_LOCAL(simd),
111 WASM_GET_LOCAL(new_val))),
112 WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, new_val, new_val,
113 old_val),
114 WASM_SET_LOCAL(
115 simd, WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_LOCAL(simd),
116 WASM_GET_LOCAL(new_val))),
117 WASM_SIMD_CHECK_SPLAT4(F32x4, simd, F32, new_val),
118 WASM_RETURN1(WASM_ONE)));
119
120 CHECK_EQ(1, r.Call(1, 2));
gdeepti 2016/12/16 23:35:24 Is there a reason we do not use floating point val
bbudge 2016/12/17 01:51:05 Changed to be more obviously floating point. Comp
121 }
122
123 // Tests both signed and unsigned conversion.
124 WASM_EXEC_TEST(F32x4FromInt32x4) {
125 FLAG_wasm_simd_prototype = true;
126 WasmRunner<int32_t, int32_t, float, float> r(kExecuteCompiled);
127 byte a = 0;
128 byte expected_signed = 1;
129 byte expected_unsigned = 2;
130 byte simd0 = r.AllocateLocal(kAstS128);
131 byte simd1 = r.AllocateLocal(kAstS128);
132 byte simd2 = r.AllocateLocal(kAstS128);
133 BUILD(r, WASM_BLOCK(
134 WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))),
135 WASM_SET_LOCAL(
136 simd1, WASM_SIMD_F32x4_FROM_INT32x4(WASM_GET_LOCAL(simd0))),
137 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected_signed),
138 WASM_SET_LOCAL(
139 simd2, WASM_SIMD_F32x4_FROM_UINT32x4(WASM_GET_LOCAL(simd0))),
140 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd2, expected_unsigned),
141 WASM_RETURN1(WASM_ONE)));
142
143 FOR_INT32_INPUTS(i) {
144 CHECK_EQ(1, r.Call(*i, static_cast<float>(*i),
145 static_cast<float>(static_cast<uint32_t>(*i))));
146 }
147 }
148
149 WASM_EXEC_TEST(S32x4Select) {
150 FLAG_wasm_simd_prototype = true;
151 WasmRunner<int32_t, int32_t, int32_t> r(kExecuteCompiled);
152 byte val1 = 0;
153 byte val2 = 1;
154 byte mask = r.AllocateLocal(kAstS128);
155 byte src1 = r.AllocateLocal(kAstS128);
156 byte src2 = r.AllocateLocal(kAstS128);
157 BUILD(r,
158 WASM_BLOCK(
159 WASM_SET_LOCAL(mask, WASM_SIMD_I32x4_SPLAT(WASM_ZERO)),
160 WASM_SET_LOCAL(src1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(val1))),
161 WASM_SET_LOCAL(src2, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(val2))),
162 WASM_SET_LOCAL(mask, WASM_SIMD_I32x4_REPLACE_LANE(
163 1, WASM_GET_LOCAL(mask), WASM_I32V(-1))),
164 WASM_SET_LOCAL(mask, WASM_SIMD_I32x4_REPLACE_LANE(
165 2, WASM_GET_LOCAL(mask), WASM_I32V(-1))),
166 WASM_SET_LOCAL(mask, WASM_SIMD_32x4_SELECT(WASM_GET_LOCAL(mask),
167 WASM_GET_LOCAL(src1),
168 WASM_GET_LOCAL(src2))),
169 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val2, 0),
170 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val1, 1),
171 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val1, 2),
172 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val2, 3),
173 WASM_RETURN1(WASM_ONE)));
174
175 CHECK_EQ(1, r.Call(0x1234, 0x5678));
176 }
177
178 #define WASM_SIMD_F32x4_BINOP_TEST(Name, OP, op) \
179 WASM_EXEC_TEST(F32x4##Name) { \
180 FLAG_wasm_simd_prototype = true; \
181 WasmRunner<int32_t, float, float, float> r(kExecuteCompiled); \
182 byte a = 0; \
183 byte b = 1; \
184 byte expected = 2; \
185 byte simd0 = r.AllocateLocal(kAstS128); \
186 byte simd1 = r.AllocateLocal(kAstS128); \
187 BUILD(r, \
188 WASM_BLOCK( \
189 WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), \
190 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), \
191 WASM_SET_LOCAL(simd1, \
192 WASM_SIMD_F32x4_##OP(WASM_GET_LOCAL(simd0), \
193 WASM_GET_LOCAL(simd1))), \
194 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected), \
195 WASM_RETURN1(WASM_ONE))); \
196 \
197 FOR_FLOAT32_INPUTS(i) { \
198 if (std::isnan(*i)) continue; \
199 FOR_FLOAT32_INPUTS(j) { \
200 if (std::isnan(*j)) continue; \
201 CHECK_EQ(1, r.Call(*i, *j, *i op *j)); \
202 } \
203 } \
204 }
205
206 WASM_SIMD_F32x4_BINOP_TEST(Add, ADD, +);
207 WASM_SIMD_F32x4_BINOP_TEST(Sub, SUB, -);
208 #endif // V8_TARGET_ARCH_ARM
209
35 WASM_EXEC_TEST(I32x4Splat) { 210 WASM_EXEC_TEST(I32x4Splat) {
36 FLAG_wasm_simd_prototype = true; 211 FLAG_wasm_simd_prototype = true;
37 212
38 // Store SIMD value in a local variable, use extract lane to check lane values 213 // Store SIMD value in a local variable, use extract lane to check lane values
39 // This test is not a test for ExtractLane as Splat does not create 214 // This test is not a test for ExtractLane as Splat does not create
40 // interesting SIMD values. 215 // interesting SIMD values.
41 // 216 //
42 // SetLocal(1, I32x4Splat(Local(0))); 217 // SetLocal(1, I32x4Splat(Local(0)));
43 // For each lane index 218 // For each lane index
44 // if(Local(0) != I32x4ExtractLane(Local(1), index) 219 // if(Local(0) != I32x4ExtractLane(Local(1), index)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 old_val), 257 old_val),
83 WASM_SET_LOCAL( 258 WASM_SET_LOCAL(
84 simd, WASM_SIMD_I32x4_REPLACE_LANE(3, WASM_GET_LOCAL(simd), 259 simd, WASM_SIMD_I32x4_REPLACE_LANE(3, WASM_GET_LOCAL(simd),
85 WASM_GET_LOCAL(new_val))), 260 WASM_GET_LOCAL(new_val))),
86 WASM_SIMD_CHECK_SPLAT4(I32x4, simd, I32, new_val), 261 WASM_SIMD_CHECK_SPLAT4(I32x4, simd, I32, new_val),
87 WASM_RETURN1(WASM_ONE))); 262 WASM_RETURN1(WASM_ONE)));
88 263
89 CHECK_EQ(1, r.Call(1, 2)); 264 CHECK_EQ(1, r.Call(1, 2));
90 } 265 }
91 266
92 WASM_EXEC_TEST(I32x4Add) { 267 #if V8_TARGET_ARCH_ARM
93 FLAG_wasm_simd_prototype = true;
94 WasmRunner<int32_t, int32_t, int32_t, int32_t> r(kExecuteCompiled);
95 byte a = 0;
96 byte b = 1;
97 byte expected = 2;
98 byte simd0 = r.AllocateLocal(kAstS128);
99 byte simd1 = r.AllocateLocal(kAstS128);
100 BUILD(r,
101 WASM_BLOCK(
102 WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))),
103 WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(b))),
104 WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_ADD(WASM_GET_LOCAL(simd0),
105 WASM_GET_LOCAL(simd1))),
106 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected),
107 WASM_RETURN1(WASM_ONE)));
108 268
109 FOR_INT32_INPUTS(i) { 269 // Determines if conversion from float to int will be valid.
110 FOR_INT32_INPUTS(j) { CHECK_EQ(1, r.Call(*i, *j, *i + *j)); } 270 bool CanRoundToZeroAndConvert(double val, bool unsigned_integer) {
271 const double max_uint = static_cast<double>(0xffffffffu);
272 const double max_int = static_cast<double>(kMaxInt);
273 const double min_int = static_cast<double>(kMinInt);
274
275 // Check for NaN.
276 if (val != val) {
277 return false;
278 }
279
280 // Round to zero and check for overflow. This code works because 32 bit
281 // integers can be exactly represented by ieee-754 64bit floating-point
282 // values.
283 return unsigned_integer ? (val < (max_uint + 1.0)) && (val > -1)
284 : (val < (max_int + 1.0)) && (val > (min_int - 1.0));
285 }
286
287 int ConvertInvalidValue(double val, bool unsigned_integer) {
288 if (val != val) {
289 return 0;
290 } else {
291 if (unsigned_integer) {
292 return (val < 0) ? 0 : 0xffffffffu;
293 } else {
294 return (val < 0) ? kMinInt : kMaxInt;
295 }
111 } 296 }
112 } 297 }
113 298
114 WASM_EXEC_TEST(I32x4Sub) { 299 int32_t ConvertToInt(double val, bool unsigned_integer) {
300 int32_t result =
301 unsigned_integer ? static_cast<uint32_t>(val) : static_cast<int32_t>(val);
302
303 if (!CanRoundToZeroAndConvert(val, unsigned_integer)) {
304 result = ConvertInvalidValue(val, unsigned_integer);
305 }
306 return result;
307 }
308
309 // Tests both signed and unsigned conversion.
310 WASM_EXEC_TEST(I32x4FromFloat32x4) {
115 FLAG_wasm_simd_prototype = true; 311 FLAG_wasm_simd_prototype = true;
116 WasmRunner<int32_t, int32_t, int32_t, int32_t> r(kExecuteCompiled); 312 WasmRunner<int32_t, float, int32_t, int32_t> r(kExecuteCompiled);
117 byte a = 0; 313 byte a = 0;
118 byte b = 1; 314 byte expected_signed = 1;
119 byte expected = 2; 315 byte expected_unsigned = 2;
120 byte simd0 = r.AllocateLocal(kAstS128); 316 byte simd0 = r.AllocateLocal(kAstS128);
121 byte simd1 = r.AllocateLocal(kAstS128); 317 byte simd1 = r.AllocateLocal(kAstS128);
318 byte simd2 = r.AllocateLocal(kAstS128);
122 BUILD(r, 319 BUILD(r,
123 WASM_BLOCK( 320 WASM_BLOCK(
124 WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))), 321 WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))),
125 WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(b))), 322 WASM_SET_LOCAL(
126 WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_SUB(WASM_GET_LOCAL(simd0), 323 simd1, WASM_SIMD_I32x4_FROM_FLOAT32x4(WASM_GET_LOCAL(simd0))),
127 WASM_GET_LOCAL(simd1))), 324 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected_signed),
128 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), 325 WASM_SET_LOCAL(
326 simd2, WASM_SIMD_UI32x4_FROM_FLOAT32x4(WASM_GET_LOCAL(simd0))),
327 WASM_SIMD_CHECK_SPLAT4(I32x4, simd2, I32, expected_unsigned),
129 WASM_RETURN1(WASM_ONE))); 328 WASM_RETURN1(WASM_ONE)));
130 329
131 FOR_INT32_INPUTS(i) { 330 FOR_FLOAT32_INPUTS(i) {
132 FOR_INT32_INPUTS(j) { CHECK_EQ(1, r.Call(*i, *j, *i - *j)); } 331 int32_t signed_value = ConvertToInt(*i, false);
332 int32_t unsigned_value = ConvertToInt(*i, true);
333 CHECK_EQ(1, r.Call(*i, signed_value, unsigned_value));
133 } 334 }
134 } 335 }
336 #endif // V8_TARGET_ARCH_ARM
337
338 #define WASM_SIMD_I32x4_BINOP_TEST(Name, OP, op) \
339 WASM_EXEC_TEST(I32x4##Name) { \
340 FLAG_wasm_simd_prototype = true; \
341 WasmRunner<int32_t, int32_t, int32_t, int32_t> r(kExecuteCompiled); \
342 byte a = 0; \
343 byte b = 1; \
344 byte expected = 2; \
345 byte simd0 = r.AllocateLocal(kAstS128); \
346 byte simd1 = r.AllocateLocal(kAstS128); \
347 BUILD(r, \
348 WASM_BLOCK( \
349 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))), \
351 WASM_SET_LOCAL(simd1, \
352 WASM_SIMD_I32x4_##OP(WASM_GET_LOCAL(simd0), \
353 WASM_GET_LOCAL(simd1))), \
354 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), \
355 WASM_RETURN1(WASM_ONE))); \
356 \
357 FOR_INT32_INPUTS(i) { \
358 FOR_INT32_INPUTS(j) { CHECK_EQ(1, r.Call(*i, *j, op(*i, *j))); } \
359 } \
360 }
361
362 WASM_SIMD_I32x4_BINOP_TEST(Add, ADD, Add);
363 WASM_SIMD_I32x4_BINOP_TEST(Sub, SUB, Sub);
364 #if V8_TARGET_ARCH_ARM
365 WASM_SIMD_I32x4_BINOP_TEST(Equal, EQUAL, Equal);
366 WASM_SIMD_I32x4_BINOP_TEST(NotEqual, NOT_EQUAL, NotEqual);
367 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« src/wasm/wasm-macro-gen.h ('K') | « test/cctest/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698