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 #include "src/compiler/access-builder.h"
6 #include "src/compiler/js-graph.h"
7 #include "src/compiler/node-properties.h"
8 #include "src/compiler/simplified-operator.h"
9 #include "src/compiler/simplified-operator-reducer.h"
10 #include "src/conversions-inl.h"
11 #include "src/types.h"
12 #include "test/unittests/compiler/graph-unittest.h"
13 #include "test/unittests/compiler/node-test-utils.h"
14 #include "testing/gmock-support.h"
15
16 using testing::BitEq;
17
18
19 namespace v8 {
20 namespace internal {
21 namespace compiler {
22
23 class SimplifiedOperatorReducerTest : public TypedGraphTest {
24 public:
SimplifiedOperatorReducerTest(int num_parameters=1)25 explicit SimplifiedOperatorReducerTest(int num_parameters = 1)
26 : TypedGraphTest(num_parameters), simplified_(zone()) {}
~SimplifiedOperatorReducerTest()27 ~SimplifiedOperatorReducerTest() override {}
28
29 protected:
Reduce(Node * node)30 Reduction Reduce(Node* node) {
31 MachineOperatorBuilder machine(zone());
32 JSOperatorBuilder javascript(zone());
33 JSGraph jsgraph(isolate(), graph(), common(), &javascript, simplified(),
34 &machine);
35 SimplifiedOperatorReducer reducer(&jsgraph);
36 return reducer.Reduce(node);
37 }
38
simplified()39 SimplifiedOperatorBuilder* simplified() { return &simplified_; }
40
41 private:
42 SimplifiedOperatorBuilder simplified_;
43 };
44
45
46 template <typename T>
47 class SimplifiedOperatorReducerTestWithParam
48 : public SimplifiedOperatorReducerTest,
49 public ::testing::WithParamInterface<T> {
50 public:
SimplifiedOperatorReducerTestWithParam(int num_parameters=1)51 explicit SimplifiedOperatorReducerTestWithParam(int num_parameters = 1)
52 : SimplifiedOperatorReducerTest(num_parameters) {}
~SimplifiedOperatorReducerTestWithParam()53 ~SimplifiedOperatorReducerTestWithParam() override {}
54 };
55
56
57 namespace {
58
59 const double kFloat64Values[] = {
60 -V8_INFINITY, -6.52696e+290, -1.05768e+290, -5.34203e+268, -1.01997e+268,
61 -8.22758e+266, -1.58402e+261, -5.15246e+241, -5.92107e+226, -1.21477e+226,
62 -1.67913e+188, -1.6257e+184, -2.60043e+170, -2.52941e+168, -3.06033e+116,
63 -4.56201e+52, -3.56788e+50, -9.9066e+38, -3.07261e+31, -2.1271e+09,
64 -1.91489e+09, -1.73053e+09, -9.30675e+08, -26030, -20453, -15790, -11699,
65 -111, -97, -78, -63, -58, -1.53858e-06, -2.98914e-12, -1.14741e-39,
66 -8.20347e-57, -1.48932e-59, -3.17692e-66, -8.93103e-81, -3.91337e-83,
67 -6.0489e-92, -8.83291e-113, -4.28266e-117, -1.92058e-178, -2.0567e-192,
68 -1.68167e-194, -1.51841e-214, -3.98738e-234, -7.31851e-242, -2.21875e-253,
69 -1.11612e-293, -0.0, 0.0, 2.22507e-308, 1.06526e-307, 4.16643e-227,
70 6.76624e-223, 2.0432e-197, 3.16254e-184, 1.37315e-173, 2.88603e-172,
71 1.54155e-99, 4.42923e-81, 1.40539e-73, 5.4462e-73, 1.24064e-58, 3.11167e-58,
72 2.75826e-39, 0.143815, 58, 67, 601, 7941, 11644, 13697, 25680, 29882,
73 1.32165e+08, 1.62439e+08, 4.16837e+08, 9.59097e+08, 1.32491e+09, 1.8728e+09,
74 1.0672e+17, 2.69606e+46, 1.98285e+79, 1.0098e+82, 7.93064e+88, 3.67444e+121,
75 9.36506e+123, 7.27954e+162, 3.05316e+168, 1.16171e+175, 1.64771e+189,
76 1.1622e+202, 2.00748e+239, 2.51778e+244, 3.90282e+306, 1.79769e+308,
77 V8_INFINITY};
78
79
80 const int32_t kInt32Values[] = {
81 -2147483647 - 1, -2104508227, -2103151830, -1435284490, -1378926425,
82 -1318814539, -1289388009, -1287537572, -1279026536, -1241605942,
83 -1226046939, -941837148, -779818051, -413830641, -245798087, -184657557,
84 -127145950, -105483328, -32325, -26653, -23858, -23834, -22363, -19858,
85 -19044, -18744, -15528, -5309, -3372, -2093, -104, -98, -97, -93, -84, -80,
86 -78, -76, -72, -58, -57, -56, -55, -45, -40, -34, -32, -25, -24, -5, -2, 0,
87 3, 10, 24, 34, 42, 46, 47, 48, 52, 56, 64, 65, 71, 76, 79, 81, 82, 97, 102,
88 103, 104, 106, 107, 109, 116, 122, 3653, 4485, 12405, 16504, 26262, 28704,
89 29755, 30554, 16476817, 605431957, 832401070, 873617242, 914205764,
90 1062628108, 1087581664, 1488498068, 1534668023, 1661587028, 1696896187,
91 1866841746, 2032089723, 2147483647};
92
93
94 const uint32_t kUint32Values[] = {
95 0x0, 0x5, 0x8, 0xc, 0xd, 0x26,
96 0x28, 0x29, 0x30, 0x34, 0x3e, 0x42,
97 0x50, 0x5b, 0x63, 0x71, 0x77, 0x7c,
98 0x83, 0x88, 0x96, 0x9c, 0xa3, 0xfa,
99 0x7a7, 0x165d, 0x234d, 0x3acb, 0x43a5, 0x4573,
100 0x5b4f, 0x5f14, 0x6996, 0x6c6e, 0x7289, 0x7b9a,
101 0x7bc9, 0x86bb, 0xa839, 0xaa41, 0xb03b, 0xc942,
102 0xce68, 0xcf4c, 0xd3ad, 0xdea3, 0xe90c, 0xed86,
103 0xfba5, 0x172dcc6, 0x114d8fc1, 0x182d6c9d, 0x1b1e3fad, 0x1db033bf,
104 0x1e1de755, 0x1f625c80, 0x28f6cf00, 0x2acb6a94, 0x2c20240e, 0x2f0fe54e,
105 0x31863a7c, 0x33325474, 0x3532fae3, 0x3bab82ea, 0x4c4b83a2, 0x4cd93d1e,
106 0x4f7331d4, 0x5491b09b, 0x57cc6ff9, 0x60d3b4dc, 0x653f5904, 0x690ae256,
107 0x69fe3276, 0x6bebf0ba, 0x6e2c69a3, 0x73b84ff7, 0x7b3a1924, 0x7ed032d9,
108 0x84dd734b, 0x8552ea53, 0x8680754f, 0x8e9660eb, 0x94fe2b9c, 0x972d30cf,
109 0x9b98c482, 0xb158667e, 0xb432932c, 0xb5b70989, 0xb669971a, 0xb7c359d1,
110 0xbeb15c0d, 0xc171c53d, 0xc743dd38, 0xc8e2af50, 0xc98e2df0, 0xd9d1cdf9,
111 0xdcc91049, 0xe46f396d, 0xee991950, 0xef64e521, 0xf7aeefc9, 0xffffffff};
112
113
114 const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
115 std::numeric_limits<double>::quiet_NaN(),
116 bit_cast<double>(V8_UINT64_C(0x7FFFFFFFFFFFFFFF)),
117 bit_cast<double>(V8_UINT64_C(0xFFFFFFFFFFFFFFFF))};
118
119 } // namespace
120
121
122 // -----------------------------------------------------------------------------
123 // BooleanNot
124
125
TEST_F(SimplifiedOperatorReducerTest,BooleanNotWithBooleanNot)126 TEST_F(SimplifiedOperatorReducerTest, BooleanNotWithBooleanNot) {
127 Node* param0 = Parameter(0);
128 Reduction reduction = Reduce(
129 graph()->NewNode(simplified()->BooleanNot(),
130 graph()->NewNode(simplified()->BooleanNot(), param0)));
131 ASSERT_TRUE(reduction.Changed());
132 EXPECT_EQ(param0, reduction.replacement());
133 }
134
135
TEST_F(SimplifiedOperatorReducerTest,BooleanNotWithFalseConstant)136 TEST_F(SimplifiedOperatorReducerTest, BooleanNotWithFalseConstant) {
137 Reduction reduction0 =
138 Reduce(graph()->NewNode(simplified()->BooleanNot(), FalseConstant()));
139 ASSERT_TRUE(reduction0.Changed());
140 EXPECT_THAT(reduction0.replacement(), IsTrueConstant());
141 }
142
143
TEST_F(SimplifiedOperatorReducerTest,BooleanNotWithTrueConstant)144 TEST_F(SimplifiedOperatorReducerTest, BooleanNotWithTrueConstant) {
145 Reduction reduction1 =
146 Reduce(graph()->NewNode(simplified()->BooleanNot(), TrueConstant()));
147 ASSERT_TRUE(reduction1.Changed());
148 EXPECT_THAT(reduction1.replacement(), IsFalseConstant());
149 }
150
151
152 // -----------------------------------------------------------------------------
153 // ChangeBoolToBit
154
155
TEST_F(SimplifiedOperatorReducerTest,ChangeBitToBoolWithChangeBoolToBit)156 TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithChangeBoolToBit) {
157 Node* param0 = Parameter(0);
158 Reduction reduction = Reduce(graph()->NewNode(
159 simplified()->ChangeBitToBool(),
160 graph()->NewNode(simplified()->ChangeBoolToBit(), param0)));
161 ASSERT_TRUE(reduction.Changed());
162 EXPECT_EQ(param0, reduction.replacement());
163 }
164
165
TEST_F(SimplifiedOperatorReducerTest,ChangeBitToBoolWithZeroConstant)166 TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithZeroConstant) {
167 Reduction reduction = Reduce(
168 graph()->NewNode(simplified()->ChangeBitToBool(), Int32Constant(0)));
169 ASSERT_TRUE(reduction.Changed());
170 EXPECT_THAT(reduction.replacement(), IsFalseConstant());
171 }
172
173
TEST_F(SimplifiedOperatorReducerTest,ChangeBitToBoolWithOneConstant)174 TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithOneConstant) {
175 Reduction reduction = Reduce(
176 graph()->NewNode(simplified()->ChangeBitToBool(), Int32Constant(1)));
177 ASSERT_TRUE(reduction.Changed());
178 EXPECT_THAT(reduction.replacement(), IsTrueConstant());
179 }
180
181
182 // -----------------------------------------------------------------------------
183 // ChangeBoolToBit
184
185
TEST_F(SimplifiedOperatorReducerTest,ChangeBoolToBitWithFalseConstant)186 TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithFalseConstant) {
187 Reduction reduction = Reduce(
188 graph()->NewNode(simplified()->ChangeBoolToBit(), FalseConstant()));
189 ASSERT_TRUE(reduction.Changed());
190 EXPECT_THAT(reduction.replacement(), IsInt32Constant(0));
191 }
192
193
TEST_F(SimplifiedOperatorReducerTest,ChangeBoolToBitWithTrueConstant)194 TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithTrueConstant) {
195 Reduction reduction =
196 Reduce(graph()->NewNode(simplified()->ChangeBoolToBit(), TrueConstant()));
197 ASSERT_TRUE(reduction.Changed());
198 EXPECT_THAT(reduction.replacement(), IsInt32Constant(1));
199 }
200
201
TEST_F(SimplifiedOperatorReducerTest,ChangeBoolToBitWithChangeBitToBool)202 TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithChangeBitToBool) {
203 Node* param0 = Parameter(0);
204 Reduction reduction = Reduce(graph()->NewNode(
205 simplified()->ChangeBoolToBit(),
206 graph()->NewNode(simplified()->ChangeBitToBool(), param0)));
207 ASSERT_TRUE(reduction.Changed());
208 EXPECT_EQ(param0, reduction.replacement());
209 }
210
211
212 // -----------------------------------------------------------------------------
213 // ChangeFloat64ToTagged
214
215
TEST_F(SimplifiedOperatorReducerTest,ChangeFloat64ToTaggedWithConstant)216 TEST_F(SimplifiedOperatorReducerTest, ChangeFloat64ToTaggedWithConstant) {
217 TRACED_FOREACH(double, n, kFloat64Values) {
218 Reduction reduction = Reduce(graph()->NewNode(
219 simplified()->ChangeFloat64ToTagged(), Float64Constant(n)));
220 ASSERT_TRUE(reduction.Changed());
221 EXPECT_THAT(reduction.replacement(), IsNumberConstant(BitEq(n)));
222 }
223 }
224
225
226 // -----------------------------------------------------------------------------
227 // ChangeInt32ToTagged
228
229
TEST_F(SimplifiedOperatorReducerTest,ChangeInt32ToTaggedWithConstant)230 TEST_F(SimplifiedOperatorReducerTest, ChangeInt32ToTaggedWithConstant) {
231 TRACED_FOREACH(int32_t, n, kInt32Values) {
232 Reduction reduction = Reduce(graph()->NewNode(
233 simplified()->ChangeInt32ToTagged(), Int32Constant(n)));
234 ASSERT_TRUE(reduction.Changed());
235 EXPECT_THAT(reduction.replacement(), IsNumberConstant(BitEq(FastI2D(n))));
236 }
237 }
238
239
240 // -----------------------------------------------------------------------------
241 // ChangeTaggedToFloat64
242
243
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToFloat64WithChangeFloat64ToTagged)244 TEST_F(SimplifiedOperatorReducerTest,
245 ChangeTaggedToFloat64WithChangeFloat64ToTagged) {
246 Node* param0 = Parameter(0);
247 Reduction reduction = Reduce(graph()->NewNode(
248 simplified()->ChangeTaggedToFloat64(),
249 graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
250 ASSERT_TRUE(reduction.Changed());
251 EXPECT_EQ(param0, reduction.replacement());
252 }
253
254
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToFloat64WithChangeInt32ToTagged)255 TEST_F(SimplifiedOperatorReducerTest,
256 ChangeTaggedToFloat64WithChangeInt32ToTagged) {
257 Node* param0 = Parameter(0);
258 Reduction reduction = Reduce(graph()->NewNode(
259 simplified()->ChangeTaggedToFloat64(),
260 graph()->NewNode(simplified()->ChangeInt32ToTagged(), param0)));
261 ASSERT_TRUE(reduction.Changed());
262 EXPECT_THAT(reduction.replacement(), IsChangeInt32ToFloat64(param0));
263 }
264
265
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToFloat64WithChangeUint32ToTagged)266 TEST_F(SimplifiedOperatorReducerTest,
267 ChangeTaggedToFloat64WithChangeUint32ToTagged) {
268 Node* param0 = Parameter(0);
269 Reduction reduction = Reduce(graph()->NewNode(
270 simplified()->ChangeTaggedToFloat64(),
271 graph()->NewNode(simplified()->ChangeUint32ToTagged(), param0)));
272 ASSERT_TRUE(reduction.Changed());
273 EXPECT_THAT(reduction.replacement(), IsChangeUint32ToFloat64(param0));
274 }
275
276
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToFloat64WithConstant)277 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToFloat64WithConstant) {
278 TRACED_FOREACH(double, n, kFloat64Values) {
279 Reduction reduction = Reduce(graph()->NewNode(
280 simplified()->ChangeTaggedToFloat64(), NumberConstant(n)));
281 ASSERT_TRUE(reduction.Changed());
282 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(n)));
283 }
284 }
285
286
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToFloat64WithNaNConstant)287 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToFloat64WithNaNConstant) {
288 TRACED_FOREACH(double, nan, kNaNs) {
289 Reduction reduction = Reduce(graph()->NewNode(
290 simplified()->ChangeTaggedToFloat64(), NumberConstant(nan)));
291 ASSERT_TRUE(reduction.Changed());
292 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(nan)));
293 }
294 }
295
296
297 // -----------------------------------------------------------------------------
298 // ChangeTaggedToInt32
299
300
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToInt32WithChangeFloat64ToTagged)301 TEST_F(SimplifiedOperatorReducerTest,
302 ChangeTaggedToInt32WithChangeFloat64ToTagged) {
303 Node* param0 = Parameter(0);
304 Reduction reduction = Reduce(graph()->NewNode(
305 simplified()->ChangeTaggedToInt32(),
306 graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
307 ASSERT_TRUE(reduction.Changed());
308 EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToInt32(param0));
309 }
310
311
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToInt32WithChangeInt32ToTagged)312 TEST_F(SimplifiedOperatorReducerTest,
313 ChangeTaggedToInt32WithChangeInt32ToTagged) {
314 Node* param0 = Parameter(0);
315 Reduction reduction = Reduce(graph()->NewNode(
316 simplified()->ChangeTaggedToInt32(),
317 graph()->NewNode(simplified()->ChangeInt32ToTagged(), param0)));
318 ASSERT_TRUE(reduction.Changed());
319 EXPECT_EQ(param0, reduction.replacement());
320 }
321
322
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToInt32WithConstant)323 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToInt32WithConstant) {
324 TRACED_FOREACH(double, n, kFloat64Values) {
325 Reduction reduction = Reduce(graph()->NewNode(
326 simplified()->ChangeTaggedToInt32(), NumberConstant(n)));
327 ASSERT_TRUE(reduction.Changed());
328 EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(n)));
329 }
330 }
331
332
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToInt32WithNaNConstant)333 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToInt32WithNaNConstant) {
334 TRACED_FOREACH(double, nan, kNaNs) {
335 Reduction reduction = Reduce(graph()->NewNode(
336 simplified()->ChangeTaggedToInt32(), NumberConstant(nan)));
337 ASSERT_TRUE(reduction.Changed());
338 EXPECT_THAT(reduction.replacement(), IsInt32Constant(0));
339 }
340 }
341
342
343 // -----------------------------------------------------------------------------
344 // ChangeTaggedToUint32
345
346
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToUint32WithChangeFloat64ToTagged)347 TEST_F(SimplifiedOperatorReducerTest,
348 ChangeTaggedToUint32WithChangeFloat64ToTagged) {
349 Node* param0 = Parameter(0);
350 Reduction reduction = Reduce(graph()->NewNode(
351 simplified()->ChangeTaggedToUint32(),
352 graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
353 ASSERT_TRUE(reduction.Changed());
354 EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToUint32(param0));
355 }
356
357
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToUint32WithChangeUint32ToTagged)358 TEST_F(SimplifiedOperatorReducerTest,
359 ChangeTaggedToUint32WithChangeUint32ToTagged) {
360 Node* param0 = Parameter(0);
361 Reduction reduction = Reduce(graph()->NewNode(
362 simplified()->ChangeTaggedToUint32(),
363 graph()->NewNode(simplified()->ChangeUint32ToTagged(), param0)));
364 ASSERT_TRUE(reduction.Changed());
365 EXPECT_EQ(param0, reduction.replacement());
366 }
367
368
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToUint32WithConstant)369 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToUint32WithConstant) {
370 TRACED_FOREACH(double, n, kFloat64Values) {
371 Reduction reduction = Reduce(graph()->NewNode(
372 simplified()->ChangeTaggedToUint32(), NumberConstant(n)));
373 ASSERT_TRUE(reduction.Changed());
374 EXPECT_THAT(reduction.replacement(),
375 IsInt32Constant(bit_cast<int32_t>(DoubleToUint32(n))));
376 }
377 }
378
379
TEST_F(SimplifiedOperatorReducerTest,ChangeTaggedToUint32WithNaNConstant)380 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToUint32WithNaNConstant) {
381 TRACED_FOREACH(double, nan, kNaNs) {
382 Reduction reduction = Reduce(graph()->NewNode(
383 simplified()->ChangeTaggedToUint32(), NumberConstant(nan)));
384 ASSERT_TRUE(reduction.Changed());
385 EXPECT_THAT(reduction.replacement(), IsInt32Constant(0));
386 }
387 }
388
389
390 // -----------------------------------------------------------------------------
391 // ChangeUint32ToTagged
392
393
TEST_F(SimplifiedOperatorReducerTest,ChangeUint32ToTagged)394 TEST_F(SimplifiedOperatorReducerTest, ChangeUint32ToTagged) {
395 TRACED_FOREACH(uint32_t, n, kUint32Values) {
396 Reduction reduction =
397 Reduce(graph()->NewNode(simplified()->ChangeUint32ToTagged(),
398 Int32Constant(bit_cast<int32_t>(n))));
399 ASSERT_TRUE(reduction.Changed());
400 EXPECT_THAT(reduction.replacement(), IsNumberConstant(BitEq(FastUI2D(n))));
401 }
402 }
403
404 } // namespace compiler
405 } // namespace internal
406 } // namespace v8
407