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/compiler/graph-unittest.h"
7#include "src/compiler/js-graph.h"
8#include "src/compiler/machine-operator-reducer.h"
9#include "src/compiler/typer.h"
10
11namespace v8 {
12namespace internal {
13namespace compiler {
14
15class MachineOperatorReducerTest : public GraphTest {
16 public:
17  explicit MachineOperatorReducerTest(int num_parameters = 2)
18      : GraphTest(num_parameters) {}
19
20 protected:
21  Reduction Reduce(Node* node) {
22    Typer typer(zone());
23    JSOperatorBuilder javascript(zone());
24    JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine_);
25    MachineOperatorReducer reducer(&jsgraph);
26    return reducer.Reduce(node);
27  }
28
29  MachineOperatorBuilder* machine() { return &machine_; }
30
31 private:
32  MachineOperatorBuilder machine_;
33};
34
35
36template <typename T>
37class MachineOperatorReducerTestWithParam
38    : public MachineOperatorReducerTest,
39      public ::testing::WithParamInterface<T> {
40 public:
41  explicit MachineOperatorReducerTestWithParam(int num_parameters = 2)
42      : MachineOperatorReducerTest(num_parameters) {}
43  virtual ~MachineOperatorReducerTestWithParam() {}
44};
45
46
47namespace {
48
49static const float kFloat32Values[] = {
50    -std::numeric_limits<float>::infinity(), -2.70497e+38f, -1.4698e+37f,
51    -1.22813e+35f,                           -1.20555e+35f, -1.34584e+34f,
52    -1.0079e+32f,                            -6.49364e+26f, -3.06077e+25f,
53    -1.46821e+25f,                           -1.17658e+23f, -1.9617e+22f,
54    -2.7357e+20f,                            -1.48708e+13f, -1.89633e+12f,
55    -4.66622e+11f,                           -2.22581e+11f, -1.45381e+10f,
56    -1.3956e+09f,                            -1.32951e+09f, -1.30721e+09f,
57    -1.19756e+09f,                           -9.26822e+08f, -6.35647e+08f,
58    -4.00037e+08f,                           -1.81227e+08f, -5.09256e+07f,
59    -964300.0f,                              -192446.0f,    -28455.0f,
60    -27194.0f,                               -26401.0f,     -20575.0f,
61    -17069.0f,                               -9167.0f,      -960.178f,
62    -113.0f,                                 -62.0f,        -15.0f,
63    -7.0f,                                   -0.0256635f,   -4.60374e-07f,
64    -3.63759e-10f,                           -4.30175e-14f, -5.27385e-15f,
65    -1.48084e-15f,                           -1.05755e-19f, -3.2995e-21f,
66    -1.67354e-23f,                           -1.11885e-23f, -1.78506e-30f,
67    -5.07594e-31f,                           -3.65799e-31f, -1.43718e-34f,
68    -1.27126e-38f,                           -0.0f,         0.0f,
69    1.17549e-38f,                            1.56657e-37f,  4.08512e-29f,
70    3.31357e-28f,                            6.25073e-22f,  4.1723e-13f,
71    1.44343e-09f,                            5.27004e-08f,  9.48298e-08f,
72    5.57888e-07f,                            4.89988e-05f,  0.244326f,
73    12.4895f,                                19.0f,         47.0f,
74    106.0f,                                  538.324f,      564.536f,
75    819.124f,                                7048.0f,       12611.0f,
76    19878.0f,                                20309.0f,      797056.0f,
77    1.77219e+09f,                            1.51116e+11f,  4.18193e+13f,
78    3.59167e+16f,                            3.38211e+19f,  2.67488e+20f,
79    1.78831e+21f,                            9.20914e+21f,  8.35654e+23f,
80    1.4495e+24f,                             5.94015e+25f,  4.43608e+30f,
81    2.44502e+33f,                            2.61152e+33f,  1.38178e+37f,
82    1.71306e+37f,                            3.31899e+38f,  3.40282e+38f,
83    std::numeric_limits<float>::infinity()};
84
85
86static const double kFloat64Values[] = {
87    -V8_INFINITY,  -4.23878e+275, -5.82632e+265, -6.60355e+220, -6.26172e+212,
88    -2.56222e+211, -4.82408e+201, -1.84106e+157, -1.63662e+127, -1.55772e+100,
89    -1.67813e+72,  -2.3382e+55,   -3.179e+30,    -1.441e+09,    -1.0647e+09,
90    -7.99361e+08,  -5.77375e+08,  -2.20984e+08,  -32757,        -13171,
91    -9970,         -3984,         -107,          -105,          -92,
92    -77,           -61,           -0.000208163,  -1.86685e-06,  -1.17296e-10,
93    -9.26358e-11,  -5.08004e-60,  -1.74753e-65,  -1.06561e-71,  -5.67879e-79,
94    -5.78459e-130, -2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263,
95    -4.40497e-267, -2.19666e-273, -4.9998e-276,  -5.59821e-278, -2.03855e-282,
96    -5.99335e-283, -7.17554e-284, -3.11744e-309, -0.0,          0.0,
97    2.22507e-308,  1.30127e-270,  7.62898e-260,  4.00313e-249,  3.16829e-233,
98    1.85244e-228,  2.03544e-129,  1.35126e-110,  1.01182e-106,  5.26333e-94,
99    1.35292e-90,   2.85394e-83,   1.78323e-77,   5.4967e-57,    1.03207e-25,
100    4.57401e-25,   1.58738e-05,   2,             125,           2310,
101    9636,          14802,         17168,         28945,         29305,
102    4.81336e+07,   1.41207e+08,   4.65962e+08,   1.40499e+09,   2.12648e+09,
103    8.80006e+30,   1.4446e+45,    1.12164e+54,   2.48188e+89,   6.71121e+102,
104    3.074e+112,    4.9699e+152,   5.58383e+166,  4.30654e+172,  7.08824e+185,
105    9.6586e+214,   2.028e+223,    6.63277e+243,  1.56192e+261,  1.23202e+269,
106    5.72883e+289,  8.5798e+290,   1.40256e+294,  1.79769e+308,  V8_INFINITY};
107
108
109static const int32_t kInt32Values[] = {
110    -2147483647 - 1, -1914954528, -1698749618, -1578693386, -1577976073,
111    -1573998034,     -1529085059, -1499540537, -1299205097, -1090814845,
112    -938186388,      -806828902,  -750927650,  -520676892,  -513661538,
113    -453036354,      -433622833,  -282638793,  -28375,      -27788,
114    -22770,          -18806,      -14173,      -11956,      -11200,
115    -10212,          -8160,       -3751,       -2758,       -1522,
116    -121,            -120,        -118,        -117,        -106,
117    -84,             -80,         -74,         -59,         -52,
118    -48,             -39,         -35,         -17,         -11,
119    -10,             -9,          -7,          -5,          0,
120    9,               12,          17,          23,          29,
121    31,              33,          35,          40,          47,
122    55,              56,          62,          64,          67,
123    68,              69,          74,          79,          84,
124    89,              90,          97,          104,         118,
125    124,             126,         127,         7278,        17787,
126    24136,           24202,       25570,       26680,       30242,
127    32399,           420886487,   642166225,   821912648,   822577803,
128    851385718,       1212241078,  1411419304,  1589626102,  1596437184,
129    1876245816,      1954730266,  2008792749,  2045320228,  2147483647};
130
131
132static const int64_t kInt64Values[] = {
133    V8_INT64_C(-9223372036854775807) - 1, V8_INT64_C(-8974392461363618006),
134    V8_INT64_C(-8874367046689588135),     V8_INT64_C(-8269197512118230839),
135    V8_INT64_C(-8146091527100606733),     V8_INT64_C(-7550917981466150848),
136    V8_INT64_C(-7216590251577894337),     V8_INT64_C(-6464086891160048440),
137    V8_INT64_C(-6365616494908257190),     V8_INT64_C(-6305630541365849726),
138    V8_INT64_C(-5982222642272245453),     V8_INT64_C(-5510103099058504169),
139    V8_INT64_C(-5496838675802432701),     V8_INT64_C(-4047626578868642657),
140    V8_INT64_C(-4033755046900164544),     V8_INT64_C(-3554299241457877041),
141    V8_INT64_C(-2482258764588614470),     V8_INT64_C(-1688515425526875335),
142    V8_INT64_C(-924784137176548532),      V8_INT64_C(-725316567157391307),
143    V8_INT64_C(-439022654781092241),      V8_INT64_C(-105545757668917080),
144    V8_INT64_C(-2088319373),              V8_INT64_C(-2073699916),
145    V8_INT64_C(-1844949911),              V8_INT64_C(-1831090548),
146    V8_INT64_C(-1756711933),              V8_INT64_C(-1559409497),
147    V8_INT64_C(-1281179700),              V8_INT64_C(-1211513985),
148    V8_INT64_C(-1182371520),              V8_INT64_C(-785934753),
149    V8_INT64_C(-767480697),               V8_INT64_C(-705745662),
150    V8_INT64_C(-514362436),               V8_INT64_C(-459916580),
151    V8_INT64_C(-312328082),               V8_INT64_C(-302949707),
152    V8_INT64_C(-285499304),               V8_INT64_C(-125701262),
153    V8_INT64_C(-95139843),                V8_INT64_C(-32768),
154    V8_INT64_C(-27542),                   V8_INT64_C(-23600),
155    V8_INT64_C(-18582),                   V8_INT64_C(-17770),
156    V8_INT64_C(-9086),                    V8_INT64_C(-9010),
157    V8_INT64_C(-8244),                    V8_INT64_C(-2890),
158    V8_INT64_C(-103),                     V8_INT64_C(-34),
159    V8_INT64_C(-27),                      V8_INT64_C(-25),
160    V8_INT64_C(-9),                       V8_INT64_C(-7),
161    V8_INT64_C(0),                        V8_INT64_C(2),
162    V8_INT64_C(38),                       V8_INT64_C(58),
163    V8_INT64_C(65),                       V8_INT64_C(93),
164    V8_INT64_C(111),                      V8_INT64_C(1003),
165    V8_INT64_C(1267),                     V8_INT64_C(12797),
166    V8_INT64_C(23122),                    V8_INT64_C(28200),
167    V8_INT64_C(30888),                    V8_INT64_C(42648848),
168    V8_INT64_C(116836693),                V8_INT64_C(263003643),
169    V8_INT64_C(571039860),                V8_INT64_C(1079398689),
170    V8_INT64_C(1145196402),               V8_INT64_C(1184846321),
171    V8_INT64_C(1758281648),               V8_INT64_C(1859991374),
172    V8_INT64_C(1960251588),               V8_INT64_C(2042443199),
173    V8_INT64_C(296220586027987448),       V8_INT64_C(1015494173071134726),
174    V8_INT64_C(1151237951914455318),      V8_INT64_C(1331941174616854174),
175    V8_INT64_C(2022020418667972654),      V8_INT64_C(2450251424374977035),
176    V8_INT64_C(3668393562685561486),      V8_INT64_C(4858229301215502171),
177    V8_INT64_C(4919426235170669383),      V8_INT64_C(5034286595330341762),
178    V8_INT64_C(5055797915536941182),      V8_INT64_C(6072389716149252074),
179    V8_INT64_C(6185309910199801210),      V8_INT64_C(6297328311011094138),
180    V8_INT64_C(6932372858072165827),      V8_INT64_C(8483640924987737210),
181    V8_INT64_C(8663764179455849203),      V8_INT64_C(8877197042645298254),
182    V8_INT64_C(8901543506779157333),      V8_INT64_C(9223372036854775807)};
183
184
185static const uint32_t kUint32Values[] = {
186    0x00000000, 0x00000001, 0xffffffff, 0x1b09788b, 0x04c5fce8, 0xcc0de5bf,
187    0x273a798e, 0x187937a3, 0xece3af83, 0x5495a16b, 0x0b668ecc, 0x11223344,
188    0x0000009e, 0x00000043, 0x0000af73, 0x0000116b, 0x00658ecc, 0x002b3b4c,
189    0x88776655, 0x70000000, 0x07200000, 0x7fffffff, 0x56123761, 0x7fffff00,
190    0x761c4761, 0x80000000, 0x88888888, 0xa0000000, 0xdddddddd, 0xe0000000,
191    0xeeeeeeee, 0xfffffffd, 0xf0000000, 0x007fffff, 0x003fffff, 0x001fffff,
192    0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff,
193    0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
194
195}  // namespace
196
197
198// -----------------------------------------------------------------------------
199// Unary operators
200
201
202namespace {
203
204struct UnaryOperator {
205  const Operator* (MachineOperatorBuilder::*constructor)();
206  const char* constructor_name;
207};
208
209
210std::ostream& operator<<(std::ostream& os, const UnaryOperator& unop) {
211  return os << unop.constructor_name;
212}
213
214
215static const UnaryOperator kUnaryOperators[] = {
216    {&MachineOperatorBuilder::ChangeInt32ToFloat64, "ChangeInt32ToFloat64"},
217    {&MachineOperatorBuilder::ChangeUint32ToFloat64, "ChangeUint32ToFloat64"},
218    {&MachineOperatorBuilder::ChangeFloat64ToInt32, "ChangeFloat64ToInt32"},
219    {&MachineOperatorBuilder::ChangeFloat64ToUint32, "ChangeFloat64ToUint32"},
220    {&MachineOperatorBuilder::ChangeInt32ToInt64, "ChangeInt32ToInt64"},
221    {&MachineOperatorBuilder::ChangeUint32ToUint64, "ChangeUint32ToUint64"},
222    {&MachineOperatorBuilder::TruncateFloat64ToInt32, "TruncateFloat64ToInt32"},
223    {&MachineOperatorBuilder::TruncateInt64ToInt32, "TruncateInt64ToInt32"}};
224
225}  // namespace
226
227
228typedef MachineOperatorReducerTestWithParam<UnaryOperator>
229    MachineUnaryOperatorReducerTest;
230
231
232TEST_P(MachineUnaryOperatorReducerTest, Parameter) {
233  const UnaryOperator unop = GetParam();
234  Reduction reduction =
235      Reduce(graph()->NewNode((machine()->*unop.constructor)(), Parameter(0)));
236  EXPECT_FALSE(reduction.Changed());
237}
238
239
240INSTANTIATE_TEST_CASE_P(MachineOperatorReducerTest,
241                        MachineUnaryOperatorReducerTest,
242                        ::testing::ValuesIn(kUnaryOperators));
243
244
245// -----------------------------------------------------------------------------
246// ChangeFloat64ToFloat32
247
248
249TEST_F(MachineOperatorReducerTest, ChangeFloat64ToFloat32WithConstant) {
250  TRACED_FOREACH(float, x, kFloat32Values) {
251    Reduction reduction = Reduce(graph()->NewNode(
252        machine()->ChangeFloat32ToFloat64(), Float32Constant(x)));
253    ASSERT_TRUE(reduction.Changed());
254    EXPECT_THAT(reduction.replacement(), IsFloat64Constant(x));
255  }
256}
257
258
259// -----------------------------------------------------------------------------
260// ChangeFloat64ToInt32
261
262
263TEST_F(MachineOperatorReducerTest,
264       ChangeFloat64ToInt32WithChangeInt32ToFloat64) {
265  Node* value = Parameter(0);
266  Reduction reduction = Reduce(graph()->NewNode(
267      machine()->ChangeFloat64ToInt32(),
268      graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
269  ASSERT_TRUE(reduction.Changed());
270  EXPECT_EQ(value, reduction.replacement());
271}
272
273
274TEST_F(MachineOperatorReducerTest, ChangeFloat64ToInt32WithConstant) {
275  TRACED_FOREACH(int32_t, x, kInt32Values) {
276    Reduction reduction = Reduce(graph()->NewNode(
277        machine()->ChangeFloat64ToInt32(), Float64Constant(FastI2D(x))));
278    ASSERT_TRUE(reduction.Changed());
279    EXPECT_THAT(reduction.replacement(), IsInt32Constant(x));
280  }
281}
282
283
284// -----------------------------------------------------------------------------
285// ChangeFloat64ToUint32
286
287
288TEST_F(MachineOperatorReducerTest,
289       ChangeFloat64ToUint32WithChangeUint32ToFloat64) {
290  Node* value = Parameter(0);
291  Reduction reduction = Reduce(graph()->NewNode(
292      machine()->ChangeFloat64ToUint32(),
293      graph()->NewNode(machine()->ChangeUint32ToFloat64(), value)));
294  ASSERT_TRUE(reduction.Changed());
295  EXPECT_EQ(value, reduction.replacement());
296}
297
298
299TEST_F(MachineOperatorReducerTest, ChangeFloat64ToUint32WithConstant) {
300  TRACED_FOREACH(uint32_t, x, kUint32Values) {
301    Reduction reduction = Reduce(graph()->NewNode(
302        machine()->ChangeFloat64ToUint32(), Float64Constant(FastUI2D(x))));
303    ASSERT_TRUE(reduction.Changed());
304    EXPECT_THAT(reduction.replacement(), IsInt32Constant(bit_cast<int32_t>(x)));
305  }
306}
307
308
309// -----------------------------------------------------------------------------
310// ChangeInt32ToFloat64
311
312
313TEST_F(MachineOperatorReducerTest, ChangeInt32ToFloat64WithConstant) {
314  TRACED_FOREACH(int32_t, x, kInt32Values) {
315    Reduction reduction = Reduce(
316        graph()->NewNode(machine()->ChangeInt32ToFloat64(), Int32Constant(x)));
317    ASSERT_TRUE(reduction.Changed());
318    EXPECT_THAT(reduction.replacement(), IsFloat64Constant(FastI2D(x)));
319  }
320}
321
322
323// -----------------------------------------------------------------------------
324// ChangeInt32ToInt64
325
326
327TEST_F(MachineOperatorReducerTest, ChangeInt32ToInt64WithConstant) {
328  TRACED_FOREACH(int32_t, x, kInt32Values) {
329    Reduction reduction = Reduce(
330        graph()->NewNode(machine()->ChangeInt32ToInt64(), Int32Constant(x)));
331    ASSERT_TRUE(reduction.Changed());
332    EXPECT_THAT(reduction.replacement(), IsInt64Constant(x));
333  }
334}
335
336
337// -----------------------------------------------------------------------------
338// ChangeUint32ToFloat64
339
340
341TEST_F(MachineOperatorReducerTest, ChangeUint32ToFloat64WithConstant) {
342  TRACED_FOREACH(uint32_t, x, kUint32Values) {
343    Reduction reduction =
344        Reduce(graph()->NewNode(machine()->ChangeUint32ToFloat64(),
345                                Int32Constant(bit_cast<int32_t>(x))));
346    ASSERT_TRUE(reduction.Changed());
347    EXPECT_THAT(reduction.replacement(), IsFloat64Constant(FastUI2D(x)));
348  }
349}
350
351
352// -----------------------------------------------------------------------------
353// ChangeUint32ToUint64
354
355
356TEST_F(MachineOperatorReducerTest, ChangeUint32ToUint64WithConstant) {
357  TRACED_FOREACH(uint32_t, x, kUint32Values) {
358    Reduction reduction =
359        Reduce(graph()->NewNode(machine()->ChangeUint32ToUint64(),
360                                Int32Constant(bit_cast<int32_t>(x))));
361    ASSERT_TRUE(reduction.Changed());
362    EXPECT_THAT(reduction.replacement(),
363                IsInt64Constant(bit_cast<int64_t>(static_cast<uint64_t>(x))));
364  }
365}
366
367
368// -----------------------------------------------------------------------------
369// TruncateFloat64ToFloat32
370
371
372TEST_F(MachineOperatorReducerTest,
373       TruncateFloat64ToFloat32WithChangeFloat32ToFloat64) {
374  Node* value = Parameter(0);
375  Reduction reduction = Reduce(graph()->NewNode(
376      machine()->TruncateFloat64ToFloat32(),
377      graph()->NewNode(machine()->ChangeFloat32ToFloat64(), value)));
378  ASSERT_TRUE(reduction.Changed());
379  EXPECT_EQ(value, reduction.replacement());
380}
381
382
383TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) {
384  TRACED_FOREACH(double, x, kFloat64Values) {
385    Reduction reduction = Reduce(graph()->NewNode(
386        machine()->TruncateFloat64ToFloat32(), Float64Constant(x)));
387    ASSERT_TRUE(reduction.Changed());
388    EXPECT_THAT(reduction.replacement(), IsFloat32Constant(DoubleToFloat32(x)));
389  }
390}
391
392
393// -----------------------------------------------------------------------------
394// TruncateFloat64ToInt32
395
396
397TEST_F(MachineOperatorReducerTest,
398       TruncateFloat64ToInt32WithChangeInt32ToFloat64) {
399  Node* value = Parameter(0);
400  Reduction reduction = Reduce(graph()->NewNode(
401      machine()->TruncateFloat64ToInt32(),
402      graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
403  ASSERT_TRUE(reduction.Changed());
404  EXPECT_EQ(value, reduction.replacement());
405}
406
407
408TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithConstant) {
409  TRACED_FOREACH(double, x, kFloat64Values) {
410    Reduction reduction = Reduce(graph()->NewNode(
411        machine()->TruncateFloat64ToInt32(), Float64Constant(x)));
412    ASSERT_TRUE(reduction.Changed());
413    EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
414  }
415}
416
417
418// -----------------------------------------------------------------------------
419// TruncateInt64ToInt32
420
421
422TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithChangeInt32ToInt64) {
423  Node* value = Parameter(0);
424  Reduction reduction = Reduce(graph()->NewNode(
425      machine()->TruncateInt64ToInt32(),
426      graph()->NewNode(machine()->ChangeInt32ToInt64(), value)));
427  ASSERT_TRUE(reduction.Changed());
428  EXPECT_EQ(value, reduction.replacement());
429}
430
431
432TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithConstant) {
433  TRACED_FOREACH(int64_t, x, kInt64Values) {
434    Reduction reduction = Reduce(
435        graph()->NewNode(machine()->TruncateInt64ToInt32(), Int64Constant(x)));
436    ASSERT_TRUE(reduction.Changed());
437    EXPECT_THAT(reduction.replacement(),
438                IsInt32Constant(bit_cast<int32_t>(
439                    static_cast<uint32_t>(bit_cast<uint64_t>(x)))));
440  }
441}
442
443
444// -----------------------------------------------------------------------------
445// Word32Ror
446
447
448TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithParameters) {
449  Node* value = Parameter(0);
450  Node* shift = Parameter(1);
451  Node* shl = graph()->NewNode(machine()->Word32Shl(), value, shift);
452  Node* shr = graph()->NewNode(
453      machine()->Word32Shr(), value,
454      graph()->NewNode(machine()->Int32Sub(), Int32Constant(32), shift));
455
456  // (x << y) | (x >> (32 - y)) => x ror y
457  Node* node1 = graph()->NewNode(machine()->Word32Or(), shl, shr);
458  Reduction reduction1 = Reduce(node1);
459  EXPECT_TRUE(reduction1.Changed());
460  EXPECT_EQ(reduction1.replacement(), node1);
461  EXPECT_THAT(reduction1.replacement(), IsWord32Ror(value, shift));
462
463  // (x >> (32 - y)) | (x << y) => x ror y
464  Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl);
465  Reduction reduction2 = Reduce(node2);
466  EXPECT_TRUE(reduction2.Changed());
467  EXPECT_EQ(reduction2.replacement(), node2);
468  EXPECT_THAT(reduction2.replacement(), IsWord32Ror(value, shift));
469}
470
471
472TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithConstant) {
473  Node* value = Parameter(0);
474  TRACED_FORRANGE(int32_t, k, 0, 31) {
475    Node* shl =
476        graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(k));
477    Node* shr =
478        graph()->NewNode(machine()->Word32Shr(), value, Int32Constant(32 - k));
479
480    // (x << K) | (x >> ((32 - K) - y)) => x ror K
481    Node* node1 = graph()->NewNode(machine()->Word32Or(), shl, shr);
482    Reduction reduction1 = Reduce(node1);
483    EXPECT_TRUE(reduction1.Changed());
484    EXPECT_EQ(reduction1.replacement(), node1);
485    EXPECT_THAT(reduction1.replacement(),
486                IsWord32Ror(value, IsInt32Constant(k)));
487
488    // (x >> (32 - K)) | (x << K) => x ror K
489    Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl);
490    Reduction reduction2 = Reduce(node2);
491    EXPECT_TRUE(reduction2.Changed());
492    EXPECT_EQ(reduction2.replacement(), node2);
493    EXPECT_THAT(reduction2.replacement(),
494                IsWord32Ror(value, IsInt32Constant(k)));
495  }
496}
497
498
499TEST_F(MachineOperatorReducerTest, Word32RorWithZeroShift) {
500  Node* value = Parameter(0);
501  Node* node =
502      graph()->NewNode(machine()->Word32Ror(), value, Int32Constant(0));
503  Reduction reduction = Reduce(node);
504  EXPECT_TRUE(reduction.Changed());
505  EXPECT_EQ(reduction.replacement(), value);
506}
507
508
509TEST_F(MachineOperatorReducerTest, Word32RorWithConstants) {
510  TRACED_FOREACH(int32_t, x, kUint32Values) {
511    TRACED_FORRANGE(int32_t, y, 0, 31) {
512      Node* node = graph()->NewNode(machine()->Word32Ror(), Int32Constant(x),
513                                    Int32Constant(y));
514      Reduction reduction = Reduce(node);
515      EXPECT_TRUE(reduction.Changed());
516      EXPECT_THAT(reduction.replacement(),
517                  IsInt32Constant(base::bits::RotateRight32(x, y)));
518    }
519  }
520}
521
522
523// -----------------------------------------------------------------------------
524// Int32AddWithOverflow
525
526
527TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) {
528  Node* p0 = Parameter(0);
529  {
530    Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
531                                 Int32Constant(0), p0);
532
533    Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
534    ASSERT_TRUE(r.Changed());
535    EXPECT_THAT(r.replacement(), IsInt32Constant(0));
536
537    r = Reduce(graph()->NewNode(common()->Projection(0), add));
538    ASSERT_TRUE(r.Changed());
539    EXPECT_EQ(p0, r.replacement());
540  }
541  {
542    Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), p0,
543                                 Int32Constant(0));
544
545    Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
546    ASSERT_TRUE(r.Changed());
547    EXPECT_THAT(r.replacement(), IsInt32Constant(0));
548
549    r = Reduce(graph()->NewNode(common()->Projection(0), add));
550    ASSERT_TRUE(r.Changed());
551    EXPECT_EQ(p0, r.replacement());
552  }
553}
554
555
556TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) {
557  TRACED_FOREACH(int32_t, x, kInt32Values) {
558    TRACED_FOREACH(int32_t, y, kInt32Values) {
559      int32_t z;
560      Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
561                                   Int32Constant(x), Int32Constant(y));
562
563      Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
564      ASSERT_TRUE(r.Changed());
565      EXPECT_THAT(r.replacement(),
566                  IsInt32Constant(base::bits::SignedAddOverflow32(x, y, &z)));
567
568      r = Reduce(graph()->NewNode(common()->Projection(0), add));
569      ASSERT_TRUE(r.Changed());
570      EXPECT_THAT(r.replacement(), IsInt32Constant(z));
571    }
572  }
573}
574
575
576// -----------------------------------------------------------------------------
577// Int32SubWithOverflow
578
579
580TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithZero) {
581  Node* p0 = Parameter(0);
582  Node* add =
583      graph()->NewNode(machine()->Int32SubWithOverflow(), p0, Int32Constant(0));
584
585  Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
586  ASSERT_TRUE(r.Changed());
587  EXPECT_THAT(r.replacement(), IsInt32Constant(0));
588
589  r = Reduce(graph()->NewNode(common()->Projection(0), add));
590  ASSERT_TRUE(r.Changed());
591  EXPECT_EQ(p0, r.replacement());
592}
593
594
595TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
596  TRACED_FOREACH(int32_t, x, kInt32Values) {
597    TRACED_FOREACH(int32_t, y, kInt32Values) {
598      int32_t z;
599      Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(),
600                                   Int32Constant(x), Int32Constant(y));
601
602      Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
603      ASSERT_TRUE(r.Changed());
604      EXPECT_THAT(r.replacement(),
605                  IsInt32Constant(base::bits::SignedSubOverflow32(x, y, &z)));
606
607      r = Reduce(graph()->NewNode(common()->Projection(0), add));
608      ASSERT_TRUE(r.Changed());
609      EXPECT_THAT(r.replacement(), IsInt32Constant(z));
610    }
611  }
612}
613
614}  // namespace compiler
615}  // namespace internal
616}  // namespace v8
617