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};
239 // -----------------------------------------------------------------------------
245 struct UnaryOperator {
246 const Operator* (MachineOperatorBuilder::*constructor)();
247 const char* constructor_name;
251 std::ostream& operator<<(std::ostream& os, const UnaryOperator& unop) {
252 return os << unop.constructor_name;
256 static const UnaryOperator kUnaryOperators[] = {
257 {&MachineOperatorBuilder::ChangeInt32ToFloat64, "ChangeInt32ToFloat64"},
258 {&MachineOperatorBuilder::ChangeUint32ToFloat64, "ChangeUint32ToFloat64"},
259 {&MachineOperatorBuilder::ChangeFloat64ToInt32, "ChangeFloat64ToInt32"},
260 {&MachineOperatorBuilder::ChangeFloat64ToUint32, "ChangeFloat64ToUint32"},
261 {&MachineOperatorBuilder::ChangeInt32ToInt64, "ChangeInt32ToInt64"},
262 {&MachineOperatorBuilder::ChangeUint32ToUint64, "ChangeUint32ToUint64"},
263 {&MachineOperatorBuilder::TruncateFloat64ToInt32, "TruncateFloat64ToInt32"},
264 {&MachineOperatorBuilder::TruncateInt64ToInt32, "TruncateInt64ToInt32"}};
269 typedef MachineOperatorReducerTestWithParam<UnaryOperator>
270 MachineUnaryOperatorReducerTest;
273 TEST_P(MachineUnaryOperatorReducerTest, Parameter) {
274 const UnaryOperator unop = GetParam();
275 Reduction reduction =
276 Reduce(graph()->NewNode((machine()->*unop.constructor)(), Parameter(0)));
277 EXPECT_FALSE(reduction.Changed());
281 INSTANTIATE_TEST_CASE_P(MachineOperatorReducerTest,
282 MachineUnaryOperatorReducerTest,
283 ::testing::ValuesIn(kUnaryOperators));
286 // -----------------------------------------------------------------------------
287 // ChangeFloat64ToFloat32
290 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToFloat32WithConstant) {
291 TRACED_FOREACH(float, x, kFloat32Values) {
292 Reduction reduction = Reduce(graph()->NewNode(
293 machine()->ChangeFloat32ToFloat64(), Float32Constant(x)));
294 ASSERT_TRUE(reduction.Changed());
295 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq<double>(x)));
300 // -----------------------------------------------------------------------------
301 // ChangeFloat64ToInt32
304 TEST_F(MachineOperatorReducerTest,
305 ChangeFloat64ToInt32WithChangeInt32ToFloat64) {
306 Node* value = Parameter(0);
307 Reduction reduction = Reduce(graph()->NewNode(
308 machine()->ChangeFloat64ToInt32(),
309 graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
310 ASSERT_TRUE(reduction.Changed());
311 EXPECT_EQ(value, reduction.replacement());
315 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToInt32WithConstant) {
316 TRACED_FOREACH(int32_t, x, kInt32Values) {
317 Reduction reduction = Reduce(graph()->NewNode(
318 machine()->ChangeFloat64ToInt32(), Float64Constant(FastI2D(x))));
319 ASSERT_TRUE(reduction.Changed());
320 EXPECT_THAT(reduction.replacement(), IsInt32Constant(x));
325 // -----------------------------------------------------------------------------
326 // ChangeFloat64ToUint32
329 TEST_F(MachineOperatorReducerTest,
330 ChangeFloat64ToUint32WithChangeUint32ToFloat64) {
331 Node* value = Parameter(0);
332 Reduction reduction = Reduce(graph()->NewNode(
333 machine()->ChangeFloat64ToUint32(),
334 graph()->NewNode(machine()->ChangeUint32ToFloat64(), value)));
335 ASSERT_TRUE(reduction.Changed());
336 EXPECT_EQ(value, reduction.replacement());
340 TEST_F(MachineOperatorReducerTest, ChangeFloat64ToUint32WithConstant) {
341 TRACED_FOREACH(uint32_t, x, kUint32Values) {
342 Reduction reduction = Reduce(graph()->NewNode(
343 machine()->ChangeFloat64ToUint32(), Float64Constant(FastUI2D(x))));
344 ASSERT_TRUE(reduction.Changed());
345 EXPECT_THAT(reduction.replacement(), IsInt32Constant(bit_cast<int32_t>(x)));
350 // -----------------------------------------------------------------------------
351 // ChangeInt32ToFloat64
354 TEST_F(MachineOperatorReducerTest, ChangeInt32ToFloat64WithConstant) {
355 TRACED_FOREACH(int32_t, x, kInt32Values) {
356 Reduction reduction = Reduce(
357 graph()->NewNode(machine()->ChangeInt32ToFloat64(), Int32Constant(x)));
358 ASSERT_TRUE(reduction.Changed());
359 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastI2D(x))));
364 // -----------------------------------------------------------------------------
365 // ChangeInt32ToInt64
368 TEST_F(MachineOperatorReducerTest, ChangeInt32ToInt64WithConstant) {
369 TRACED_FOREACH(int32_t, x, kInt32Values) {
370 Reduction reduction = Reduce(
371 graph()->NewNode(machine()->ChangeInt32ToInt64(), Int32Constant(x)));
372 ASSERT_TRUE(reduction.Changed());
373 EXPECT_THAT(reduction.replacement(), IsInt64Constant(x));
378 // -----------------------------------------------------------------------------
379 // ChangeUint32ToFloat64
382 TEST_F(MachineOperatorReducerTest, ChangeUint32ToFloat64WithConstant) {
383 TRACED_FOREACH(uint32_t, x, kUint32Values) {
384 Reduction reduction =
385 Reduce(graph()->NewNode(machine()->ChangeUint32ToFloat64(),
386 Int32Constant(bit_cast<int32_t>(x))));
387 ASSERT_TRUE(reduction.Changed());
388 EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastUI2D(x))));
393 // -----------------------------------------------------------------------------
394 // ChangeUint32ToUint64
397 TEST_F(MachineOperatorReducerTest, ChangeUint32ToUint64WithConstant) {
398 TRACED_FOREACH(uint32_t, x, kUint32Values) {
399 Reduction reduction =
400 Reduce(graph()->NewNode(machine()->ChangeUint32ToUint64(),
401 Int32Constant(bit_cast<int32_t>(x))));
402 ASSERT_TRUE(reduction.Changed());
403 EXPECT_THAT(reduction.replacement(),
404 IsInt64Constant(bit_cast<int64_t>(static_cast<uint64_t>(x))));
409 // -----------------------------------------------------------------------------
410 // TruncateFloat64ToFloat32
413 TEST_F(MachineOperatorReducerTest,
414 TruncateFloat64ToFloat32WithChangeFloat32ToFloat64) {
415 Node* value = Parameter(0);
416 Reduction reduction = Reduce(graph()->NewNode(
417 machine()->TruncateFloat64ToFloat32(),
418 graph()->NewNode(machine()->ChangeFloat32ToFloat64(), value)));
419 ASSERT_TRUE(reduction.Changed());
420 EXPECT_EQ(value, reduction.replacement());
424 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) {
425 TRACED_FOREACH(double, x, kFloat64Values) {
426 Reduction reduction = Reduce(graph()->NewNode(
427 machine()->TruncateFloat64ToFloat32(), Float64Constant(x)));
428 ASSERT_TRUE(reduction.Changed());
429 EXPECT_THAT(reduction.replacement(),
430 IsFloat32Constant(BitEq(DoubleToFloat32(x))));
435 // -----------------------------------------------------------------------------
436 // TruncateFloat64ToInt32
439 TEST_F(MachineOperatorReducerTest,
440 TruncateFloat64ToInt32WithChangeInt32ToFloat64) {
441 Node* value = Parameter(0);
442 Reduction reduction = Reduce(graph()->NewNode(
443 machine()->TruncateFloat64ToInt32(),
444 graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
445 ASSERT_TRUE(reduction.Changed());
446 EXPECT_EQ(value, reduction.replacement());
450 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithConstant) {
451 TRACED_FOREACH(double, x, kFloat64Values) {
452 Reduction reduction = Reduce(graph()->NewNode(
453 machine()->TruncateFloat64ToInt32(), Float64Constant(x)));
454 ASSERT_TRUE(reduction.Changed());
455 EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
460 TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithPhi) {
461 Node* const p0 = Parameter(0);
462 Node* const p1 = Parameter(1);
463 Node* const merge = graph()->start();
464 Reduction reduction = Reduce(graph()->NewNode(
465 machine()->TruncateFloat64ToInt32(),
466 graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge)));
467 ASSERT_TRUE(reduction.Changed());
468 EXPECT_THAT(reduction.replacement(),
469 IsPhi(kMachInt32, IsTruncateFloat64ToInt32(p0),
470 IsTruncateFloat64ToInt32(p1), merge));
474 // -----------------------------------------------------------------------------
475 // TruncateInt64ToInt32
478 TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithChangeInt32ToInt64) {
479 Node* value = Parameter(0);
480 Reduction reduction = Reduce(graph()->NewNode(
481 machine()->TruncateInt64ToInt32(),
482 graph()->NewNode(machine()->ChangeInt32ToInt64(), value)));
483 ASSERT_TRUE(reduction.Changed());
484 EXPECT_EQ(value, reduction.replacement());
488 TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithConstant) {
489 TRACED_FOREACH(int64_t, x, kInt64Values) {
490 Reduction reduction = Reduce(
491 graph()->NewNode(machine()->TruncateInt64ToInt32(), Int64Constant(x)));
492 ASSERT_TRUE(reduction.Changed());
493 EXPECT_THAT(reduction.replacement(),
494 IsInt32Constant(bit_cast<int32_t>(
495 static_cast<uint32_t>(bit_cast<uint64_t>(x)))));
500 // -----------------------------------------------------------------------------
504 TEST_F(MachineOperatorReducerTest, Word32AndWithWord32ShlWithConstant) {
505 Node* const p0 = Parameter(0);
507 TRACED_FORRANGE(int32_t, l, 1, 31) {
508 TRACED_FORRANGE(int32_t, k, 1, l) {
509 // (x << L) & (-1 << K) => x << L
510 Reduction const r1 = Reduce(graph()->NewNode(
511 machine()->Word32And(),
512 graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l)),
513 Int32Constant(-1 << k)));
514 ASSERT_TRUE(r1.Changed());
515 EXPECT_THAT(r1.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
517 // (-1 << K) & (x << L) => x << L
518 Reduction const r2 = Reduce(graph()->NewNode(
519 machine()->Word32And(), Int32Constant(-1 << k),
520 graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l))));
521 ASSERT_TRUE(r2.Changed());
522 EXPECT_THAT(r2.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
528 TEST_F(MachineOperatorReducerTest, Word32AndWithWord32AndWithConstant) {
529 Node* const p0 = Parameter(0);
531 TRACED_FOREACH(int32_t, k, kInt32Values) {
532 TRACED_FOREACH(int32_t, l, kInt32Values) {
533 if (k == 0 || k == -1 || l == 0 || l == -1) continue;
535 // (x & K) & L => x & (K & L)
536 Reduction const r1 = Reduce(graph()->NewNode(
537 machine()->Word32And(),
538 graph()->NewNode(machine()->Word32And(), p0, Int32Constant(k)),
540 ASSERT_TRUE(r1.Changed());
541 EXPECT_THAT(r1.replacement(),
542 (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
543 : IsInt32Constant(0));
545 // (K & x) & L => x & (K & L)
546 Reduction const r2 = Reduce(graph()->NewNode(
547 machine()->Word32And(),
548 graph()->NewNode(machine()->Word32And(), Int32Constant(k), p0),
550 ASSERT_TRUE(r2.Changed());
551 EXPECT_THAT(r2.replacement(),
552 (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
553 : IsInt32Constant(0));
559 TEST_F(MachineOperatorReducerTest, Word32AndWithInt32AddAndConstant) {
560 Node* const p0 = Parameter(0);
561 Node* const p1 = Parameter(1);
563 TRACED_FORRANGE(int32_t, l, 1, 31) {
564 TRACED_FOREACH(int32_t, k, kInt32Values) {
565 if ((k << l) == 0) continue;
566 // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
567 Reduction const r = Reduce(graph()->NewNode(
568 machine()->Word32And(),
569 graph()->NewNode(machine()->Int32Add(), p0, Int32Constant(k << l)),
570 Int32Constant(-1 << l)));
571 ASSERT_TRUE(r.Changed());
572 EXPECT_THAT(r.replacement(),
573 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
574 IsInt32Constant(k << l)));
577 Node* s1 = graph()->NewNode(machine()->Word32Shl(), p1, Int32Constant(l));
579 // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
580 Reduction const r1 = Reduce(graph()->NewNode(
581 machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), s1, p0),
582 Int32Constant(-1 << l)));
583 ASSERT_TRUE(r1.Changed());
584 EXPECT_THAT(r1.replacement(),
585 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)), s1));
587 // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
588 Reduction const r2 = Reduce(graph()->NewNode(
589 machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), p0, s1),
590 Int32Constant(-1 << l)));
591 ASSERT_TRUE(r2.Changed());
592 EXPECT_THAT(r2.replacement(),
593 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)), s1));
598 TEST_F(MachineOperatorReducerTest,
599 Word32AndWithInt32AddAndInt32MulAndConstant) {
600 Node* const p0 = Parameter(0);
601 Node* const p1 = Parameter(1);
603 TRACED_FORRANGE(int32_t, l, 1, 31) {
604 TRACED_FOREACH(int32_t, k, kInt32Values) {
605 if ((k << l) == 0) continue;
606 // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
607 Reduction const r1 = Reduce(graph()->NewNode(
608 machine()->Word32And(),
609 graph()->NewNode(machine()->Int32Add(),
610 graph()->NewNode(machine()->Int32Mul(), p1,
611 Int32Constant(k << l)),
613 Int32Constant(-1 << l)));
614 ASSERT_TRUE(r1.Changed());
615 EXPECT_THAT(r1.replacement(),
616 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
617 IsInt32Mul(p1, IsInt32Constant(k << l))));
619 // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
620 Reduction const r2 = Reduce(graph()->NewNode(
621 machine()->Word32And(),
622 graph()->NewNode(machine()->Int32Add(), p0,
623 graph()->NewNode(machine()->Int32Mul(), p1,
624 Int32Constant(k << l))),
625 Int32Constant(-1 << l)));
626 ASSERT_TRUE(r2.Changed());
627 EXPECT_THAT(r2.replacement(),
628 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
629 IsInt32Mul(p1, IsInt32Constant(k << l))));
635 // -----------------------------------------------------------------------------
639 TEST_F(MachineOperatorReducerTest, Word32XorWithWord32XorAndMinusOne) {
640 Node* const p0 = Parameter(0);
642 // (x ^ -1) ^ -1 => x
643 Reduction r1 = Reduce(graph()->NewNode(
644 machine()->Word32Xor(),
645 graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1)),
647 ASSERT_TRUE(r1.Changed());
648 EXPECT_EQ(r1.replacement(), p0);
650 // -1 ^ (x ^ -1) => x
651 Reduction r2 = Reduce(graph()->NewNode(
652 machine()->Word32Xor(), Int32Constant(-1),
653 graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1))));
654 ASSERT_TRUE(r2.Changed());
655 EXPECT_EQ(r2.replacement(), p0);
657 // (-1 ^ x) ^ -1 => x
658 Reduction r3 = Reduce(graph()->NewNode(
659 machine()->Word32Xor(),
660 graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0),
662 ASSERT_TRUE(r3.Changed());
663 EXPECT_EQ(r3.replacement(), p0);
665 // -1 ^ (-1 ^ x) => x
666 Reduction r4 = Reduce(graph()->NewNode(
667 machine()->Word32Xor(), Int32Constant(-1),
668 graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0)));
669 ASSERT_TRUE(r4.Changed());
670 EXPECT_EQ(r4.replacement(), p0);
674 // -----------------------------------------------------------------------------
678 TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithParameters) {
679 Node* value = Parameter(0);
680 Node* shift = Parameter(1);
681 Node* sub = graph()->NewNode(machine()->Int32Sub(), Int32Constant(32), shift);
683 // Testing rotate left.
684 Node* shl_l = graph()->NewNode(machine()->Word32Shl(), value, shift);
685 Node* shr_l = graph()->NewNode(machine()->Word32Shr(), value, sub);
687 // (x << y) | (x >>> (32 - y)) => x ror (32 - y)
688 Node* node1 = graph()->NewNode(machine()->Word32Or(), shl_l, shr_l);
689 Reduction reduction1 = Reduce(node1);
690 EXPECT_TRUE(reduction1.Changed());
691 EXPECT_EQ(reduction1.replacement(), node1);
692 EXPECT_THAT(reduction1.replacement(), IsWord32Ror(value, sub));
694 // (x >>> (32 - y)) | (x << y) => x ror (32 - y)
695 Node* node2 = graph()->NewNode(machine()->Word32Or(), shr_l, shl_l);
696 Reduction reduction2 = Reduce(node2);
697 EXPECT_TRUE(reduction2.Changed());
698 EXPECT_EQ(reduction2.replacement(), node2);
699 EXPECT_THAT(reduction2.replacement(), IsWord32Ror(value, sub));
701 // Testing rotate right.
702 Node* shl_r = graph()->NewNode(machine()->Word32Shl(), value, sub);
703 Node* shr_r = graph()->NewNode(machine()->Word32Shr(), value, shift);
705 // (x << (32 - y)) | (x >>> y) => x ror y
706 Node* node3 = graph()->NewNode(machine()->Word32Or(), shl_r, shr_r);
707 Reduction reduction3 = Reduce(node3);
708 EXPECT_TRUE(reduction3.Changed());
709 EXPECT_EQ(reduction3.replacement(), node3);
710 EXPECT_THAT(reduction3.replacement(), IsWord32Ror(value, shift));
712 // (x >>> y) | (x << (32 - y)) => x ror y
713 Node* node4 = graph()->NewNode(machine()->Word32Or(), shr_r, shl_r);
714 Reduction reduction4 = Reduce(node4);
715 EXPECT_TRUE(reduction4.Changed());
716 EXPECT_EQ(reduction4.replacement(), node4);
717 EXPECT_THAT(reduction4.replacement(), IsWord32Ror(value, shift));
721 TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithConstant) {
722 Node* value = Parameter(0);
723 TRACED_FORRANGE(int32_t, k, 0, 31) {
725 graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(k));
727 graph()->NewNode(machine()->Word32Shr(), value, Int32Constant(32 - k));
729 // (x << K) | (x >>> ((32 - K) - y)) => x ror (32 - K)
730 Node* node1 = graph()->NewNode(machine()->Word32Or(), shl, shr);
731 Reduction reduction1 = Reduce(node1);
732 EXPECT_TRUE(reduction1.Changed());
733 EXPECT_EQ(reduction1.replacement(), node1);
734 EXPECT_THAT(reduction1.replacement(),
735 IsWord32Ror(value, IsInt32Constant(32 - k)));
737 // (x >>> (32 - K)) | (x << K) => x ror (32 - K)
738 Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl);
739 Reduction reduction2 = Reduce(node2);
740 EXPECT_TRUE(reduction2.Changed());
741 EXPECT_EQ(reduction2.replacement(), node2);
742 EXPECT_THAT(reduction2.replacement(),
743 IsWord32Ror(value, IsInt32Constant(32 - k)));
748 TEST_F(MachineOperatorReducerTest, Word32RorWithZeroShift) {
749 Node* value = Parameter(0);
751 graph()->NewNode(machine()->Word32Ror(), value, Int32Constant(0));
752 Reduction reduction = Reduce(node);
753 EXPECT_TRUE(reduction.Changed());
754 EXPECT_EQ(reduction.replacement(), value);
758 TEST_F(MachineOperatorReducerTest, Word32RorWithConstants) {
759 TRACED_FOREACH(int32_t, x, kUint32Values) {
760 TRACED_FORRANGE(int32_t, y, 0, 31) {
761 Node* node = graph()->NewNode(machine()->Word32Ror(), Int32Constant(x),
763 Reduction reduction = Reduce(node);
764 EXPECT_TRUE(reduction.Changed());
765 EXPECT_THAT(reduction.replacement(),
766 IsInt32Constant(base::bits::RotateRight32(x, y)));
772 // -----------------------------------------------------------------------------
776 TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndLoad) {
777 Node* const p0 = Parameter(0);
778 Node* const p1 = Parameter(1);
780 Node* const l = graph()->NewNode(machine()->Load(kMachInt8), p0, p1,
781 graph()->start(), graph()->start());
782 Reduction const r = Reduce(graph()->NewNode(
783 machine()->Word32Sar(),
784 graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(24)),
786 ASSERT_TRUE(r.Changed());
787 EXPECT_EQ(l, r.replacement());
790 Node* const l = graph()->NewNode(machine()->Load(kMachInt16), p0, p1,
791 graph()->start(), graph()->start());
792 Reduction const r = Reduce(graph()->NewNode(
793 machine()->Word32Sar(),
794 graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(16)),
796 ASSERT_TRUE(r.Changed());
797 EXPECT_EQ(l, r.replacement());
802 // -----------------------------------------------------------------------------
806 TEST_F(MachineOperatorReducerTest, Word32ShlWithZeroShift) {
807 Node* p0 = Parameter(0);
808 Node* node = graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(0));
809 Reduction r = Reduce(node);
810 ASSERT_TRUE(r.Changed());
811 EXPECT_EQ(p0, r.replacement());
815 TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Sar) {
816 Node* p0 = Parameter(0);
817 TRACED_FORRANGE(int32_t, x, 1, 31) {
818 Node* node = graph()->NewNode(
819 machine()->Word32Shl(),
820 graph()->NewNode(machine()->Word32Sar(), p0, Int32Constant(x)),
822 Reduction r = Reduce(node);
823 ASSERT_TRUE(r.Changed());
824 int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
825 EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
830 TEST_F(MachineOperatorReducerTest,
831 Word32ShlWithWord32SarAndInt32AddAndConstant) {
832 Node* const p0 = Parameter(0);
833 TRACED_FOREACH(int32_t, k, kInt32Values) {
834 TRACED_FORRANGE(int32_t, l, 1, 31) {
835 if ((k << l) == 0) continue;
836 // (x + (K << L)) >> L << L => (x & (-1 << L)) + (K << L)
837 Reduction const r = Reduce(graph()->NewNode(
838 machine()->Word32Shl(),
839 graph()->NewNode(machine()->Word32Sar(),
840 graph()->NewNode(machine()->Int32Add(), p0,
841 Int32Constant(k << l)),
844 ASSERT_TRUE(r.Changed());
845 EXPECT_THAT(r.replacement(),
846 IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
847 IsInt32Constant(k << l)));
853 TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Shr) {
854 Node* p0 = Parameter(0);
855 TRACED_FORRANGE(int32_t, x, 1, 31) {
856 Node* node = graph()->NewNode(
857 machine()->Word32Shl(),
858 graph()->NewNode(machine()->Word32Shr(), p0, Int32Constant(x)),
860 Reduction r = Reduce(node);
861 ASSERT_TRUE(r.Changed());
862 int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
863 EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
868 // -----------------------------------------------------------------------------
872 TEST_F(MachineOperatorReducerTest, Int32SubWithConstant) {
873 Node* const p0 = Parameter(0);
874 TRACED_FOREACH(int32_t, k, kInt32Values) {
876 Reduce(graph()->NewNode(machine()->Int32Sub(), p0, Int32Constant(k)));
877 ASSERT_TRUE(r.Changed());
879 EXPECT_EQ(p0, r.replacement());
881 EXPECT_THAT(r.replacement(), IsInt32Add(p0, IsInt32Constant(-k)));
887 // -----------------------------------------------------------------------------
891 TEST_F(MachineOperatorReducerTest, Int32DivWithConstant) {
892 Node* const p0 = Parameter(0);
894 Reduction const r = Reduce(graph()->NewNode(
895 machine()->Int32Div(), p0, Int32Constant(0), graph()->start()));
896 ASSERT_TRUE(r.Changed());
897 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
900 Reduction const r = Reduce(graph()->NewNode(
901 machine()->Int32Div(), p0, Int32Constant(1), graph()->start()));
902 ASSERT_TRUE(r.Changed());
903 EXPECT_EQ(r.replacement(), p0);
906 Reduction const r = Reduce(graph()->NewNode(
907 machine()->Int32Div(), p0, Int32Constant(-1), graph()->start()));
908 ASSERT_TRUE(r.Changed());
909 EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0), p0));
912 Reduction const r = Reduce(graph()->NewNode(
913 machine()->Int32Div(), p0, Int32Constant(2), graph()->start()));
914 ASSERT_TRUE(r.Changed());
917 IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
918 IsInt32Constant(1)));
921 Reduction const r = Reduce(graph()->NewNode(
922 machine()->Int32Div(), p0, Int32Constant(-2), graph()->start()));
923 ASSERT_TRUE(r.Changed());
928 IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
929 IsInt32Constant(1))));
931 TRACED_FORRANGE(int32_t, shift, 2, 30) {
933 Reduce(graph()->NewNode(machine()->Int32Div(), p0,
934 Int32Constant(1 << shift), graph()->start()));
935 ASSERT_TRUE(r.Changed());
938 IsWord32Sar(IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
939 IsInt32Constant(32 - shift)),
941 IsInt32Constant(shift)));
943 TRACED_FORRANGE(int32_t, shift, 2, 31) {
944 Reduction const r = Reduce(graph()->NewNode(
945 machine()->Int32Div(), p0,
946 Uint32Constant(bit_cast<uint32_t, int32_t>(-1) << shift),
948 ASSERT_TRUE(r.Changed());
954 IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
955 IsInt32Constant(32 - shift)),
957 IsInt32Constant(shift))));
959 TRACED_FOREACH(int32_t, divisor, kInt32Values) {
961 if (base::bits::IsPowerOfTwo32(-divisor)) continue;
962 Reduction const r = Reduce(graph()->NewNode(
963 machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
964 ASSERT_TRUE(r.Changed());
965 EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0),
966 IsTruncatingDiv(p0, -divisor)));
967 } else if (divisor > 0) {
968 if (base::bits::IsPowerOfTwo32(divisor)) continue;
969 Reduction const r = Reduce(graph()->NewNode(
970 machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
971 ASSERT_TRUE(r.Changed());
972 EXPECT_THAT(r.replacement(), IsTruncatingDiv(p0, divisor));
978 TEST_F(MachineOperatorReducerTest, Int32DivWithParameters) {
979 Node* const p0 = Parameter(0);
981 Reduce(graph()->NewNode(machine()->Int32Div(), p0, p0, graph()->start()));
982 ASSERT_TRUE(r.Changed());
985 IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
989 // -----------------------------------------------------------------------------
993 TEST_F(MachineOperatorReducerTest, Uint32DivWithConstant) {
994 Node* const p0 = Parameter(0);
996 Reduction const r = Reduce(graph()->NewNode(
997 machine()->Uint32Div(), Int32Constant(0), p0, graph()->start()));
998 ASSERT_TRUE(r.Changed());
999 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1002 Reduction const r = Reduce(graph()->NewNode(
1003 machine()->Uint32Div(), p0, Int32Constant(0), graph()->start()));
1004 ASSERT_TRUE(r.Changed());
1005 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1008 Reduction const r = Reduce(graph()->NewNode(
1009 machine()->Uint32Div(), p0, Int32Constant(1), graph()->start()));
1010 ASSERT_TRUE(r.Changed());
1011 EXPECT_EQ(r.replacement(), p0);
1013 TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1014 TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1015 Reduction const r = Reduce(
1016 graph()->NewNode(machine()->Uint32Div(), Uint32Constant(dividend),
1017 Uint32Constant(divisor), graph()->start()));
1018 ASSERT_TRUE(r.Changed());
1019 EXPECT_THAT(r.replacement(),
1020 IsInt32Constant(bit_cast<int32_t>(
1021 base::bits::UnsignedDiv32(dividend, divisor))));
1024 TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1026 Reduce(graph()->NewNode(machine()->Uint32Div(), p0,
1027 Uint32Constant(1u << shift), graph()->start()));
1028 ASSERT_TRUE(r.Changed());
1029 EXPECT_THAT(r.replacement(),
1030 IsWord32Shr(p0, IsInt32Constant(bit_cast<int32_t>(shift))));
1035 TEST_F(MachineOperatorReducerTest, Uint32DivWithParameters) {
1036 Node* const p0 = Parameter(0);
1037 Reduction const r = Reduce(
1038 graph()->NewNode(machine()->Uint32Div(), p0, p0, graph()->start()));
1039 ASSERT_TRUE(r.Changed());
1042 IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
1046 // -----------------------------------------------------------------------------
1050 TEST_F(MachineOperatorReducerTest, Int32ModWithConstant) {
1051 Node* const p0 = Parameter(0);
1053 Reduction const r = Reduce(graph()->NewNode(
1054 machine()->Int32Mod(), Int32Constant(0), p0, graph()->start()));
1055 ASSERT_TRUE(r.Changed());
1056 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1059 Reduction const r = Reduce(graph()->NewNode(
1060 machine()->Int32Mod(), p0, Int32Constant(0), graph()->start()));
1061 ASSERT_TRUE(r.Changed());
1062 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1065 Reduction const r = Reduce(graph()->NewNode(
1066 machine()->Int32Mod(), p0, Int32Constant(1), graph()->start()));
1067 ASSERT_TRUE(r.Changed());
1068 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1071 Reduction const r = Reduce(graph()->NewNode(
1072 machine()->Int32Mod(), p0, Int32Constant(-1), graph()->start()));
1073 ASSERT_TRUE(r.Changed());
1074 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1076 TRACED_FOREACH(int32_t, dividend, kInt32Values) {
1077 TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1078 Reduction const r = Reduce(
1079 graph()->NewNode(machine()->Int32Mod(), Int32Constant(dividend),
1080 Int32Constant(divisor), graph()->start()));
1081 ASSERT_TRUE(r.Changed());
1082 EXPECT_THAT(r.replacement(),
1083 IsInt32Constant(base::bits::SignedMod32(dividend, divisor)));
1086 TRACED_FORRANGE(int32_t, shift, 1, 30) {
1088 Reduce(graph()->NewNode(machine()->Int32Mod(), p0,
1089 Int32Constant(1 << shift), graph()->start()));
1090 int32_t const mask = (1 << shift) - 1;
1091 ASSERT_TRUE(r.Changed());
1094 IsSelect(kMachInt32, IsInt32LessThan(p0, IsInt32Constant(0)),
1095 IsInt32Sub(IsInt32Constant(0),
1096 IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1097 IsInt32Constant(mask))),
1098 IsWord32And(p0, IsInt32Constant(mask))));
1100 TRACED_FORRANGE(int32_t, shift, 1, 31) {
1101 Reduction const r = Reduce(graph()->NewNode(
1102 machine()->Int32Mod(), p0,
1103 Uint32Constant(bit_cast<uint32_t, int32_t>(-1) << shift),
1105 int32_t const mask = bit_cast<int32_t, uint32_t>((1U << shift) - 1);
1106 ASSERT_TRUE(r.Changed());
1109 IsSelect(kMachInt32, IsInt32LessThan(p0, IsInt32Constant(0)),
1110 IsInt32Sub(IsInt32Constant(0),
1111 IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1112 IsInt32Constant(mask))),
1113 IsWord32And(p0, IsInt32Constant(mask))));
1115 TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1116 if (divisor == 0 || base::bits::IsPowerOfTwo32(Abs(divisor))) continue;
1117 Reduction const r = Reduce(graph()->NewNode(
1118 machine()->Int32Mod(), p0, Int32Constant(divisor), graph()->start()));
1119 ASSERT_TRUE(r.Changed());
1120 EXPECT_THAT(r.replacement(),
1121 IsInt32Sub(p0, IsInt32Mul(IsTruncatingDiv(p0, Abs(divisor)),
1122 IsInt32Constant(Abs(divisor)))));
1127 TEST_F(MachineOperatorReducerTest, Int32ModWithParameters) {
1128 Node* const p0 = Parameter(0);
1130 Reduce(graph()->NewNode(machine()->Int32Mod(), p0, p0, graph()->start()));
1131 ASSERT_TRUE(r.Changed());
1132 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1136 // -----------------------------------------------------------------------------
1140 TEST_F(MachineOperatorReducerTest, Uint32ModWithConstant) {
1141 Node* const p0 = Parameter(0);
1143 Reduction const r = Reduce(graph()->NewNode(
1144 machine()->Uint32Mod(), p0, Int32Constant(0), graph()->start()));
1145 ASSERT_TRUE(r.Changed());
1146 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1149 Reduction const r = Reduce(graph()->NewNode(
1150 machine()->Uint32Mod(), Int32Constant(0), p0, graph()->start()));
1151 ASSERT_TRUE(r.Changed());
1152 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1155 Reduction const r = Reduce(graph()->NewNode(
1156 machine()->Uint32Mod(), p0, Int32Constant(1), graph()->start()));
1157 ASSERT_TRUE(r.Changed());
1158 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1160 TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1161 TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1162 Reduction const r = Reduce(
1163 graph()->NewNode(machine()->Uint32Mod(), Uint32Constant(dividend),
1164 Uint32Constant(divisor), graph()->start()));
1165 ASSERT_TRUE(r.Changed());
1166 EXPECT_THAT(r.replacement(),
1167 IsInt32Constant(bit_cast<int32_t>(
1168 base::bits::UnsignedMod32(dividend, divisor))));
1171 TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1173 Reduce(graph()->NewNode(machine()->Uint32Mod(), p0,
1174 Uint32Constant(1u << shift), graph()->start()));
1175 ASSERT_TRUE(r.Changed());
1176 EXPECT_THAT(r.replacement(),
1177 IsWord32And(p0, IsInt32Constant(
1178 bit_cast<int32_t>((1u << shift) - 1u))));
1183 TEST_F(MachineOperatorReducerTest, Uint32ModWithParameters) {
1184 Node* const p0 = Parameter(0);
1185 Reduction const r = Reduce(
1186 graph()->NewNode(machine()->Uint32Mod(), p0, p0, graph()->start()));
1187 ASSERT_TRUE(r.Changed());
1188 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1192 // -----------------------------------------------------------------------------
1193 // Int32AddWithOverflow
1196 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) {
1197 Node* p0 = Parameter(0);
1199 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1200 Int32Constant(0), p0);
1202 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1203 ASSERT_TRUE(r.Changed());
1204 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1206 r = Reduce(graph()->NewNode(common()->Projection(0), add));
1207 ASSERT_TRUE(r.Changed());
1208 EXPECT_EQ(p0, r.replacement());
1211 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), p0,
1214 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1215 ASSERT_TRUE(r.Changed());
1216 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1218 r = Reduce(graph()->NewNode(common()->Projection(0), add));
1219 ASSERT_TRUE(r.Changed());
1220 EXPECT_EQ(p0, r.replacement());
1225 TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) {
1226 TRACED_FOREACH(int32_t, x, kInt32Values) {
1227 TRACED_FOREACH(int32_t, y, kInt32Values) {
1229 Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1230 Int32Constant(x), Int32Constant(y));
1232 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1233 ASSERT_TRUE(r.Changed());
1234 EXPECT_THAT(r.replacement(),
1235 IsInt32Constant(base::bits::SignedAddOverflow32(x, y, &z)));
1237 r = Reduce(graph()->NewNode(common()->Projection(0), add));
1238 ASSERT_TRUE(r.Changed());
1239 EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1245 // -----------------------------------------------------------------------------
1246 // Int32SubWithOverflow
1249 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithZero) {
1250 Node* p0 = Parameter(0);
1252 graph()->NewNode(machine()->Int32SubWithOverflow(), p0, Int32Constant(0));
1254 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1255 ASSERT_TRUE(r.Changed());
1256 EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1258 r = Reduce(graph()->NewNode(common()->Projection(0), add));
1259 ASSERT_TRUE(r.Changed());
1260 EXPECT_EQ(p0, r.replacement());
1264 TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
1265 TRACED_FOREACH(int32_t, x, kInt32Values) {
1266 TRACED_FOREACH(int32_t, y, kInt32Values) {
1268 Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(),
1269 Int32Constant(x), Int32Constant(y));
1271 Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add));
1272 ASSERT_TRUE(r.Changed());
1273 EXPECT_THAT(r.replacement(),
1274 IsInt32Constant(base::bits::SignedSubOverflow32(x, y, &z)));
1276 r = Reduce(graph()->NewNode(common()->Projection(0), add));
1277 ASSERT_TRUE(r.Changed());
1278 EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1284 // -----------------------------------------------------------------------------
1288 TEST_F(MachineOperatorReducerTest, Uint32LessThanWithWord32Sar) {
1289 Node* const p0 = Parameter(0);
1290 TRACED_FORRANGE(uint32_t, shift, 1, 3) {
1291 const uint32_t limit = (kMaxInt >> shift) - 1;
1292 Node* const node = graph()->NewNode(
1293 machine()->Uint32LessThan(),
1294 graph()->NewNode(machine()->Word32Sar(), p0, Uint32Constant(shift)),
1295 Uint32Constant(limit));
1297 Reduction r = Reduce(node);
1298 ASSERT_TRUE(r.Changed());
1299 EXPECT_THAT(r.replacement(),
1301 p0, IsInt32Constant(bit_cast<int32_t>(limit << shift))));
1306 // -----------------------------------------------------------------------------
1310 TEST_F(MachineOperatorReducerTest, Float64MulWithMinusOne) {
1311 Node* const p0 = Parameter(0);
1313 Reduction r = Reduce(
1314 graph()->NewNode(machine()->Float64Mul(), p0, Float64Constant(-1.0)));
1315 ASSERT_TRUE(r.Changed());
1316 EXPECT_THAT(r.replacement(),
1317 IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1320 Reduction r = Reduce(
1321 graph()->NewNode(machine()->Float64Mul(), Float64Constant(-1.0), p0));
1322 ASSERT_TRUE(r.Changed());
1323 EXPECT_THAT(r.replacement(),
1324 IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1329 // -----------------------------------------------------------------------------
1333 TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32And) {
1334 const StoreRepresentation rep(kRepWord8, kNoWriteBarrier);
1335 Node* const base = Parameter(0);
1336 Node* const index = Parameter(1);
1337 Node* const value = Parameter(2);
1338 Node* const effect = graph()->start();
1339 Node* const control = graph()->start();
1340 TRACED_FOREACH(uint32_t, x, kUint32Values) {
1342 graph()->NewNode(machine()->Store(rep), base, index,
1343 graph()->NewNode(machine()->Word32And(), value,
1344 Uint32Constant(x | 0xffu)),
1347 Reduction r = Reduce(node);
1348 ASSERT_TRUE(r.Changed());
1349 EXPECT_THAT(r.replacement(),
1350 IsStore(rep, base, index, value, effect, control));
1355 TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32SarAndWord32Shl) {
1356 const StoreRepresentation rep(kRepWord8, kNoWriteBarrier);
1357 Node* const base = Parameter(0);
1358 Node* const index = Parameter(1);
1359 Node* const value = Parameter(2);
1360 Node* const effect = graph()->start();
1361 Node* const control = graph()->start();
1362 TRACED_FORRANGE(int32_t, x, 1, 24) {
1363 Node* const node = graph()->NewNode(
1364 machine()->Store(rep), base, index,
1366 machine()->Word32Sar(),
1367 graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
1371 Reduction r = Reduce(node);
1372 ASSERT_TRUE(r.Changed());
1373 EXPECT_THAT(r.replacement(),
1374 IsStore(rep, base, index, value, effect, control));
1379 TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32And) {
1380 const StoreRepresentation rep(kRepWord16, kNoWriteBarrier);
1381 Node* const base = Parameter(0);
1382 Node* const index = Parameter(1);
1383 Node* const value = Parameter(2);
1384 Node* const effect = graph()->start();
1385 Node* const control = graph()->start();
1386 TRACED_FOREACH(uint32_t, x, kUint32Values) {
1388 graph()->NewNode(machine()->Store(rep), base, index,
1389 graph()->NewNode(machine()->Word32And(), value,
1390 Uint32Constant(x | 0xffffu)),
1393 Reduction r = Reduce(node);
1394 ASSERT_TRUE(r.Changed());
1395 EXPECT_THAT(r.replacement(),
1396 IsStore(rep, base, index, value, effect, control));
1401 TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32SarAndWord32Shl) {
1402 const StoreRepresentation rep(kRepWord16, kNoWriteBarrier);
1403 Node* const base = Parameter(0);
1404 Node* const index = Parameter(1);
1405 Node* const value = Parameter(2);
1406 Node* const effect = graph()->start();
1407 Node* const control = graph()->start();
1408 TRACED_FORRANGE(int32_t, x, 1, 16) {
1409 Node* const node = graph()->NewNode(
1410 machine()->Store(rep), base, index,
1412 machine()->Word32Sar(),
1413 graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
1417 Reduction r = Reduce(node);
1418 ASSERT_TRUE(r.Changed());
1419 EXPECT_THAT(r.replacement(),
1420 IsStore(rep, base, index, value, effect, control));
1424 } // namespace compiler
1425 } // namespace internal