1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "src/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"
16 using testing::Capture;
17 using testing::CaptureEq;
23 class MachineOperatorReducerTest : public TypedGraphTest {
25 explicit MachineOperatorReducerTest(int num_parameters = 2)
26 : TypedGraphTest(num_parameters), machine_(zone()) {}
29 Reduction Reduce(Node* node) {
30 JSOperatorBuilder javascript(zone());
31 JSGraph jsgraph(isolate(), graph(), common(), &javascript, &machine_);
32 MachineOperatorReducer reducer(&jsgraph);
33 return reducer.Reduce(node);
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);
50 quotient_matcher = IsWord32Sar(quotient_matcher, IsInt32Constant(shift));
52 return IsInt32Add(quotient_matcher,
53 IsWord32Shr(dividend_matcher, IsInt32Constant(31)));
56 MachineOperatorBuilder* machine() { return &machine_; }
59 MachineOperatorBuilder machine_;
64 class MachineOperatorReducerTestWithParam
65 : public MachineOperatorReducerTest,
66 public ::testing::WithParamInterface<T> {
68 explicit MachineOperatorReducerTestWithParam(int num_parameters = 2)
69 : MachineOperatorReducerTest(num_parameters) {}
70 ~MachineOperatorReducerTestWithParam() OVERRIDE {}
76 const float kFloat32Values[] = {
77 -std::numeric_limits<float>::infinity(), -2.70497e+38f, -1.4698e+37f,
78 -1.22813e+35f, -1.20555e+35f, -1.34584e+34f,
79 -1.0079e+32f, -6.49364e+26f, -3.06077e+25f,
80 -1.46821e+25f, -1.17658e+23f, -1.9617e+22f,
81 -2.7357e+20f, -1.48708e+13f, -1.89633e+12f,
82 -4.66622e+11f, -2.22581e+11f, -1.45381e+10f,
83 -1.3956e+09f, -1.32951e+09f, -1.30721e+09f,
84 -1.19756e+09f, -9.26822e+08f, -6.35647e+08f,
85 -4.00037e+08f, -1.81227e+08f, -5.09256e+07f,
86 -964300.0f, -192446.0f, -28455.0f,
87 -27194.0f, -26401.0f, -20575.0f,
88 -17069.0f, -9167.0f, -960.178f,
89 -113.0f, -62.0f, -15.0f,
90 -7.0f, -0.0256635f, -4.60374e-07f,
91 -3.63759e-10f, -4.30175e-14f, -5.27385e-15f,
92 -1.48084e-15f, -1.05755e-19f, -3.2995e-21f,
93 -1.67354e-23f, -1.11885e-23f, -1.78506e-30f,
94 -5.07594e-31f, -3.65799e-31f, -1.43718e-34f,
95 -1.27126e-38f, -0.0f, 0.0f,
96 1.17549e-38f, 1.56657e-37f, 4.08512e-29f,
97 3.31357e-28f, 6.25073e-22f, 4.1723e-13f,
98 1.44343e-09f, 5.27004e-08f, 9.48298e-08f,
99 5.57888e-07f, 4.89988e-05f, 0.244326f,
100 12.4895f, 19.0f, 47.0f,
101 106.0f, 538.324f, 564.536f,
102 819.124f, 7048.0f, 12611.0f,
103 19878.0f, 20309.0f, 797056.0f,
104 1.77219e+09f, 1.51116e+11f, 4.18193e+13f,
105 3.59167e+16f, 3.38211e+19f, 2.67488e+20f,
106 1.78831e+21f, 9.20914e+21f, 8.35654e+23f,
107 1.4495e+24f, 5.94015e+25f, 4.43608e+30f,
108 2.44502e+33f, 2.61152e+33f, 1.38178e+37f,
109 1.71306e+37f, 3.31899e+38f, 3.40282e+38f,
110 std::numeric_limits<float>::infinity()};
113 const double kFloat64Values[] = {
114 -V8_INFINITY, -4.23878e+275, -5.82632e+265, -6.60355e+220, -6.26172e+212,
115 -2.56222e+211, -4.82408e+201, -1.84106e+157, -1.63662e+127, -1.55772e+100,
116 -1.67813e+72, -2.3382e+55, -3.179e+30, -1.441e+09, -1.0647e+09,
117 -7.99361e+08, -5.77375e+08, -2.20984e+08, -32757, -13171,
118 -9970, -3984, -107, -105, -92,
119 -77, -61, -0.000208163, -1.86685e-06, -1.17296e-10,
120 -9.26358e-11, -5.08004e-60, -1.74753e-65, -1.06561e-71, -5.67879e-79,
121 -5.78459e-130, -2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263,
122 -4.40497e-267, -2.19666e-273, -4.9998e-276, -5.59821e-278, -2.03855e-282,
123 -5.99335e-283, -7.17554e-284, -3.11744e-309, -0.0, 0.0,
124 2.22507e-308, 1.30127e-270, 7.62898e-260, 4.00313e-249, 3.16829e-233,
125 1.85244e-228, 2.03544e-129, 1.35126e-110, 1.01182e-106, 5.26333e-94,
126 1.35292e-90, 2.85394e-83, 1.78323e-77, 5.4967e-57, 1.03207e-25,
127 4.57401e-25, 1.58738e-05, 2, 125, 2310,
128 9636, 14802, 17168, 28945, 29305,
129 4.81336e+07, 1.41207e+08, 4.65962e+08, 1.40499e+09, 2.12648e+09,
130 8.80006e+30, 1.4446e+45, 1.12164e+54, 2.48188e+89, 6.71121e+102,
131 3.074e+112, 4.9699e+152, 5.58383e+166, 4.30654e+172, 7.08824e+185,
132 9.6586e+214, 2.028e+223, 6.63277e+243, 1.56192e+261, 1.23202e+269,
133 5.72883e+289, 8.5798e+290, 1.40256e+294, 1.79769e+308, V8_INFINITY};
136 const int32_t kInt32Values[] = {
137 std::numeric_limits<int32_t>::min(), -1914954528, -1698749618,
138 -1578693386, -1577976073, -1573998034,
139 -1529085059, -1499540537, -1299205097,
140 -1090814845, -938186388, -806828902,
141 -750927650, -520676892, -513661538,
142 -453036354, -433622833, -282638793,
143 -28375, -27788, -22770,
144 -18806, -14173, -11956,
145 -11200, -10212, -8160,
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()};
173 const int64_t kInt64Values[] = {
174 std::numeric_limits<int64_t>::min(), V8_INT64_C(-8974392461363618006),
175 V8_INT64_C(-8874367046689588135), V8_INT64_C(-8269197512118230839),
176 V8_INT64_C(-8146091527100606733), V8_INT64_C(-7550917981466150848),
177 V8_INT64_C(-7216590251577894337), V8_INT64_C(-6464086891160048440),
178 V8_INT64_C(-6365616494908257190), V8_INT64_C(-6305630541365849726),
179 V8_INT64_C(-5982222642272245453), V8_INT64_C(-5510103099058504169),
180 V8_INT64_C(-5496838675802432701), V8_INT64_C(-4047626578868642657),
181 V8_INT64_C(-4033755046900164544), V8_INT64_C(-3554299241457877041),
182 V8_INT64_C(-2482258764588614470), V8_INT64_C(-1688515425526875335),
183 V8_INT64_C(-924784137176548532), V8_INT64_C(-725316567157391307),
184 V8_INT64_C(-439022654781092241), V8_INT64_C(-105545757668917080),
185 V8_INT64_C(-2088319373), V8_INT64_C(-2073699916),
186 V8_INT64_C(-1844949911), V8_INT64_C(-1831090548),
187 V8_INT64_C(-1756711933), V8_INT64_C(-1559409497),
188 V8_INT64_C(-1281179700), V8_INT64_C(-1211513985),
189 V8_INT64_C(-1182371520), V8_INT64_C(-785934753),
190 V8_INT64_C(-767480697), V8_INT64_C(-705745662),
191 V8_INT64_C(-514362436), V8_INT64_C(-459916580),
192 V8_INT64_C(-312328082), V8_INT64_C(-302949707),
193 V8_INT64_C(-285499304), V8_INT64_C(-125701262),
194 V8_INT64_C(-95139843), V8_INT64_C(-32768),
195 V8_INT64_C(-27542), V8_INT64_C(-23600),
196 V8_INT64_C(-18582), V8_INT64_C(-17770),
197 V8_INT64_C(-9086), V8_INT64_C(-9010),
198 V8_INT64_C(-8244), V8_INT64_C(-2890),
199 V8_INT64_C(-103), V8_INT64_C(-34),
200 V8_INT64_C(-27), V8_INT64_C(-25),
201 V8_INT64_C(-9), V8_INT64_C(-7),
202 V8_INT64_C(0), V8_INT64_C(2),
203 V8_INT64_C(38), V8_INT64_C(58),
204 V8_INT64_C(65), V8_INT64_C(93),
205 V8_INT64_C(111), V8_INT64_C(1003),
206 V8_INT64_C(1267), V8_INT64_C(12797),
207 V8_INT64_C(23122), V8_INT64_C(28200),
208 V8_INT64_C(30888), V8_INT64_C(42648848),
209 V8_INT64_C(116836693), V8_INT64_C(263003643),
210 V8_INT64_C(571039860), V8_INT64_C(1079398689),
211 V8_INT64_C(1145196402), V8_INT64_C(1184846321),
212 V8_INT64_C(1758281648), V8_INT64_C(1859991374),
213 V8_INT64_C(1960251588), V8_INT64_C(2042443199),
214 V8_INT64_C(296220586027987448), V8_INT64_C(1015494173071134726),
215 V8_INT64_C(1151237951914455318), V8_INT64_C(1331941174616854174),
216 V8_INT64_C(2022020418667972654), V8_INT64_C(2450251424374977035),
217 V8_INT64_C(3668393562685561486), V8_INT64_C(4858229301215502171),
218 V8_INT64_C(4919426235170669383), V8_INT64_C(5034286595330341762),
219 V8_INT64_C(5055797915536941182), V8_INT64_C(6072389716149252074),
220 V8_INT64_C(6185309910199801210), V8_INT64_C(6297328311011094138),
221 V8_INT64_C(6932372858072165827), V8_INT64_C(8483640924987737210),
222 V8_INT64_C(8663764179455849203), V8_INT64_C(8877197042645298254),
223 V8_INT64_C(8901543506779157333), std::numeric_limits<int64_t>::max()};
226 const uint32_t kUint32Values[] = {
227 0x00000000, 0x00000001, 0xffffffff, 0x1b09788b, 0x04c5fce8, 0xcc0de5bf,
228 0x273a798e, 0x187937a3, 0xece3af83, 0x5495a16b, 0x0b668ecc, 0x11223344,
229 0x0000009e, 0x00000043, 0x0000af73, 0x0000116b, 0x00658ecc, 0x002b3b4c,
230 0x88776655, 0x70000000, 0x07200000, 0x7fffffff, 0x56123761, 0x7fffff00,
231 0x761c4761, 0x80000000, 0x88888888, 0xa0000000, 0xdddddddd, 0xe0000000,
232 0xeeeeeeee, 0xfffffffd, 0xf0000000, 0x007fffff, 0x003fffff, 0x001fffff,
233 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff,
234 0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
237 struct ComparisonBinaryOperator {
238 const Operator* (MachineOperatorBuilder::*constructor)();
239 const char* constructor_name;
243 std::ostream& operator<<(std::ostream& os,
244 ComparisonBinaryOperator const& cbop) {
245 return os << cbop.constructor_name;
249 const ComparisonBinaryOperator kComparisonBinaryOperators[] = {
250 #define OPCODE(Opcode) \
251 { &MachineOperatorBuilder::Opcode, #Opcode } \
253 MACHINE_COMPARE_BINOP_LIST(OPCODE)
260 // -----------------------------------------------------------------------------
266 struct UnaryOperator {
267 const Operator* (MachineOperatorBuilder::*constructor)();
268 const char* constructor_name;
272 std::ostream& operator<<(std::ostream& os, const UnaryOperator& unop) {
273 return os << unop.constructor_name;
277 static const UnaryOperator kUnaryOperators[] = {
278 {&MachineOperatorBuilder::ChangeInt32ToFloat64, "ChangeInt32ToFloat64"},
279 {&MachineOperatorBuilder::ChangeUint32ToFloat64, "ChangeUint32ToFloat64"},
280 {&MachineOperatorBuilder::ChangeFloat64ToInt32, "ChangeFloat64ToInt32"},
281 {&MachineOperatorBuilder::ChangeFloat64ToUint32, "ChangeFloat64ToUint32"},
282 {&MachineOperatorBuilder::ChangeInt32ToInt64, "ChangeInt32ToInt64"},
283 {&MachineOperatorBuilder::ChangeUint32ToUint64, "ChangeUint32ToUint64"},
284 {&MachineOperatorBuilder::TruncateFloat64ToInt32, "TruncateFloat64ToInt32"},
285 {&MachineOperatorBuilder::TruncateInt64ToInt32, "TruncateInt64ToInt32"}};
290 typedef MachineOperatorReducerTestWithParam<UnaryOperator>
291 MachineUnaryOperatorReducerTest;
294 TEST_P(MachineUnaryOperatorReducerTest, Parameter) {
295 const UnaryOperator unop = GetParam();
296 Reduction reduction =
297 Reduce(graph()->NewNode((machine()->*unop.constructor)(), Parameter(0)));
298 EXPECT_FALSE(reduction.Changed());
302 INSTANTIATE_TEST_CASE_P(MachineOperatorReducerTest,
303 MachineUnaryOperatorReducerTest,
304 ::testing::ValuesIn(kUnaryOperators));
307 // -----------------------------------------------------------------------------
308 // ChangeFloat64ToFloat32
311 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToFloat32WithConstant) {
312 TRACED_FOREACH(float, x, kFloat32Values) {
313 Reduction reduction = Reduce(graph()->NewNode(
314 machine()->ChangeFloat32ToFloat64(), Float32Constant(x)));
315 ASSERT_TRUE(reduction.Changed());
316 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq<double>(x)));
321 // -----------------------------------------------------------------------------
322 // ChangeFloat64ToInt32
325 TEST_F(MachineOperatorReducerTest,
326 ChangeFloat64ToInt32WithChangeInt32ToFloat64) {
327 Node* value = Parameter(0);
328 Reduction reduction = Reduce(graph()->NewNode(
329 machine()->ChangeFloat64ToInt32(),
330 graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
331 ASSERT_TRUE(reduction.Changed());
332 EXPECT_EQ(value, reduction.replacement());
336 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToInt32WithConstant) {
337 TRACED_FOREACH(int32_t, x, kInt32Values) {
338 Reduction reduction = Reduce(graph()->NewNode(
339 machine()->ChangeFloat64ToInt32(), Float64Constant(FastI2D(x))));
340 ASSERT_TRUE(reduction.Changed());
341 EXPECT_THAT(reduction.replacement(), IsInt32Constant(x));
346 // -----------------------------------------------------------------------------
347 // ChangeFloat64ToUint32
350 TEST_F(MachineOperatorReducerTest,
351 ChangeFloat64ToUint32WithChangeUint32ToFloat64) {
352 Node* value = Parameter(0);
353 Reduction reduction = Reduce(graph()->NewNode(
354 machine()->ChangeFloat64ToUint32(),
355 graph()->NewNode(machine()->ChangeUint32ToFloat64(), value)));
356 ASSERT_TRUE(reduction.Changed());
357 EXPECT_EQ(value, reduction.replacement());
361 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToUint32WithConstant) {
362 TRACED_FOREACH(uint32_t, x, kUint32Values) {
363 Reduction reduction = Reduce(graph()->NewNode(
364 machine()->ChangeFloat64ToUint32(), Float64Constant(FastUI2D(x))));
365 ASSERT_TRUE(reduction.Changed());
366 EXPECT_THAT(reduction.replacement(), IsInt32Constant(bit_cast<int32_t>(x)));
371 // -----------------------------------------------------------------------------
372 // ChangeInt32ToFloat64
375 TEST_F(MachineOperatorReducerTest, ChangeInt32ToFloat64WithConstant) {
376 TRACED_FOREACH(int32_t, x, kInt32Values) {
377 Reduction reduction = Reduce(
378 graph()->NewNode(machine()->ChangeInt32ToFloat64(), Int32Constant(x)));
379 ASSERT_TRUE(reduction.Changed());
380 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastI2D(x))));
385 // -----------------------------------------------------------------------------
386 // ChangeInt32ToInt64
389 TEST_F(MachineOperatorReducerTest, ChangeInt32ToInt64WithConstant) {
390 TRACED_FOREACH(int32_t, x, kInt32Values) {
391 Reduction reduction = Reduce(
392 graph()->NewNode(machine()->ChangeInt32ToInt64(), Int32Constant(x)));
393 ASSERT_TRUE(reduction.Changed());
394 EXPECT_THAT(reduction.replacement(), IsInt64Constant(x));
399 // -----------------------------------------------------------------------------
400 // ChangeUint32ToFloat64
403 TEST_F(MachineOperatorReducerTest, ChangeUint32ToFloat64WithConstant) {
404 TRACED_FOREACH(uint32_t, x, kUint32Values) {
405 Reduction reduction =
406 Reduce(graph()->NewNode(machine()->ChangeUint32ToFloat64(),
407 Int32Constant(bit_cast<int32_t>(x))));
408 ASSERT_TRUE(reduction.Changed());
409 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastUI2D(x))));
414 // -----------------------------------------------------------------------------
415 // ChangeUint32ToUint64
418 TEST_F(MachineOperatorReducerTest, ChangeUint32ToUint64WithConstant) {
419 TRACED_FOREACH(uint32_t, x, kUint32Values) {
420 Reduction reduction =
421 Reduce(graph()->NewNode(machine()->ChangeUint32ToUint64(),
422 Int32Constant(bit_cast<int32_t>(x))));
423 ASSERT_TRUE(reduction.Changed());
424 EXPECT_THAT(reduction.replacement(),
425 IsInt64Constant(bit_cast<int64_t>(static_cast<uint64_t>(x))));
430 // -----------------------------------------------------------------------------
431 // TruncateFloat64ToFloat32
434 TEST_F(MachineOperatorReducerTest,
435 TruncateFloat64ToFloat32WithChangeFloat32ToFloat64) {
436 Node* value = Parameter(0);
437 Reduction reduction = Reduce(graph()->NewNode(
438 machine()->TruncateFloat64ToFloat32(),
439 graph()->NewNode(machine()->ChangeFloat32ToFloat64(), value)));
440 ASSERT_TRUE(reduction.Changed());
441 EXPECT_EQ(value, reduction.replacement());
445 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) {
446 TRACED_FOREACH(double, x, kFloat64Values) {
447 Reduction reduction = Reduce(graph()->NewNode(
448 machine()->TruncateFloat64ToFloat32(), Float64Constant(x)));
449 ASSERT_TRUE(reduction.Changed());
450 EXPECT_THAT(reduction.replacement(),
451 IsFloat32Constant(BitEq(DoubleToFloat32(x))));
456 // -----------------------------------------------------------------------------
457 // TruncateFloat64ToInt32
460 TEST_F(MachineOperatorReducerTest,
461 TruncateFloat64ToInt32WithChangeInt32ToFloat64) {
462 Node* value = Parameter(0);
463 Reduction reduction = Reduce(graph()->NewNode(
464 machine()->TruncateFloat64ToInt32(),
465 graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
466 ASSERT_TRUE(reduction.Changed());
467 EXPECT_EQ(value, reduction.replacement());
471 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithConstant) {
472 TRACED_FOREACH(double, x, kFloat64Values) {
473 Reduction reduction = Reduce(graph()->NewNode(
474 machine()->TruncateFloat64ToInt32(), Float64Constant(x)));
475 ASSERT_TRUE(reduction.Changed());
476 EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
481 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithPhi) {
482 Node* const p0 = Parameter(0);
483 Node* const p1 = Parameter(1);
484 Node* const merge = graph()->start();
485 Reduction reduction = Reduce(graph()->NewNode(
486 machine()->TruncateFloat64ToInt32(),
487 graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge)));
488 ASSERT_TRUE(reduction.Changed());
489 EXPECT_THAT(reduction.replacement(),
490 IsPhi(kMachInt32, IsTruncateFloat64ToInt32(p0),
491 IsTruncateFloat64ToInt32(p1), merge));
495 // -----------------------------------------------------------------------------
496 // TruncateInt64ToInt32
499 TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithChangeInt32ToInt64) {
500 Node* value = Parameter(0);
501 Reduction reduction = Reduce(graph()->NewNode(
502 machine()->TruncateInt64ToInt32(),
503 graph()->NewNode(machine()->ChangeInt32ToInt64(), value)));
504 ASSERT_TRUE(reduction.Changed());
505 EXPECT_EQ(value, reduction.replacement());
509 TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithConstant) {
510 TRACED_FOREACH(int64_t, x, kInt64Values) {
511 Reduction reduction = Reduce(
512 graph()->NewNode(machine()->TruncateInt64ToInt32(), Int64Constant(x)));
513 ASSERT_TRUE(reduction.Changed());
514 EXPECT_THAT(reduction.replacement(),
515 IsInt32Constant(bit_cast<int32_t>(
516 static_cast<uint32_t>(bit_cast<uint64_t>(x)))));
521 // -----------------------------------------------------------------------------
525 TEST_F(MachineOperatorReducerTest, Word32AndWithWord32ShlWithConstant) {
526 Node* const p0 = Parameter(0);
528 TRACED_FORRANGE(int32_t, l, 1, 31) {
529 TRACED_FORRANGE(int32_t, k, 1, l) {
530 // (x << L) & (-1 << K) => x << L
531 Reduction const r1 = Reduce(graph()->NewNode(
532 machine()->Word32And(),
533 graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l)),
534 Int32Constant(-1 << k)));
535 ASSERT_TRUE(r1.Changed());
536 EXPECT_THAT(r1.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
538 // (-1 << K) & (x << L) => x << L
539 Reduction const r2 = Reduce(graph()->NewNode(
540 machine()->Word32And(), Int32Constant(-1 << k),
541 graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l))));
542 ASSERT_TRUE(r2.Changed());
543 EXPECT_THAT(r2.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
549 TEST_F(MachineOperatorReducerTest, Word32AndWithWord32AndWithConstant) {
550 Node* const p0 = Parameter(0);
552 TRACED_FOREACH(int32_t, k, kInt32Values) {
553 TRACED_FOREACH(int32_t, l, kInt32Values) {
554 if (k == 0 || k == -1 || l == 0 || l == -1) continue;
556 // (x & K) & L => x & (K & L)
557 Reduction const r1 = Reduce(graph()->NewNode(
558 machine()->Word32And(),
559 graph()->NewNode(machine()->Word32And(), p0, Int32Constant(k)),
561 ASSERT_TRUE(r1.Changed());
562 EXPECT_THAT(r1.replacement(),
563 (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
564 : IsInt32Constant(0));
566 // (K & x) & L => x & (K & L)
567 Reduction const r2 = Reduce(graph()->NewNode(
568 machine()->Word32And(),
569 graph()->NewNode(machine()->Word32And(), Int32Constant(k), p0),
571 ASSERT_TRUE(r2.Changed());
572 EXPECT_THAT(r2.replacement(),
573 (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
574 : IsInt32Constant(0));
580 TEST_F(MachineOperatorReducerTest, Word32AndWithInt32AddAndConstant) {
581 Node* const p0 = Parameter(0);
582 Node* const p1 = Parameter(1);
584 TRACED_FORRANGE(int32_t, l, 1, 31) {
585 TRACED_FOREACH(int32_t, k, kInt32Values) {
586 if ((k << l) == 0) continue;
587 // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
588 Reduction const r = Reduce(graph()->NewNode(
589 machine()->Word32And(),
590 graph()->NewNode(machine()->Int32Add(), p0, Int32Constant(k << l)),
591 Int32Constant(-1 << l)));
592 ASSERT_TRUE(r.Changed());
593 EXPECT_THAT(r.replacement(),
594 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
595 IsInt32Constant(k << l)));
598 Node* s1 = graph()->NewNode(machine()->Word32Shl(), p1, Int32Constant(l));
600 // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
601 Reduction const r1 = Reduce(graph()->NewNode(
602 machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), s1, p0),
603 Int32Constant(-1 << l)));
604 ASSERT_TRUE(r1.Changed());
605 EXPECT_THAT(r1.replacement(),
606 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)), s1));
608 // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
609 Reduction const r2 = Reduce(graph()->NewNode(
610 machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), p0, s1),
611 Int32Constant(-1 << l)));
612 ASSERT_TRUE(r2.Changed());
613 EXPECT_THAT(r2.replacement(),
614 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)), s1));
619 TEST_F(MachineOperatorReducerTest, Word32AndWithInt32MulAndConstant) {
620 Node* const p0 = Parameter(0);
622 TRACED_FORRANGE(int32_t, l, 1, 31) {
623 TRACED_FOREACH(int32_t, k, kInt32Values) {
624 if ((k << l) == 0) continue;
626 // (x * (K << L)) & (-1 << L) => x * (K << L)
627 Reduction const r1 = Reduce(graph()->NewNode(
628 machine()->Word32And(),
629 graph()->NewNode(machine()->Int32Mul(), p0, Int32Constant(k << l)),
630 Int32Constant(-1 << l)));
631 ASSERT_TRUE(r1.Changed());
632 EXPECT_THAT(r1.replacement(), IsInt32Mul(p0, IsInt32Constant(k << l)));
634 // ((K << L) * x) & (-1 << L) => x * (K << L)
635 Reduction const r2 = Reduce(graph()->NewNode(
636 machine()->Word32And(),
637 graph()->NewNode(machine()->Int32Mul(), Int32Constant(k << l), p0),
638 Int32Constant(-1 << l)));
639 ASSERT_TRUE(r2.Changed());
640 EXPECT_THAT(r2.replacement(), IsInt32Mul(p0, IsInt32Constant(k << l)));
646 TEST_F(MachineOperatorReducerTest,
647 Word32AndWithInt32AddAndInt32MulAndConstant) {
648 Node* const p0 = Parameter(0);
649 Node* const p1 = Parameter(1);
651 TRACED_FORRANGE(int32_t, l, 1, 31) {
652 TRACED_FOREACH(int32_t, k, kInt32Values) {
653 if ((k << l) == 0) continue;
654 // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
655 Reduction const r1 = Reduce(graph()->NewNode(
656 machine()->Word32And(),
657 graph()->NewNode(machine()->Int32Add(),
658 graph()->NewNode(machine()->Int32Mul(), p1,
659 Int32Constant(k << l)),
661 Int32Constant(-1 << l)));
662 ASSERT_TRUE(r1.Changed());
663 EXPECT_THAT(r1.replacement(),
664 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
665 IsInt32Mul(p1, IsInt32Constant(k << l))));
667 // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
668 Reduction const r2 = Reduce(graph()->NewNode(
669 machine()->Word32And(),
670 graph()->NewNode(machine()->Int32Add(), p0,
671 graph()->NewNode(machine()->Int32Mul(), p1,
672 Int32Constant(k << l))),
673 Int32Constant(-1 << l)));
674 ASSERT_TRUE(r2.Changed());
675 EXPECT_THAT(r2.replacement(),
676 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
677 IsInt32Mul(p1, IsInt32Constant(k << l))));
683 TEST_F(MachineOperatorReducerTest, Word32AndWithComparisonAndConstantOne) {
684 Node* const p0 = Parameter(0);
685 Node* const p1 = Parameter(1);
686 TRACED_FOREACH(ComparisonBinaryOperator, cbop, kComparisonBinaryOperators) {
687 Node* cmp = graph()->NewNode((machine()->*cbop.constructor)(), p0, p1);
691 Reduce(graph()->NewNode(machine()->Word32And(), cmp, Int32Constant(1)));
692 ASSERT_TRUE(r1.Changed());
693 EXPECT_EQ(cmp, r1.replacement());
697 Reduce(graph()->NewNode(machine()->Word32And(), Int32Constant(1), cmp));
698 ASSERT_TRUE(r2.Changed());
699 EXPECT_EQ(cmp, r2.replacement());
704 // -----------------------------------------------------------------------------
708 TEST_F(MachineOperatorReducerTest, Word32XorWithWord32XorAndMinusOne) {
709 Node* const p0 = Parameter(0);
711 // (x ^ -1) ^ -1 => x
712 Reduction r1 = Reduce(graph()->NewNode(
713 machine()->Word32Xor(),
714 graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1)),
716 ASSERT_TRUE(r1.Changed());
717 EXPECT_EQ(r1.replacement(), p0);
719 // -1 ^ (x ^ -1) => x
720 Reduction r2 = Reduce(graph()->NewNode(
721 machine()->Word32Xor(), Int32Constant(-1),
722 graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1))));
723 ASSERT_TRUE(r2.Changed());
724 EXPECT_EQ(r2.replacement(), p0);
726 // (-1 ^ x) ^ -1 => x
727 Reduction r3 = Reduce(graph()->NewNode(
728 machine()->Word32Xor(),
729 graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0),
731 ASSERT_TRUE(r3.Changed());
732 EXPECT_EQ(r3.replacement(), p0);
734 // -1 ^ (-1 ^ x) => x
735 Reduction r4 = Reduce(graph()->NewNode(
736 machine()->Word32Xor(), Int32Constant(-1),
737 graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0)));
738 ASSERT_TRUE(r4.Changed());
739 EXPECT_EQ(r4.replacement(), p0);
743 // -----------------------------------------------------------------------------
747 TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithParameters) {
748 Node* value = Parameter(0);
749 Node* shift = Parameter(1);
750 Node* sub = graph()->NewNode(machine()->Int32Sub(), Int32Constant(32), shift);
752 // Testing rotate left.
753 Node* shl_l = graph()->NewNode(machine()->Word32Shl(), value, shift);
754 Node* shr_l = graph()->NewNode(machine()->Word32Shr(), value, sub);
756 // (x << y) | (x >>> (32 - y)) => x ror (32 - y)
757 Node* node1 = graph()->NewNode(machine()->Word32Or(), shl_l, shr_l);
758 Reduction reduction1 = Reduce(node1);
759 EXPECT_TRUE(reduction1.Changed());
760 EXPECT_EQ(reduction1.replacement(), node1);
761 EXPECT_THAT(reduction1.replacement(), IsWord32Ror(value, sub));
763 // (x >>> (32 - y)) | (x << y) => x ror (32 - y)
764 Node* node2 = graph()->NewNode(machine()->Word32Or(), shr_l, shl_l);
765 Reduction reduction2 = Reduce(node2);
766 EXPECT_TRUE(reduction2.Changed());
767 EXPECT_EQ(reduction2.replacement(), node2);
768 EXPECT_THAT(reduction2.replacement(), IsWord32Ror(value, sub));
770 // Testing rotate right.
771 Node* shl_r = graph()->NewNode(machine()->Word32Shl(), value, sub);
772 Node* shr_r = graph()->NewNode(machine()->Word32Shr(), value, shift);
774 // (x << (32 - y)) | (x >>> y) => x ror y
775 Node* node3 = graph()->NewNode(machine()->Word32Or(), shl_r, shr_r);
776 Reduction reduction3 = Reduce(node3);
777 EXPECT_TRUE(reduction3.Changed());
778 EXPECT_EQ(reduction3.replacement(), node3);
779 EXPECT_THAT(reduction3.replacement(), IsWord32Ror(value, shift));
781 // (x >>> y) | (x << (32 - y)) => x ror y
782 Node* node4 = graph()->NewNode(machine()->Word32Or(), shr_r, shl_r);
783 Reduction reduction4 = Reduce(node4);
784 EXPECT_TRUE(reduction4.Changed());
785 EXPECT_EQ(reduction4.replacement(), node4);
786 EXPECT_THAT(reduction4.replacement(), IsWord32Ror(value, shift));
790 TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithConstant) {
791 Node* value = Parameter(0);
792 TRACED_FORRANGE(int32_t, k, 0, 31) {
794 graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(k));
796 graph()->NewNode(machine()->Word32Shr(), value, Int32Constant(32 - k));
798 // (x << K) | (x >>> ((32 - K) - y)) => x ror (32 - K)
799 Node* node1 = graph()->NewNode(machine()->Word32Or(), shl, shr);
800 Reduction reduction1 = Reduce(node1);
801 EXPECT_TRUE(reduction1.Changed());
802 EXPECT_EQ(reduction1.replacement(), node1);
803 EXPECT_THAT(reduction1.replacement(),
804 IsWord32Ror(value, IsInt32Constant(32 - k)));
806 // (x >>> (32 - K)) | (x << K) => x ror (32 - K)
807 Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl);
808 Reduction reduction2 = Reduce(node2);
809 EXPECT_TRUE(reduction2.Changed());
810 EXPECT_EQ(reduction2.replacement(), node2);
811 EXPECT_THAT(reduction2.replacement(),
812 IsWord32Ror(value, IsInt32Constant(32 - k)));
817 TEST_F(MachineOperatorReducerTest, Word32RorWithZeroShift) {
818 Node* value = Parameter(0);
820 graph()->NewNode(machine()->Word32Ror(), value, Int32Constant(0));
821 Reduction reduction = Reduce(node);
822 EXPECT_TRUE(reduction.Changed());
823 EXPECT_EQ(reduction.replacement(), value);
827 TEST_F(MachineOperatorReducerTest, Word32RorWithConstants) {
828 TRACED_FOREACH(int32_t, x, kUint32Values) {
829 TRACED_FORRANGE(int32_t, y, 0, 31) {
830 Node* node = graph()->NewNode(machine()->Word32Ror(), Int32Constant(x),
832 Reduction reduction = Reduce(node);
833 EXPECT_TRUE(reduction.Changed());
834 EXPECT_THAT(reduction.replacement(),
835 IsInt32Constant(base::bits::RotateRight32(x, y)));
841 // -----------------------------------------------------------------------------
845 TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndComparison) {
846 Node* const p0 = Parameter(0);
847 Node* const p1 = Parameter(1);
849 TRACED_FOREACH(ComparisonBinaryOperator, cbop, kComparisonBinaryOperators) {
850 Node* cmp = graph()->NewNode((machine()->*cbop.constructor)(), p0, p1);
852 // cmp << 31 >> 31 => 0 - cmp
853 Reduction const r = Reduce(graph()->NewNode(
854 machine()->Word32Sar(),
855 graph()->NewNode(machine()->Word32Shl(), cmp, Int32Constant(31)),
857 ASSERT_TRUE(r.Changed());
858 EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0), cmp));
863 TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndLoad) {
864 Node* const p0 = Parameter(0);
865 Node* const p1 = Parameter(1);
867 Node* const l = graph()->NewNode(machine()->Load(kMachInt8), p0, p1,
868 graph()->start(), graph()->start());
869 Reduction const r = Reduce(graph()->NewNode(
870 machine()->Word32Sar(),
871 graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(24)),
873 ASSERT_TRUE(r.Changed());
874 EXPECT_EQ(l, r.replacement());
877 Node* const l = graph()->NewNode(machine()->Load(kMachInt16), p0, p1,
878 graph()->start(), graph()->start());
879 Reduction const r = Reduce(graph()->NewNode(
880 machine()->Word32Sar(),
881 graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(16)),
883 ASSERT_TRUE(r.Changed());
884 EXPECT_EQ(l, r.replacement());
889 // -----------------------------------------------------------------------------
893 TEST_F(MachineOperatorReducerTest, Word32ShlWithZeroShift) {
894 Node* p0 = Parameter(0);
895 Node* node = graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(0));
896 Reduction r = Reduce(node);
897 ASSERT_TRUE(r.Changed());
898 EXPECT_EQ(p0, r.replacement());
902 TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Sar) {
903 Node* p0 = Parameter(0);
904 TRACED_FORRANGE(int32_t, x, 1, 31) {
905 Node* node = graph()->NewNode(
906 machine()->Word32Shl(),
907 graph()->NewNode(machine()->Word32Sar(), p0, Int32Constant(x)),
909 Reduction r = Reduce(node);
910 ASSERT_TRUE(r.Changed());
911 int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
912 EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
917 TEST_F(MachineOperatorReducerTest,
918 Word32ShlWithWord32SarAndInt32AddAndConstant) {
919 Node* const p0 = Parameter(0);
920 TRACED_FOREACH(int32_t, k, kInt32Values) {
921 TRACED_FORRANGE(int32_t, l, 1, 31) {
922 if ((k << l) == 0) continue;
923 // (x + (K << L)) >> L << L => (x & (-1 << L)) + (K << L)
924 Reduction const r = Reduce(graph()->NewNode(
925 machine()->Word32Shl(),
926 graph()->NewNode(machine()->Word32Sar(),
927 graph()->NewNode(machine()->Int32Add(), p0,
928 Int32Constant(k << l)),
931 ASSERT_TRUE(r.Changed());
932 EXPECT_THAT(r.replacement(),
933 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
934 IsInt32Constant(k << l)));
940 TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Shr) {
941 Node* p0 = Parameter(0);
942 TRACED_FORRANGE(int32_t, x, 1, 31) {
943 Node* node = graph()->NewNode(
944 machine()->Word32Shl(),
945 graph()->NewNode(machine()->Word32Shr(), p0, Int32Constant(x)),
947 Reduction r = Reduce(node);
948 ASSERT_TRUE(r.Changed());
949 int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
950 EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
955 // -----------------------------------------------------------------------------
959 TEST_F(MachineOperatorReducerTest, Int32SubWithConstant) {
960 Node* const p0 = Parameter(0);
961 TRACED_FOREACH(int32_t, k, kInt32Values) {
963 Reduce(graph()->NewNode(machine()->Int32Sub(), p0, Int32Constant(k)));
964 ASSERT_TRUE(r.Changed());
966 EXPECT_EQ(p0, r.replacement());
968 EXPECT_THAT(r.replacement(), IsInt32Add(p0, IsInt32Constant(-k)));
974 // -----------------------------------------------------------------------------
978 TEST_F(MachineOperatorReducerTest, Int32DivWithConstant) {
979 Node* const p0 = Parameter(0);
981 Reduction const r = Reduce(graph()->NewNode(
982 machine()->Int32Div(), p0, Int32Constant(0), graph()->start()));
983 ASSERT_TRUE(r.Changed());
984 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
987 Reduction const r = Reduce(graph()->NewNode(
988 machine()->Int32Div(), p0, Int32Constant(1), graph()->start()));
989 ASSERT_TRUE(r.Changed());
990 EXPECT_EQ(r.replacement(), p0);
993 Reduction const r = Reduce(graph()->NewNode(
994 machine()->Int32Div(), p0, Int32Constant(-1), graph()->start()));
995 ASSERT_TRUE(r.Changed());
996 EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0), p0));
999 Reduction const r = Reduce(graph()->NewNode(
1000 machine()->Int32Div(), p0, Int32Constant(2), graph()->start()));
1001 ASSERT_TRUE(r.Changed());
1004 IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
1005 IsInt32Constant(1)));
1008 Reduction const r = Reduce(graph()->NewNode(
1009 machine()->Int32Div(), p0, Int32Constant(-2), graph()->start()));
1010 ASSERT_TRUE(r.Changed());
1015 IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
1016 IsInt32Constant(1))));
1018 TRACED_FORRANGE(int32_t, shift, 2, 30) {
1020 Reduce(graph()->NewNode(machine()->Int32Div(), p0,
1021 Int32Constant(1 << shift), graph()->start()));
1022 ASSERT_TRUE(r.Changed());
1025 IsWord32Sar(IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
1026 IsInt32Constant(32 - shift)),
1028 IsInt32Constant(shift)));
1030 TRACED_FORRANGE(int32_t, shift, 2, 31) {
1031 Reduction const r = Reduce(graph()->NewNode(
1032 machine()->Int32Div(), p0,
1033 Uint32Constant(bit_cast<uint32_t, int32_t>(-1) << shift),
1035 ASSERT_TRUE(r.Changed());
1041 IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
1042 IsInt32Constant(32 - shift)),
1044 IsInt32Constant(shift))));
1046 TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1048 if (base::bits::IsPowerOfTwo32(-divisor)) continue;
1049 Reduction const r = Reduce(graph()->NewNode(
1050 machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
1051 ASSERT_TRUE(r.Changed());
1052 EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0),
1053 IsTruncatingDiv(p0, -divisor)));
1054 } else if (divisor > 0) {
1055 if (base::bits::IsPowerOfTwo32(divisor)) continue;
1056 Reduction const r = Reduce(graph()->NewNode(
1057 machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
1058 ASSERT_TRUE(r.Changed());
1059 EXPECT_THAT(r.replacement(), IsTruncatingDiv(p0, divisor));
1065 TEST_F(MachineOperatorReducerTest, Int32DivWithParameters) {
1066 Node* const p0 = Parameter(0);
1068 Reduce(graph()->NewNode(machine()->Int32Div(), p0, p0, graph()->start()));
1069 ASSERT_TRUE(r.Changed());
1072 IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
1076 // -----------------------------------------------------------------------------
1080 TEST_F(MachineOperatorReducerTest, Uint32DivWithConstant) {
1081 Node* const p0 = Parameter(0);
1083 Reduction const r = Reduce(graph()->NewNode(
1084 machine()->Uint32Div(), Int32Constant(0), p0, graph()->start()));
1085 ASSERT_TRUE(r.Changed());
1086 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1089 Reduction const r = Reduce(graph()->NewNode(
1090 machine()->Uint32Div(), p0, Int32Constant(0), graph()->start()));
1091 ASSERT_TRUE(r.Changed());
1092 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1095 Reduction const r = Reduce(graph()->NewNode(
1096 machine()->Uint32Div(), p0, Int32Constant(1), graph()->start()));
1097 ASSERT_TRUE(r.Changed());
1098 EXPECT_EQ(r.replacement(), p0);
1100 TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1101 TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1102 Reduction const r = Reduce(
1103 graph()->NewNode(machine()->Uint32Div(), Uint32Constant(dividend),
1104 Uint32Constant(divisor), graph()->start()));
1105 ASSERT_TRUE(r.Changed());
1106 EXPECT_THAT(r.replacement(),
1107 IsInt32Constant(bit_cast<int32_t>(
1108 base::bits::UnsignedDiv32(dividend, divisor))));
1111 TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1113 Reduce(graph()->NewNode(machine()->Uint32Div(), p0,
1114 Uint32Constant(1u << shift), graph()->start()));
1115 ASSERT_TRUE(r.Changed());
1116 EXPECT_THAT(r.replacement(),
1117 IsWord32Shr(p0, IsInt32Constant(bit_cast<int32_t>(shift))));
1122 TEST_F(MachineOperatorReducerTest, Uint32DivWithParameters) {
1123 Node* const p0 = Parameter(0);
1124 Reduction const r = Reduce(
1125 graph()->NewNode(machine()->Uint32Div(), p0, p0, graph()->start()));
1126 ASSERT_TRUE(r.Changed());
1129 IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
1133 // -----------------------------------------------------------------------------
1137 TEST_F(MachineOperatorReducerTest, Int32ModWithConstant) {
1138 Node* const p0 = Parameter(0);
1140 Reduction const r = Reduce(graph()->NewNode(
1141 machine()->Int32Mod(), Int32Constant(0), p0, graph()->start()));
1142 ASSERT_TRUE(r.Changed());
1143 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1146 Reduction const r = Reduce(graph()->NewNode(
1147 machine()->Int32Mod(), p0, Int32Constant(0), graph()->start()));
1148 ASSERT_TRUE(r.Changed());
1149 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1152 Reduction const r = Reduce(graph()->NewNode(
1153 machine()->Int32Mod(), p0, Int32Constant(1), graph()->start()));
1154 ASSERT_TRUE(r.Changed());
1155 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1158 Reduction const r = Reduce(graph()->NewNode(
1159 machine()->Int32Mod(), p0, Int32Constant(-1), graph()->start()));
1160 ASSERT_TRUE(r.Changed());
1161 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1163 TRACED_FOREACH(int32_t, dividend, kInt32Values) {
1164 TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1165 Reduction const r = Reduce(
1166 graph()->NewNode(machine()->Int32Mod(), Int32Constant(dividend),
1167 Int32Constant(divisor), graph()->start()));
1168 ASSERT_TRUE(r.Changed());
1169 EXPECT_THAT(r.replacement(),
1170 IsInt32Constant(base::bits::SignedMod32(dividend, divisor)));
1173 TRACED_FORRANGE(int32_t, shift, 1, 30) {
1175 Reduce(graph()->NewNode(machine()->Int32Mod(), p0,
1176 Int32Constant(1 << shift), graph()->start()));
1177 int32_t const mask = (1 << shift) - 1;
1178 ASSERT_TRUE(r.Changed());
1181 IsSelect(kMachInt32, IsInt32LessThan(p0, IsInt32Constant(0)),
1182 IsInt32Sub(IsInt32Constant(0),
1183 IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1184 IsInt32Constant(mask))),
1185 IsWord32And(p0, IsInt32Constant(mask))));
1187 TRACED_FORRANGE(int32_t, shift, 1, 31) {
1188 Reduction const r = Reduce(graph()->NewNode(
1189 machine()->Int32Mod(), p0,
1190 Uint32Constant(bit_cast<uint32_t, int32_t>(-1) << shift),
1192 int32_t const mask = bit_cast<int32_t, uint32_t>((1U << shift) - 1);
1193 ASSERT_TRUE(r.Changed());
1196 IsSelect(kMachInt32, IsInt32LessThan(p0, IsInt32Constant(0)),
1197 IsInt32Sub(IsInt32Constant(0),
1198 IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1199 IsInt32Constant(mask))),
1200 IsWord32And(p0, IsInt32Constant(mask))));
1202 TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1203 if (divisor == 0 || base::bits::IsPowerOfTwo32(Abs(divisor))) continue;
1204 Reduction const r = Reduce(graph()->NewNode(
1205 machine()->Int32Mod(), p0, Int32Constant(divisor), graph()->start()));
1206 ASSERT_TRUE(r.Changed());
1207 EXPECT_THAT(r.replacement(),
1208 IsInt32Sub(p0, IsInt32Mul(IsTruncatingDiv(p0, Abs(divisor)),
1209 IsInt32Constant(Abs(divisor)))));
1214 TEST_F(MachineOperatorReducerTest, Int32ModWithParameters) {
1215 Node* const p0 = Parameter(0);
1217 Reduce(graph()->NewNode(machine()->Int32Mod(), p0, p0, graph()->start()));
1218 ASSERT_TRUE(r.Changed());
1219 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1223 // -----------------------------------------------------------------------------
1227 TEST_F(MachineOperatorReducerTest, Uint32ModWithConstant) {
1228 Node* const p0 = Parameter(0);
1230 Reduction const r = Reduce(graph()->NewNode(
1231 machine()->Uint32Mod(), p0, Int32Constant(0), graph()->start()));
1232 ASSERT_TRUE(r.Changed());
1233 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1236 Reduction const r = Reduce(graph()->NewNode(
1237 machine()->Uint32Mod(), Int32Constant(0), p0, graph()->start()));
1238 ASSERT_TRUE(r.Changed());
1239 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1242 Reduction const r = Reduce(graph()->NewNode(
1243 machine()->Uint32Mod(), p0, Int32Constant(1), graph()->start()));
1244 ASSERT_TRUE(r.Changed());
1245 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1247 TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1248 TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1249 Reduction const r = Reduce(
1250 graph()->NewNode(machine()->Uint32Mod(), Uint32Constant(dividend),
1251 Uint32Constant(divisor), graph()->start()));
1252 ASSERT_TRUE(r.Changed());
1253 EXPECT_THAT(r.replacement(),
1254 IsInt32Constant(bit_cast<int32_t>(
1255 base::bits::UnsignedMod32(dividend, divisor))));
1258 TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1260 Reduce(graph()->NewNode(machine()->Uint32Mod(), p0,
1261 Uint32Constant(1u << shift), graph()->start()));
1262 ASSERT_TRUE(r.Changed());
1263 EXPECT_THAT(r.replacement(),
1264 IsWord32And(p0, IsInt32Constant(
1265 bit_cast<int32_t>((1u << shift) - 1u))));
1270 TEST_F(MachineOperatorReducerTest, Uint32ModWithParameters) {
1271 Node* const p0 = Parameter(0);
1272 Reduction const r = Reduce(
1273 graph()->NewNode(machine()->Uint32Mod(), p0, p0, graph()->start()));
1274 ASSERT_TRUE(r.Changed());
1275 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1279 // -----------------------------------------------------------------------------
1283 TEST_F(MachineOperatorReducerTest, Int32AddWithInt32SubWithConstantZero) {
1284 Node* const p0 = Parameter(0);
1285 Node* const p1 = Parameter(1);
1287 Reduction const r1 = Reduce(graph()->NewNode(
1288 machine()->Int32Add(),
1289 graph()->NewNode(machine()->Int32Sub(), Int32Constant(0), p0), p1));
1290 ASSERT_TRUE(r1.Changed());
1291 EXPECT_THAT(r1.replacement(), IsInt32Sub(p1, p0));
1293 Reduction const r2 = Reduce(graph()->NewNode(
1294 machine()->Int32Add(), p0,
1295 graph()->NewNode(machine()->Int32Sub(), Int32Constant(0), p1)));
1296 ASSERT_TRUE(r2.Changed());
1297 EXPECT_THAT(r2.replacement(), IsInt32Sub(p0, p1));
1301 // -----------------------------------------------------------------------------
1302 // Int32AddWithOverflow
1305 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) {
1306 Node* p0 = Parameter(0);
1308 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1309 Int32Constant(0), p0);
1311 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1312 ASSERT_TRUE(r.Changed());
1313 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1315 r = Reduce(graph()->NewNode(common()->Projection(0), add));
1316 ASSERT_TRUE(r.Changed());
1317 EXPECT_EQ(p0, r.replacement());
1320 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), p0,
1323 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1324 ASSERT_TRUE(r.Changed());
1325 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1327 r = Reduce(graph()->NewNode(common()->Projection(0), add));
1328 ASSERT_TRUE(r.Changed());
1329 EXPECT_EQ(p0, r.replacement());
1334 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) {
1335 TRACED_FOREACH(int32_t, x, kInt32Values) {
1336 TRACED_FOREACH(int32_t, y, kInt32Values) {
1338 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1339 Int32Constant(x), Int32Constant(y));
1341 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1342 ASSERT_TRUE(r.Changed());
1343 EXPECT_THAT(r.replacement(),
1344 IsInt32Constant(base::bits::SignedAddOverflow32(x, y, &z)));
1346 r = Reduce(graph()->NewNode(common()->Projection(0), add));
1347 ASSERT_TRUE(r.Changed());
1348 EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1354 // -----------------------------------------------------------------------------
1355 // Int32SubWithOverflow
1358 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithZero) {
1359 Node* p0 = Parameter(0);
1361 graph()->NewNode(machine()->Int32SubWithOverflow(), p0, Int32Constant(0));
1363 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1364 ASSERT_TRUE(r.Changed());
1365 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1367 r = Reduce(graph()->NewNode(common()->Projection(0), add));
1368 ASSERT_TRUE(r.Changed());
1369 EXPECT_EQ(p0, r.replacement());
1373 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
1374 TRACED_FOREACH(int32_t, x, kInt32Values) {
1375 TRACED_FOREACH(int32_t, y, kInt32Values) {
1377 Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(),
1378 Int32Constant(x), Int32Constant(y));
1380 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1381 ASSERT_TRUE(r.Changed());
1382 EXPECT_THAT(r.replacement(),
1383 IsInt32Constant(base::bits::SignedSubOverflow32(x, y, &z)));
1385 r = Reduce(graph()->NewNode(common()->Projection(0), add));
1386 ASSERT_TRUE(r.Changed());
1387 EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1393 // -----------------------------------------------------------------------------
1397 TEST_F(MachineOperatorReducerTest, Uint32LessThanWithWord32Sar) {
1398 Node* const p0 = Parameter(0);
1399 TRACED_FORRANGE(uint32_t, shift, 1, 3) {
1400 const uint32_t limit = (kMaxInt >> shift) - 1;
1401 Node* const node = graph()->NewNode(
1402 machine()->Uint32LessThan(),
1403 graph()->NewNode(machine()->Word32Sar(), p0, Uint32Constant(shift)),
1404 Uint32Constant(limit));
1406 Reduction r = Reduce(node);
1407 ASSERT_TRUE(r.Changed());
1408 EXPECT_THAT(r.replacement(),
1410 p0, IsInt32Constant(bit_cast<int32_t>(limit << shift))));
1415 // -----------------------------------------------------------------------------
1419 TEST_F(MachineOperatorReducerTest, Float64MulWithMinusOne) {
1420 Node* const p0 = Parameter(0);
1422 Reduction r = Reduce(
1423 graph()->NewNode(machine()->Float64Mul(), p0, Float64Constant(-1.0)));
1424 ASSERT_TRUE(r.Changed());
1425 EXPECT_THAT(r.replacement(),
1426 IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1429 Reduction r = Reduce(
1430 graph()->NewNode(machine()->Float64Mul(), Float64Constant(-1.0), p0));
1431 ASSERT_TRUE(r.Changed());
1432 EXPECT_THAT(r.replacement(),
1433 IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1438 // -----------------------------------------------------------------------------
1439 // Float64InsertLowWord32
1442 TEST_F(MachineOperatorReducerTest, Float64InsertLowWord32WithConstant) {
1443 TRACED_FOREACH(double, x, kFloat64Values) {
1444 TRACED_FOREACH(uint32_t, y, kUint32Values) {
1446 Reduce(graph()->NewNode(machine()->Float64InsertLowWord32(),
1447 Float64Constant(x), Uint32Constant(y)));
1448 ASSERT_TRUE(r.Changed());
1451 IsFloat64Constant(BitEq(bit_cast<double>(
1452 (bit_cast<uint64_t>(x) & V8_UINT64_C(0xFFFFFFFF00000000)) | y))));
1458 // -----------------------------------------------------------------------------
1459 // Float64InsertHighWord32
1462 TEST_F(MachineOperatorReducerTest, Float64InsertHighWord32WithConstant) {
1463 TRACED_FOREACH(double, x, kFloat64Values) {
1464 TRACED_FOREACH(uint32_t, y, kUint32Values) {
1466 Reduce(graph()->NewNode(machine()->Float64InsertHighWord32(),
1467 Float64Constant(x), Uint32Constant(y)));
1468 ASSERT_TRUE(r.Changed());
1469 EXPECT_THAT(r.replacement(),
1470 IsFloat64Constant(BitEq(bit_cast<double>(
1471 (bit_cast<uint64_t>(x) & V8_UINT64_C(0xFFFFFFFF)) |
1472 (static_cast<uint64_t>(y) << 32)))));
1478 // -----------------------------------------------------------------------------
1482 TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32And) {
1483 const StoreRepresentation rep(kRepWord8, kNoWriteBarrier);
1484 Node* const base = Parameter(0);
1485 Node* const index = Parameter(1);
1486 Node* const value = Parameter(2);
1487 Node* const effect = graph()->start();
1488 Node* const control = graph()->start();
1489 TRACED_FOREACH(uint32_t, x, kUint32Values) {
1491 graph()->NewNode(machine()->Store(rep), base, index,
1492 graph()->NewNode(machine()->Word32And(), value,
1493 Uint32Constant(x | 0xffu)),
1496 Reduction r = Reduce(node);
1497 ASSERT_TRUE(r.Changed());
1498 EXPECT_THAT(r.replacement(),
1499 IsStore(rep, base, index, value, effect, control));
1504 TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32SarAndWord32Shl) {
1505 const StoreRepresentation rep(kRepWord8, kNoWriteBarrier);
1506 Node* const base = Parameter(0);
1507 Node* const index = Parameter(1);
1508 Node* const value = Parameter(2);
1509 Node* const effect = graph()->start();
1510 Node* const control = graph()->start();
1511 TRACED_FORRANGE(int32_t, x, 1, 24) {
1512 Node* const node = graph()->NewNode(
1513 machine()->Store(rep), base, index,
1515 machine()->Word32Sar(),
1516 graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
1520 Reduction r = Reduce(node);
1521 ASSERT_TRUE(r.Changed());
1522 EXPECT_THAT(r.replacement(),
1523 IsStore(rep, base, index, value, effect, control));
1528 TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32And) {
1529 const StoreRepresentation rep(kRepWord16, kNoWriteBarrier);
1530 Node* const base = Parameter(0);
1531 Node* const index = Parameter(1);
1532 Node* const value = Parameter(2);
1533 Node* const effect = graph()->start();
1534 Node* const control = graph()->start();
1535 TRACED_FOREACH(uint32_t, x, kUint32Values) {
1537 graph()->NewNode(machine()->Store(rep), base, index,
1538 graph()->NewNode(machine()->Word32And(), value,
1539 Uint32Constant(x | 0xffffu)),
1542 Reduction r = Reduce(node);
1543 ASSERT_TRUE(r.Changed());
1544 EXPECT_THAT(r.replacement(),
1545 IsStore(rep, base, index, value, effect, control));
1550 TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32SarAndWord32Shl) {
1551 const StoreRepresentation rep(kRepWord16, kNoWriteBarrier);
1552 Node* const base = Parameter(0);
1553 Node* const index = Parameter(1);
1554 Node* const value = Parameter(2);
1555 Node* const effect = graph()->start();
1556 Node* const control = graph()->start();
1557 TRACED_FORRANGE(int32_t, x, 1, 16) {
1558 Node* const node = graph()->NewNode(
1559 machine()->Store(rep), base, index,
1561 machine()->Word32Sar(),
1562 graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
1566 Reduction r = Reduce(node);
1567 ASSERT_TRUE(r.Changed());
1568 EXPECT_THAT(r.replacement(),
1569 IsStore(rep, base, index, value, effect, control));
1573 } // namespace compiler
1574 } // namespace internal