1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_CCTEST_COMPILER_VALUE_HELPER_H_
6 #define V8_CCTEST_COMPILER_VALUE_HELPER_H_
7
8 #include <stdint.h>
9
10 #include "src/base/template-utils.h"
11 #include "src/compiler/common-operator.h"
12 #include "src/compiler/node-matchers.h"
13 #include "src/compiler/node.h"
14 #include "src/execution/isolate.h"
15 #include "src/objects/objects.h"
16 #include "test/cctest/cctest.h"
17
18 namespace v8 {
19 namespace internal {
20 namespace compiler {
21
22 // A collection of utilities related to numerical and heap values, including
23 // example input values of various types, including int32_t, uint32_t, double,
24 // etc.
25 class ValueHelper {
26 public:
27 Isolate* isolate_;
28
ValueHelper()29 ValueHelper() : isolate_(CcTest::InitIsolateOnce()) {}
30
CheckFloat64Constant(double expected,Node * node)31 void CheckFloat64Constant(double expected, Node* node) {
32 CHECK_EQ(IrOpcode::kFloat64Constant, node->opcode());
33 CHECK_EQ(expected, OpParameter<double>(node->op()));
34 }
35
CheckNumberConstant(double expected,Node * node)36 void CheckNumberConstant(double expected, Node* node) {
37 CHECK_EQ(IrOpcode::kNumberConstant, node->opcode());
38 CHECK_EQ(expected, OpParameter<double>(node->op()));
39 }
40
CheckInt32Constant(int32_t expected,Node * node)41 void CheckInt32Constant(int32_t expected, Node* node) {
42 CHECK_EQ(IrOpcode::kInt32Constant, node->opcode());
43 CHECK_EQ(expected, OpParameter<int32_t>(node->op()));
44 }
45
CheckUint32Constant(int32_t expected,Node * node)46 void CheckUint32Constant(int32_t expected, Node* node) {
47 CHECK_EQ(IrOpcode::kInt32Constant, node->opcode());
48 CHECK_EQ(expected, OpParameter<int32_t>(node->op()));
49 }
50
CheckHeapConstant(HeapObject expected,Node * node)51 void CheckHeapConstant(HeapObject expected, Node* node) {
52 CHECK_EQ(IrOpcode::kHeapConstant, node->opcode());
53 CHECK_EQ(expected, *HeapConstantOf(node->op()));
54 }
55
56 static constexpr float float32_array[] = {
57 -std::numeric_limits<float>::infinity(),
58 -2.70497e+38f,
59 -1.4698e+37f,
60 -1.22813e+35f,
61 -1.20555e+35f,
62 -1.34584e+34f,
63 -1.0079e+32f,
64 -6.49364e+26f,
65 -3.06077e+25f,
66 -1.46821e+25f,
67 -1.17658e+23f,
68 -1.9617e+22f,
69 -2.7357e+20f,
70 -9223372036854775808.0f, // INT64_MIN
71 -1.48708e+13f,
72 -1.89633e+12f,
73 -4.66622e+11f,
74 -2.22581e+11f,
75 -1.45381e+10f,
76 -2147483904.0f, // First float32 after INT32_MIN
77 -2147483648.0f, // INT32_MIN
78 -2147483520.0f, // Last float32 before INT32_MIN
79 -1.3956e+09f,
80 -1.32951e+09f,
81 -1.30721e+09f,
82 -1.19756e+09f,
83 -9.26822e+08f,
84 -6.35647e+08f,
85 -4.00037e+08f,
86 -1.81227e+08f,
87 -5.09256e+07f,
88 -964300.0f,
89 -192446.0f,
90 -28455.0f,
91 -27194.0f,
92 -26401.0f,
93 -20575.0f,
94 -17069.0f,
95 -9167.0f,
96 -960.178f,
97 -113.0f,
98 -62.0f,
99 -15.0f,
100 -7.0f,
101 -1.0f,
102 -0.0256635f,
103 -4.60374e-07f,
104 -3.63759e-10f,
105 -4.30175e-14f,
106 -5.27385e-15f,
107 -1.5707963267948966f,
108 -1.48084e-15f,
109 -2.220446049250313e-16f,
110 -1.05755e-19f,
111 -3.2995e-21f,
112 -1.67354e-23f,
113 -1.11885e-23f,
114 -1.78506e-30f,
115 -5.07594e-31f,
116 -3.65799e-31f,
117 -1.43718e-34f,
118 -1.27126e-38f,
119 -0.0f,
120 0.0f,
121 1.17549e-38f,
122 1.56657e-37f,
123 4.08512e-29f,
124 3.31357e-28f,
125 6.25073e-22f,
126 4.1723e-13f,
127 1.44343e-09f,
128 1.5707963267948966f,
129 5.27004e-08f,
130 9.48298e-08f,
131 5.57888e-07f,
132 4.89988e-05f,
133 0.244326f,
134 1.0f,
135 12.4895f,
136 19.0f,
137 47.0f,
138 106.0f,
139 538.324f,
140 564.536f,
141 819.124f,
142 7048.0f,
143 12611.0f,
144 19878.0f,
145 20309.0f,
146 797056.0f,
147 1.77219e+09f,
148 2147483648.0f, // INT32_MAX + 1
149 4294967296.0f, // UINT32_MAX + 1
150 1.51116e+11f,
151 4.18193e+13f,
152 3.59167e+16f,
153 9223372036854775808.0f, // INT64_MAX + 1
154 18446744073709551616.0f, // UINT64_MAX + 1
155 3.38211e+19f,
156 2.67488e+20f,
157 1.78831e+21f,
158 9.20914e+21f,
159 8.35654e+23f,
160 1.4495e+24f,
161 5.94015e+25f,
162 4.43608e+30f,
163 2.44502e+33f,
164 2.61152e+33f,
165 1.38178e+37f,
166 1.71306e+37f,
167 3.31899e+38f,
168 3.40282e+38f,
169 std::numeric_limits<float>::infinity(),
170 std::numeric_limits<float>::quiet_NaN(),
171 -std::numeric_limits<float>::quiet_NaN()};
172
float32_vector()173 static constexpr base::Vector<const float> float32_vector() {
174 return base::ArrayVector(float32_array);
175 }
176
177 static constexpr double float64_array[] = {
178 -2e66,
179 -2.220446049250313e-16,
180 -9223373136366403584.0,
181 -9223372036854775808.0, // INT64_MIN
182 -2147483649.5,
183 -2147483648.25,
184 -2147483648.0,
185 -2147483647.875,
186 -2147483647.125,
187 -2147483647.0,
188 -999.75,
189 -2e66,
190 -1.75,
191 -1.5707963267948966,
192 -1.0,
193 -0.5,
194 -0.0,
195 0.0,
196 3e-88,
197 0.125,
198 0.25,
199 0.375,
200 0.5,
201 1.0,
202 1.17549e-38,
203 1.56657e-37,
204 1.0000001,
205 1.25,
206 1.5707963267948966,
207 2,
208 3.1e7,
209 5.125,
210 6.25,
211 888,
212 982983.25,
213 2147483647.0,
214 2147483647.375,
215 2147483647.75,
216 2147483648.0,
217 2147483648.25,
218 2147483649.25,
219 9223372036854775808.0, // INT64_MAX + 1
220 9223373136366403584.0,
221 18446744073709551616.0, // UINT64_MAX + 1
222 2e66,
223 V8_INFINITY,
224 -V8_INFINITY,
225 std::numeric_limits<double>::quiet_NaN(),
226 -std::numeric_limits<double>::quiet_NaN()};
227
float64_vector()228 static constexpr base::Vector<const double> float64_vector() {
229 return base::ArrayVector(float64_array);
230 }
231
232 static constexpr uint32_t uint32_array[] = {
233 0x00000000, 0x00000001, 0xFFFFFFFF, 0x1B09788B, 0x04C5FCE8, 0xCC0DE5BF,
234 // This row is useful for testing lea optimizations on intel.
235 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009,
236 0x273A798E, 0x187937A3, 0xECE3AF83, 0x5495A16B, 0x0B668ECC, 0x11223344,
237 0x0000009E, 0x00000043, 0x0000AF73, 0x0000116B, 0x00658ECC, 0x002B3B4C,
238 0x88776655, 0x70000000, 0x07200000, 0x7FFFFFFF, 0x56123761, 0x7FFFFF00,
239 0x761C4761, 0x80000000, 0x88888888, 0xA0000000, 0xDDDDDDDD, 0xE0000000,
240 0xEEEEEEEE, 0xFFFFFFFD, 0xF0000000, 0x007FFFFF, 0x003FFFFF, 0x001FFFFF,
241 0x000FFFFF, 0x0007FFFF, 0x0003FFFF, 0x0001FFFF, 0x0000FFFF, 0x00007FFF,
242 0x00003FFF, 0x00001FFF, 0x00000FFF, 0x000007FF, 0x000003FF, 0x000001FF,
243 // Bit pattern of a quiet NaN and signaling NaN, with or without
244 // additional payload.
245 0x7FC00000, 0x7F800000, 0x7FFFFFFF, 0x7F876543};
246
uint32_vector()247 static constexpr base::Vector<const uint32_t> uint32_vector() {
248 return base::ArrayVector(uint32_array);
249 }
250
int32_vector()251 static base::Vector<const int32_t> int32_vector() {
252 return base::Vector<const int32_t>::cast(uint32_vector());
253 }
254
255 static constexpr uint64_t uint64_array[] = {
256 0x00000000, 0x00000001, 0xFFFFFFFF, 0x1B09788B, 0x04C5FCE8, 0xCC0DE5BF,
257 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000008, 0x00000009,
258 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFD,
259 0x0000000000000000, 0x0000000100000000, 0xFFFFFFFF00000000,
260 0x1B09788B00000000, 0x04C5FCE800000000, 0xCC0DE5BF00000000,
261 0x0000000200000000, 0x0000000300000000, 0x0000000400000000,
262 0x0000000500000000, 0x0000000800000000, 0x0000000900000000,
263 0x273A798E187937A3, 0xECE3AF835495A16B, 0x0B668ECC11223344, 0x0000009E,
264 0x00000043, 0x0000AF73, 0x0000116B, 0x00658ECC, 0x002B3B4C, 0x88776655,
265 0x70000000, 0x07200000, 0x7FFFFFFF, 0x56123761, 0x7FFFFF00,
266 0x761C4761EEEEEEEE, 0x80000000EEEEEEEE, 0x88888888DDDDDDDD,
267 0xA0000000DDDDDDDD, 0xDDDDDDDDAAAAAAAA, 0xE0000000AAAAAAAA,
268 0xEEEEEEEEEEEEEEEE, 0xFFFFFFFDEEEEEEEE, 0xF0000000DDDDDDDD,
269 0x007FFFFFDDDDDDDD, 0x003FFFFFAAAAAAAA, 0x001FFFFFAAAAAAAA, 0x000FFFFF,
270 0x0007FFFF, 0x0003FFFF, 0x0001FFFF, 0x0000FFFF, 0x00007FFF, 0x00003FFF,
271 0x00001FFF, 0x00000FFF, 0x000007FF, 0x000003FF, 0x000001FF,
272 0x00003FFFFFFFFFFF, 0x00001FFFFFFFFFFF, 0x00000FFFFFFFFFFF,
273 0x000007FFFFFFFFFF, 0x000003FFFFFFFFFF, 0x000001FFFFFFFFFF,
274 0x8000008000000000, 0x8000008000000001, 0x8000000000000400,
275 0x8000000000000401, 0x0000000000000020,
276 0x8000000000000000, // int64_t min
277 0x7FFFFFFFFFFFFFFF, // int64_t max
278 // Bit pattern of a quiet NaN and signaling NaN, with or without
279 // additional payload.
280 0x7FF8000000000000, 0x7FF0000000000000, 0x7FF8123456789ABC,
281 0x7FF7654321FEDCBA};
282
uint64_vector()283 static constexpr base::Vector<const uint64_t> uint64_vector() {
284 return base::ArrayVector(uint64_array);
285 }
286
int64_vector()287 static base::Vector<const int64_t> int64_vector() {
288 return base::Vector<const int64_t>::cast(uint64_vector());
289 }
290
291 static constexpr int16_t int16_array[] = {
292 0, 1, 2, INT16_MAX - 1, INT16_MAX, INT16_MIN, INT16_MIN + 1, -2, -1};
293
int16_vector()294 static constexpr base::Vector<const int16_t> int16_vector() {
295 return base::ArrayVector(int16_array);
296 }
297
uint16_vector()298 static base::Vector<const uint16_t> uint16_vector() {
299 return base::Vector<const uint16_t>::cast(int16_vector());
300 }
301
302 static constexpr int8_t int8_array[] = {
303 0, 1, 2, INT8_MAX - 1, INT8_MAX, INT8_MIN, INT8_MIN + 1, -2, -1};
304
int8_vector()305 static constexpr base::Vector<const int8_t> int8_vector() {
306 return base::ArrayVector(int8_array);
307 }
308
uint8_vector()309 static base::Vector<const uint8_t> uint8_vector() {
310 return base::Vector<const uint8_t>::cast(base::ArrayVector(int8_array));
311 }
312
313 static constexpr uint32_t ror_array[31] = {
314 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
315 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
316
ror_vector()317 static constexpr base::Vector<const uint32_t> ror_vector() {
318 return base::ArrayVector(ror_array);
319 }
320
321 template <typename T>
322 static inline base::Vector<const T> GetVector();
323 };
324
325 template <>
GetVector()326 inline base::Vector<const int8_t> ValueHelper::GetVector() {
327 return int8_vector();
328 }
329
330 template <>
GetVector()331 inline base::Vector<const uint8_t> ValueHelper::GetVector() {
332 return uint8_vector();
333 }
334
335 template <>
GetVector()336 inline base::Vector<const int16_t> ValueHelper::GetVector() {
337 return int16_vector();
338 }
339
340 template <>
GetVector()341 inline base::Vector<const uint16_t> ValueHelper::GetVector() {
342 return uint16_vector();
343 }
344
345 template <>
GetVector()346 inline base::Vector<const int32_t> ValueHelper::GetVector() {
347 return int32_vector();
348 }
349
350 template <>
GetVector()351 inline base::Vector<const uint32_t> ValueHelper::GetVector() {
352 return uint32_vector();
353 }
354
355 template <>
GetVector()356 inline base::Vector<const int64_t> ValueHelper::GetVector() {
357 return int64_vector();
358 }
359
360 template <>
GetVector()361 inline base::Vector<const float> ValueHelper::GetVector() {
362 return float32_vector();
363 }
364
365 template <>
GetVector()366 inline base::Vector<const double> ValueHelper::GetVector() {
367 return float64_vector();
368 }
369
370 // Helper macros that can be used in FOR_INT32_INPUTS(i) { ... i ... }
371 #define FOR_INPUTS(ctype, itype, var) \
372 for (ctype var : ::v8::internal::compiler::ValueHelper::itype##_vector())
373
374 #define FOR_INT32_INPUTS(var) FOR_INPUTS(int32_t, int32, var)
375 #define FOR_UINT32_INPUTS(var) FOR_INPUTS(uint32_t, uint32, var)
376 #define FOR_INT16_INPUTS(var) FOR_INPUTS(int16_t, int16, var)
377 #define FOR_UINT16_INPUTS(var) FOR_INPUTS(uint16_t, uint16, var)
378 #define FOR_INT8_INPUTS(var) FOR_INPUTS(int8_t, int8, var)
379 #define FOR_UINT8_INPUTS(var) FOR_INPUTS(uint8_t, uint8, var)
380 #define FOR_INT64_INPUTS(var) FOR_INPUTS(int64_t, int64, var)
381 #define FOR_UINT64_INPUTS(var) FOR_INPUTS(uint64_t, uint64, var)
382 #define FOR_FLOAT32_INPUTS(var) FOR_INPUTS(float, float32, var)
383 #define FOR_FLOAT64_INPUTS(var) FOR_INPUTS(double, float64, var)
384
385 #define FOR_INT32_SHIFTS(var) for (int32_t var = 0; var < 32; var++)
386
387 #define FOR_UINT32_SHIFTS(var) for (uint32_t var = 0; var < 32; var++)
388
389 template <typename type>
390 struct FloatCompareWrapper {
391 type value;
FloatCompareWrapperFloatCompareWrapper392 explicit FloatCompareWrapper(type x) : value(x) {}
393 bool operator==(FloatCompareWrapper<type> const& other) const {
394 return std::isnan(value)
395 ? std::isnan(other.value)
396 : value == other.value &&
397 std::signbit(value) == std::signbit(other.value);
398 }
399 };
400
401 template <typename type>
402 std::ostream& operator<<(std::ostream& out, FloatCompareWrapper<type> wrapper) {
403 uint8_t bytes[sizeof(type)];
404 memcpy(bytes, &wrapper.value, sizeof(type));
405 out << wrapper.value << " (0x";
406 const char* kHexDigits = "0123456789ABCDEF";
407 for (unsigned i = 0; i < sizeof(type); ++i) {
408 out << kHexDigits[bytes[i] >> 4] << kHexDigits[bytes[i] & 15];
409 }
410 return out << ")";
411 }
412
413 #define CHECK_FLOAT_EQ(lhs, rhs) \
414 do { \
415 using FloatWrapper = ::v8::internal::compiler::FloatCompareWrapper<float>; \
416 CHECK_EQ(FloatWrapper(lhs), FloatWrapper(rhs)); \
417 } while (false)
418
419 #define CHECK_DOUBLE_EQ(lhs, rhs) \
420 do { \
421 using DoubleWrapper = \
422 ::v8::internal::compiler::FloatCompareWrapper<double>; \
423 CHECK_EQ(DoubleWrapper(lhs), DoubleWrapper(rhs)); \
424 } while (false)
425
426 } // namespace compiler
427 } // namespace internal
428 } // namespace v8
429
430 #endif // V8_CCTEST_COMPILER_VALUE_HELPER_H_
431