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