• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/compiler/machine-operator-reducer.h"
6 #include "src/base/bits.h"
7 #include "src/base/division-by-constant.h"
8 #include "src/base/ieee754.h"
9 #include "src/compiler/js-graph.h"
10 #include "src/compiler/typer.h"
11 #include "src/conversions-inl.h"
12 #include "test/unittests/compiler/graph-unittest.h"
13 #include "test/unittests/compiler/node-test-utils.h"
14 #include "testing/gmock-support.h"
15 
16 using testing::AllOf;
17 using testing::BitEq;
18 using testing::Capture;
19 using testing::CaptureEq;
20 using testing::NanSensitiveDoubleEq;
21 
22 namespace v8 {
23 namespace internal {
24 namespace compiler {
25 
26 class MachineOperatorReducerTest : public TypedGraphTest {
27  public:
MachineOperatorReducerTest(int num_parameters=2)28   explicit MachineOperatorReducerTest(int num_parameters = 2)
29       : TypedGraphTest(num_parameters), machine_(zone()) {}
30 
31  protected:
Reduce(Node * node)32   Reduction Reduce(Node* node) {
33     JSOperatorBuilder javascript(zone());
34     JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
35                     &machine_);
36     MachineOperatorReducer reducer(&jsgraph);
37     return reducer.Reduce(node);
38   }
39 
IsTruncatingDiv(const Matcher<Node * > & dividend_matcher,const int32_t divisor)40   Matcher<Node*> IsTruncatingDiv(const Matcher<Node*>& dividend_matcher,
41                                  const int32_t divisor) {
42     base::MagicNumbersForDivision<uint32_t> const mag =
43         base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
44     int32_t const multiplier = bit_cast<int32_t>(mag.multiplier);
45     int32_t const shift = bit_cast<int32_t>(mag.shift);
46     Matcher<Node*> quotient_matcher =
47         IsInt32MulHigh(dividend_matcher, IsInt32Constant(multiplier));
48     if (divisor > 0 && multiplier < 0) {
49       quotient_matcher = IsInt32Add(quotient_matcher, dividend_matcher);
50     } else if (divisor < 0 && multiplier > 0) {
51       quotient_matcher = IsInt32Sub(quotient_matcher, dividend_matcher);
52     }
53     if (shift) {
54       quotient_matcher = IsWord32Sar(quotient_matcher, IsInt32Constant(shift));
55     }
56     return IsInt32Add(quotient_matcher,
57                       IsWord32Shr(dividend_matcher, IsInt32Constant(31)));
58   }
59 
machine()60   MachineOperatorBuilder* machine() { return &machine_; }
61 
62  private:
63   MachineOperatorBuilder machine_;
64 };
65 
66 
67 template <typename T>
68 class MachineOperatorReducerTestWithParam
69     : public MachineOperatorReducerTest,
70       public ::testing::WithParamInterface<T> {
71  public:
MachineOperatorReducerTestWithParam(int num_parameters=2)72   explicit MachineOperatorReducerTestWithParam(int num_parameters = 2)
73       : MachineOperatorReducerTest(num_parameters) {}
~MachineOperatorReducerTestWithParam()74   ~MachineOperatorReducerTestWithParam() override {}
75 };
76 
77 
78 namespace {
79 
80 const float kFloat32Values[] = {
81     -std::numeric_limits<float>::infinity(), -2.70497e+38f, -1.4698e+37f,
82     -1.22813e+35f,                           -1.20555e+35f, -1.34584e+34f,
83     -1.0079e+32f,                            -6.49364e+26f, -3.06077e+25f,
84     -1.46821e+25f,                           -1.17658e+23f, -1.9617e+22f,
85     -2.7357e+20f,                            -1.48708e+13f, -1.89633e+12f,
86     -4.66622e+11f,                           -2.22581e+11f, -1.45381e+10f,
87     -1.3956e+09f,                            -1.32951e+09f, -1.30721e+09f,
88     -1.19756e+09f,                           -9.26822e+08f, -6.35647e+08f,
89     -4.00037e+08f,                           -1.81227e+08f, -5.09256e+07f,
90     -964300.0f,                              -192446.0f,    -28455.0f,
91     -27194.0f,                               -26401.0f,     -20575.0f,
92     -17069.0f,                               -9167.0f,      -960.178f,
93     -113.0f,                                 -62.0f,        -15.0f,
94     -7.0f,                                   -0.0256635f,   -4.60374e-07f,
95     -3.63759e-10f,                           -4.30175e-14f, -5.27385e-15f,
96     -1.48084e-15f,                           -1.05755e-19f, -3.2995e-21f,
97     -1.67354e-23f,                           -1.11885e-23f, -1.78506e-30f,
98     -5.07594e-31f,                           -3.65799e-31f, -1.43718e-34f,
99     -1.27126e-38f,                           -0.0f,         0.0f,
100     1.17549e-38f,                            1.56657e-37f,  4.08512e-29f,
101     3.31357e-28f,                            6.25073e-22f,  4.1723e-13f,
102     1.44343e-09f,                            5.27004e-08f,  9.48298e-08f,
103     5.57888e-07f,                            4.89988e-05f,  0.244326f,
104     12.4895f,                                19.0f,         47.0f,
105     106.0f,                                  538.324f,      564.536f,
106     819.124f,                                7048.0f,       12611.0f,
107     19878.0f,                                20309.0f,      797056.0f,
108     1.77219e+09f,                            1.51116e+11f,  4.18193e+13f,
109     3.59167e+16f,                            3.38211e+19f,  2.67488e+20f,
110     1.78831e+21f,                            9.20914e+21f,  8.35654e+23f,
111     1.4495e+24f,                             5.94015e+25f,  4.43608e+30f,
112     2.44502e+33f,                            2.61152e+33f,  1.38178e+37f,
113     1.71306e+37f,                            3.31899e+38f,  3.40282e+38f,
114     std::numeric_limits<float>::infinity()};
115 
116 
117 const double kFloat64Values[] = {
118     -V8_INFINITY,  -4.23878e+275, -5.82632e+265, -6.60355e+220, -6.26172e+212,
119     -2.56222e+211, -4.82408e+201, -1.84106e+157, -1.63662e+127, -1.55772e+100,
120     -1.67813e+72,  -2.3382e+55,   -3.179e+30,    -1.441e+09,    -1.0647e+09,
121     -7.99361e+08,  -5.77375e+08,  -2.20984e+08,  -32757,        -13171,
122     -9970,         -3984,         -107,          -105,          -92,
123     -77,           -61,           -0.000208163,  -1.86685e-06,  -1.17296e-10,
124     -9.26358e-11,  -5.08004e-60,  -1.74753e-65,  -1.06561e-71,  -5.67879e-79,
125     -5.78459e-130, -2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263,
126     -4.40497e-267, -2.19666e-273, -4.9998e-276,  -5.59821e-278, -2.03855e-282,
127     -5.99335e-283, -7.17554e-284, -3.11744e-309, -0.0,          0.0,
128     2.22507e-308,  1.30127e-270,  7.62898e-260,  4.00313e-249,  3.16829e-233,
129     1.85244e-228,  2.03544e-129,  1.35126e-110,  1.01182e-106,  5.26333e-94,
130     1.35292e-90,   2.85394e-83,   1.78323e-77,   5.4967e-57,    1.03207e-25,
131     4.57401e-25,   1.58738e-05,   2,             125,           2310,
132     9636,          14802,         17168,         28945,         29305,
133     4.81336e+07,   1.41207e+08,   4.65962e+08,   1.40499e+09,   2.12648e+09,
134     8.80006e+30,   1.4446e+45,    1.12164e+54,   2.48188e+89,   6.71121e+102,
135     3.074e+112,    4.9699e+152,   5.58383e+166,  4.30654e+172,  7.08824e+185,
136     9.6586e+214,   2.028e+223,    6.63277e+243,  1.56192e+261,  1.23202e+269,
137     5.72883e+289,  8.5798e+290,   1.40256e+294,  1.79769e+308,  V8_INFINITY};
138 
139 
140 const int32_t kInt32Values[] = {
141     std::numeric_limits<int32_t>::min(), -1914954528, -1698749618,
142     -1578693386,                         -1577976073, -1573998034,
143     -1529085059,                         -1499540537, -1299205097,
144     -1090814845,                         -938186388,  -806828902,
145     -750927650,                          -520676892,  -513661538,
146     -453036354,                          -433622833,  -282638793,
147     -28375,                              -27788,      -22770,
148     -18806,                              -14173,      -11956,
149     -11200,                              -10212,      -8160,
150     -3751,                               -2758,       -1522,
151     -121,                                -120,        -118,
152     -117,                                -106,        -84,
153     -80,                                 -74,         -59,
154     -52,                                 -48,         -39,
155     -35,                                 -17,         -11,
156     -10,                                 -9,          -7,
157     -5,                                  0,           9,
158     12,                                  17,          23,
159     29,                                  31,          33,
160     35,                                  40,          47,
161     55,                                  56,          62,
162     64,                                  67,          68,
163     69,                                  74,          79,
164     84,                                  89,          90,
165     97,                                  104,         118,
166     124,                                 126,         127,
167     7278,                                17787,       24136,
168     24202,                               25570,       26680,
169     30242,                               32399,       420886487,
170     642166225,                           821912648,   822577803,
171     851385718,                           1212241078,  1411419304,
172     1589626102,                          1596437184,  1876245816,
173     1954730266,                          2008792749,  2045320228,
174     std::numeric_limits<int32_t>::max()};
175 
176 
177 const int64_t kInt64Values[] = {
178     std::numeric_limits<int64_t>::min(), V8_INT64_C(-8974392461363618006),
179     V8_INT64_C(-8874367046689588135),    V8_INT64_C(-8269197512118230839),
180     V8_INT64_C(-8146091527100606733),    V8_INT64_C(-7550917981466150848),
181     V8_INT64_C(-7216590251577894337),    V8_INT64_C(-6464086891160048440),
182     V8_INT64_C(-6365616494908257190),    V8_INT64_C(-6305630541365849726),
183     V8_INT64_C(-5982222642272245453),    V8_INT64_C(-5510103099058504169),
184     V8_INT64_C(-5496838675802432701),    V8_INT64_C(-4047626578868642657),
185     V8_INT64_C(-4033755046900164544),    V8_INT64_C(-3554299241457877041),
186     V8_INT64_C(-2482258764588614470),    V8_INT64_C(-1688515425526875335),
187     V8_INT64_C(-924784137176548532),     V8_INT64_C(-725316567157391307),
188     V8_INT64_C(-439022654781092241),     V8_INT64_C(-105545757668917080),
189     V8_INT64_C(-2088319373),             V8_INT64_C(-2073699916),
190     V8_INT64_C(-1844949911),             V8_INT64_C(-1831090548),
191     V8_INT64_C(-1756711933),             V8_INT64_C(-1559409497),
192     V8_INT64_C(-1281179700),             V8_INT64_C(-1211513985),
193     V8_INT64_C(-1182371520),             V8_INT64_C(-785934753),
194     V8_INT64_C(-767480697),              V8_INT64_C(-705745662),
195     V8_INT64_C(-514362436),              V8_INT64_C(-459916580),
196     V8_INT64_C(-312328082),              V8_INT64_C(-302949707),
197     V8_INT64_C(-285499304),              V8_INT64_C(-125701262),
198     V8_INT64_C(-95139843),               V8_INT64_C(-32768),
199     V8_INT64_C(-27542),                  V8_INT64_C(-23600),
200     V8_INT64_C(-18582),                  V8_INT64_C(-17770),
201     V8_INT64_C(-9086),                   V8_INT64_C(-9010),
202     V8_INT64_C(-8244),                   V8_INT64_C(-2890),
203     V8_INT64_C(-103),                    V8_INT64_C(-34),
204     V8_INT64_C(-27),                     V8_INT64_C(-25),
205     V8_INT64_C(-9),                      V8_INT64_C(-7),
206     V8_INT64_C(0),                       V8_INT64_C(2),
207     V8_INT64_C(38),                      V8_INT64_C(58),
208     V8_INT64_C(65),                      V8_INT64_C(93),
209     V8_INT64_C(111),                     V8_INT64_C(1003),
210     V8_INT64_C(1267),                    V8_INT64_C(12797),
211     V8_INT64_C(23122),                   V8_INT64_C(28200),
212     V8_INT64_C(30888),                   V8_INT64_C(42648848),
213     V8_INT64_C(116836693),               V8_INT64_C(263003643),
214     V8_INT64_C(571039860),               V8_INT64_C(1079398689),
215     V8_INT64_C(1145196402),              V8_INT64_C(1184846321),
216     V8_INT64_C(1758281648),              V8_INT64_C(1859991374),
217     V8_INT64_C(1960251588),              V8_INT64_C(2042443199),
218     V8_INT64_C(296220586027987448),      V8_INT64_C(1015494173071134726),
219     V8_INT64_C(1151237951914455318),     V8_INT64_C(1331941174616854174),
220     V8_INT64_C(2022020418667972654),     V8_INT64_C(2450251424374977035),
221     V8_INT64_C(3668393562685561486),     V8_INT64_C(4858229301215502171),
222     V8_INT64_C(4919426235170669383),     V8_INT64_C(5034286595330341762),
223     V8_INT64_C(5055797915536941182),     V8_INT64_C(6072389716149252074),
224     V8_INT64_C(6185309910199801210),     V8_INT64_C(6297328311011094138),
225     V8_INT64_C(6932372858072165827),     V8_INT64_C(8483640924987737210),
226     V8_INT64_C(8663764179455849203),     V8_INT64_C(8877197042645298254),
227     V8_INT64_C(8901543506779157333),     std::numeric_limits<int64_t>::max()};
228 
229 
230 const uint32_t kUint32Values[] = {
231     0x00000000, 0x00000001, 0xffffffff, 0x1b09788b, 0x04c5fce8, 0xcc0de5bf,
232     0x273a798e, 0x187937a3, 0xece3af83, 0x5495a16b, 0x0b668ecc, 0x11223344,
233     0x0000009e, 0x00000043, 0x0000af73, 0x0000116b, 0x00658ecc, 0x002b3b4c,
234     0x88776655, 0x70000000, 0x07200000, 0x7fffffff, 0x56123761, 0x7fffff00,
235     0x761c4761, 0x80000000, 0x88888888, 0xa0000000, 0xdddddddd, 0xe0000000,
236     0xeeeeeeee, 0xfffffffd, 0xf0000000, 0x007fffff, 0x003fffff, 0x001fffff,
237     0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff,
238     0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
239 
240 
241 struct ComparisonBinaryOperator {
242   const Operator* (MachineOperatorBuilder::*constructor)();
243   const char* constructor_name;
244 };
245 
246 
operator <<(std::ostream & os,ComparisonBinaryOperator const & cbop)247 std::ostream& operator<<(std::ostream& os,
248                          ComparisonBinaryOperator const& cbop) {
249   return os << cbop.constructor_name;
250 }
251 
252 
253 const ComparisonBinaryOperator kComparisonBinaryOperators[] = {
254 #define OPCODE(Opcode)                         \
255   { &MachineOperatorBuilder::Opcode, #Opcode } \
256   ,
257     MACHINE_COMPARE_BINOP_LIST(OPCODE)
258 #undef OPCODE
259 };
260 
261 }  // namespace
262 
263 
264 // -----------------------------------------------------------------------------
265 // ChangeFloat64ToFloat32
266 
267 
TEST_F(MachineOperatorReducerTest,ChangeFloat64ToFloat32WithConstant)268 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToFloat32WithConstant) {
269   TRACED_FOREACH(float, x, kFloat32Values) {
270     Reduction reduction = Reduce(graph()->NewNode(
271         machine()->ChangeFloat32ToFloat64(), Float32Constant(x)));
272     ASSERT_TRUE(reduction.Changed());
273     EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq<double>(x)));
274   }
275 }
276 
277 
278 // -----------------------------------------------------------------------------
279 // ChangeFloat64ToInt32
280 
281 
TEST_F(MachineOperatorReducerTest,ChangeFloat64ToInt32WithChangeInt32ToFloat64)282 TEST_F(MachineOperatorReducerTest,
283        ChangeFloat64ToInt32WithChangeInt32ToFloat64) {
284   Node* value = Parameter(0);
285   Reduction reduction = Reduce(graph()->NewNode(
286       machine()->ChangeFloat64ToInt32(),
287       graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
288   ASSERT_TRUE(reduction.Changed());
289   EXPECT_EQ(value, reduction.replacement());
290 }
291 
292 
TEST_F(MachineOperatorReducerTest,ChangeFloat64ToInt32WithConstant)293 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToInt32WithConstant) {
294   TRACED_FOREACH(int32_t, x, kInt32Values) {
295     Reduction reduction = Reduce(graph()->NewNode(
296         machine()->ChangeFloat64ToInt32(), Float64Constant(FastI2D(x))));
297     ASSERT_TRUE(reduction.Changed());
298     EXPECT_THAT(reduction.replacement(), IsInt32Constant(x));
299   }
300 }
301 
302 
303 // -----------------------------------------------------------------------------
304 // ChangeFloat64ToUint32
305 
306 
TEST_F(MachineOperatorReducerTest,ChangeFloat64ToUint32WithChangeUint32ToFloat64)307 TEST_F(MachineOperatorReducerTest,
308        ChangeFloat64ToUint32WithChangeUint32ToFloat64) {
309   Node* value = Parameter(0);
310   Reduction reduction = Reduce(graph()->NewNode(
311       machine()->ChangeFloat64ToUint32(),
312       graph()->NewNode(machine()->ChangeUint32ToFloat64(), value)));
313   ASSERT_TRUE(reduction.Changed());
314   EXPECT_EQ(value, reduction.replacement());
315 }
316 
317 
TEST_F(MachineOperatorReducerTest,ChangeFloat64ToUint32WithConstant)318 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToUint32WithConstant) {
319   TRACED_FOREACH(uint32_t, x, kUint32Values) {
320     Reduction reduction = Reduce(graph()->NewNode(
321         machine()->ChangeFloat64ToUint32(), Float64Constant(FastUI2D(x))));
322     ASSERT_TRUE(reduction.Changed());
323     EXPECT_THAT(reduction.replacement(), IsInt32Constant(bit_cast<int32_t>(x)));
324   }
325 }
326 
327 
328 // -----------------------------------------------------------------------------
329 // ChangeInt32ToFloat64
330 
331 
TEST_F(MachineOperatorReducerTest,ChangeInt32ToFloat64WithConstant)332 TEST_F(MachineOperatorReducerTest, ChangeInt32ToFloat64WithConstant) {
333   TRACED_FOREACH(int32_t, x, kInt32Values) {
334     Reduction reduction = Reduce(
335         graph()->NewNode(machine()->ChangeInt32ToFloat64(), Int32Constant(x)));
336     ASSERT_TRUE(reduction.Changed());
337     EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastI2D(x))));
338   }
339 }
340 
341 
342 // -----------------------------------------------------------------------------
343 // ChangeInt32ToInt64
344 
345 
TEST_F(MachineOperatorReducerTest,ChangeInt32ToInt64WithConstant)346 TEST_F(MachineOperatorReducerTest, ChangeInt32ToInt64WithConstant) {
347   TRACED_FOREACH(int32_t, x, kInt32Values) {
348     Reduction reduction = Reduce(
349         graph()->NewNode(machine()->ChangeInt32ToInt64(), Int32Constant(x)));
350     ASSERT_TRUE(reduction.Changed());
351     EXPECT_THAT(reduction.replacement(), IsInt64Constant(x));
352   }
353 }
354 
355 
356 // -----------------------------------------------------------------------------
357 // ChangeUint32ToFloat64
358 
359 
TEST_F(MachineOperatorReducerTest,ChangeUint32ToFloat64WithConstant)360 TEST_F(MachineOperatorReducerTest, ChangeUint32ToFloat64WithConstant) {
361   TRACED_FOREACH(uint32_t, x, kUint32Values) {
362     Reduction reduction =
363         Reduce(graph()->NewNode(machine()->ChangeUint32ToFloat64(),
364                                 Int32Constant(bit_cast<int32_t>(x))));
365     ASSERT_TRUE(reduction.Changed());
366     EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastUI2D(x))));
367   }
368 }
369 
370 
371 // -----------------------------------------------------------------------------
372 // ChangeUint32ToUint64
373 
374 
TEST_F(MachineOperatorReducerTest,ChangeUint32ToUint64WithConstant)375 TEST_F(MachineOperatorReducerTest, ChangeUint32ToUint64WithConstant) {
376   TRACED_FOREACH(uint32_t, x, kUint32Values) {
377     Reduction reduction =
378         Reduce(graph()->NewNode(machine()->ChangeUint32ToUint64(),
379                                 Int32Constant(bit_cast<int32_t>(x))));
380     ASSERT_TRUE(reduction.Changed());
381     EXPECT_THAT(reduction.replacement(),
382                 IsInt64Constant(bit_cast<int64_t>(static_cast<uint64_t>(x))));
383   }
384 }
385 
386 
387 // -----------------------------------------------------------------------------
388 // TruncateFloat64ToFloat32
389 
390 
TEST_F(MachineOperatorReducerTest,TruncateFloat64ToFloat32WithChangeFloat32ToFloat64)391 TEST_F(MachineOperatorReducerTest,
392        TruncateFloat64ToFloat32WithChangeFloat32ToFloat64) {
393   Node* value = Parameter(0);
394   Reduction reduction = Reduce(graph()->NewNode(
395       machine()->TruncateFloat64ToFloat32(),
396       graph()->NewNode(machine()->ChangeFloat32ToFloat64(), value)));
397   ASSERT_TRUE(reduction.Changed());
398   EXPECT_EQ(value, reduction.replacement());
399 }
400 
401 
TEST_F(MachineOperatorReducerTest,TruncateFloat64ToFloat32WithConstant)402 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) {
403   TRACED_FOREACH(double, x, kFloat64Values) {
404     Reduction reduction = Reduce(graph()->NewNode(
405         machine()->TruncateFloat64ToFloat32(), Float64Constant(x)));
406     ASSERT_TRUE(reduction.Changed());
407     EXPECT_THAT(reduction.replacement(),
408                 IsFloat32Constant(BitEq(DoubleToFloat32(x))));
409   }
410 }
411 
412 
413 // -----------------------------------------------------------------------------
414 // TruncateFloat64ToWord32
415 
TEST_F(MachineOperatorReducerTest,TruncateFloat64ToWord32WithChangeInt32ToFloat64)416 TEST_F(MachineOperatorReducerTest,
417        TruncateFloat64ToWord32WithChangeInt32ToFloat64) {
418   Node* value = Parameter(0);
419   Reduction reduction = Reduce(graph()->NewNode(
420       machine()->TruncateFloat64ToWord32(),
421       graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
422   ASSERT_TRUE(reduction.Changed());
423   EXPECT_EQ(value, reduction.replacement());
424 }
425 
TEST_F(MachineOperatorReducerTest,TruncateFloat64ToWord32WithConstant)426 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToWord32WithConstant) {
427   TRACED_FOREACH(double, x, kFloat64Values) {
428     Reduction reduction = Reduce(graph()->NewNode(
429         machine()->TruncateFloat64ToWord32(), Float64Constant(x)));
430     ASSERT_TRUE(reduction.Changed());
431     EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
432   }
433 }
434 
435 
436 // -----------------------------------------------------------------------------
437 // TruncateInt64ToInt32
438 
439 
TEST_F(MachineOperatorReducerTest,TruncateInt64ToInt32WithChangeInt32ToInt64)440 TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithChangeInt32ToInt64) {
441   Node* value = Parameter(0);
442   Reduction reduction = Reduce(graph()->NewNode(
443       machine()->TruncateInt64ToInt32(),
444       graph()->NewNode(machine()->ChangeInt32ToInt64(), value)));
445   ASSERT_TRUE(reduction.Changed());
446   EXPECT_EQ(value, reduction.replacement());
447 }
448 
449 
TEST_F(MachineOperatorReducerTest,TruncateInt64ToInt32WithConstant)450 TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithConstant) {
451   TRACED_FOREACH(int64_t, x, kInt64Values) {
452     Reduction reduction = Reduce(
453         graph()->NewNode(machine()->TruncateInt64ToInt32(), Int64Constant(x)));
454     ASSERT_TRUE(reduction.Changed());
455     EXPECT_THAT(reduction.replacement(),
456                 IsInt32Constant(bit_cast<int32_t>(
457                     static_cast<uint32_t>(bit_cast<uint64_t>(x)))));
458   }
459 }
460 
461 
462 // -----------------------------------------------------------------------------
463 // RoundFloat64ToInt32
464 
TEST_F(MachineOperatorReducerTest,RoundFloat64ToInt32WithChangeInt32ToFloat64)465 TEST_F(MachineOperatorReducerTest,
466        RoundFloat64ToInt32WithChangeInt32ToFloat64) {
467   Node* value = Parameter(0);
468   Reduction reduction = Reduce(graph()->NewNode(
469       machine()->RoundFloat64ToInt32(),
470       graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
471   ASSERT_TRUE(reduction.Changed());
472   EXPECT_EQ(value, reduction.replacement());
473 }
474 
TEST_F(MachineOperatorReducerTest,RoundFloat64ToInt32WithConstant)475 TEST_F(MachineOperatorReducerTest, RoundFloat64ToInt32WithConstant) {
476   TRACED_FOREACH(double, x, kFloat64Values) {
477     Reduction reduction = Reduce(
478         graph()->NewNode(machine()->RoundFloat64ToInt32(), Float64Constant(x)));
479     ASSERT_TRUE(reduction.Changed());
480     EXPECT_THAT(reduction.replacement(),
481                 IsInt32Constant(static_cast<int32_t>(x)));
482   }
483 }
484 
485 // -----------------------------------------------------------------------------
486 // Word32And
487 
TEST_F(MachineOperatorReducerTest,Word32AndWithWord32ShlWithConstant)488 TEST_F(MachineOperatorReducerTest, Word32AndWithWord32ShlWithConstant) {
489   Node* const p0 = Parameter(0);
490 
491   TRACED_FORRANGE(int32_t, l, 1, 31) {
492     TRACED_FORRANGE(int32_t, k, 1, l) {
493       // (x << L) & (-1 << K) => x << L
494       Reduction const r1 = Reduce(graph()->NewNode(
495           machine()->Word32And(),
496           graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l)),
497           Int32Constant(-1 << k)));
498       ASSERT_TRUE(r1.Changed());
499       EXPECT_THAT(r1.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
500 
501       // (-1 << K) & (x << L) => x << L
502       Reduction const r2 = Reduce(graph()->NewNode(
503           machine()->Word32And(), Int32Constant(-1 << k),
504           graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l))));
505       ASSERT_TRUE(r2.Changed());
506       EXPECT_THAT(r2.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
507     }
508   }
509 }
510 
511 
TEST_F(MachineOperatorReducerTest,Word32AndWithWord32AndWithConstant)512 TEST_F(MachineOperatorReducerTest, Word32AndWithWord32AndWithConstant) {
513   Node* const p0 = Parameter(0);
514 
515   TRACED_FOREACH(int32_t, k, kInt32Values) {
516     TRACED_FOREACH(int32_t, l, kInt32Values) {
517       if (k == 0 || k == -1 || l == 0 || l == -1) continue;
518 
519       // (x & K) & L => x & (K & L)
520       Reduction const r1 = Reduce(graph()->NewNode(
521           machine()->Word32And(),
522           graph()->NewNode(machine()->Word32And(), p0, Int32Constant(k)),
523           Int32Constant(l)));
524       ASSERT_TRUE(r1.Changed());
525       EXPECT_THAT(r1.replacement(),
526                   (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
527                           : IsInt32Constant(0));
528 
529       // (K & x) & L => x & (K & L)
530       Reduction const r2 = Reduce(graph()->NewNode(
531           machine()->Word32And(),
532           graph()->NewNode(machine()->Word32And(), Int32Constant(k), p0),
533           Int32Constant(l)));
534       ASSERT_TRUE(r2.Changed());
535       EXPECT_THAT(r2.replacement(),
536                   (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
537                           : IsInt32Constant(0));
538     }
539   }
540 }
541 
542 
TEST_F(MachineOperatorReducerTest,Word32AndWithInt32AddAndConstant)543 TEST_F(MachineOperatorReducerTest, Word32AndWithInt32AddAndConstant) {
544   Node* const p0 = Parameter(0);
545   Node* const p1 = Parameter(1);
546 
547   TRACED_FORRANGE(int32_t, l, 1, 31) {
548     TRACED_FOREACH(int32_t, k, kInt32Values) {
549       if ((k << l) == 0) continue;
550       // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
551       Reduction const r = Reduce(graph()->NewNode(
552           machine()->Word32And(),
553           graph()->NewNode(machine()->Int32Add(), p0, Int32Constant(k << l)),
554           Int32Constant(-1 << l)));
555       ASSERT_TRUE(r.Changed());
556       EXPECT_THAT(r.replacement(),
557                   IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
558                              IsInt32Constant(k << l)));
559     }
560 
561     Node* s1 = graph()->NewNode(machine()->Word32Shl(), p1, Int32Constant(l));
562 
563     // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
564     Reduction const r1 = Reduce(graph()->NewNode(
565         machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), s1, p0),
566         Int32Constant(-1 << l)));
567     ASSERT_TRUE(r1.Changed());
568     EXPECT_THAT(r1.replacement(),
569                 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)), s1));
570 
571     // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
572     Reduction const r2 = Reduce(graph()->NewNode(
573         machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), p0, s1),
574         Int32Constant(-1 << l)));
575     ASSERT_TRUE(r2.Changed());
576     EXPECT_THAT(r2.replacement(),
577                 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)), s1));
578   }
579 }
580 
581 
TEST_F(MachineOperatorReducerTest,Word32AndWithInt32MulAndConstant)582 TEST_F(MachineOperatorReducerTest, Word32AndWithInt32MulAndConstant) {
583   Node* const p0 = Parameter(0);
584 
585   TRACED_FORRANGE(int32_t, l, 1, 31) {
586     TRACED_FOREACH(int32_t, k, kInt32Values) {
587       if ((k << l) == 0) continue;
588 
589       // (x * (K << L)) & (-1 << L) => x * (K << L)
590       Reduction const r1 = Reduce(graph()->NewNode(
591           machine()->Word32And(),
592           graph()->NewNode(machine()->Int32Mul(), p0, Int32Constant(k << l)),
593           Int32Constant(-1 << l)));
594       ASSERT_TRUE(r1.Changed());
595       EXPECT_THAT(r1.replacement(), IsInt32Mul(p0, IsInt32Constant(k << l)));
596 
597       // ((K << L) * x) & (-1 << L) => x * (K << L)
598       Reduction const r2 = Reduce(graph()->NewNode(
599           machine()->Word32And(),
600           graph()->NewNode(machine()->Int32Mul(), Int32Constant(k << l), p0),
601           Int32Constant(-1 << l)));
602       ASSERT_TRUE(r2.Changed());
603       EXPECT_THAT(r2.replacement(), IsInt32Mul(p0, IsInt32Constant(k << l)));
604     }
605   }
606 }
607 
608 
TEST_F(MachineOperatorReducerTest,Word32AndWithInt32AddAndInt32MulAndConstant)609 TEST_F(MachineOperatorReducerTest,
610        Word32AndWithInt32AddAndInt32MulAndConstant) {
611   Node* const p0 = Parameter(0);
612   Node* const p1 = Parameter(1);
613 
614   TRACED_FORRANGE(int32_t, l, 1, 31) {
615     TRACED_FOREACH(int32_t, k, kInt32Values) {
616       if ((k << l) == 0) continue;
617       // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
618       Reduction const r1 = Reduce(graph()->NewNode(
619           machine()->Word32And(),
620           graph()->NewNode(machine()->Int32Add(),
621                            graph()->NewNode(machine()->Int32Mul(), p1,
622                                             Int32Constant(k << l)),
623                            p0),
624           Int32Constant(-1 << l)));
625       ASSERT_TRUE(r1.Changed());
626       EXPECT_THAT(r1.replacement(),
627                   IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
628                              IsInt32Mul(p1, IsInt32Constant(k << l))));
629 
630       // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
631       Reduction const r2 = Reduce(graph()->NewNode(
632           machine()->Word32And(),
633           graph()->NewNode(machine()->Int32Add(), p0,
634                            graph()->NewNode(machine()->Int32Mul(), p1,
635                                             Int32Constant(k << l))),
636           Int32Constant(-1 << l)));
637       ASSERT_TRUE(r2.Changed());
638       EXPECT_THAT(r2.replacement(),
639                   IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
640                              IsInt32Mul(p1, IsInt32Constant(k << l))));
641     }
642   }
643 }
644 
645 
TEST_F(MachineOperatorReducerTest,Word32AndWithComparisonAndConstantOne)646 TEST_F(MachineOperatorReducerTest, Word32AndWithComparisonAndConstantOne) {
647   Node* const p0 = Parameter(0);
648   Node* const p1 = Parameter(1);
649   TRACED_FOREACH(ComparisonBinaryOperator, cbop, kComparisonBinaryOperators) {
650     Node* cmp = graph()->NewNode((machine()->*cbop.constructor)(), p0, p1);
651 
652     // cmp & 1 => cmp
653     Reduction const r1 =
654         Reduce(graph()->NewNode(machine()->Word32And(), cmp, Int32Constant(1)));
655     ASSERT_TRUE(r1.Changed());
656     EXPECT_EQ(cmp, r1.replacement());
657 
658     // 1 & cmp => cmp
659     Reduction const r2 =
660         Reduce(graph()->NewNode(machine()->Word32And(), Int32Constant(1), cmp));
661     ASSERT_TRUE(r2.Changed());
662     EXPECT_EQ(cmp, r2.replacement());
663   }
664 }
665 
666 
667 // -----------------------------------------------------------------------------
668 // Word32Xor
669 
670 
TEST_F(MachineOperatorReducerTest,Word32XorWithWord32XorAndMinusOne)671 TEST_F(MachineOperatorReducerTest, Word32XorWithWord32XorAndMinusOne) {
672   Node* const p0 = Parameter(0);
673 
674   // (x ^ -1) ^ -1 => x
675   Reduction r1 = Reduce(graph()->NewNode(
676       machine()->Word32Xor(),
677       graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1)),
678       Int32Constant(-1)));
679   ASSERT_TRUE(r1.Changed());
680   EXPECT_EQ(r1.replacement(), p0);
681 
682   // -1 ^ (x ^ -1) => x
683   Reduction r2 = Reduce(graph()->NewNode(
684       machine()->Word32Xor(), Int32Constant(-1),
685       graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1))));
686   ASSERT_TRUE(r2.Changed());
687   EXPECT_EQ(r2.replacement(), p0);
688 
689   // (-1 ^ x) ^ -1 => x
690   Reduction r3 = Reduce(graph()->NewNode(
691       machine()->Word32Xor(),
692       graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0),
693       Int32Constant(-1)));
694   ASSERT_TRUE(r3.Changed());
695   EXPECT_EQ(r3.replacement(), p0);
696 
697   // -1 ^ (-1 ^ x) => x
698   Reduction r4 = Reduce(graph()->NewNode(
699       machine()->Word32Xor(), Int32Constant(-1),
700       graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0)));
701   ASSERT_TRUE(r4.Changed());
702   EXPECT_EQ(r4.replacement(), p0);
703 }
704 
705 
706 // -----------------------------------------------------------------------------
707 // Word32Ror
708 
709 
TEST_F(MachineOperatorReducerTest,ReduceToWord32RorWithParameters)710 TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithParameters) {
711   Node* value = Parameter(0);
712   Node* shift = Parameter(1);
713   Node* sub = graph()->NewNode(machine()->Int32Sub(), Int32Constant(32), shift);
714 
715   // Testing rotate left.
716   Node* shl_l = graph()->NewNode(machine()->Word32Shl(), value, shift);
717   Node* shr_l = graph()->NewNode(machine()->Word32Shr(), value, sub);
718 
719   // (x << y) | (x >>> (32 - y)) => x ror (32 - y)
720   Node* node1 = graph()->NewNode(machine()->Word32Or(), shl_l, shr_l);
721   Reduction reduction1 = Reduce(node1);
722   EXPECT_TRUE(reduction1.Changed());
723   EXPECT_EQ(reduction1.replacement(), node1);
724   EXPECT_THAT(reduction1.replacement(), IsWord32Ror(value, sub));
725 
726   // (x >>> (32 - y)) | (x << y) => x ror (32 - y)
727   Node* node2 = graph()->NewNode(machine()->Word32Or(), shr_l, shl_l);
728   Reduction reduction2 = Reduce(node2);
729   EXPECT_TRUE(reduction2.Changed());
730   EXPECT_EQ(reduction2.replacement(), node2);
731   EXPECT_THAT(reduction2.replacement(), IsWord32Ror(value, sub));
732 
733   // Testing rotate right.
734   Node* shl_r = graph()->NewNode(machine()->Word32Shl(), value, sub);
735   Node* shr_r = graph()->NewNode(machine()->Word32Shr(), value, shift);
736 
737   // (x << (32 - y)) | (x >>> y) => x ror y
738   Node* node3 = graph()->NewNode(machine()->Word32Or(), shl_r, shr_r);
739   Reduction reduction3 = Reduce(node3);
740   EXPECT_TRUE(reduction3.Changed());
741   EXPECT_EQ(reduction3.replacement(), node3);
742   EXPECT_THAT(reduction3.replacement(), IsWord32Ror(value, shift));
743 
744   // (x >>> y) | (x << (32 - y)) => x ror y
745   Node* node4 = graph()->NewNode(machine()->Word32Or(), shr_r, shl_r);
746   Reduction reduction4 = Reduce(node4);
747   EXPECT_TRUE(reduction4.Changed());
748   EXPECT_EQ(reduction4.replacement(), node4);
749   EXPECT_THAT(reduction4.replacement(), IsWord32Ror(value, shift));
750 }
751 
752 
TEST_F(MachineOperatorReducerTest,ReduceToWord32RorWithConstant)753 TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithConstant) {
754   Node* value = Parameter(0);
755   TRACED_FORRANGE(int32_t, k, 0, 31) {
756     Node* shl =
757         graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(k));
758     Node* shr =
759         graph()->NewNode(machine()->Word32Shr(), value, Int32Constant(32 - k));
760 
761     // (x << K) | (x >>> ((32 - K) - y)) => x ror (32 - K)
762     Node* node1 = graph()->NewNode(machine()->Word32Or(), shl, shr);
763     Reduction reduction1 = Reduce(node1);
764     EXPECT_TRUE(reduction1.Changed());
765     EXPECT_EQ(reduction1.replacement(), node1);
766     EXPECT_THAT(reduction1.replacement(),
767                 IsWord32Ror(value, IsInt32Constant(32 - k)));
768 
769     // (x >>> (32 - K)) | (x << K) => x ror (32 - K)
770     Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl);
771     Reduction reduction2 = Reduce(node2);
772     EXPECT_TRUE(reduction2.Changed());
773     EXPECT_EQ(reduction2.replacement(), node2);
774     EXPECT_THAT(reduction2.replacement(),
775                 IsWord32Ror(value, IsInt32Constant(32 - k)));
776   }
777 }
778 
779 
TEST_F(MachineOperatorReducerTest,Word32RorWithZeroShift)780 TEST_F(MachineOperatorReducerTest, Word32RorWithZeroShift) {
781   Node* value = Parameter(0);
782   Node* node =
783       graph()->NewNode(machine()->Word32Ror(), value, Int32Constant(0));
784   Reduction reduction = Reduce(node);
785   EXPECT_TRUE(reduction.Changed());
786   EXPECT_EQ(reduction.replacement(), value);
787 }
788 
789 
TEST_F(MachineOperatorReducerTest,Word32RorWithConstants)790 TEST_F(MachineOperatorReducerTest, Word32RorWithConstants) {
791   TRACED_FOREACH(int32_t, x, kUint32Values) {
792     TRACED_FORRANGE(int32_t, y, 0, 31) {
793       Node* node = graph()->NewNode(machine()->Word32Ror(), Int32Constant(x),
794                                     Int32Constant(y));
795       Reduction reduction = Reduce(node);
796       EXPECT_TRUE(reduction.Changed());
797       EXPECT_THAT(reduction.replacement(),
798                   IsInt32Constant(base::bits::RotateRight32(x, y)));
799     }
800   }
801 }
802 
803 
804 // -----------------------------------------------------------------------------
805 // Word32Sar
806 
807 
TEST_F(MachineOperatorReducerTest,Word32SarWithWord32ShlAndComparison)808 TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndComparison) {
809   Node* const p0 = Parameter(0);
810   Node* const p1 = Parameter(1);
811 
812   TRACED_FOREACH(ComparisonBinaryOperator, cbop, kComparisonBinaryOperators) {
813     Node* cmp = graph()->NewNode((machine()->*cbop.constructor)(), p0, p1);
814 
815     // cmp << 31 >> 31 => 0 - cmp
816     Reduction const r = Reduce(graph()->NewNode(
817         machine()->Word32Sar(),
818         graph()->NewNode(machine()->Word32Shl(), cmp, Int32Constant(31)),
819         Int32Constant(31)));
820     ASSERT_TRUE(r.Changed());
821     EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0), cmp));
822   }
823 }
824 
825 
TEST_F(MachineOperatorReducerTest,Word32SarWithWord32ShlAndLoad)826 TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndLoad) {
827   Node* const p0 = Parameter(0);
828   Node* const p1 = Parameter(1);
829   {
830     Node* const l = graph()->NewNode(machine()->Load(MachineType::Int8()), p0,
831                                      p1, graph()->start(), graph()->start());
832     Reduction const r = Reduce(graph()->NewNode(
833         machine()->Word32Sar(),
834         graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(24)),
835         Int32Constant(24)));
836     ASSERT_TRUE(r.Changed());
837     EXPECT_EQ(l, r.replacement());
838   }
839   {
840     Node* const l = graph()->NewNode(machine()->Load(MachineType::Int16()), p0,
841                                      p1, graph()->start(), graph()->start());
842     Reduction const r = Reduce(graph()->NewNode(
843         machine()->Word32Sar(),
844         graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(16)),
845         Int32Constant(16)));
846     ASSERT_TRUE(r.Changed());
847     EXPECT_EQ(l, r.replacement());
848   }
849 }
850 
851 
852 // -----------------------------------------------------------------------------
853 // Word32Shr
854 
TEST_F(MachineOperatorReducerTest,Word32ShrWithWord32And)855 TEST_F(MachineOperatorReducerTest, Word32ShrWithWord32And) {
856   Node* const p0 = Parameter(0);
857   TRACED_FORRANGE(int32_t, shift, 1, 31) {
858     uint32_t mask = (1 << shift) - 1;
859     Node* node = graph()->NewNode(
860         machine()->Word32Shr(),
861         graph()->NewNode(machine()->Word32And(), p0, Int32Constant(mask)),
862         Int32Constant(shift));
863     Reduction r = Reduce(node);
864     ASSERT_TRUE(r.Changed());
865     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
866   }
867 }
868 
869 // -----------------------------------------------------------------------------
870 // Word32Shl
871 
TEST_F(MachineOperatorReducerTest,Word32ShlWithZeroShift)872 TEST_F(MachineOperatorReducerTest, Word32ShlWithZeroShift) {
873   Node* p0 = Parameter(0);
874   Node* node = graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(0));
875   Reduction r = Reduce(node);
876   ASSERT_TRUE(r.Changed());
877   EXPECT_EQ(p0, r.replacement());
878 }
879 
880 
TEST_F(MachineOperatorReducerTest,Word32ShlWithWord32Sar)881 TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Sar) {
882   Node* p0 = Parameter(0);
883   TRACED_FORRANGE(int32_t, x, 1, 31) {
884     Node* node = graph()->NewNode(
885         machine()->Word32Shl(),
886         graph()->NewNode(machine()->Word32Sar(), p0, Int32Constant(x)),
887         Int32Constant(x));
888     Reduction r = Reduce(node);
889     ASSERT_TRUE(r.Changed());
890     int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
891     EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
892   }
893 }
894 
895 
TEST_F(MachineOperatorReducerTest,Word32ShlWithWord32SarAndInt32AddAndConstant)896 TEST_F(MachineOperatorReducerTest,
897        Word32ShlWithWord32SarAndInt32AddAndConstant) {
898   Node* const p0 = Parameter(0);
899   TRACED_FOREACH(int32_t, k, kInt32Values) {
900     TRACED_FORRANGE(int32_t, l, 1, 31) {
901       if ((k << l) == 0) continue;
902       // (x + (K << L)) >> L << L => (x & (-1 << L)) + (K << L)
903       Reduction const r = Reduce(graph()->NewNode(
904           machine()->Word32Shl(),
905           graph()->NewNode(machine()->Word32Sar(),
906                            graph()->NewNode(machine()->Int32Add(), p0,
907                                             Int32Constant(k << l)),
908                            Int32Constant(l)),
909           Int32Constant(l)));
910       ASSERT_TRUE(r.Changed());
911       EXPECT_THAT(r.replacement(),
912                   IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
913                              IsInt32Constant(k << l)));
914     }
915   }
916 }
917 
918 
TEST_F(MachineOperatorReducerTest,Word32ShlWithWord32Shr)919 TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Shr) {
920   Node* p0 = Parameter(0);
921   TRACED_FORRANGE(int32_t, x, 1, 31) {
922     Node* node = graph()->NewNode(
923         machine()->Word32Shl(),
924         graph()->NewNode(machine()->Word32Shr(), p0, Int32Constant(x)),
925         Int32Constant(x));
926     Reduction r = Reduce(node);
927     ASSERT_TRUE(r.Changed());
928     int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
929     EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
930   }
931 }
932 
933 
934 // -----------------------------------------------------------------------------
935 // Int32Sub
936 
937 
TEST_F(MachineOperatorReducerTest,Int32SubWithConstant)938 TEST_F(MachineOperatorReducerTest, Int32SubWithConstant) {
939   Node* const p0 = Parameter(0);
940   TRACED_FOREACH(int32_t, k, kInt32Values) {
941     Reduction const r =
942         Reduce(graph()->NewNode(machine()->Int32Sub(), p0, Int32Constant(k)));
943     ASSERT_TRUE(r.Changed());
944     if (k == 0) {
945       EXPECT_EQ(p0, r.replacement());
946     } else {
947       EXPECT_THAT(r.replacement(), IsInt32Add(p0, IsInt32Constant(-k)));
948     }
949   }
950 }
951 
952 
953 // -----------------------------------------------------------------------------
954 // Int32Div
955 
956 
TEST_F(MachineOperatorReducerTest,Int32DivWithConstant)957 TEST_F(MachineOperatorReducerTest, Int32DivWithConstant) {
958   Node* const p0 = Parameter(0);
959   {
960     Reduction const r = Reduce(graph()->NewNode(
961         machine()->Int32Div(), p0, Int32Constant(0), graph()->start()));
962     ASSERT_TRUE(r.Changed());
963     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
964   }
965   {
966     Reduction const r = Reduce(graph()->NewNode(
967         machine()->Int32Div(), p0, Int32Constant(1), graph()->start()));
968     ASSERT_TRUE(r.Changed());
969     EXPECT_EQ(r.replacement(), p0);
970   }
971   {
972     Reduction const r = Reduce(graph()->NewNode(
973         machine()->Int32Div(), p0, Int32Constant(-1), graph()->start()));
974     ASSERT_TRUE(r.Changed());
975     EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0), p0));
976   }
977   {
978     Reduction const r = Reduce(graph()->NewNode(
979         machine()->Int32Div(), p0, Int32Constant(2), graph()->start()));
980     ASSERT_TRUE(r.Changed());
981     EXPECT_THAT(
982         r.replacement(),
983         IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
984                     IsInt32Constant(1)));
985   }
986   {
987     Reduction const r = Reduce(graph()->NewNode(
988         machine()->Int32Div(), p0, Int32Constant(-2), graph()->start()));
989     ASSERT_TRUE(r.Changed());
990     EXPECT_THAT(
991         r.replacement(),
992         IsInt32Sub(
993             IsInt32Constant(0),
994             IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
995                         IsInt32Constant(1))));
996   }
997   TRACED_FORRANGE(int32_t, shift, 2, 30) {
998     Reduction const r =
999         Reduce(graph()->NewNode(machine()->Int32Div(), p0,
1000                                 Int32Constant(1 << shift), graph()->start()));
1001     ASSERT_TRUE(r.Changed());
1002     EXPECT_THAT(
1003         r.replacement(),
1004         IsWord32Sar(IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
1005                                            IsInt32Constant(32 - shift)),
1006                                p0),
1007                     IsInt32Constant(shift)));
1008   }
1009   TRACED_FORRANGE(int32_t, shift, 2, 31) {
1010     Reduction const r = Reduce(graph()->NewNode(
1011         machine()->Int32Div(), p0,
1012         Uint32Constant(bit_cast<uint32_t, int32_t>(-1) << shift),
1013         graph()->start()));
1014     ASSERT_TRUE(r.Changed());
1015     EXPECT_THAT(
1016         r.replacement(),
1017         IsInt32Sub(
1018             IsInt32Constant(0),
1019             IsWord32Sar(
1020                 IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
1021                                        IsInt32Constant(32 - shift)),
1022                            p0),
1023                 IsInt32Constant(shift))));
1024   }
1025   TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1026     if (divisor < 0) {
1027       if (base::bits::IsPowerOfTwo32(-divisor)) continue;
1028       Reduction const r = Reduce(graph()->NewNode(
1029           machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
1030       ASSERT_TRUE(r.Changed());
1031       EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0),
1032                                               IsTruncatingDiv(p0, -divisor)));
1033     } else if (divisor > 0) {
1034       if (base::bits::IsPowerOfTwo32(divisor)) continue;
1035       Reduction const r = Reduce(graph()->NewNode(
1036           machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
1037       ASSERT_TRUE(r.Changed());
1038       EXPECT_THAT(r.replacement(), IsTruncatingDiv(p0, divisor));
1039     }
1040   }
1041 }
1042 
1043 
TEST_F(MachineOperatorReducerTest,Int32DivWithParameters)1044 TEST_F(MachineOperatorReducerTest, Int32DivWithParameters) {
1045   Node* const p0 = Parameter(0);
1046   Reduction const r =
1047       Reduce(graph()->NewNode(machine()->Int32Div(), p0, p0, graph()->start()));
1048   ASSERT_TRUE(r.Changed());
1049   EXPECT_THAT(
1050       r.replacement(),
1051       IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
1052 }
1053 
1054 
1055 // -----------------------------------------------------------------------------
1056 // Uint32Div
1057 
1058 
TEST_F(MachineOperatorReducerTest,Uint32DivWithConstant)1059 TEST_F(MachineOperatorReducerTest, Uint32DivWithConstant) {
1060   Node* const p0 = Parameter(0);
1061   {
1062     Reduction const r = Reduce(graph()->NewNode(
1063         machine()->Uint32Div(), Int32Constant(0), p0, graph()->start()));
1064     ASSERT_TRUE(r.Changed());
1065     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1066   }
1067   {
1068     Reduction const r = Reduce(graph()->NewNode(
1069         machine()->Uint32Div(), p0, Int32Constant(0), graph()->start()));
1070     ASSERT_TRUE(r.Changed());
1071     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1072   }
1073   {
1074     Reduction const r = Reduce(graph()->NewNode(
1075         machine()->Uint32Div(), p0, Int32Constant(1), graph()->start()));
1076     ASSERT_TRUE(r.Changed());
1077     EXPECT_EQ(r.replacement(), p0);
1078   }
1079   TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1080     TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1081       Reduction const r = Reduce(
1082           graph()->NewNode(machine()->Uint32Div(), Uint32Constant(dividend),
1083                            Uint32Constant(divisor), graph()->start()));
1084       ASSERT_TRUE(r.Changed());
1085       EXPECT_THAT(r.replacement(),
1086                   IsInt32Constant(bit_cast<int32_t>(
1087                       base::bits::UnsignedDiv32(dividend, divisor))));
1088     }
1089   }
1090   TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1091     Reduction const r =
1092         Reduce(graph()->NewNode(machine()->Uint32Div(), p0,
1093                                 Uint32Constant(1u << shift), graph()->start()));
1094     ASSERT_TRUE(r.Changed());
1095     EXPECT_THAT(r.replacement(),
1096                 IsWord32Shr(p0, IsInt32Constant(bit_cast<int32_t>(shift))));
1097   }
1098 }
1099 
1100 
TEST_F(MachineOperatorReducerTest,Uint32DivWithParameters)1101 TEST_F(MachineOperatorReducerTest, Uint32DivWithParameters) {
1102   Node* const p0 = Parameter(0);
1103   Reduction const r = Reduce(
1104       graph()->NewNode(machine()->Uint32Div(), p0, p0, graph()->start()));
1105   ASSERT_TRUE(r.Changed());
1106   EXPECT_THAT(
1107       r.replacement(),
1108       IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
1109 }
1110 
1111 
1112 // -----------------------------------------------------------------------------
1113 // Int32Mod
1114 
1115 
TEST_F(MachineOperatorReducerTest,Int32ModWithConstant)1116 TEST_F(MachineOperatorReducerTest, Int32ModWithConstant) {
1117   Node* const p0 = Parameter(0);
1118   {
1119     Reduction const r = Reduce(graph()->NewNode(
1120         machine()->Int32Mod(), Int32Constant(0), p0, graph()->start()));
1121     ASSERT_TRUE(r.Changed());
1122     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1123   }
1124   {
1125     Reduction const r = Reduce(graph()->NewNode(
1126         machine()->Int32Mod(), p0, Int32Constant(0), graph()->start()));
1127     ASSERT_TRUE(r.Changed());
1128     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1129   }
1130   {
1131     Reduction const r = Reduce(graph()->NewNode(
1132         machine()->Int32Mod(), p0, Int32Constant(1), graph()->start()));
1133     ASSERT_TRUE(r.Changed());
1134     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1135   }
1136   {
1137     Reduction const r = Reduce(graph()->NewNode(
1138         machine()->Int32Mod(), p0, Int32Constant(-1), graph()->start()));
1139     ASSERT_TRUE(r.Changed());
1140     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1141   }
1142   TRACED_FOREACH(int32_t, dividend, kInt32Values) {
1143     TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1144       Reduction const r = Reduce(
1145           graph()->NewNode(machine()->Int32Mod(), Int32Constant(dividend),
1146                            Int32Constant(divisor), graph()->start()));
1147       ASSERT_TRUE(r.Changed());
1148       EXPECT_THAT(r.replacement(),
1149                   IsInt32Constant(base::bits::SignedMod32(dividend, divisor)));
1150     }
1151   }
1152   TRACED_FORRANGE(int32_t, shift, 1, 30) {
1153     Reduction const r =
1154         Reduce(graph()->NewNode(machine()->Int32Mod(), p0,
1155                                 Int32Constant(1 << shift), graph()->start()));
1156     int32_t const mask = (1 << shift) - 1;
1157     ASSERT_TRUE(r.Changed());
1158     EXPECT_THAT(
1159         r.replacement(),
1160         IsSelect(MachineRepresentation::kWord32,
1161                  IsInt32LessThan(p0, IsInt32Constant(0)),
1162                  IsInt32Sub(IsInt32Constant(0),
1163                             IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1164                                         IsInt32Constant(mask))),
1165                  IsWord32And(p0, IsInt32Constant(mask))));
1166   }
1167   TRACED_FORRANGE(int32_t, shift, 1, 31) {
1168     Reduction const r = Reduce(graph()->NewNode(
1169         machine()->Int32Mod(), p0,
1170         Uint32Constant(bit_cast<uint32_t, int32_t>(-1) << shift),
1171         graph()->start()));
1172     int32_t const mask = bit_cast<int32_t, uint32_t>((1U << shift) - 1);
1173     ASSERT_TRUE(r.Changed());
1174     EXPECT_THAT(
1175         r.replacement(),
1176         IsSelect(MachineRepresentation::kWord32,
1177                  IsInt32LessThan(p0, IsInt32Constant(0)),
1178                  IsInt32Sub(IsInt32Constant(0),
1179                             IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1180                                         IsInt32Constant(mask))),
1181                  IsWord32And(p0, IsInt32Constant(mask))));
1182   }
1183   TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1184     if (divisor == 0 || base::bits::IsPowerOfTwo32(Abs(divisor))) continue;
1185     Reduction const r = Reduce(graph()->NewNode(
1186         machine()->Int32Mod(), p0, Int32Constant(divisor), graph()->start()));
1187     ASSERT_TRUE(r.Changed());
1188     EXPECT_THAT(r.replacement(),
1189                 IsInt32Sub(p0, IsInt32Mul(IsTruncatingDiv(p0, Abs(divisor)),
1190                                           IsInt32Constant(Abs(divisor)))));
1191   }
1192 }
1193 
1194 
TEST_F(MachineOperatorReducerTest,Int32ModWithParameters)1195 TEST_F(MachineOperatorReducerTest, Int32ModWithParameters) {
1196   Node* const p0 = Parameter(0);
1197   Reduction const r =
1198       Reduce(graph()->NewNode(machine()->Int32Mod(), p0, p0, graph()->start()));
1199   ASSERT_TRUE(r.Changed());
1200   EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1201 }
1202 
1203 
1204 // -----------------------------------------------------------------------------
1205 // Uint32Mod
1206 
1207 
TEST_F(MachineOperatorReducerTest,Uint32ModWithConstant)1208 TEST_F(MachineOperatorReducerTest, Uint32ModWithConstant) {
1209   Node* const p0 = Parameter(0);
1210   {
1211     Reduction const r = Reduce(graph()->NewNode(
1212         machine()->Uint32Mod(), p0, Int32Constant(0), graph()->start()));
1213     ASSERT_TRUE(r.Changed());
1214     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1215   }
1216   {
1217     Reduction const r = Reduce(graph()->NewNode(
1218         machine()->Uint32Mod(), Int32Constant(0), p0, graph()->start()));
1219     ASSERT_TRUE(r.Changed());
1220     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1221   }
1222   {
1223     Reduction const r = Reduce(graph()->NewNode(
1224         machine()->Uint32Mod(), p0, Int32Constant(1), graph()->start()));
1225     ASSERT_TRUE(r.Changed());
1226     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1227   }
1228   TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1229     TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1230       Reduction const r = Reduce(
1231           graph()->NewNode(machine()->Uint32Mod(), Uint32Constant(dividend),
1232                            Uint32Constant(divisor), graph()->start()));
1233       ASSERT_TRUE(r.Changed());
1234       EXPECT_THAT(r.replacement(),
1235                   IsInt32Constant(bit_cast<int32_t>(
1236                       base::bits::UnsignedMod32(dividend, divisor))));
1237     }
1238   }
1239   TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1240     Reduction const r =
1241         Reduce(graph()->NewNode(machine()->Uint32Mod(), p0,
1242                                 Uint32Constant(1u << shift), graph()->start()));
1243     ASSERT_TRUE(r.Changed());
1244     EXPECT_THAT(r.replacement(),
1245                 IsWord32And(p0, IsInt32Constant(
1246                                     bit_cast<int32_t>((1u << shift) - 1u))));
1247   }
1248 }
1249 
1250 
TEST_F(MachineOperatorReducerTest,Uint32ModWithParameters)1251 TEST_F(MachineOperatorReducerTest, Uint32ModWithParameters) {
1252   Node* const p0 = Parameter(0);
1253   Reduction const r = Reduce(
1254       graph()->NewNode(machine()->Uint32Mod(), p0, p0, graph()->start()));
1255   ASSERT_TRUE(r.Changed());
1256   EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1257 }
1258 
1259 
1260 // -----------------------------------------------------------------------------
1261 // Int32Add
1262 
1263 
TEST_F(MachineOperatorReducerTest,Int32AddWithInt32SubWithConstantZero)1264 TEST_F(MachineOperatorReducerTest, Int32AddWithInt32SubWithConstantZero) {
1265   Node* const p0 = Parameter(0);
1266   Node* const p1 = Parameter(1);
1267 
1268   Reduction const r1 = Reduce(graph()->NewNode(
1269       machine()->Int32Add(),
1270       graph()->NewNode(machine()->Int32Sub(), Int32Constant(0), p0), p1));
1271   ASSERT_TRUE(r1.Changed());
1272   EXPECT_THAT(r1.replacement(), IsInt32Sub(p1, p0));
1273 
1274   Reduction const r2 = Reduce(graph()->NewNode(
1275       machine()->Int32Add(), p0,
1276       graph()->NewNode(machine()->Int32Sub(), Int32Constant(0), p1)));
1277   ASSERT_TRUE(r2.Changed());
1278   EXPECT_THAT(r2.replacement(), IsInt32Sub(p0, p1));
1279 }
1280 
1281 
1282 // -----------------------------------------------------------------------------
1283 // Int32AddWithOverflow
1284 
1285 
TEST_F(MachineOperatorReducerTest,Int32AddWithOverflowWithZero)1286 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) {
1287   Node* control = graph()->start();
1288   Node* p0 = Parameter(0);
1289   {
1290     Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1291                                  Int32Constant(0), p0, control);
1292 
1293     Reduction r =
1294         Reduce(graph()->NewNode(common()->Projection(1), add, control));
1295     ASSERT_TRUE(r.Changed());
1296     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1297 
1298     r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1299     ASSERT_TRUE(r.Changed());
1300     EXPECT_EQ(p0, r.replacement());
1301   }
1302   {
1303     Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), p0,
1304                                  Int32Constant(0), control);
1305 
1306     Reduction r =
1307         Reduce(graph()->NewNode(common()->Projection(1), add, control));
1308     ASSERT_TRUE(r.Changed());
1309     EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1310 
1311     r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1312     ASSERT_TRUE(r.Changed());
1313     EXPECT_EQ(p0, r.replacement());
1314   }
1315 }
1316 
1317 
TEST_F(MachineOperatorReducerTest,Int32AddWithOverflowWithConstant)1318 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) {
1319   Node* control = graph()->start();
1320   TRACED_FOREACH(int32_t, x, kInt32Values) {
1321     TRACED_FOREACH(int32_t, y, kInt32Values) {
1322       int32_t z;
1323       Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1324                                    Int32Constant(x), Int32Constant(y), control);
1325 
1326       Reduction r =
1327           Reduce(graph()->NewNode(common()->Projection(1), add, control));
1328       ASSERT_TRUE(r.Changed());
1329       EXPECT_THAT(r.replacement(),
1330                   IsInt32Constant(base::bits::SignedAddOverflow32(x, y, &z)));
1331 
1332       r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1333       ASSERT_TRUE(r.Changed());
1334       EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1335     }
1336   }
1337 }
1338 
1339 
1340 // -----------------------------------------------------------------------------
1341 // Int32SubWithOverflow
1342 
1343 
TEST_F(MachineOperatorReducerTest,Int32SubWithOverflowWithZero)1344 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithZero) {
1345   Node* control = graph()->start();
1346   Node* p0 = Parameter(0);
1347   Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(), p0,
1348                                Int32Constant(0), control);
1349 
1350   Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add, control));
1351   ASSERT_TRUE(r.Changed());
1352   EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1353 
1354   r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1355   ASSERT_TRUE(r.Changed());
1356   EXPECT_EQ(p0, r.replacement());
1357 }
1358 
1359 
TEST_F(MachineOperatorReducerTest,Int32SubWithOverflowWithConstant)1360 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
1361   Node* control = graph()->start();
1362   TRACED_FOREACH(int32_t, x, kInt32Values) {
1363     TRACED_FOREACH(int32_t, y, kInt32Values) {
1364       int32_t z;
1365       Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(),
1366                                    Int32Constant(x), Int32Constant(y), control);
1367 
1368       Reduction r =
1369           Reduce(graph()->NewNode(common()->Projection(1), add, control));
1370       ASSERT_TRUE(r.Changed());
1371       EXPECT_THAT(r.replacement(),
1372                   IsInt32Constant(base::bits::SignedSubOverflow32(x, y, &z)));
1373 
1374       r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1375       ASSERT_TRUE(r.Changed());
1376       EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1377     }
1378   }
1379 }
1380 
1381 
1382 // -----------------------------------------------------------------------------
1383 // Uint32LessThan
1384 
1385 
TEST_F(MachineOperatorReducerTest,Uint32LessThanWithWord32Sar)1386 TEST_F(MachineOperatorReducerTest, Uint32LessThanWithWord32Sar) {
1387   Node* const p0 = Parameter(0);
1388   TRACED_FORRANGE(uint32_t, shift, 1, 3) {
1389     const uint32_t limit = (kMaxInt >> shift) - 1;
1390     Node* const node = graph()->NewNode(
1391         machine()->Uint32LessThan(),
1392         graph()->NewNode(machine()->Word32Sar(), p0, Uint32Constant(shift)),
1393         Uint32Constant(limit));
1394 
1395     Reduction r = Reduce(node);
1396     ASSERT_TRUE(r.Changed());
1397     EXPECT_THAT(r.replacement(),
1398                 IsUint32LessThan(
1399                     p0, IsInt32Constant(bit_cast<int32_t>(limit << shift))));
1400   }
1401 }
1402 
1403 
1404 // -----------------------------------------------------------------------------
1405 // Float64Mul
1406 
1407 
TEST_F(MachineOperatorReducerTest,Float64MulWithMinusOne)1408 TEST_F(MachineOperatorReducerTest, Float64MulWithMinusOne) {
1409   Node* const p0 = Parameter(0);
1410   {
1411     Reduction r = Reduce(
1412         graph()->NewNode(machine()->Float64Mul(), p0, Float64Constant(-1.0)));
1413     ASSERT_TRUE(r.Changed());
1414     EXPECT_THAT(r.replacement(),
1415                 IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1416   }
1417   {
1418     Reduction r = Reduce(
1419         graph()->NewNode(machine()->Float64Mul(), Float64Constant(-1.0), p0));
1420     ASSERT_TRUE(r.Changed());
1421     EXPECT_THAT(r.replacement(),
1422                 IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1423   }
1424 }
1425 
1426 
1427 // -----------------------------------------------------------------------------
1428 // Float64Atan
1429 
TEST_F(MachineOperatorReducerTest,Float64AtanWithConstant)1430 TEST_F(MachineOperatorReducerTest, Float64AtanWithConstant) {
1431   TRACED_FOREACH(double, x, kFloat64Values) {
1432     Reduction const r =
1433         Reduce(graph()->NewNode(machine()->Float64Atan(), Float64Constant(x)));
1434     ASSERT_TRUE(r.Changed());
1435     EXPECT_THAT(
1436         r.replacement(),
1437         IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::atan(x))));
1438   }
1439 }
1440 
1441 // -----------------------------------------------------------------------------
1442 // Float64Atan2
1443 
TEST_F(MachineOperatorReducerTest,Float64Atan2WithConstant)1444 TEST_F(MachineOperatorReducerTest, Float64Atan2WithConstant) {
1445   TRACED_FOREACH(double, y, kFloat64Values) {
1446     TRACED_FOREACH(double, x, kFloat64Values) {
1447       Reduction const r = Reduce(graph()->NewNode(
1448           machine()->Float64Atan2(), Float64Constant(y), Float64Constant(x)));
1449       ASSERT_TRUE(r.Changed());
1450       EXPECT_THAT(
1451           r.replacement(),
1452           IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::atan2(y, x))));
1453     }
1454   }
1455 }
1456 
TEST_F(MachineOperatorReducerTest,Float64Atan2WithNaN)1457 TEST_F(MachineOperatorReducerTest, Float64Atan2WithNaN) {
1458   Node* const p0 = Parameter(0);
1459   Node* const nan = Float64Constant(std::numeric_limits<double>::quiet_NaN());
1460   {
1461     Reduction const r =
1462         Reduce(graph()->NewNode(machine()->Float64Atan2(), p0, nan));
1463     ASSERT_TRUE(r.Changed());
1464     EXPECT_EQ(nan, r.replacement());
1465   }
1466   {
1467     Reduction const r =
1468         Reduce(graph()->NewNode(machine()->Float64Atan2(), nan, p0));
1469     ASSERT_TRUE(r.Changed());
1470     EXPECT_EQ(nan, r.replacement());
1471   }
1472 }
1473 
1474 // -----------------------------------------------------------------------------
1475 // Float64Cos
1476 
TEST_F(MachineOperatorReducerTest,Float64CosWithConstant)1477 TEST_F(MachineOperatorReducerTest, Float64CosWithConstant) {
1478   TRACED_FOREACH(double, x, kFloat64Values) {
1479     Reduction const r =
1480         Reduce(graph()->NewNode(machine()->Float64Cos(), Float64Constant(x)));
1481     ASSERT_TRUE(r.Changed());
1482     EXPECT_THAT(r.replacement(),
1483                 IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::cos(x))));
1484   }
1485 }
1486 
1487 // -----------------------------------------------------------------------------
1488 // Float64Exp
1489 
TEST_F(MachineOperatorReducerTest,Float64ExpWithConstant)1490 TEST_F(MachineOperatorReducerTest, Float64ExpWithConstant) {
1491   TRACED_FOREACH(double, x, kFloat64Values) {
1492     Reduction const r =
1493         Reduce(graph()->NewNode(machine()->Float64Exp(), Float64Constant(x)));
1494     ASSERT_TRUE(r.Changed());
1495     EXPECT_THAT(r.replacement(),
1496                 IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::exp(x))));
1497   }
1498 }
1499 
1500 // -----------------------------------------------------------------------------
1501 // Float64Log
1502 
TEST_F(MachineOperatorReducerTest,Float64LogWithConstant)1503 TEST_F(MachineOperatorReducerTest, Float64LogWithConstant) {
1504   TRACED_FOREACH(double, x, kFloat64Values) {
1505     Reduction const r =
1506         Reduce(graph()->NewNode(machine()->Float64Log(), Float64Constant(x)));
1507     ASSERT_TRUE(r.Changed());
1508     EXPECT_THAT(r.replacement(),
1509                 IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::log(x))));
1510   }
1511 }
1512 
1513 // -----------------------------------------------------------------------------
1514 // Float64Log1p
1515 
TEST_F(MachineOperatorReducerTest,Float64Log1pWithConstant)1516 TEST_F(MachineOperatorReducerTest, Float64Log1pWithConstant) {
1517   TRACED_FOREACH(double, x, kFloat64Values) {
1518     Reduction const r =
1519         Reduce(graph()->NewNode(machine()->Float64Log1p(), Float64Constant(x)));
1520     ASSERT_TRUE(r.Changed());
1521     EXPECT_THAT(
1522         r.replacement(),
1523         IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::log1p(x))));
1524   }
1525 }
1526 
1527 // -----------------------------------------------------------------------------
1528 // Float64Sin
1529 
TEST_F(MachineOperatorReducerTest,Float64SinWithConstant)1530 TEST_F(MachineOperatorReducerTest, Float64SinWithConstant) {
1531   TRACED_FOREACH(double, x, kFloat64Values) {
1532     Reduction const r =
1533         Reduce(graph()->NewNode(machine()->Float64Sin(), Float64Constant(x)));
1534     ASSERT_TRUE(r.Changed());
1535     EXPECT_THAT(r.replacement(),
1536                 IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::sin(x))));
1537   }
1538 }
1539 
1540 // -----------------------------------------------------------------------------
1541 // Float64Tan
1542 
TEST_F(MachineOperatorReducerTest,Float64TanWithConstant)1543 TEST_F(MachineOperatorReducerTest, Float64TanWithConstant) {
1544   TRACED_FOREACH(double, x, kFloat64Values) {
1545     Reduction const r =
1546         Reduce(graph()->NewNode(machine()->Float64Tan(), Float64Constant(x)));
1547     ASSERT_TRUE(r.Changed());
1548     EXPECT_THAT(r.replacement(),
1549                 IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::tan(x))));
1550   }
1551 }
1552 
1553 // -----------------------------------------------------------------------------
1554 // Float64InsertLowWord32
1555 
TEST_F(MachineOperatorReducerTest,Float64InsertLowWord32WithConstant)1556 TEST_F(MachineOperatorReducerTest, Float64InsertLowWord32WithConstant) {
1557   TRACED_FOREACH(double, x, kFloat64Values) {
1558     TRACED_FOREACH(uint32_t, y, kUint32Values) {
1559       Reduction const r =
1560           Reduce(graph()->NewNode(machine()->Float64InsertLowWord32(),
1561                                   Float64Constant(x), Uint32Constant(y)));
1562       ASSERT_TRUE(r.Changed());
1563       EXPECT_THAT(
1564           r.replacement(),
1565           IsFloat64Constant(BitEq(bit_cast<double>(
1566               (bit_cast<uint64_t>(x) & V8_UINT64_C(0xFFFFFFFF00000000)) | y))));
1567     }
1568   }
1569 }
1570 
1571 
1572 // -----------------------------------------------------------------------------
1573 // Float64InsertHighWord32
1574 
1575 
TEST_F(MachineOperatorReducerTest,Float64InsertHighWord32WithConstant)1576 TEST_F(MachineOperatorReducerTest, Float64InsertHighWord32WithConstant) {
1577   TRACED_FOREACH(double, x, kFloat64Values) {
1578     TRACED_FOREACH(uint32_t, y, kUint32Values) {
1579       Reduction const r =
1580           Reduce(graph()->NewNode(machine()->Float64InsertHighWord32(),
1581                                   Float64Constant(x), Uint32Constant(y)));
1582       ASSERT_TRUE(r.Changed());
1583       EXPECT_THAT(r.replacement(),
1584                   IsFloat64Constant(BitEq(bit_cast<double>(
1585                       (bit_cast<uint64_t>(x) & V8_UINT64_C(0xFFFFFFFF)) |
1586                       (static_cast<uint64_t>(y) << 32)))));
1587     }
1588   }
1589 }
1590 
1591 
1592 // -----------------------------------------------------------------------------
1593 // Float64Equal
1594 
1595 
TEST_F(MachineOperatorReducerTest,Float64EqualWithFloat32Conversions)1596 TEST_F(MachineOperatorReducerTest, Float64EqualWithFloat32Conversions) {
1597   Node* const p0 = Parameter(0);
1598   Node* const p1 = Parameter(1);
1599   Reduction const r = Reduce(graph()->NewNode(
1600       machine()->Float64Equal(),
1601       graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
1602       graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p1)));
1603   ASSERT_TRUE(r.Changed());
1604   EXPECT_THAT(r.replacement(), IsFloat32Equal(p0, p1));
1605 }
1606 
1607 
TEST_F(MachineOperatorReducerTest,Float64EqualWithFloat32Constant)1608 TEST_F(MachineOperatorReducerTest, Float64EqualWithFloat32Constant) {
1609   Node* const p0 = Parameter(0);
1610   TRACED_FOREACH(float, x, kFloat32Values) {
1611     Reduction r = Reduce(graph()->NewNode(
1612         machine()->Float64Equal(),
1613         graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
1614         Float64Constant(x)));
1615     ASSERT_TRUE(r.Changed());
1616     EXPECT_THAT(r.replacement(), IsFloat32Equal(p0, IsFloat32Constant(x)));
1617   }
1618 }
1619 
1620 
1621 // -----------------------------------------------------------------------------
1622 // Float64LessThan
1623 
1624 
TEST_F(MachineOperatorReducerTest,Float64LessThanWithFloat32Conversions)1625 TEST_F(MachineOperatorReducerTest, Float64LessThanWithFloat32Conversions) {
1626   Node* const p0 = Parameter(0);
1627   Node* const p1 = Parameter(1);
1628   Reduction const r = Reduce(graph()->NewNode(
1629       machine()->Float64LessThan(),
1630       graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
1631       graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p1)));
1632   ASSERT_TRUE(r.Changed());
1633   EXPECT_THAT(r.replacement(), IsFloat32LessThan(p0, p1));
1634 }
1635 
1636 
TEST_F(MachineOperatorReducerTest,Float64LessThanWithFloat32Constant)1637 TEST_F(MachineOperatorReducerTest, Float64LessThanWithFloat32Constant) {
1638   Node* const p0 = Parameter(0);
1639   {
1640     TRACED_FOREACH(float, x, kFloat32Values) {
1641       Reduction r = Reduce(graph()->NewNode(
1642           machine()->Float64LessThan(),
1643           graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
1644           Float64Constant(x)));
1645       ASSERT_TRUE(r.Changed());
1646       EXPECT_THAT(r.replacement(), IsFloat32LessThan(p0, IsFloat32Constant(x)));
1647     }
1648   }
1649   {
1650     TRACED_FOREACH(float, x, kFloat32Values) {
1651       Reduction r = Reduce(graph()->NewNode(
1652           machine()->Float64LessThan(), Float64Constant(x),
1653           graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0)));
1654       ASSERT_TRUE(r.Changed());
1655       EXPECT_THAT(r.replacement(), IsFloat32LessThan(IsFloat32Constant(x), p0));
1656     }
1657   }
1658 }
1659 
1660 
1661 // -----------------------------------------------------------------------------
1662 // Float64LessThanOrEqual
1663 
1664 
TEST_F(MachineOperatorReducerTest,Float64LessThanOrEqualWithFloat32Conversions)1665 TEST_F(MachineOperatorReducerTest,
1666        Float64LessThanOrEqualWithFloat32Conversions) {
1667   Node* const p0 = Parameter(0);
1668   Node* const p1 = Parameter(1);
1669   Reduction const r = Reduce(graph()->NewNode(
1670       machine()->Float64LessThanOrEqual(),
1671       graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
1672       graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p1)));
1673   ASSERT_TRUE(r.Changed());
1674   EXPECT_THAT(r.replacement(), IsFloat32LessThanOrEqual(p0, p1));
1675 }
1676 
1677 
TEST_F(MachineOperatorReducerTest,Float64LessThanOrEqualWithFloat32Constant)1678 TEST_F(MachineOperatorReducerTest, Float64LessThanOrEqualWithFloat32Constant) {
1679   Node* const p0 = Parameter(0);
1680   {
1681     TRACED_FOREACH(float, x, kFloat32Values) {
1682       Reduction r = Reduce(graph()->NewNode(
1683           machine()->Float64LessThanOrEqual(),
1684           graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
1685           Float64Constant(x)));
1686       ASSERT_TRUE(r.Changed());
1687       EXPECT_THAT(r.replacement(),
1688                   IsFloat32LessThanOrEqual(p0, IsFloat32Constant(x)));
1689     }
1690   }
1691   {
1692     TRACED_FOREACH(float, x, kFloat32Values) {
1693       Reduction r = Reduce(graph()->NewNode(
1694           machine()->Float64LessThanOrEqual(), Float64Constant(x),
1695           graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0)));
1696       ASSERT_TRUE(r.Changed());
1697       EXPECT_THAT(r.replacement(),
1698                   IsFloat32LessThanOrEqual(IsFloat32Constant(x), p0));
1699     }
1700   }
1701 }
1702 
1703 
1704 // -----------------------------------------------------------------------------
1705 // Store
1706 
1707 
TEST_F(MachineOperatorReducerTest,StoreRepWord8WithWord32And)1708 TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32And) {
1709   const StoreRepresentation rep(MachineRepresentation::kWord8, kNoWriteBarrier);
1710   Node* const base = Parameter(0);
1711   Node* const index = Parameter(1);
1712   Node* const value = Parameter(2);
1713   Node* const effect = graph()->start();
1714   Node* const control = graph()->start();
1715   TRACED_FOREACH(uint32_t, x, kUint32Values) {
1716     Node* const node =
1717         graph()->NewNode(machine()->Store(rep), base, index,
1718                          graph()->NewNode(machine()->Word32And(), value,
1719                                           Uint32Constant(x | 0xffu)),
1720                          effect, control);
1721 
1722     Reduction r = Reduce(node);
1723     ASSERT_TRUE(r.Changed());
1724     EXPECT_THAT(r.replacement(),
1725                 IsStore(rep, base, index, value, effect, control));
1726   }
1727 }
1728 
1729 
TEST_F(MachineOperatorReducerTest,StoreRepWord8WithWord32SarAndWord32Shl)1730 TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32SarAndWord32Shl) {
1731   const StoreRepresentation rep(MachineRepresentation::kWord8, kNoWriteBarrier);
1732   Node* const base = Parameter(0);
1733   Node* const index = Parameter(1);
1734   Node* const value = Parameter(2);
1735   Node* const effect = graph()->start();
1736   Node* const control = graph()->start();
1737   TRACED_FORRANGE(int32_t, x, 1, 24) {
1738     Node* const node = graph()->NewNode(
1739         machine()->Store(rep), base, index,
1740         graph()->NewNode(
1741             machine()->Word32Sar(),
1742             graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
1743             Int32Constant(x)),
1744         effect, control);
1745 
1746     Reduction r = Reduce(node);
1747     ASSERT_TRUE(r.Changed());
1748     EXPECT_THAT(r.replacement(),
1749                 IsStore(rep, base, index, value, effect, control));
1750   }
1751 }
1752 
1753 
TEST_F(MachineOperatorReducerTest,StoreRepWord16WithWord32And)1754 TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32And) {
1755   const StoreRepresentation rep(MachineRepresentation::kWord16,
1756                                 kNoWriteBarrier);
1757   Node* const base = Parameter(0);
1758   Node* const index = Parameter(1);
1759   Node* const value = Parameter(2);
1760   Node* const effect = graph()->start();
1761   Node* const control = graph()->start();
1762   TRACED_FOREACH(uint32_t, x, kUint32Values) {
1763     Node* const node =
1764         graph()->NewNode(machine()->Store(rep), base, index,
1765                          graph()->NewNode(machine()->Word32And(), value,
1766                                           Uint32Constant(x | 0xffffu)),
1767                          effect, control);
1768 
1769     Reduction r = Reduce(node);
1770     ASSERT_TRUE(r.Changed());
1771     EXPECT_THAT(r.replacement(),
1772                 IsStore(rep, base, index, value, effect, control));
1773   }
1774 }
1775 
1776 
TEST_F(MachineOperatorReducerTest,StoreRepWord16WithWord32SarAndWord32Shl)1777 TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32SarAndWord32Shl) {
1778   const StoreRepresentation rep(MachineRepresentation::kWord16,
1779                                 kNoWriteBarrier);
1780   Node* const base = Parameter(0);
1781   Node* const index = Parameter(1);
1782   Node* const value = Parameter(2);
1783   Node* const effect = graph()->start();
1784   Node* const control = graph()->start();
1785   TRACED_FORRANGE(int32_t, x, 1, 16) {
1786     Node* const node = graph()->NewNode(
1787         machine()->Store(rep), base, index,
1788         graph()->NewNode(
1789             machine()->Word32Sar(),
1790             graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
1791             Int32Constant(x)),
1792         effect, control);
1793 
1794     Reduction r = Reduce(node);
1795     ASSERT_TRUE(r.Changed());
1796     EXPECT_THAT(r.replacement(),
1797                 IsStore(rep, base, index, value, effect, control));
1798   }
1799 }
1800 
1801 }  // namespace compiler
1802 }  // namespace internal
1803 }  // namespace v8
1804