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

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: Deepti's comments. 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
« no previous file with comments | « 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
44 // TODO(bbudge) Figure out how to compare floats in Wasm code that can handle
45 // NaNs. For now, our tests avoid using NaNs.
20 #define WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lane_value, lane_index) \ 46 #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), \ 47 WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \
22 WASM_SIMD_##TYPE##_EXTRACT_LANE( \ 48 WASM_SIMD_##TYPE##_EXTRACT_LANE( \
23 lane_index, WASM_GET_LOCAL(value))), \ 49 lane_index, WASM_GET_LOCAL(value))), \
24 WASM_RETURN1(WASM_ZERO)) 50 WASM_RETURN1(WASM_ZERO))
25 51
26 #define WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3) \ 52 #define WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3) \
27 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \ 53 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \
28 , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \ 54 , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \
29 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \ 55 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \
30 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3) 56 WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3)
31 57
32 #define WASM_SIMD_CHECK_SPLAT4(TYPE, value, LANE_TYPE, lv) \ 58 #define WASM_SIMD_CHECK_SPLAT4(TYPE, value, LANE_TYPE, lv) \
33 WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv, lv, lv, lv) 59 WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv, lv, lv, lv)
34 60
61 #define WASM_SIMD_CHECK_F32_LANE(TYPE, value, lane_value, lane_index) \
62 WASM_IF( \
63 WASM_I32_NE(WASM_I32_REINTERPRET_F32(WASM_GET_LOCAL(lane_value)), \
64 WASM_I32_REINTERPRET_F32(WASM_SIMD_##TYPE##_EXTRACT_LANE( \
65 lane_index, WASM_GET_LOCAL(value)))), \
66 WASM_RETURN1(WASM_ZERO))
67
68 #define WASM_SIMD_CHECK4_F32(TYPE, value, lv0, lv1, lv2, lv3) \
69 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv0, 0) \
70 , WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv1, 1), \
71 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv2, 2), \
72 WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv3, 3)
73
74 #define WASM_SIMD_CHECK_SPLAT4_F32(TYPE, value, lv) \
75 WASM_SIMD_CHECK4_F32(TYPE, value, lv, lv, lv, lv)
76
77 #if V8_TARGET_ARCH_ARM
78 WASM_EXEC_TEST(F32x4Splat) {
79 FLAG_wasm_simd_prototype = true;
80
81 WasmRunner<int32_t, float> r(kExecuteCompiled);
82 byte lane_val = 0;
83 byte simd = r.AllocateLocal(kAstS128);
84 BUILD(r, WASM_BLOCK(WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(
85 WASM_GET_LOCAL(lane_val))),
86 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd, lane_val),
87 WASM_RETURN1(WASM_ONE)));
88
89 FOR_FLOAT32_INPUTS(i) { CHECK_EQ(1, r.Call(*i)); }
90 }
91
92 WASM_EXEC_TEST(F32x4ReplaceLane) {
93 FLAG_wasm_simd_prototype = true;
94 WasmRunner<int32_t, float, float> r(kExecuteCompiled);
95 byte old_val = 0;
96 byte new_val = 1;
97 byte simd = r.AllocateLocal(kAstS128);
98 BUILD(r, WASM_BLOCK(
99 WASM_SET_LOCAL(simd,
100 WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(old_val))),
101 WASM_SET_LOCAL(
102 simd, WASM_SIMD_F32x4_REPLACE_LANE(0, WASM_GET_LOCAL(simd),
103 WASM_GET_LOCAL(new_val))),
104 WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, old_val, old_val,
105 old_val),
106 WASM_SET_LOCAL(
107 simd, WASM_SIMD_F32x4_REPLACE_LANE(1, WASM_GET_LOCAL(simd),
108 WASM_GET_LOCAL(new_val))),
109 WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, new_val, old_val,
110 old_val),
111 WASM_SET_LOCAL(
112 simd, WASM_SIMD_F32x4_REPLACE_LANE(2, WASM_GET_LOCAL(simd),
113 WASM_GET_LOCAL(new_val))),
114 WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, new_val, new_val,
115 old_val),
116 WASM_SET_LOCAL(
117 simd, WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_LOCAL(simd),
118 WASM_GET_LOCAL(new_val))),
119 WASM_SIMD_CHECK_SPLAT4(F32x4, simd, F32, new_val),
120 WASM_RETURN1(WASM_ONE)));
121
122 CHECK_EQ(1, r.Call(3.14159, -1.5));
123 }
124
125 // Tests both signed and unsigned conversion.
126 WASM_EXEC_TEST(F32x4FromInt32x4) {
127 FLAG_wasm_simd_prototype = true;
128 WasmRunner<int32_t, int32_t, float, float> r(kExecuteCompiled);
129 byte a = 0;
130 byte expected_signed = 1;
131 byte expected_unsigned = 2;
132 byte simd0 = r.AllocateLocal(kAstS128);
133 byte simd1 = r.AllocateLocal(kAstS128);
134 byte simd2 = r.AllocateLocal(kAstS128);
135 BUILD(r, WASM_BLOCK(
136 WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))),
137 WASM_SET_LOCAL(
138 simd1, WASM_SIMD_F32x4_FROM_I32x4(WASM_GET_LOCAL(simd0))),
139 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected_signed),
140 WASM_SET_LOCAL(
141 simd2, WASM_SIMD_F32x4_FROM_U32x4(WASM_GET_LOCAL(simd0))),
142 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd2, expected_unsigned),
143 WASM_RETURN1(WASM_ONE)));
144
145 FOR_INT32_INPUTS(i) {
146 CHECK_EQ(1, r.Call(*i, static_cast<float>(*i),
147 static_cast<float>(static_cast<uint32_t>(*i))));
148 }
149 }
150
151 WASM_EXEC_TEST(S32x4Select) {
152 FLAG_wasm_simd_prototype = true;
153 WasmRunner<int32_t, int32_t, int32_t> r(kExecuteCompiled);
154 byte val1 = 0;
155 byte val2 = 1;
156 byte mask = r.AllocateLocal(kAstS128);
157 byte src1 = r.AllocateLocal(kAstS128);
158 byte src2 = r.AllocateLocal(kAstS128);
159 BUILD(r,
160 WASM_BLOCK(
161 WASM_SET_LOCAL(mask, WASM_SIMD_I32x4_SPLAT(WASM_ZERO)),
162 WASM_SET_LOCAL(src1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(val1))),
163 WASM_SET_LOCAL(src2, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(val2))),
164 WASM_SET_LOCAL(mask, WASM_SIMD_I32x4_REPLACE_LANE(
165 1, WASM_GET_LOCAL(mask), WASM_I32V(-1))),
166 WASM_SET_LOCAL(mask, WASM_SIMD_I32x4_REPLACE_LANE(
167 2, WASM_GET_LOCAL(mask), WASM_I32V(-1))),
168 WASM_SET_LOCAL(mask, WASM_SIMD_S32x4_SELECT(WASM_GET_LOCAL(mask),
169 WASM_GET_LOCAL(src1),
170 WASM_GET_LOCAL(src2))),
171 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val2, 0),
172 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val1, 1),
173 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val1, 2),
174 WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val2, 3),
175 WASM_RETURN1(WASM_ONE)));
176
177 CHECK_EQ(1, r.Call(0x1234, 0x5678));
178 }
179
180 #define WASM_SIMD_F32x4_BINOP_TEST(Name, OP, op) \
titzer 2016/12/19 15:26:59 I would prefer to have a helper function rather th
bbudge 2016/12/20 00:57:13 I replaced the macro expansions here and below wit
181 WASM_EXEC_TEST(F32x4##Name) { \
182 FLAG_wasm_simd_prototype = true; \
183 WasmRunner<int32_t, float, float, float> r(kExecuteCompiled); \
184 byte a = 0; \
185 byte b = 1; \
186 byte expected = 2; \
187 byte simd0 = r.AllocateLocal(kAstS128); \
188 byte simd1 = r.AllocateLocal(kAstS128); \
189 BUILD(r, \
190 WASM_BLOCK( \
191 WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), \
192 WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), \
193 WASM_SET_LOCAL(simd1, \
194 WASM_SIMD_F32x4_##OP(WASM_GET_LOCAL(simd0), \
195 WASM_GET_LOCAL(simd1))), \
196 WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected), \
197 WASM_RETURN1(WASM_ONE))); \
198 \
199 FOR_FLOAT32_INPUTS(i) { \
200 if (std::isnan(*i)) continue; \
201 FOR_FLOAT32_INPUTS(j) { \
202 if (std::isnan(*j)) continue; \
203 CHECK_EQ(1, r.Call(*i, *j, *i op *j)); \
204 } \
205 } \
206 }
207
208 WASM_SIMD_F32x4_BINOP_TEST(Add, ADD, +);
209 WASM_SIMD_F32x4_BINOP_TEST(Sub, SUB, -);
210 #endif // V8_TARGET_ARCH_ARM
211
35 WASM_EXEC_TEST(I32x4Splat) { 212 WASM_EXEC_TEST(I32x4Splat) {
36 FLAG_wasm_simd_prototype = true; 213 FLAG_wasm_simd_prototype = true;
37 214
38 // Store SIMD value in a local variable, use extract lane to check lane values 215 // 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 216 // This test is not a test for ExtractLane as Splat does not create
40 // interesting SIMD values. 217 // interesting SIMD values.
41 // 218 //
42 // SetLocal(1, I32x4Splat(Local(0))); 219 // SetLocal(1, I32x4Splat(Local(0)));
43 // For each lane index 220 // For each lane index
44 // if(Local(0) != I32x4ExtractLane(Local(1), index) 221 // if(Local(0) != I32x4ExtractLane(Local(1), index)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 old_val), 259 old_val),
83 WASM_SET_LOCAL( 260 WASM_SET_LOCAL(
84 simd, WASM_SIMD_I32x4_REPLACE_LANE(3, WASM_GET_LOCAL(simd), 261 simd, WASM_SIMD_I32x4_REPLACE_LANE(3, WASM_GET_LOCAL(simd),
85 WASM_GET_LOCAL(new_val))), 262 WASM_GET_LOCAL(new_val))),
86 WASM_SIMD_CHECK_SPLAT4(I32x4, simd, I32, new_val), 263 WASM_SIMD_CHECK_SPLAT4(I32x4, simd, I32, new_val),
87 WASM_RETURN1(WASM_ONE))); 264 WASM_RETURN1(WASM_ONE)));
88 265
89 CHECK_EQ(1, r.Call(1, 2)); 266 CHECK_EQ(1, r.Call(1, 2));
90 } 267 }
91 268
92 WASM_EXEC_TEST(I32x4Add) { 269 #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 270
109 FOR_INT32_INPUTS(i) { 271 // Determines if conversion from float to int will be valid.
110 FOR_INT32_INPUTS(j) { CHECK_EQ(1, r.Call(*i, *j, *i + *j)); } 272 bool CanRoundToZeroAndConvert(double val, bool unsigned_integer) {
273 const double max_uint = static_cast<double>(0xffffffffu);
274 const double max_int = static_cast<double>(kMaxInt);
275 const double min_int = static_cast<double>(kMinInt);
276
277 // Check for NaN.
278 if (val != val) {
279 return false;
280 }
281
282 // Round to zero and check for overflow. This code works because 32 bit
283 // integers can be exactly represented by ieee-754 64bit floating-point
284 // values.
285 return unsigned_integer ? (val < (max_uint + 1.0)) && (val > -1)
286 : (val < (max_int + 1.0)) && (val > (min_int - 1.0));
287 }
288
289 int ConvertInvalidValue(double val, bool unsigned_integer) {
290 if (val != val) {
291 return 0;
292 } else {
293 if (unsigned_integer) {
294 return (val < 0) ? 0 : 0xffffffffu;
295 } else {
296 return (val < 0) ? kMinInt : kMaxInt;
297 }
111 } 298 }
112 } 299 }
113 300
114 WASM_EXEC_TEST(I32x4Sub) { 301 int32_t ConvertToInt(double val, bool unsigned_integer) {
302 int32_t result =
303 unsigned_integer ? static_cast<uint32_t>(val) : static_cast<int32_t>(val);
304
305 if (!CanRoundToZeroAndConvert(val, unsigned_integer)) {
306 result = ConvertInvalidValue(val, unsigned_integer);
307 }
308 return result;
309 }
310
311 // Tests both signed and unsigned conversion.
312 WASM_EXEC_TEST(I32x4FromFloat32x4) {
115 FLAG_wasm_simd_prototype = true; 313 FLAG_wasm_simd_prototype = true;
116 WasmRunner<int32_t, int32_t, int32_t, int32_t> r(kExecuteCompiled); 314 WasmRunner<int32_t, float, int32_t, int32_t> r(kExecuteCompiled);
117 byte a = 0; 315 byte a = 0;
118 byte b = 1; 316 byte expected_signed = 1;
119 byte expected = 2; 317 byte expected_unsigned = 2;
120 byte simd0 = r.AllocateLocal(kAstS128); 318 byte simd0 = r.AllocateLocal(kAstS128);
121 byte simd1 = r.AllocateLocal(kAstS128); 319 byte simd1 = r.AllocateLocal(kAstS128);
122 BUILD(r, 320 byte simd2 = r.AllocateLocal(kAstS128);
123 WASM_BLOCK( 321 BUILD(r, WASM_BLOCK(
124 WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))), 322 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))), 323 WASM_SET_LOCAL(
126 WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_SUB(WASM_GET_LOCAL(simd0), 324 simd1, WASM_SIMD_I32x4_FROM_F32x4(WASM_GET_LOCAL(simd0))),
127 WASM_GET_LOCAL(simd1))), 325 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected_signed),
128 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), 326 WASM_SET_LOCAL(
129 WASM_RETURN1(WASM_ONE))); 327 simd2, WASM_SIMD_U32x4_FROM_F32x4(WASM_GET_LOCAL(simd0))),
328 WASM_SIMD_CHECK_SPLAT4(I32x4, simd2, I32, expected_unsigned),
329 WASM_RETURN1(WASM_ONE)));
130 330
131 FOR_INT32_INPUTS(i) { 331 FOR_FLOAT32_INPUTS(i) {
132 FOR_INT32_INPUTS(j) { CHECK_EQ(1, r.Call(*i, *j, *i - *j)); } 332 int32_t signed_value = ConvertToInt(*i, false);
333 int32_t unsigned_value = ConvertToInt(*i, true);
334 CHECK_EQ(1, r.Call(*i, signed_value, unsigned_value));
133 } 335 }
134 } 336 }
337 #endif // V8_TARGET_ARCH_ARM
338
339 #define WASM_SIMD_I32x4_BINOP_TEST(Name, OP, op) \
340 WASM_EXEC_TEST(I32x4##Name) { \
341 FLAG_wasm_simd_prototype = true; \
342 WasmRunner<int32_t, int32_t, int32_t, int32_t> r(kExecuteCompiled); \
343 byte a = 0; \
344 byte b = 1; \
345 byte expected = 2; \
346 byte simd0 = r.AllocateLocal(kAstS128); \
347 byte simd1 = r.AllocateLocal(kAstS128); \
348 BUILD(r, \
349 WASM_BLOCK( \
350 WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))), \
351 WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(b))), \
352 WASM_SET_LOCAL(simd1, \
353 WASM_SIMD_I32x4_##OP(WASM_GET_LOCAL(simd0), \
354 WASM_GET_LOCAL(simd1))), \
355 WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), \
356 WASM_RETURN1(WASM_ONE))); \
357 \
358 FOR_INT32_INPUTS(i) { \
359 FOR_INT32_INPUTS(j) { CHECK_EQ(1, r.Call(*i, *j, op(*i, *j))); } \
360 } \
361 }
362
363 WASM_SIMD_I32x4_BINOP_TEST(Add, ADD, Add);
364 WASM_SIMD_I32x4_BINOP_TEST(Sub, SUB, Sub);
365 #if V8_TARGET_ARCH_ARM
366 WASM_SIMD_I32x4_BINOP_TEST(Equal, EQUAL, Equal);
367 WASM_SIMD_I32x4_BINOP_TEST(NotEqual, NOT_EQUAL, NotEqual);
368 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « test/cctest/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698