f63e70da5a0e75ed8d106176f20d019f70c5e6b7
[platform/upstream/nodejs.git] / deps / v8 / test / unittests / compiler / machine-operator-reducer-unittest.cc
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/base/bits.h"
6 #include "src/base/division-by-constant.h"
7 #include "src/compiler/js-graph.h"
8 #include "src/compiler/machine-operator-reducer.h"
9 #include "src/compiler/typer.h"
10 #include "test/unittests/compiler/graph-unittest.h"
11 #include "test/unittests/compiler/node-test-utils.h"
12 #include "testing/gmock-support.h"
13
14 using testing::AllOf;
15 using testing::BitEq;
16 using testing::Capture;
17 using testing::CaptureEq;
18
19 namespace v8 {
20 namespace internal {
21 namespace compiler {
22
23 class MachineOperatorReducerTest : public TypedGraphTest {
24  public:
25   explicit MachineOperatorReducerTest(int num_parameters = 2)
26       : TypedGraphTest(num_parameters), machine_(zone()) {}
27
28  protected:
29   Reduction Reduce(Node* node) {
30     JSOperatorBuilder javascript(zone());
31     JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine_);
32     MachineOperatorReducer reducer(&jsgraph);
33     return reducer.Reduce(node);
34   }
35
36   Matcher<Node*> IsTruncatingDiv(const Matcher<Node*>& dividend_matcher,
37                                  const int32_t divisor) {
38     base::MagicNumbersForDivision<uint32_t> const mag =
39         base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
40     int32_t const multiplier = bit_cast<int32_t>(mag.multiplier);
41     int32_t const shift = bit_cast<int32_t>(mag.shift);
42     Matcher<Node*> quotient_matcher =
43         IsInt32MulHigh(dividend_matcher, IsInt32Constant(multiplier));
44     if (divisor > 0 && multiplier < 0) {
45       quotient_matcher = IsInt32Add(quotient_matcher, dividend_matcher);
46     } else if (divisor < 0 && multiplier > 0) {
47       quotient_matcher = IsInt32Sub(quotient_matcher, dividend_matcher);
48     }
49     if (shift) {
50       quotient_matcher = IsWord32Sar(quotient_matcher, IsInt32Constant(shift));
51     }
52     return IsInt32Add(quotient_matcher,
53                       IsWord32Shr(dividend_matcher, IsInt32Constant(31)));
54   }
55
56   MachineOperatorBuilder* machine() { return &machine_; }
57
58  private:
59   MachineOperatorBuilder machine_;
60 };
61
62
63 template <typename T>
64 class MachineOperatorReducerTestWithParam
65     : public MachineOperatorReducerTest,
66       public ::testing::WithParamInterface<T> {
67  public:
68   explicit MachineOperatorReducerTestWithParam(int num_parameters = 2)
69       : MachineOperatorReducerTest(num_parameters) {}
70   ~MachineOperatorReducerTestWithParam() OVERRIDE {}
71 };
72
73
74 namespace {
75
76 const float kFloat32Values[] = {
77     -std::numeric_limits<float>::infinity(), -2.70497e+38f, -1.4698e+37f,
78     -1.22813e+35f,                           -1.20555e+35f, -1.34584e+34f,
79     -1.0079e+32f,                            -6.49364e+26f, -3.06077e+25f,
80     -1.46821e+25f,                           -1.17658e+23f, -1.9617e+22f,
81     -2.7357e+20f,                            -1.48708e+13f, -1.89633e+12f,
82     -4.66622e+11f,                           -2.22581e+11f, -1.45381e+10f,
83     -1.3956e+09f,                            -1.32951e+09f, -1.30721e+09f,
84     -1.19756e+09f,                           -9.26822e+08f, -6.35647e+08f,
85     -4.00037e+08f,                           -1.81227e+08f, -5.09256e+07f,
86     -964300.0f,                              -192446.0f,    -28455.0f,
87     -27194.0f,                               -26401.0f,     -20575.0f,
88     -17069.0f,                               -9167.0f,      -960.178f,
89     -113.0f,                                 -62.0f,        -15.0f,
90     -7.0f,                                   -0.0256635f,   -4.60374e-07f,
91     -3.63759e-10f,                           -4.30175e-14f, -5.27385e-15f,
92     -1.48084e-15f,                           -1.05755e-19f, -3.2995e-21f,
93     -1.67354e-23f,                           -1.11885e-23f, -1.78506e-30f,
94     -5.07594e-31f,                           -3.65799e-31f, -1.43718e-34f,
95     -1.27126e-38f,                           -0.0f,         0.0f,
96     1.17549e-38f,                            1.56657e-37f,  4.08512e-29f,
97     3.31357e-28f,                            6.25073e-22f,  4.1723e-13f,
98     1.44343e-09f,                            5.27004e-08f,  9.48298e-08f,
99     5.57888e-07f,                            4.89988e-05f,  0.244326f,
100     12.4895f,                                19.0f,         47.0f,
101     106.0f,                                  538.324f,      564.536f,
102     819.124f,                                7048.0f,       12611.0f,
103     19878.0f,                                20309.0f,      797056.0f,
104     1.77219e+09f,                            1.51116e+11f,  4.18193e+13f,
105     3.59167e+16f,                            3.38211e+19f,  2.67488e+20f,
106     1.78831e+21f,                            9.20914e+21f,  8.35654e+23f,
107     1.4495e+24f,                             5.94015e+25f,  4.43608e+30f,
108     2.44502e+33f,                            2.61152e+33f,  1.38178e+37f,
109     1.71306e+37f,                            3.31899e+38f,  3.40282e+38f,
110     std::numeric_limits<float>::infinity()};
111
112
113 const double kFloat64Values[] = {
114     -V8_INFINITY,  -4.23878e+275, -5.82632e+265, -6.60355e+220, -6.26172e+212,
115     -2.56222e+211, -4.82408e+201, -1.84106e+157, -1.63662e+127, -1.55772e+100,
116     -1.67813e+72,  -2.3382e+55,   -3.179e+30,    -1.441e+09,    -1.0647e+09,
117     -7.99361e+08,  -5.77375e+08,  -2.20984e+08,  -32757,        -13171,
118     -9970,         -3984,         -107,          -105,          -92,
119     -77,           -61,           -0.000208163,  -1.86685e-06,  -1.17296e-10,
120     -9.26358e-11,  -5.08004e-60,  -1.74753e-65,  -1.06561e-71,  -5.67879e-79,
121     -5.78459e-130, -2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263,
122     -4.40497e-267, -2.19666e-273, -4.9998e-276,  -5.59821e-278, -2.03855e-282,
123     -5.99335e-283, -7.17554e-284, -3.11744e-309, -0.0,          0.0,
124     2.22507e-308,  1.30127e-270,  7.62898e-260,  4.00313e-249,  3.16829e-233,
125     1.85244e-228,  2.03544e-129,  1.35126e-110,  1.01182e-106,  5.26333e-94,
126     1.35292e-90,   2.85394e-83,   1.78323e-77,   5.4967e-57,    1.03207e-25,
127     4.57401e-25,   1.58738e-05,   2,             125,           2310,
128     9636,          14802,         17168,         28945,         29305,
129     4.81336e+07,   1.41207e+08,   4.65962e+08,   1.40499e+09,   2.12648e+09,
130     8.80006e+30,   1.4446e+45,    1.12164e+54,   2.48188e+89,   6.71121e+102,
131     3.074e+112,    4.9699e+152,   5.58383e+166,  4.30654e+172,  7.08824e+185,
132     9.6586e+214,   2.028e+223,    6.63277e+243,  1.56192e+261,  1.23202e+269,
133     5.72883e+289,  8.5798e+290,   1.40256e+294,  1.79769e+308,  V8_INFINITY};
134
135
136 const int32_t kInt32Values[] = {
137     std::numeric_limits<int32_t>::min(), -1914954528, -1698749618,
138     -1578693386,                         -1577976073, -1573998034,
139     -1529085059,                         -1499540537, -1299205097,
140     -1090814845,                         -938186388,  -806828902,
141     -750927650,                          -520676892,  -513661538,
142     -453036354,                          -433622833,  -282638793,
143     -28375,                              -27788,      -22770,
144     -18806,                              -14173,      -11956,
145     -11200,                              -10212,      -8160,
146     -3751,                               -2758,       -1522,
147     -121,                                -120,        -118,
148     -117,                                -106,        -84,
149     -80,                                 -74,         -59,
150     -52,                                 -48,         -39,
151     -35,                                 -17,         -11,
152     -10,                                 -9,          -7,
153     -5,                                  0,           9,
154     12,                                  17,          23,
155     29,                                  31,          33,
156     35,                                  40,          47,
157     55,                                  56,          62,
158     64,                                  67,          68,
159     69,                                  74,          79,
160     84,                                  89,          90,
161     97,                                  104,         118,
162     124,                                 126,         127,
163     7278,                                17787,       24136,
164     24202,                               25570,       26680,
165     30242,                               32399,       420886487,
166     642166225,                           821912648,   822577803,
167     851385718,                           1212241078,  1411419304,
168     1589626102,                          1596437184,  1876245816,
169     1954730266,                          2008792749,  2045320228,
170     std::numeric_limits<int32_t>::max()};
171
172
173 const int64_t kInt64Values[] = {
174     std::numeric_limits<int64_t>::min(), V8_INT64_C(-8974392461363618006),
175     V8_INT64_C(-8874367046689588135),    V8_INT64_C(-8269197512118230839),
176     V8_INT64_C(-8146091527100606733),    V8_INT64_C(-7550917981466150848),
177     V8_INT64_C(-7216590251577894337),    V8_INT64_C(-6464086891160048440),
178     V8_INT64_C(-6365616494908257190),    V8_INT64_C(-6305630541365849726),
179     V8_INT64_C(-5982222642272245453),    V8_INT64_C(-5510103099058504169),
180     V8_INT64_C(-5496838675802432701),    V8_INT64_C(-4047626578868642657),
181     V8_INT64_C(-4033755046900164544),    V8_INT64_C(-3554299241457877041),
182     V8_INT64_C(-2482258764588614470),    V8_INT64_C(-1688515425526875335),
183     V8_INT64_C(-924784137176548532),     V8_INT64_C(-725316567157391307),
184     V8_INT64_C(-439022654781092241),     V8_INT64_C(-105545757668917080),
185     V8_INT64_C(-2088319373),             V8_INT64_C(-2073699916),
186     V8_INT64_C(-1844949911),             V8_INT64_C(-1831090548),
187     V8_INT64_C(-1756711933),             V8_INT64_C(-1559409497),
188     V8_INT64_C(-1281179700),             V8_INT64_C(-1211513985),
189     V8_INT64_C(-1182371520),             V8_INT64_C(-785934753),
190     V8_INT64_C(-767480697),              V8_INT64_C(-705745662),
191     V8_INT64_C(-514362436),              V8_INT64_C(-459916580),
192     V8_INT64_C(-312328082),              V8_INT64_C(-302949707),
193     V8_INT64_C(-285499304),              V8_INT64_C(-125701262),
194     V8_INT64_C(-95139843),               V8_INT64_C(-32768),
195     V8_INT64_C(-27542),                  V8_INT64_C(-23600),
196     V8_INT64_C(-18582),                  V8_INT64_C(-17770),
197     V8_INT64_C(-9086),                   V8_INT64_C(-9010),
198     V8_INT64_C(-8244),                   V8_INT64_C(-2890),
199     V8_INT64_C(-103),                    V8_INT64_C(-34),
200     V8_INT64_C(-27),                     V8_INT64_C(-25),
201     V8_INT64_C(-9),                      V8_INT64_C(-7),
202     V8_INT64_C(0),                       V8_INT64_C(2),
203     V8_INT64_C(38),                      V8_INT64_C(58),
204     V8_INT64_C(65),                      V8_INT64_C(93),
205     V8_INT64_C(111),                     V8_INT64_C(1003),
206     V8_INT64_C(1267),                    V8_INT64_C(12797),
207     V8_INT64_C(23122),                   V8_INT64_C(28200),
208     V8_INT64_C(30888),                   V8_INT64_C(42648848),
209     V8_INT64_C(116836693),               V8_INT64_C(263003643),
210     V8_INT64_C(571039860),               V8_INT64_C(1079398689),
211     V8_INT64_C(1145196402),              V8_INT64_C(1184846321),
212     V8_INT64_C(1758281648),              V8_INT64_C(1859991374),
213     V8_INT64_C(1960251588),              V8_INT64_C(2042443199),
214     V8_INT64_C(296220586027987448),      V8_INT64_C(1015494173071134726),
215     V8_INT64_C(1151237951914455318),     V8_INT64_C(1331941174616854174),
216     V8_INT64_C(2022020418667972654),     V8_INT64_C(2450251424374977035),
217     V8_INT64_C(3668393562685561486),     V8_INT64_C(4858229301215502171),
218     V8_INT64_C(4919426235170669383),     V8_INT64_C(5034286595330341762),
219     V8_INT64_C(5055797915536941182),     V8_INT64_C(6072389716149252074),
220     V8_INT64_C(6185309910199801210),     V8_INT64_C(6297328311011094138),
221     V8_INT64_C(6932372858072165827),     V8_INT64_C(8483640924987737210),
222     V8_INT64_C(8663764179455849203),     V8_INT64_C(8877197042645298254),
223     V8_INT64_C(8901543506779157333),     std::numeric_limits<int64_t>::max()};
224
225
226 const uint32_t kUint32Values[] = {
227     0x00000000, 0x00000001, 0xffffffff, 0x1b09788b, 0x04c5fce8, 0xcc0de5bf,
228     0x273a798e, 0x187937a3, 0xece3af83, 0x5495a16b, 0x0b668ecc, 0x11223344,
229     0x0000009e, 0x00000043, 0x0000af73, 0x0000116b, 0x00658ecc, 0x002b3b4c,
230     0x88776655, 0x70000000, 0x07200000, 0x7fffffff, 0x56123761, 0x7fffff00,
231     0x761c4761, 0x80000000, 0x88888888, 0xa0000000, 0xdddddddd, 0xe0000000,
232     0xeeeeeeee, 0xfffffffd, 0xf0000000, 0x007fffff, 0x003fffff, 0x001fffff,
233     0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff,
234     0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
235
236 }  // namespace
237
238
239 // -----------------------------------------------------------------------------
240 // Unary operators
241
242
243 namespace {
244
245 struct UnaryOperator {
246   const Operator* (MachineOperatorBuilder::*constructor)();
247   const char* constructor_name;
248 };
249
250
251 std::ostream& operator<<(std::ostream& os, const UnaryOperator& unop) {
252   return os << unop.constructor_name;
253 }
254
255
256 static const UnaryOperator kUnaryOperators[] = {
257     {&MachineOperatorBuilder::ChangeInt32ToFloat64, "ChangeInt32ToFloat64"},
258     {&MachineOperatorBuilder::ChangeUint32ToFloat64, "ChangeUint32ToFloat64"},
259     {&MachineOperatorBuilder::ChangeFloat64ToInt32, "ChangeFloat64ToInt32"},
260     {&MachineOperatorBuilder::ChangeFloat64ToUint32, "ChangeFloat64ToUint32"},
261     {&MachineOperatorBuilder::ChangeInt32ToInt64, "ChangeInt32ToInt64"},
262     {&MachineOperatorBuilder::ChangeUint32ToUint64, "ChangeUint32ToUint64"},
263     {&MachineOperatorBuilder::TruncateFloat64ToInt32, "TruncateFloat64ToInt32"},
264     {&MachineOperatorBuilder::TruncateInt64ToInt32, "TruncateInt64ToInt32"}};
265
266 }  // namespace
267
268
269 typedef MachineOperatorReducerTestWithParam<UnaryOperator>
270     MachineUnaryOperatorReducerTest;
271
272
273 TEST_P(MachineUnaryOperatorReducerTest, Parameter) {
274   const UnaryOperator unop = GetParam();
275   Reduction reduction =
276       Reduce(graph()->NewNode((machine()->*unop.constructor)(), Parameter(0)));
277   EXPECT_FALSE(reduction.Changed());
278 }
279
280
281 INSTANTIATE_TEST_CASE_P(MachineOperatorReducerTest,
282                         MachineUnaryOperatorReducerTest,
283                         ::testing::ValuesIn(kUnaryOperators));
284
285
286 // -----------------------------------------------------------------------------
287 // ChangeFloat64ToFloat32
288
289
290 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToFloat32WithConstant) {
291   TRACED_FOREACH(float, x, kFloat32Values) {
292     Reduction reduction = Reduce(graph()->NewNode(
293         machine()->ChangeFloat32ToFloat64(), Float32Constant(x)));
294     ASSERT_TRUE(reduction.Changed());
295     EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq<double>(x)));
296   }
297 }
298
299
300 // -----------------------------------------------------------------------------
301 // ChangeFloat64ToInt32
302
303
304 TEST_F(MachineOperatorReducerTest,
305        ChangeFloat64ToInt32WithChangeInt32ToFloat64) {
306   Node* value = Parameter(0);
307   Reduction reduction = Reduce(graph()->NewNode(
308       machine()->ChangeFloat64ToInt32(),
309       graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
310   ASSERT_TRUE(reduction.Changed());
311   EXPECT_EQ(value, reduction.replacement());
312 }
313
314
315 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToInt32WithConstant) {
316   TRACED_FOREACH(int32_t, x, kInt32Values) {
317     Reduction reduction = Reduce(graph()->NewNode(
318         machine()->ChangeFloat64ToInt32(), Float64Constant(FastI2D(x))));
319     ASSERT_TRUE(reduction.Changed());
320     EXPECT_THAT(reduction.replacement(), IsInt32Constant(x));
321   }
322 }
323
324
325 // -----------------------------------------------------------------------------
326 // ChangeFloat64ToUint32
327
328
329 TEST_F(MachineOperatorReducerTest,
330        ChangeFloat64ToUint32WithChangeUint32ToFloat64) {
331   Node* value = Parameter(0);
332   Reduction reduction = Reduce(graph()->NewNode(
333       machine()->ChangeFloat64ToUint32(),
334       graph()->NewNode(machine()->ChangeUint32ToFloat64(), value)));
335   ASSERT_TRUE(reduction.Changed());
336   EXPECT_EQ(value, reduction.replacement());
337 }
338
339
340 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToUint32WithConstant) {
341   TRACED_FOREACH(uint32_t, x, kUint32Values) {
342     Reduction reduction = Reduce(graph()->NewNode(
343         machine()->ChangeFloat64ToUint32(), Float64Constant(FastUI2D(x))));
344     ASSERT_TRUE(reduction.Changed());
345     EXPECT_THAT(reduction.replacement(), IsInt32Constant(bit_cast<int32_t>(x)));
346   }
347 }
348
349
350 // -----------------------------------------------------------------------------
351 // ChangeInt32ToFloat64
352
353
354 TEST_F(MachineOperatorReducerTest, ChangeInt32ToFloat64WithConstant) {
355   TRACED_FOREACH(int32_t, x, kInt32Values) {
356     Reduction reduction = Reduce(
357         graph()->NewNode(machine()->ChangeInt32ToFloat64(), Int32Constant(x)));
358     ASSERT_TRUE(reduction.Changed());
359     EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastI2D(x))));
360   }
361 }
362
363
364 // -----------------------------------------------------------------------------
365 // ChangeInt32ToInt64
366
367
368 TEST_F(MachineOperatorReducerTest, ChangeInt32ToInt64WithConstant) {
369   TRACED_FOREACH(int32_t, x, kInt32Values) {
370     Reduction reduction = Reduce(
371         graph()->NewNode(machine()->ChangeInt32ToInt64(), Int32Constant(x)));
372     ASSERT_TRUE(reduction.Changed());
373     EXPECT_THAT(reduction.replacement(), IsInt64Constant(x));
374   }
375 }
376
377
378 // -----------------------------------------------------------------------------
379 // ChangeUint32ToFloat64
380
381
382 TEST_F(MachineOperatorReducerTest, ChangeUint32ToFloat64WithConstant) {
383   TRACED_FOREACH(uint32_t, x, kUint32Values) {
384     Reduction reduction =
385         Reduce(graph()->NewNode(machine()->ChangeUint32ToFloat64(),
386                                 Int32Constant(bit_cast<int32_t>(x))));
387     ASSERT_TRUE(reduction.Changed());
388     EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastUI2D(x))));
389   }
390 }
391
392
393 // -----------------------------------------------------------------------------
394 // ChangeUint32ToUint64
395
396
397 TEST_F(MachineOperatorReducerTest, ChangeUint32ToUint64WithConstant) {
398   TRACED_FOREACH(uint32_t, x, kUint32Values) {
399     Reduction reduction =
400         Reduce(graph()->NewNode(machine()->ChangeUint32ToUint64(),
401                                 Int32Constant(bit_cast<int32_t>(x))));
402     ASSERT_TRUE(reduction.Changed());
403     EXPECT_THAT(reduction.replacement(),
404                 IsInt64Constant(bit_cast<int64_t>(static_cast<uint64_t>(x))));
405   }
406 }
407
408
409 // -----------------------------------------------------------------------------
410 // TruncateFloat64ToFloat32
411
412
413 TEST_F(MachineOperatorReducerTest,
414        TruncateFloat64ToFloat32WithChangeFloat32ToFloat64) {
415   Node* value = Parameter(0);
416   Reduction reduction = Reduce(graph()->NewNode(
417       machine()->TruncateFloat64ToFloat32(),
418       graph()->NewNode(machine()->ChangeFloat32ToFloat64(), value)));
419   ASSERT_TRUE(reduction.Changed());
420   EXPECT_EQ(value, reduction.replacement());
421 }
422
423
424 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) {
425   TRACED_FOREACH(double, x, kFloat64Values) {
426     Reduction reduction = Reduce(graph()->NewNode(
427         machine()->TruncateFloat64ToFloat32(), Float64Constant(x)));
428     ASSERT_TRUE(reduction.Changed());
429     EXPECT_THAT(reduction.replacement(),
430                 IsFloat32Constant(BitEq(DoubleToFloat32(x))));
431   }
432 }
433
434
435 // -----------------------------------------------------------------------------
436 // TruncateFloat64ToInt32
437
438
439 TEST_F(MachineOperatorReducerTest,
440        TruncateFloat64ToInt32WithChangeInt32ToFloat64) {
441   Node* value = Parameter(0);
442   Reduction reduction = Reduce(graph()->NewNode(
443       machine()->TruncateFloat64ToInt32(),
444       graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
445   ASSERT_TRUE(reduction.Changed());
446   EXPECT_EQ(value, reduction.replacement());
447 }
448
449
450 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithConstant) {
451   TRACED_FOREACH(double, x, kFloat64Values) {
452     Reduction reduction = Reduce(graph()->NewNode(
453         machine()->TruncateFloat64ToInt32(), Float64Constant(x)));
454     ASSERT_TRUE(reduction.Changed());
455     EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
456   }
457 }
458
459
460 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithPhi) {
461   Node* const p0 = Parameter(0);
462   Node* const p1 = Parameter(1);
463   Node* const merge = graph()->start();
464   Reduction reduction = Reduce(graph()->NewNode(
465       machine()->TruncateFloat64ToInt32(),
466       graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge)));
467   ASSERT_TRUE(reduction.Changed());
468   EXPECT_THAT(reduction.replacement(),
469               IsPhi(kMachInt32, IsTruncateFloat64ToInt32(p0),
470                     IsTruncateFloat64ToInt32(p1), merge));
471 }
472
473
474 // -----------------------------------------------------------------------------
475 // TruncateInt64ToInt32
476
477
478 TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithChangeInt32ToInt64) {
479   Node* value = Parameter(0);
480   Reduction reduction = Reduce(graph()->NewNode(
481       machine()->TruncateInt64ToInt32(),
482       graph()->NewNode(machine()->ChangeInt32ToInt64(), value)));
483   ASSERT_TRUE(reduction.Changed());
484   EXPECT_EQ(value, reduction.replacement());
485 }
486
487
488 TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithConstant) {
489   TRACED_FOREACH(int64_t, x, kInt64Values) {
490     Reduction reduction = Reduce(
491         graph()->NewNode(machine()->TruncateInt64ToInt32(), Int64Constant(x)));
492     ASSERT_TRUE(reduction.Changed());
493     EXPECT_THAT(reduction.replacement(),
494                 IsInt32Constant(bit_cast<int32_t>(
495                     static_cast<uint32_t>(bit_cast<uint64_t>(x)))));
496   }
497 }
498
499
500 // -----------------------------------------------------------------------------
501 // Word32And
502
503
504 TEST_F(MachineOperatorReducerTest, Word32AndWithWord32ShlWithConstant) {
505   Node* const p0 = Parameter(0);
506
507   TRACED_FORRANGE(int32_t, l, 1, 31) {
508     TRACED_FORRANGE(int32_t, k, 1, l) {
509       // (x << L) & (-1 << K) => x << L
510       Reduction const r1 = Reduce(graph()->NewNode(
511           machine()->Word32And(),
512           graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l)),
513           Int32Constant(-1 << k)));
514       ASSERT_TRUE(r1.Changed());
515       EXPECT_THAT(r1.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
516
517       // (-1 << K) & (x << L) => x << L
518       Reduction const r2 = Reduce(graph()->NewNode(
519           machine()->Word32And(), Int32Constant(-1 << k),
520           graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l))));
521       ASSERT_TRUE(r2.Changed());
522       EXPECT_THAT(r2.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
523     }
524   }
525 }
526
527
528 TEST_F(MachineOperatorReducerTest, Word32AndWithWord32AndWithConstant) {
529   Node* const p0 = Parameter(0);
530
531   TRACED_FOREACH(int32_t, k, kInt32Values) {
532     TRACED_FOREACH(int32_t, l, kInt32Values) {
533       if (k == 0 || k == -1 || l == 0 || l == -1) continue;
534
535       // (x & K) & L => x & (K & L)
536       Reduction const r1 = Reduce(graph()->NewNode(
537           machine()->Word32And(),
538           graph()->NewNode(machine()->Word32And(), p0, Int32Constant(k)),
539           Int32Constant(l)));
540       ASSERT_TRUE(r1.Changed());
541       EXPECT_THAT(r1.replacement(),
542                   (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
543                           : IsInt32Constant(0));
544
545       // (K & x) & L => x & (K & L)
546       Reduction const r2 = Reduce(graph()->NewNode(
547           machine()->Word32And(),
548           graph()->NewNode(machine()->Word32And(), Int32Constant(k), p0),
549           Int32Constant(l)));
550       ASSERT_TRUE(r2.Changed());
551       EXPECT_THAT(r2.replacement(),
552                   (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
553                           : IsInt32Constant(0));
554     }
555   }
556 }
557
558
559 TEST_F(MachineOperatorReducerTest, Word32AndWithInt32AddAndConstant) {
560   Node* const p0 = Parameter(0);
561   Node* const p1 = Parameter(1);
562
563   TRACED_FORRANGE(int32_t, l, 1, 31) {
564     TRACED_FOREACH(int32_t, k, kInt32Values) {
565       if ((k << l) == 0) continue;
566       // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
567       Reduction const r = Reduce(graph()->NewNode(
568           machine()->Word32And(),
569           graph()->NewNode(machine()->Int32Add(), p0, Int32Constant(k << l)),
570           Int32Constant(-1 << l)));
571       ASSERT_TRUE(r.Changed());
572       EXPECT_THAT(r.replacement(),
573                   IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
574                              IsInt32Constant(k << l)));
575     }
576
577     Node* s1 = graph()->NewNode(machine()->Word32Shl(), p1, Int32Constant(l));
578
579     // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
580     Reduction const r1 = Reduce(graph()->NewNode(
581         machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), s1, p0),
582         Int32Constant(-1 << l)));
583     ASSERT_TRUE(r1.Changed());
584     EXPECT_THAT(r1.replacement(),
585                 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)), s1));
586
587     // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
588     Reduction const r2 = Reduce(graph()->NewNode(
589         machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), p0, s1),
590         Int32Constant(-1 << l)));
591     ASSERT_TRUE(r2.Changed());
592     EXPECT_THAT(r2.replacement(),
593                 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)), s1));
594   }
595 }
596
597
598 TEST_F(MachineOperatorReducerTest,
599        Word32AndWithInt32AddAndInt32MulAndConstant) {
600   Node* const p0 = Parameter(0);
601   Node* const p1 = Parameter(1);
602
603   TRACED_FORRANGE(int32_t, l, 1, 31) {
604     TRACED_FOREACH(int32_t, k, kInt32Values) {
605       if ((k << l) == 0) continue;
606       // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
607       Reduction const r1 = Reduce(graph()->NewNode(
608           machine()->Word32And(),
609           graph()->NewNode(machine()->Int32Add(),
610                            graph()->NewNode(machine()->Int32Mul(), p1,
611                                             Int32Constant(k << l)),
612                            p0),
613           Int32Constant(-1 << l)));
614       ASSERT_TRUE(r1.Changed());
615       EXPECT_THAT(r1.replacement(),
616                   IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
617                              IsInt32Mul(p1, IsInt32Constant(k << l))));
618
619       // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
620       Reduction const r2 = Reduce(graph()->NewNode(
621           machine()->Word32And(),
622           graph()->NewNode(machine()->Int32Add(), p0,
623                            graph()->NewNode(machine()->Int32Mul(), p1,
624                                             Int32Constant(k << l))),
625           Int32Constant(-1 << l)));
626       ASSERT_TRUE(r2.Changed());
627       EXPECT_THAT(r2.replacement(),
628                   IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
629                              IsInt32Mul(p1, IsInt32Constant(k << l))));
630     }
631   }
632 }
633
634
635 // -----------------------------------------------------------------------------
636 // Word32Xor
637
638
639 TEST_F(MachineOperatorReducerTest, Word32XorWithWord32XorAndMinusOne) {
640   Node* const p0 = Parameter(0);
641
642   // (x ^ -1) ^ -1 => x
643   Reduction r1 = Reduce(graph()->NewNode(
644       machine()->Word32Xor(),
645       graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1)),
646       Int32Constant(-1)));
647   ASSERT_TRUE(r1.Changed());
648   EXPECT_EQ(r1.replacement(), p0);
649
650   // -1 ^ (x ^ -1) => x
651   Reduction r2 = Reduce(graph()->NewNode(
652       machine()->Word32Xor(), Int32Constant(-1),
653       graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1))));
654   ASSERT_TRUE(r2.Changed());
655   EXPECT_EQ(r2.replacement(), p0);
656
657   // (-1 ^ x) ^ -1 => x
658   Reduction r3 = Reduce(graph()->NewNode(
659       machine()->Word32Xor(),
660       graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0),
661       Int32Constant(-1)));
662   ASSERT_TRUE(r3.Changed());
663   EXPECT_EQ(r3.replacement(), p0);
664
665   // -1 ^ (-1 ^ x) => x
666   Reduction r4 = Reduce(graph()->NewNode(
667       machine()->Word32Xor(), Int32Constant(-1),
668       graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0)));
669   ASSERT_TRUE(r4.Changed());
670   EXPECT_EQ(r4.replacement(), p0);
671 }
672
673
674 // -----------------------------------------------------------------------------
675 // Word32Ror
676
677
678 TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithParameters) {
679   Node* value = Parameter(0);
680   Node* shift = Parameter(1);
681   Node* sub = graph()->NewNode(machine()->Int32Sub(), Int32Constant(32), shift);
682
683   // Testing rotate left.
684   Node* shl_l = graph()->NewNode(machine()->Word32Shl(), value, shift);
685   Node* shr_l = graph()->NewNode(machine()->Word32Shr(), value, sub);
686
687   // (x << y) | (x >>> (32 - y)) => x ror (32 - y)
688   Node* node1 = graph()->NewNode(machine()->Word32Or(), shl_l, shr_l);
689   Reduction reduction1 = Reduce(node1);
690   EXPECT_TRUE(reduction1.Changed());
691   EXPECT_EQ(reduction1.replacement(), node1);
692   EXPECT_THAT(reduction1.replacement(), IsWord32Ror(value, sub));
693
694   // (x >>> (32 - y)) | (x << y) => x ror (32 - y)
695   Node* node2 = graph()->NewNode(machine()->Word32Or(), shr_l, shl_l);
696   Reduction reduction2 = Reduce(node2);
697   EXPECT_TRUE(reduction2.Changed());
698   EXPECT_EQ(reduction2.replacement(), node2);
699   EXPECT_THAT(reduction2.replacement(), IsWord32Ror(value, sub));
700
701   // Testing rotate right.
702   Node* shl_r = graph()->NewNode(machine()->Word32Shl(), value, sub);
703   Node* shr_r = graph()->NewNode(machine()->Word32Shr(), value, shift);
704
705   // (x << (32 - y)) | (x >>> y) => x ror y
706   Node* node3 = graph()->NewNode(machine()->Word32Or(), shl_r, shr_r);
707   Reduction reduction3 = Reduce(node3);
708   EXPECT_TRUE(reduction3.Changed());
709   EXPECT_EQ(reduction3.replacement(), node3);
710   EXPECT_THAT(reduction3.replacement(), IsWord32Ror(value, shift));
711
712   // (x >>> y) | (x << (32 - y)) => x ror y
713   Node* node4 = graph()->NewNode(machine()->Word32Or(), shr_r, shl_r);
714   Reduction reduction4 = Reduce(node4);
715   EXPECT_TRUE(reduction4.Changed());
716   EXPECT_EQ(reduction4.replacement(), node4);
717   EXPECT_THAT(reduction4.replacement(), IsWord32Ror(value, shift));
718 }
719
720
721 TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithConstant) {
722   Node* value = Parameter(0);
723   TRACED_FORRANGE(int32_t, k, 0, 31) {
724     Node* shl =
725         graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(k));
726     Node* shr =
727         graph()->NewNode(machine()->Word32Shr(), value, Int32Constant(32 - k));
728
729     // (x << K) | (x >>> ((32 - K) - y)) => x ror (32 - K)
730     Node* node1 = graph()->NewNode(machine()->Word32Or(), shl, shr);
731     Reduction reduction1 = Reduce(node1);
732     EXPECT_TRUE(reduction1.Changed());
733     EXPECT_EQ(reduction1.replacement(), node1);
734     EXPECT_THAT(reduction1.replacement(),
735                 IsWord32Ror(value, IsInt32Constant(32 - k)));
736
737     // (x >>> (32 - K)) | (x << K) => x ror (32 - K)
738     Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl);
739     Reduction reduction2 = Reduce(node2);
740     EXPECT_TRUE(reduction2.Changed());
741     EXPECT_EQ(reduction2.replacement(), node2);
742     EXPECT_THAT(reduction2.replacement(),
743                 IsWord32Ror(value, IsInt32Constant(32 - k)));
744   }
745 }
746
747
748 TEST_F(MachineOperatorReducerTest, Word32RorWithZeroShift) {
749   Node* value = Parameter(0);
750   Node* node =
751       graph()->NewNode(machine()->Word32Ror(), value, Int32Constant(0));
752   Reduction reduction = Reduce(node);
753   EXPECT_TRUE(reduction.Changed());
754   EXPECT_EQ(reduction.replacement(), value);
755 }
756
757
758 TEST_F(MachineOperatorReducerTest, Word32RorWithConstants) {
759   TRACED_FOREACH(int32_t, x, kUint32Values) {
760     TRACED_FORRANGE(int32_t, y, 0, 31) {
761       Node* node = graph()->NewNode(machine()->Word32Ror(), Int32Constant(x),
762                                     Int32Constant(y));
763       Reduction reduction = Reduce(node);
764       EXPECT_TRUE(reduction.Changed());
765       EXPECT_THAT(reduction.replacement(),
766                   IsInt32Constant(base::bits::RotateRight32(x, y)));
767     }
768   }
769 }
770
771
772 // -----------------------------------------------------------------------------
773 // Word32Sar
774
775
776 TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndLoad) {
777   Node* const p0 = Parameter(0);
778   Node* const p1 = Parameter(1);
779   {
780     Node* const l = graph()->NewNode(machine()->Load(kMachInt8), p0, p1,
781                                      graph()->start(), graph()->start());
782     Reduction const r = Reduce(graph()->NewNode(
783         machine()->Word32Sar(),
784         graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(24)),
785         Int32Constant(24)));
786     ASSERT_TRUE(r.Changed());
787     EXPECT_EQ(l, r.replacement());
788   }
789   {
790     Node* const l = graph()->NewNode(machine()->Load(kMachInt16), p0, p1,
791                                      graph()->start(), graph()->start());
792     Reduction const r = Reduce(graph()->NewNode(
793         machine()->Word32Sar(),
794         graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(16)),
795         Int32Constant(16)));
796     ASSERT_TRUE(r.Changed());
797     EXPECT_EQ(l, r.replacement());
798   }
799 }
800
801
802 // -----------------------------------------------------------------------------
803 // Word32Shl
804
805
806 TEST_F(MachineOperatorReducerTest, Word32ShlWithZeroShift) {
807   Node* p0 = Parameter(0);
808   Node* node = graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(0));
809   Reduction r = Reduce(node);
810   ASSERT_TRUE(r.Changed());
811   EXPECT_EQ(p0, r.replacement());
812 }
813
814
815 TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Sar) {
816   Node* p0 = Parameter(0);
817   TRACED_FORRANGE(int32_t, x, 1, 31) {
818     Node* node = graph()->NewNode(
819         machine()->Word32Shl(),
820         graph()->NewNode(machine()->Word32Sar(), p0, Int32Constant(x)),
821         Int32Constant(x));
822     Reduction r = Reduce(node);
823     ASSERT_TRUE(r.Changed());
824     int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
825     EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
826   }
827 }
828
829
830 TEST_F(MachineOperatorReducerTest,
831        Word32ShlWithWord32SarAndInt32AddAndConstant) {
832   Node* const p0 = Parameter(0);
833   TRACED_FOREACH(int32_t, k, kInt32Values) {
834     TRACED_FORRANGE(int32_t, l, 1, 31) {
835       if ((k << l) == 0) continue;
836       // (x + (K << L)) >> L << L => (x & (-1 << L)) + (K << L)
837       Reduction const r = Reduce(graph()->NewNode(
838           machine()->Word32Shl(),
839           graph()->NewNode(machine()->Word32Sar(),
840                            graph()->NewNode(machine()->Int32Add(), p0,
841                                             Int32Constant(k << l)),
842                            Int32Constant(l)),
843           Int32Constant(l)));
844       ASSERT_TRUE(r.Changed());
845       EXPECT_THAT(r.replacement(),
846                   IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
847                              IsInt32Constant(k << l)));
848     }
849   }
850 }
851
852
853 TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Shr) {
854   Node* p0 = Parameter(0);
855   TRACED_FORRANGE(int32_t, x, 1, 31) {
856     Node* node = graph()->NewNode(
857         machine()->Word32Shl(),
858         graph()->NewNode(machine()->Word32Shr(), p0, Int32Constant(x)),
859         Int32Constant(x));
860     Reduction r = Reduce(node);
861     ASSERT_TRUE(r.Changed());
862     int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
863     EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
864   }
865 }
866
867
868 // -----------------------------------------------------------------------------
869 // Int32Sub
870
871
872 TEST_F(MachineOperatorReducerTest, Int32SubWithConstant) {
873   Node* const p0 = Parameter(0);
874   TRACED_FOREACH(int32_t, k, kInt32Values) {
875     Reduction const r =
876         Reduce(graph()->NewNode(machine()->Int32Sub(), p0, Int32Constant(k)));
877     ASSERT_TRUE(r.Changed());
878     if (k == 0) {
879       EXPECT_EQ(p0, r.replacement());
880     } else {
881       EXPECT_THAT(r.replacement(), IsInt32Add(p0, IsInt32Constant(-k)));
882     }
883   }
884 }
885
886
887 // -----------------------------------------------------------------------------
888 // Int32Div
889
890
891 TEST_F(MachineOperatorReducerTest, Int32DivWithConstant) {
892   Node* const p0 = Parameter(0);
893   {
894     Reduction const r = Reduce(graph()->NewNode(
895         machine()->Int32Div(), p0, Int32Constant(0), graph()->start()));
896     ASSERT_TRUE(r.Changed());
897     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
898   }
899   {
900     Reduction const r = Reduce(graph()->NewNode(
901         machine()->Int32Div(), p0, Int32Constant(1), graph()->start()));
902     ASSERT_TRUE(r.Changed());
903     EXPECT_EQ(r.replacement(), p0);
904   }
905   {
906     Reduction const r = Reduce(graph()->NewNode(
907         machine()->Int32Div(), p0, Int32Constant(-1), graph()->start()));
908     ASSERT_TRUE(r.Changed());
909     EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0), p0));
910   }
911   {
912     Reduction const r = Reduce(graph()->NewNode(
913         machine()->Int32Div(), p0, Int32Constant(2), graph()->start()));
914     ASSERT_TRUE(r.Changed());
915     EXPECT_THAT(
916         r.replacement(),
917         IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
918                     IsInt32Constant(1)));
919   }
920   {
921     Reduction const r = Reduce(graph()->NewNode(
922         machine()->Int32Div(), p0, Int32Constant(-2), graph()->start()));
923     ASSERT_TRUE(r.Changed());
924     EXPECT_THAT(
925         r.replacement(),
926         IsInt32Sub(
927             IsInt32Constant(0),
928             IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
929                         IsInt32Constant(1))));
930   }
931   TRACED_FORRANGE(int32_t, shift, 2, 30) {
932     Reduction const r =
933         Reduce(graph()->NewNode(machine()->Int32Div(), p0,
934                                 Int32Constant(1 << shift), graph()->start()));
935     ASSERT_TRUE(r.Changed());
936     EXPECT_THAT(
937         r.replacement(),
938         IsWord32Sar(IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
939                                            IsInt32Constant(32 - shift)),
940                                p0),
941                     IsInt32Constant(shift)));
942   }
943   TRACED_FORRANGE(int32_t, shift, 2, 31) {
944     Reduction const r = Reduce(graph()->NewNode(
945         machine()->Int32Div(), p0,
946         Uint32Constant(bit_cast<uint32_t, int32_t>(-1) << shift),
947         graph()->start()));
948     ASSERT_TRUE(r.Changed());
949     EXPECT_THAT(
950         r.replacement(),
951         IsInt32Sub(
952             IsInt32Constant(0),
953             IsWord32Sar(
954                 IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
955                                        IsInt32Constant(32 - shift)),
956                            p0),
957                 IsInt32Constant(shift))));
958   }
959   TRACED_FOREACH(int32_t, divisor, kInt32Values) {
960     if (divisor < 0) {
961       if (base::bits::IsPowerOfTwo32(-divisor)) continue;
962       Reduction const r = Reduce(graph()->NewNode(
963           machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
964       ASSERT_TRUE(r.Changed());
965       EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0),
966                                               IsTruncatingDiv(p0, -divisor)));
967     } else if (divisor > 0) {
968       if (base::bits::IsPowerOfTwo32(divisor)) continue;
969       Reduction const r = Reduce(graph()->NewNode(
970           machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
971       ASSERT_TRUE(r.Changed());
972       EXPECT_THAT(r.replacement(), IsTruncatingDiv(p0, divisor));
973     }
974   }
975 }
976
977
978 TEST_F(MachineOperatorReducerTest, Int32DivWithParameters) {
979   Node* const p0 = Parameter(0);
980   Reduction const r =
981       Reduce(graph()->NewNode(machine()->Int32Div(), p0, p0, graph()->start()));
982   ASSERT_TRUE(r.Changed());
983   EXPECT_THAT(
984       r.replacement(),
985       IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
986 }
987
988
989 // -----------------------------------------------------------------------------
990 // Uint32Div
991
992
993 TEST_F(MachineOperatorReducerTest, Uint32DivWithConstant) {
994   Node* const p0 = Parameter(0);
995   {
996     Reduction const r = Reduce(graph()->NewNode(
997         machine()->Uint32Div(), Int32Constant(0), p0, graph()->start()));
998     ASSERT_TRUE(r.Changed());
999     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1000   }
1001   {
1002     Reduction const r = Reduce(graph()->NewNode(
1003         machine()->Uint32Div(), p0, Int32Constant(0), graph()->start()));
1004     ASSERT_TRUE(r.Changed());
1005     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1006   }
1007   {
1008     Reduction const r = Reduce(graph()->NewNode(
1009         machine()->Uint32Div(), p0, Int32Constant(1), graph()->start()));
1010     ASSERT_TRUE(r.Changed());
1011     EXPECT_EQ(r.replacement(), p0);
1012   }
1013   TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1014     TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1015       Reduction const r = Reduce(
1016           graph()->NewNode(machine()->Uint32Div(), Uint32Constant(dividend),
1017                            Uint32Constant(divisor), graph()->start()));
1018       ASSERT_TRUE(r.Changed());
1019       EXPECT_THAT(r.replacement(),
1020                   IsInt32Constant(bit_cast<int32_t>(
1021                       base::bits::UnsignedDiv32(dividend, divisor))));
1022     }
1023   }
1024   TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1025     Reduction const r =
1026         Reduce(graph()->NewNode(machine()->Uint32Div(), p0,
1027                                 Uint32Constant(1u << shift), graph()->start()));
1028     ASSERT_TRUE(r.Changed());
1029     EXPECT_THAT(r.replacement(),
1030                 IsWord32Shr(p0, IsInt32Constant(bit_cast<int32_t>(shift))));
1031   }
1032 }
1033
1034
1035 TEST_F(MachineOperatorReducerTest, Uint32DivWithParameters) {
1036   Node* const p0 = Parameter(0);
1037   Reduction const r = Reduce(
1038       graph()->NewNode(machine()->Uint32Div(), p0, p0, graph()->start()));
1039   ASSERT_TRUE(r.Changed());
1040   EXPECT_THAT(
1041       r.replacement(),
1042       IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
1043 }
1044
1045
1046 // -----------------------------------------------------------------------------
1047 // Int32Mod
1048
1049
1050 TEST_F(MachineOperatorReducerTest, Int32ModWithConstant) {
1051   Node* const p0 = Parameter(0);
1052   {
1053     Reduction const r = Reduce(graph()->NewNode(
1054         machine()->Int32Mod(), Int32Constant(0), p0, graph()->start()));
1055     ASSERT_TRUE(r.Changed());
1056     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1057   }
1058   {
1059     Reduction const r = Reduce(graph()->NewNode(
1060         machine()->Int32Mod(), p0, Int32Constant(0), graph()->start()));
1061     ASSERT_TRUE(r.Changed());
1062     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1063   }
1064   {
1065     Reduction const r = Reduce(graph()->NewNode(
1066         machine()->Int32Mod(), p0, Int32Constant(1), graph()->start()));
1067     ASSERT_TRUE(r.Changed());
1068     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1069   }
1070   {
1071     Reduction const r = Reduce(graph()->NewNode(
1072         machine()->Int32Mod(), p0, Int32Constant(-1), graph()->start()));
1073     ASSERT_TRUE(r.Changed());
1074     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1075   }
1076   TRACED_FOREACH(int32_t, dividend, kInt32Values) {
1077     TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1078       Reduction const r = Reduce(
1079           graph()->NewNode(machine()->Int32Mod(), Int32Constant(dividend),
1080                            Int32Constant(divisor), graph()->start()));
1081       ASSERT_TRUE(r.Changed());
1082       EXPECT_THAT(r.replacement(),
1083                   IsInt32Constant(base::bits::SignedMod32(dividend, divisor)));
1084     }
1085   }
1086   TRACED_FORRANGE(int32_t, shift, 1, 30) {
1087     Reduction const r =
1088         Reduce(graph()->NewNode(machine()->Int32Mod(), p0,
1089                                 Int32Constant(1 << shift), graph()->start()));
1090     int32_t const mask = (1 << shift) - 1;
1091     ASSERT_TRUE(r.Changed());
1092     EXPECT_THAT(
1093         r.replacement(),
1094         IsSelect(kMachInt32, IsInt32LessThan(p0, IsInt32Constant(0)),
1095                  IsInt32Sub(IsInt32Constant(0),
1096                             IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1097                                         IsInt32Constant(mask))),
1098                  IsWord32And(p0, IsInt32Constant(mask))));
1099   }
1100   TRACED_FORRANGE(int32_t, shift, 1, 31) {
1101     Reduction const r = Reduce(graph()->NewNode(
1102         machine()->Int32Mod(), p0,
1103         Uint32Constant(bit_cast<uint32_t, int32_t>(-1) << shift),
1104         graph()->start()));
1105     int32_t const mask = bit_cast<int32_t, uint32_t>((1U << shift) - 1);
1106     ASSERT_TRUE(r.Changed());
1107     EXPECT_THAT(
1108         r.replacement(),
1109         IsSelect(kMachInt32, IsInt32LessThan(p0, IsInt32Constant(0)),
1110                  IsInt32Sub(IsInt32Constant(0),
1111                             IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1112                                         IsInt32Constant(mask))),
1113                  IsWord32And(p0, IsInt32Constant(mask))));
1114   }
1115   TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1116     if (divisor == 0 || base::bits::IsPowerOfTwo32(Abs(divisor))) continue;
1117     Reduction const r = Reduce(graph()->NewNode(
1118         machine()->Int32Mod(), p0, Int32Constant(divisor), graph()->start()));
1119     ASSERT_TRUE(r.Changed());
1120     EXPECT_THAT(r.replacement(),
1121                 IsInt32Sub(p0, IsInt32Mul(IsTruncatingDiv(p0, Abs(divisor)),
1122                                           IsInt32Constant(Abs(divisor)))));
1123   }
1124 }
1125
1126
1127 TEST_F(MachineOperatorReducerTest, Int32ModWithParameters) {
1128   Node* const p0 = Parameter(0);
1129   Reduction const r =
1130       Reduce(graph()->NewNode(machine()->Int32Mod(), p0, p0, graph()->start()));
1131   ASSERT_TRUE(r.Changed());
1132   EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1133 }
1134
1135
1136 // -----------------------------------------------------------------------------
1137 // Uint32Mod
1138
1139
1140 TEST_F(MachineOperatorReducerTest, Uint32ModWithConstant) {
1141   Node* const p0 = Parameter(0);
1142   {
1143     Reduction const r = Reduce(graph()->NewNode(
1144         machine()->Uint32Mod(), p0, Int32Constant(0), graph()->start()));
1145     ASSERT_TRUE(r.Changed());
1146     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1147   }
1148   {
1149     Reduction const r = Reduce(graph()->NewNode(
1150         machine()->Uint32Mod(), Int32Constant(0), p0, graph()->start()));
1151     ASSERT_TRUE(r.Changed());
1152     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1153   }
1154   {
1155     Reduction const r = Reduce(graph()->NewNode(
1156         machine()->Uint32Mod(), p0, Int32Constant(1), graph()->start()));
1157     ASSERT_TRUE(r.Changed());
1158     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1159   }
1160   TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1161     TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1162       Reduction const r = Reduce(
1163           graph()->NewNode(machine()->Uint32Mod(), Uint32Constant(dividend),
1164                            Uint32Constant(divisor), graph()->start()));
1165       ASSERT_TRUE(r.Changed());
1166       EXPECT_THAT(r.replacement(),
1167                   IsInt32Constant(bit_cast<int32_t>(
1168                       base::bits::UnsignedMod32(dividend, divisor))));
1169     }
1170   }
1171   TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1172     Reduction const r =
1173         Reduce(graph()->NewNode(machine()->Uint32Mod(), p0,
1174                                 Uint32Constant(1u << shift), graph()->start()));
1175     ASSERT_TRUE(r.Changed());
1176     EXPECT_THAT(r.replacement(),
1177                 IsWord32And(p0, IsInt32Constant(
1178                                     bit_cast<int32_t>((1u << shift) - 1u))));
1179   }
1180 }
1181
1182
1183 TEST_F(MachineOperatorReducerTest, Uint32ModWithParameters) {
1184   Node* const p0 = Parameter(0);
1185   Reduction const r = Reduce(
1186       graph()->NewNode(machine()->Uint32Mod(), p0, p0, graph()->start()));
1187   ASSERT_TRUE(r.Changed());
1188   EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1189 }
1190
1191
1192 // -----------------------------------------------------------------------------
1193 // Int32AddWithOverflow
1194
1195
1196 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) {
1197   Node* p0 = Parameter(0);
1198   {
1199     Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1200                                  Int32Constant(0), p0);
1201
1202     Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1203     ASSERT_TRUE(r.Changed());
1204     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1205
1206     r = Reduce(graph()->NewNode(common()->Projection(0), add));
1207     ASSERT_TRUE(r.Changed());
1208     EXPECT_EQ(p0, r.replacement());
1209   }
1210   {
1211     Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), p0,
1212                                  Int32Constant(0));
1213
1214     Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1215     ASSERT_TRUE(r.Changed());
1216     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1217
1218     r = Reduce(graph()->NewNode(common()->Projection(0), add));
1219     ASSERT_TRUE(r.Changed());
1220     EXPECT_EQ(p0, r.replacement());
1221   }
1222 }
1223
1224
1225 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) {
1226   TRACED_FOREACH(int32_t, x, kInt32Values) {
1227     TRACED_FOREACH(int32_t, y, kInt32Values) {
1228       int32_t z;
1229       Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1230                                    Int32Constant(x), Int32Constant(y));
1231
1232       Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1233       ASSERT_TRUE(r.Changed());
1234       EXPECT_THAT(r.replacement(),
1235                   IsInt32Constant(base::bits::SignedAddOverflow32(x, y, &z)));
1236
1237       r = Reduce(graph()->NewNode(common()->Projection(0), add));
1238       ASSERT_TRUE(r.Changed());
1239       EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1240     }
1241   }
1242 }
1243
1244
1245 // -----------------------------------------------------------------------------
1246 // Int32SubWithOverflow
1247
1248
1249 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithZero) {
1250   Node* p0 = Parameter(0);
1251   Node* add =
1252       graph()->NewNode(machine()->Int32SubWithOverflow(), p0, Int32Constant(0));
1253
1254   Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1255   ASSERT_TRUE(r.Changed());
1256   EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1257
1258   r = Reduce(graph()->NewNode(common()->Projection(0), add));
1259   ASSERT_TRUE(r.Changed());
1260   EXPECT_EQ(p0, r.replacement());
1261 }
1262
1263
1264 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
1265   TRACED_FOREACH(int32_t, x, kInt32Values) {
1266     TRACED_FOREACH(int32_t, y, kInt32Values) {
1267       int32_t z;
1268       Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(),
1269                                    Int32Constant(x), Int32Constant(y));
1270
1271       Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1272       ASSERT_TRUE(r.Changed());
1273       EXPECT_THAT(r.replacement(),
1274                   IsInt32Constant(base::bits::SignedSubOverflow32(x, y, &z)));
1275
1276       r = Reduce(graph()->NewNode(common()->Projection(0), add));
1277       ASSERT_TRUE(r.Changed());
1278       EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1279     }
1280   }
1281 }
1282
1283
1284 // -----------------------------------------------------------------------------
1285 // Uint32LessThan
1286
1287
1288 TEST_F(MachineOperatorReducerTest, Uint32LessThanWithWord32Sar) {
1289   Node* const p0 = Parameter(0);
1290   TRACED_FORRANGE(uint32_t, shift, 1, 3) {
1291     const uint32_t limit = (kMaxInt >> shift) - 1;
1292     Node* const node = graph()->NewNode(
1293         machine()->Uint32LessThan(),
1294         graph()->NewNode(machine()->Word32Sar(), p0, Uint32Constant(shift)),
1295         Uint32Constant(limit));
1296
1297     Reduction r = Reduce(node);
1298     ASSERT_TRUE(r.Changed());
1299     EXPECT_THAT(r.replacement(),
1300                 IsUint32LessThan(
1301                     p0, IsInt32Constant(bit_cast<int32_t>(limit << shift))));
1302   }
1303 }
1304
1305
1306 // -----------------------------------------------------------------------------
1307 // Float64Mul
1308
1309
1310 TEST_F(MachineOperatorReducerTest, Float64MulWithMinusOne) {
1311   Node* const p0 = Parameter(0);
1312   {
1313     Reduction r = Reduce(
1314         graph()->NewNode(machine()->Float64Mul(), p0, Float64Constant(-1.0)));
1315     ASSERT_TRUE(r.Changed());
1316     EXPECT_THAT(r.replacement(),
1317                 IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1318   }
1319   {
1320     Reduction r = Reduce(
1321         graph()->NewNode(machine()->Float64Mul(), Float64Constant(-1.0), p0));
1322     ASSERT_TRUE(r.Changed());
1323     EXPECT_THAT(r.replacement(),
1324                 IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1325   }
1326 }
1327
1328
1329 // -----------------------------------------------------------------------------
1330 // Store
1331
1332
1333 TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32And) {
1334   const StoreRepresentation rep(kRepWord8, kNoWriteBarrier);
1335   Node* const base = Parameter(0);
1336   Node* const index = Parameter(1);
1337   Node* const value = Parameter(2);
1338   Node* const effect = graph()->start();
1339   Node* const control = graph()->start();
1340   TRACED_FOREACH(uint32_t, x, kUint32Values) {
1341     Node* const node =
1342         graph()->NewNode(machine()->Store(rep), base, index,
1343                          graph()->NewNode(machine()->Word32And(), value,
1344                                           Uint32Constant(x | 0xffu)),
1345                          effect, control);
1346
1347     Reduction r = Reduce(node);
1348     ASSERT_TRUE(r.Changed());
1349     EXPECT_THAT(r.replacement(),
1350                 IsStore(rep, base, index, value, effect, control));
1351   }
1352 }
1353
1354
1355 TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32SarAndWord32Shl) {
1356   const StoreRepresentation rep(kRepWord8, kNoWriteBarrier);
1357   Node* const base = Parameter(0);
1358   Node* const index = Parameter(1);
1359   Node* const value = Parameter(2);
1360   Node* const effect = graph()->start();
1361   Node* const control = graph()->start();
1362   TRACED_FORRANGE(int32_t, x, 1, 24) {
1363     Node* const node = graph()->NewNode(
1364         machine()->Store(rep), base, index,
1365         graph()->NewNode(
1366             machine()->Word32Sar(),
1367             graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
1368             Int32Constant(x)),
1369         effect, control);
1370
1371     Reduction r = Reduce(node);
1372     ASSERT_TRUE(r.Changed());
1373     EXPECT_THAT(r.replacement(),
1374                 IsStore(rep, base, index, value, effect, control));
1375   }
1376 }
1377
1378
1379 TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32And) {
1380   const StoreRepresentation rep(kRepWord16, kNoWriteBarrier);
1381   Node* const base = Parameter(0);
1382   Node* const index = Parameter(1);
1383   Node* const value = Parameter(2);
1384   Node* const effect = graph()->start();
1385   Node* const control = graph()->start();
1386   TRACED_FOREACH(uint32_t, x, kUint32Values) {
1387     Node* const node =
1388         graph()->NewNode(machine()->Store(rep), base, index,
1389                          graph()->NewNode(machine()->Word32And(), value,
1390                                           Uint32Constant(x | 0xffffu)),
1391                          effect, control);
1392
1393     Reduction r = Reduce(node);
1394     ASSERT_TRUE(r.Changed());
1395     EXPECT_THAT(r.replacement(),
1396                 IsStore(rep, base, index, value, effect, control));
1397   }
1398 }
1399
1400
1401 TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32SarAndWord32Shl) {
1402   const StoreRepresentation rep(kRepWord16, kNoWriteBarrier);
1403   Node* const base = Parameter(0);
1404   Node* const index = Parameter(1);
1405   Node* const value = Parameter(2);
1406   Node* const effect = graph()->start();
1407   Node* const control = graph()->start();
1408   TRACED_FORRANGE(int32_t, x, 1, 16) {
1409     Node* const node = graph()->NewNode(
1410         machine()->Store(rep), base, index,
1411         graph()->NewNode(
1412             machine()->Word32Sar(),
1413             graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
1414             Int32Constant(x)),
1415         effect, control);
1416
1417     Reduction r = Reduce(node);
1418     ASSERT_TRUE(r.Changed());
1419     EXPECT_THAT(r.replacement(),
1420                 IsStore(rep, base, index, value, effect, control));
1421   }
1422 }
1423
1424 }  // namespace compiler
1425 }  // namespace internal
1426 }  // namespace v8