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.
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.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"
23 class SimplifiedOperatorReducerTest : public TypedGraphTest {
25 explicit SimplifiedOperatorReducerTest(int num_parameters = 1)
26 : TypedGraphTest(num_parameters), simplified_(zone()) {}
27 ~SimplifiedOperatorReducerTest() OVERRIDE {}
30 Reduction Reduce(Node* node) {
31 MachineOperatorBuilder machine(zone());
32 JSOperatorBuilder javascript(zone());
33 JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine);
34 SimplifiedOperatorReducer reducer(&jsgraph);
35 return reducer.Reduce(node);
38 SimplifiedOperatorBuilder* simplified() { return &simplified_; }
41 SimplifiedOperatorBuilder simplified_;
46 class SimplifiedOperatorReducerTestWithParam
47 : public SimplifiedOperatorReducerTest,
48 public ::testing::WithParamInterface<T> {
50 explicit SimplifiedOperatorReducerTestWithParam(int num_parameters = 1)
51 : SimplifiedOperatorReducerTest(num_parameters) {}
52 ~SimplifiedOperatorReducerTestWithParam() OVERRIDE {}
58 const double kFloat64Values[] = {
59 -V8_INFINITY, -6.52696e+290, -1.05768e+290, -5.34203e+268, -1.01997e+268,
60 -8.22758e+266, -1.58402e+261, -5.15246e+241, -5.92107e+226, -1.21477e+226,
61 -1.67913e+188, -1.6257e+184, -2.60043e+170, -2.52941e+168, -3.06033e+116,
62 -4.56201e+52, -3.56788e+50, -9.9066e+38, -3.07261e+31, -2.1271e+09,
63 -1.91489e+09, -1.73053e+09, -9.30675e+08, -26030, -20453, -15790, -11699,
64 -111, -97, -78, -63, -58, -1.53858e-06, -2.98914e-12, -1.14741e-39,
65 -8.20347e-57, -1.48932e-59, -3.17692e-66, -8.93103e-81, -3.91337e-83,
66 -6.0489e-92, -8.83291e-113, -4.28266e-117, -1.92058e-178, -2.0567e-192,
67 -1.68167e-194, -1.51841e-214, -3.98738e-234, -7.31851e-242, -2.21875e-253,
68 -1.11612e-293, -0.0, 0.0, 2.22507e-308, 1.06526e-307, 4.16643e-227,
69 6.76624e-223, 2.0432e-197, 3.16254e-184, 1.37315e-173, 2.88603e-172,
70 1.54155e-99, 4.42923e-81, 1.40539e-73, 5.4462e-73, 1.24064e-58, 3.11167e-58,
71 2.75826e-39, 0.143815, 58, 67, 601, 7941, 11644, 13697, 25680, 29882,
72 1.32165e+08, 1.62439e+08, 4.16837e+08, 9.59097e+08, 1.32491e+09, 1.8728e+09,
73 1.0672e+17, 2.69606e+46, 1.98285e+79, 1.0098e+82, 7.93064e+88, 3.67444e+121,
74 9.36506e+123, 7.27954e+162, 3.05316e+168, 1.16171e+175, 1.64771e+189,
75 1.1622e+202, 2.00748e+239, 2.51778e+244, 3.90282e+306, 1.79769e+308,
79 const int32_t kInt32Values[] = {
80 -2147483647 - 1, -2104508227, -2103151830, -1435284490, -1378926425,
81 -1318814539, -1289388009, -1287537572, -1279026536, -1241605942,
82 -1226046939, -941837148, -779818051, -413830641, -245798087, -184657557,
83 -127145950, -105483328, -32325, -26653, -23858, -23834, -22363, -19858,
84 -19044, -18744, -15528, -5309, -3372, -2093, -104, -98, -97, -93, -84, -80,
85 -78, -76, -72, -58, -57, -56, -55, -45, -40, -34, -32, -25, -24, -5, -2, 0,
86 3, 10, 24, 34, 42, 46, 47, 48, 52, 56, 64, 65, 71, 76, 79, 81, 82, 97, 102,
87 103, 104, 106, 107, 109, 116, 122, 3653, 4485, 12405, 16504, 26262, 28704,
88 29755, 30554, 16476817, 605431957, 832401070, 873617242, 914205764,
89 1062628108, 1087581664, 1488498068, 1534668023, 1661587028, 1696896187,
90 1866841746, 2032089723, 2147483647};
93 const uint32_t kUint32Values[] = {
94 0x0, 0x5, 0x8, 0xc, 0xd, 0x26,
95 0x28, 0x29, 0x30, 0x34, 0x3e, 0x42,
96 0x50, 0x5b, 0x63, 0x71, 0x77, 0x7c,
97 0x83, 0x88, 0x96, 0x9c, 0xa3, 0xfa,
98 0x7a7, 0x165d, 0x234d, 0x3acb, 0x43a5, 0x4573,
99 0x5b4f, 0x5f14, 0x6996, 0x6c6e, 0x7289, 0x7b9a,
100 0x7bc9, 0x86bb, 0xa839, 0xaa41, 0xb03b, 0xc942,
101 0xce68, 0xcf4c, 0xd3ad, 0xdea3, 0xe90c, 0xed86,
102 0xfba5, 0x172dcc6, 0x114d8fc1, 0x182d6c9d, 0x1b1e3fad, 0x1db033bf,
103 0x1e1de755, 0x1f625c80, 0x28f6cf00, 0x2acb6a94, 0x2c20240e, 0x2f0fe54e,
104 0x31863a7c, 0x33325474, 0x3532fae3, 0x3bab82ea, 0x4c4b83a2, 0x4cd93d1e,
105 0x4f7331d4, 0x5491b09b, 0x57cc6ff9, 0x60d3b4dc, 0x653f5904, 0x690ae256,
106 0x69fe3276, 0x6bebf0ba, 0x6e2c69a3, 0x73b84ff7, 0x7b3a1924, 0x7ed032d9,
107 0x84dd734b, 0x8552ea53, 0x8680754f, 0x8e9660eb, 0x94fe2b9c, 0x972d30cf,
108 0x9b98c482, 0xb158667e, 0xb432932c, 0xb5b70989, 0xb669971a, 0xb7c359d1,
109 0xbeb15c0d, 0xc171c53d, 0xc743dd38, 0xc8e2af50, 0xc98e2df0, 0xd9d1cdf9,
110 0xdcc91049, 0xe46f396d, 0xee991950, 0xef64e521, 0xf7aeefc9, 0xffffffff};
113 const double kNaNs[] = {-std::numeric_limits<double>::quiet_NaN(),
114 std::numeric_limits<double>::quiet_NaN(),
115 bit_cast<double>(V8_UINT64_C(0x7FFFFFFFFFFFFFFF)),
116 bit_cast<double>(V8_UINT64_C(0xFFFFFFFFFFFFFFFF))};
121 // -----------------------------------------------------------------------------
125 TEST_F(SimplifiedOperatorReducerTest, AnyToBooleanWithBoolean) {
126 Node* p = Parameter(Type::Boolean());
127 Reduction r = Reduce(graph()->NewNode(simplified()->AnyToBoolean(), p));
128 ASSERT_TRUE(r.Changed());
129 EXPECT_EQ(p, r.replacement());
133 TEST_F(SimplifiedOperatorReducerTest, AnyToBooleanWithOrderedNumber) {
134 Node* p = Parameter(Type::OrderedNumber());
135 Reduction r = Reduce(graph()->NewNode(simplified()->AnyToBoolean(), p));
136 ASSERT_TRUE(r.Changed());
137 EXPECT_THAT(r.replacement(),
138 IsBooleanNot(IsNumberEqual(p, IsNumberConstant(0))));
142 TEST_F(SimplifiedOperatorReducerTest, AnyToBooleanWithString) {
143 Node* p = Parameter(Type::String());
144 Reduction r = Reduce(graph()->NewNode(simplified()->AnyToBoolean(), p));
145 ASSERT_TRUE(r.Changed());
146 EXPECT_THAT(r.replacement(),
148 IsNumberEqual(IsLoadField(AccessBuilder::ForStringLength(), p,
149 graph()->start(), graph()->start()),
150 IsNumberConstant(0))));
154 // -----------------------------------------------------------------------------
158 TEST_F(SimplifiedOperatorReducerTest, BooleanNotWithBooleanNot) {
159 Node* param0 = Parameter(0);
160 Reduction reduction = Reduce(
161 graph()->NewNode(simplified()->BooleanNot(),
162 graph()->NewNode(simplified()->BooleanNot(), param0)));
163 ASSERT_TRUE(reduction.Changed());
164 EXPECT_EQ(param0, reduction.replacement());
168 TEST_F(SimplifiedOperatorReducerTest, BooleanNotWithFalseConstant) {
169 Reduction reduction0 =
170 Reduce(graph()->NewNode(simplified()->BooleanNot(), FalseConstant()));
171 ASSERT_TRUE(reduction0.Changed());
172 EXPECT_THAT(reduction0.replacement(), IsTrueConstant());
176 TEST_F(SimplifiedOperatorReducerTest, BooleanNotWithTrueConstant) {
177 Reduction reduction1 =
178 Reduce(graph()->NewNode(simplified()->BooleanNot(), TrueConstant()));
179 ASSERT_TRUE(reduction1.Changed());
180 EXPECT_THAT(reduction1.replacement(), IsFalseConstant());
184 // -----------------------------------------------------------------------------
188 TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithChangeBoolToBit) {
189 Node* param0 = Parameter(0);
190 Reduction reduction = Reduce(graph()->NewNode(
191 simplified()->ChangeBitToBool(),
192 graph()->NewNode(simplified()->ChangeBoolToBit(), param0)));
193 ASSERT_TRUE(reduction.Changed());
194 EXPECT_EQ(param0, reduction.replacement());
198 TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithZeroConstant) {
199 Reduction reduction = Reduce(
200 graph()->NewNode(simplified()->ChangeBitToBool(), Int32Constant(0)));
201 ASSERT_TRUE(reduction.Changed());
202 EXPECT_THAT(reduction.replacement(), IsFalseConstant());
206 TEST_F(SimplifiedOperatorReducerTest, ChangeBitToBoolWithOneConstant) {
207 Reduction reduction = Reduce(
208 graph()->NewNode(simplified()->ChangeBitToBool(), Int32Constant(1)));
209 ASSERT_TRUE(reduction.Changed());
210 EXPECT_THAT(reduction.replacement(), IsTrueConstant());
214 // -----------------------------------------------------------------------------
218 TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithFalseConstant) {
219 Reduction reduction = Reduce(
220 graph()->NewNode(simplified()->ChangeBoolToBit(), FalseConstant()));
221 ASSERT_TRUE(reduction.Changed());
222 EXPECT_THAT(reduction.replacement(), IsInt32Constant(0));
226 TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithTrueConstant) {
227 Reduction reduction =
228 Reduce(graph()->NewNode(simplified()->ChangeBoolToBit(), TrueConstant()));
229 ASSERT_TRUE(reduction.Changed());
230 EXPECT_THAT(reduction.replacement(), IsInt32Constant(1));
234 TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithChangeBitToBool) {
235 Node* param0 = Parameter(0);
236 Reduction reduction = Reduce(graph()->NewNode(
237 simplified()->ChangeBoolToBit(),
238 graph()->NewNode(simplified()->ChangeBitToBool(), param0)));
239 ASSERT_TRUE(reduction.Changed());
240 EXPECT_EQ(param0, reduction.replacement());
244 // -----------------------------------------------------------------------------
245 // ChangeFloat64ToTagged
248 TEST_F(SimplifiedOperatorReducerTest, ChangeFloat64ToTaggedWithConstant) {
249 TRACED_FOREACH(double, n, kFloat64Values) {
250 Reduction reduction = Reduce(graph()->NewNode(
251 simplified()->ChangeFloat64ToTagged(), Float64Constant(n)));
252 ASSERT_TRUE(reduction.Changed());
253 EXPECT_THAT(reduction.replacement(), IsNumberConstant(BitEq(n)));
258 // -----------------------------------------------------------------------------
259 // ChangeInt32ToTagged
262 TEST_F(SimplifiedOperatorReducerTest, ChangeInt32ToTaggedWithConstant) {
263 TRACED_FOREACH(int32_t, n, kInt32Values) {
264 Reduction reduction = Reduce(graph()->NewNode(
265 simplified()->ChangeInt32ToTagged(), Int32Constant(n)));
266 ASSERT_TRUE(reduction.Changed());
267 EXPECT_THAT(reduction.replacement(), IsNumberConstant(BitEq(FastI2D(n))));
272 // -----------------------------------------------------------------------------
273 // ChangeTaggedToFloat64
276 TEST_F(SimplifiedOperatorReducerTest,
277 ChangeTaggedToFloat64WithChangeFloat64ToTagged) {
278 Node* param0 = Parameter(0);
279 Reduction reduction = Reduce(graph()->NewNode(
280 simplified()->ChangeTaggedToFloat64(),
281 graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
282 ASSERT_TRUE(reduction.Changed());
283 EXPECT_EQ(param0, reduction.replacement());
287 TEST_F(SimplifiedOperatorReducerTest,
288 ChangeTaggedToFloat64WithChangeInt32ToTagged) {
289 Node* param0 = Parameter(0);
290 Reduction reduction = Reduce(graph()->NewNode(
291 simplified()->ChangeTaggedToFloat64(),
292 graph()->NewNode(simplified()->ChangeInt32ToTagged(), param0)));
293 ASSERT_TRUE(reduction.Changed());
294 EXPECT_THAT(reduction.replacement(), IsChangeInt32ToFloat64(param0));
298 TEST_F(SimplifiedOperatorReducerTest,
299 ChangeTaggedToFloat64WithChangeUint32ToTagged) {
300 Node* param0 = Parameter(0);
301 Reduction reduction = Reduce(graph()->NewNode(
302 simplified()->ChangeTaggedToFloat64(),
303 graph()->NewNode(simplified()->ChangeUint32ToTagged(), param0)));
304 ASSERT_TRUE(reduction.Changed());
305 EXPECT_THAT(reduction.replacement(), IsChangeUint32ToFloat64(param0));
309 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToFloat64WithConstant) {
310 TRACED_FOREACH(double, n, kFloat64Values) {
311 Reduction reduction = Reduce(graph()->NewNode(
312 simplified()->ChangeTaggedToFloat64(), NumberConstant(n)));
313 ASSERT_TRUE(reduction.Changed());
314 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(n)));
319 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToFloat64WithNaNConstant) {
320 TRACED_FOREACH(double, nan, kNaNs) {
321 Reduction reduction = Reduce(graph()->NewNode(
322 simplified()->ChangeTaggedToFloat64(), NumberConstant(nan)));
323 ASSERT_TRUE(reduction.Changed());
324 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(nan)));
329 // -----------------------------------------------------------------------------
330 // ChangeTaggedToInt32
333 TEST_F(SimplifiedOperatorReducerTest,
334 ChangeTaggedToInt32WithChangeFloat64ToTagged) {
335 Node* param0 = Parameter(0);
336 Reduction reduction = Reduce(graph()->NewNode(
337 simplified()->ChangeTaggedToInt32(),
338 graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
339 ASSERT_TRUE(reduction.Changed());
340 EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToInt32(param0));
344 TEST_F(SimplifiedOperatorReducerTest,
345 ChangeTaggedToInt32WithChangeInt32ToTagged) {
346 Node* param0 = Parameter(0);
347 Reduction reduction = Reduce(graph()->NewNode(
348 simplified()->ChangeTaggedToInt32(),
349 graph()->NewNode(simplified()->ChangeInt32ToTagged(), param0)));
350 ASSERT_TRUE(reduction.Changed());
351 EXPECT_EQ(param0, reduction.replacement());
355 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToInt32WithConstant) {
356 TRACED_FOREACH(double, n, kFloat64Values) {
357 Reduction reduction = Reduce(graph()->NewNode(
358 simplified()->ChangeTaggedToInt32(), NumberConstant(n)));
359 ASSERT_TRUE(reduction.Changed());
360 EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(n)));
365 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToInt32WithNaNConstant) {
366 TRACED_FOREACH(double, nan, kNaNs) {
367 Reduction reduction = Reduce(graph()->NewNode(
368 simplified()->ChangeTaggedToInt32(), NumberConstant(nan)));
369 ASSERT_TRUE(reduction.Changed());
370 EXPECT_THAT(reduction.replacement(), IsInt32Constant(0));
375 // -----------------------------------------------------------------------------
376 // ChangeTaggedToUint32
379 TEST_F(SimplifiedOperatorReducerTest,
380 ChangeTaggedToUint32WithChangeFloat64ToTagged) {
381 Node* param0 = Parameter(0);
382 Reduction reduction = Reduce(graph()->NewNode(
383 simplified()->ChangeTaggedToUint32(),
384 graph()->NewNode(simplified()->ChangeFloat64ToTagged(), param0)));
385 ASSERT_TRUE(reduction.Changed());
386 EXPECT_THAT(reduction.replacement(), IsChangeFloat64ToUint32(param0));
390 TEST_F(SimplifiedOperatorReducerTest,
391 ChangeTaggedToUint32WithChangeUint32ToTagged) {
392 Node* param0 = Parameter(0);
393 Reduction reduction = Reduce(graph()->NewNode(
394 simplified()->ChangeTaggedToUint32(),
395 graph()->NewNode(simplified()->ChangeUint32ToTagged(), param0)));
396 ASSERT_TRUE(reduction.Changed());
397 EXPECT_EQ(param0, reduction.replacement());
401 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToUint32WithConstant) {
402 TRACED_FOREACH(double, n, kFloat64Values) {
403 Reduction reduction = Reduce(graph()->NewNode(
404 simplified()->ChangeTaggedToUint32(), NumberConstant(n)));
405 ASSERT_TRUE(reduction.Changed());
406 EXPECT_THAT(reduction.replacement(),
407 IsInt32Constant(bit_cast<int32_t>(DoubleToUint32(n))));
412 TEST_F(SimplifiedOperatorReducerTest, ChangeTaggedToUint32WithNaNConstant) {
413 TRACED_FOREACH(double, nan, kNaNs) {
414 Reduction reduction = Reduce(graph()->NewNode(
415 simplified()->ChangeTaggedToUint32(), NumberConstant(nan)));
416 ASSERT_TRUE(reduction.Changed());
417 EXPECT_THAT(reduction.replacement(), IsInt32Constant(0));
422 // -----------------------------------------------------------------------------
423 // ChangeUint32ToTagged
426 TEST_F(SimplifiedOperatorReducerTest, ChangeUint32ToTagged) {
427 TRACED_FOREACH(uint32_t, n, kUint32Values) {
428 Reduction reduction =
429 Reduce(graph()->NewNode(simplified()->ChangeUint32ToTagged(),
430 Int32Constant(bit_cast<int32_t>(n))));
431 ASSERT_TRUE(reduction.Changed());
432 EXPECT_THAT(reduction.replacement(), IsNumberConstant(BitEq(FastUI2D(n))));
436 } // namespace compiler
437 } // namespace internal