Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/compiler/machine-operator-reducer.h"
6 : #include "src/base/bits.h"
7 : #include "src/base/division-by-constant.h"
8 : #include "src/base/ieee754.h"
9 : #include "src/base/overflowing-math.h"
10 : #include "src/compiler/js-graph.h"
11 : #include "src/compiler/typer.h"
12 : #include "src/conversions-inl.h"
13 : #include "test/unittests/compiler/graph-unittest.h"
14 : #include "test/unittests/compiler/node-test-utils.h"
15 : #include "testing/gmock-support.h"
16 :
17 : using testing::AllOf;
18 : using testing::BitEq;
19 : using testing::Capture;
20 : using testing::CaptureEq;
21 : using testing::NanSensitiveDoubleEq;
22 :
23 : namespace v8 {
24 : namespace internal {
25 : namespace compiler {
26 :
27 101 : class MachineOperatorReducerTest : public GraphTest {
28 : public:
29 101 : explicit MachineOperatorReducerTest(int num_parameters = 2)
30 : : GraphTest(num_parameters),
31 : machine_(zone()),
32 : common_(zone()),
33 : javascript_(zone()),
34 : jsgraph_(isolate(), graph(), &common_, &javascript_, nullptr,
35 : &machine_),
36 303 : graph_reducer_(zone(), graph(), jsgraph_.Dead()) {}
37 :
38 : protected:
39 180224 : Reduction Reduce(Node* node) {
40 180224 : JSOperatorBuilder javascript(zone());
41 : JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
42 360448 : &machine_);
43 360448 : MachineOperatorReducer reducer(&graph_reducer_, &jsgraph);
44 360448 : return reducer.Reduce(node);
45 : }
46 :
47 194 : Matcher<Node*> IsTruncatingDiv(const Matcher<Node*>& dividend_matcher,
48 : const int32_t divisor) {
49 : base::MagicNumbersForDivision<uint32_t> const mag =
50 194 : base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
51 : int32_t const multiplier = bit_cast<int32_t>(mag.multiplier);
52 : int32_t const shift = bit_cast<int32_t>(mag.shift);
53 : Matcher<Node*> quotient_matcher =
54 582 : IsInt32MulHigh(dividend_matcher, IsInt32Constant(multiplier));
55 194 : if (divisor > 0 && multiplier < 0) {
56 136 : quotient_matcher = IsInt32Add(quotient_matcher, dividend_matcher);
57 126 : } else if (divisor < 0 && multiplier > 0) {
58 0 : quotient_matcher = IsInt32Sub(quotient_matcher, dividend_matcher);
59 : }
60 194 : if (shift) {
61 776 : quotient_matcher = IsWord32Sar(quotient_matcher, IsInt32Constant(shift));
62 : }
63 : return IsInt32Add(quotient_matcher,
64 970 : IsWord32Shr(dividend_matcher, IsInt32Constant(31)));
65 : }
66 :
67 118979 : MachineOperatorBuilder* machine() { return &machine_; }
68 :
69 : private:
70 : MachineOperatorBuilder machine_;
71 : CommonOperatorBuilder common_;
72 : JSOperatorBuilder javascript_;
73 : JSGraph jsgraph_;
74 : GraphReducer graph_reducer_;
75 : };
76 :
77 :
78 : template <typename T>
79 : class MachineOperatorReducerTestWithParam
80 : : public MachineOperatorReducerTest,
81 : public ::testing::WithParamInterface<T> {
82 : public:
83 : explicit MachineOperatorReducerTestWithParam(int num_parameters = 2)
84 : : MachineOperatorReducerTest(num_parameters) {}
85 : ~MachineOperatorReducerTestWithParam() override = default;
86 : };
87 :
88 :
89 : namespace {
90 :
91 : const float kFloat32Values[] = {
92 : -std::numeric_limits<float>::infinity(), -2.70497e+38f, -1.4698e+37f,
93 : -1.22813e+35f, -1.20555e+35f, -1.34584e+34f,
94 : -1.0079e+32f, -6.49364e+26f, -3.06077e+25f,
95 : -1.46821e+25f, -1.17658e+23f, -1.9617e+22f,
96 : -2.7357e+20f, -1.48708e+13f, -1.89633e+12f,
97 : -4.66622e+11f, -2.22581e+11f, -1.45381e+10f,
98 : -1.3956e+09f, -1.32951e+09f, -1.30721e+09f,
99 : -1.19756e+09f, -9.26822e+08f, -6.35647e+08f,
100 : -4.00037e+08f, -1.81227e+08f, -5.09256e+07f,
101 : -964300.0f, -192446.0f, -28455.0f,
102 : -27194.0f, -26401.0f, -20575.0f,
103 : -17069.0f, -9167.0f, -960.178f,
104 : -113.0f, -62.0f, -15.0f,
105 : -7.0f, -0.0256635f, -4.60374e-07f,
106 : -3.63759e-10f, -4.30175e-14f, -5.27385e-15f,
107 : -1.48084e-15f, -1.05755e-19f, -3.2995e-21f,
108 : -1.67354e-23f, -1.11885e-23f, -1.78506e-30f,
109 : -5.07594e-31f, -3.65799e-31f, -1.43718e-34f,
110 : -1.27126e-38f, -0.0f, 0.0f,
111 : 1.17549e-38f, 1.56657e-37f, 4.08512e-29f,
112 : 3.31357e-28f, 6.25073e-22f, 4.1723e-13f,
113 : 1.44343e-09f, 5.27004e-08f, 9.48298e-08f,
114 : 5.57888e-07f, 4.89988e-05f, 0.244326f,
115 : 12.4895f, 19.0f, 47.0f,
116 : 106.0f, 538.324f, 564.536f,
117 : 819.124f, 7048.0f, 12611.0f,
118 : 19878.0f, 20309.0f, 797056.0f,
119 : 1.77219e+09f, 1.51116e+11f, 4.18193e+13f,
120 : 3.59167e+16f, 3.38211e+19f, 2.67488e+20f,
121 : 1.78831e+21f, 9.20914e+21f, 8.35654e+23f,
122 : 1.4495e+24f, 5.94015e+25f, 4.43608e+30f,
123 : 2.44502e+33f, 2.61152e+33f, 1.38178e+37f,
124 : 1.71306e+37f, 3.31899e+38f, 3.40282e+38f,
125 : std::numeric_limits<float>::infinity()};
126 :
127 :
128 : const double kFloat64Values[] = {
129 : -V8_INFINITY, -4.23878e+275, -5.82632e+265, -6.60355e+220, -6.26172e+212,
130 : -2.56222e+211, -4.82408e+201, -1.84106e+157, -1.63662e+127, -1.55772e+100,
131 : -1.67813e+72, -2.3382e+55, -3.179e+30, -1.441e+09, -1.0647e+09,
132 : -7.99361e+08, -5.77375e+08, -2.20984e+08, -32757, -13171,
133 : -9970, -3984, -107, -105, -92,
134 : -77, -61, -0.000208163, -1.86685e-06, -1.17296e-10,
135 : -9.26358e-11, -5.08004e-60, -1.74753e-65, -1.06561e-71, -5.67879e-79,
136 : -5.78459e-130, -2.90989e-171, -7.15489e-243, -3.76242e-252, -1.05639e-263,
137 : -4.40497e-267, -2.19666e-273, -4.9998e-276, -5.59821e-278, -2.03855e-282,
138 : -5.99335e-283, -7.17554e-284, -3.11744e-309, -0.0, 0.0,
139 : 2.22507e-308, 1.30127e-270, 7.62898e-260, 4.00313e-249, 3.16829e-233,
140 : 1.85244e-228, 2.03544e-129, 1.35126e-110, 1.01182e-106, 5.26333e-94,
141 : 1.35292e-90, 2.85394e-83, 1.78323e-77, 5.4967e-57, 1.03207e-25,
142 : 4.57401e-25, 1.58738e-05, 2, 125, 2310,
143 : 9636, 14802, 17168, 28945, 29305,
144 : 4.81336e+07, 1.41207e+08, 4.65962e+08, 1.40499e+09, 2.12648e+09,
145 : 8.80006e+30, 1.4446e+45, 1.12164e+54, 2.48188e+89, 6.71121e+102,
146 : 3.074e+112, 4.9699e+152, 5.58383e+166, 4.30654e+172, 7.08824e+185,
147 : 9.6586e+214, 2.028e+223, 6.63277e+243, 1.56192e+261, 1.23202e+269,
148 : 5.72883e+289, 8.5798e+290, 1.40256e+294, 1.79769e+308, V8_INFINITY};
149 :
150 :
151 : const int32_t kInt32Values[] = {
152 : std::numeric_limits<int32_t>::min(), -1914954528, -1698749618,
153 : -1578693386, -1577976073, -1573998034,
154 : -1529085059, -1499540537, -1299205097,
155 : -1090814845, -938186388, -806828902,
156 : -750927650, -520676892, -513661538,
157 : -453036354, -433622833, -282638793,
158 : -28375, -27788, -22770,
159 : -18806, -14173, -11956,
160 : -11200, -10212, -8160,
161 : -3751, -2758, -1522,
162 : -121, -120, -118,
163 : -117, -106, -84,
164 : -80, -74, -59,
165 : -52, -48, -39,
166 : -35, -17, -11,
167 : -10, -9, -7,
168 : -5, 0, 9,
169 : 12, 17, 23,
170 : 29, 31, 33,
171 : 35, 40, 47,
172 : 55, 56, 62,
173 : 64, 67, 68,
174 : 69, 74, 79,
175 : 84, 89, 90,
176 : 97, 104, 118,
177 : 124, 126, 127,
178 : 7278, 17787, 24136,
179 : 24202, 25570, 26680,
180 : 30242, 32399, 420886487,
181 : 642166225, 821912648, 822577803,
182 : 851385718, 1212241078, 1411419304,
183 : 1589626102, 1596437184, 1876245816,
184 : 1954730266, 2008792749, 2045320228,
185 : std::numeric_limits<int32_t>::max()};
186 :
187 : const int64_t kInt64Values[] = {std::numeric_limits<int64_t>::min(),
188 : int64_t{-8974392461363618006},
189 : int64_t{-8874367046689588135},
190 : int64_t{-8269197512118230839},
191 : int64_t{-8146091527100606733},
192 : int64_t{-7550917981466150848},
193 : int64_t{-7216590251577894337},
194 : int64_t{-6464086891160048440},
195 : int64_t{-6365616494908257190},
196 : int64_t{-6305630541365849726},
197 : int64_t{-5982222642272245453},
198 : int64_t{-5510103099058504169},
199 : int64_t{-5496838675802432701},
200 : int64_t{-4047626578868642657},
201 : int64_t{-4033755046900164544},
202 : int64_t{-3554299241457877041},
203 : int64_t{-2482258764588614470},
204 : int64_t{-1688515425526875335},
205 : int64_t{-924784137176548532},
206 : int64_t{-725316567157391307},
207 : int64_t{-439022654781092241},
208 : int64_t{-105545757668917080},
209 : int64_t{-2088319373},
210 : int64_t{-2073699916},
211 : int64_t{-1844949911},
212 : int64_t{-1831090548},
213 : int64_t{-1756711933},
214 : int64_t{-1559409497},
215 : int64_t{-1281179700},
216 : int64_t{-1211513985},
217 : int64_t{-1182371520},
218 : int64_t{-785934753},
219 : int64_t{-767480697},
220 : int64_t{-705745662},
221 : int64_t{-514362436},
222 : int64_t{-459916580},
223 : int64_t{-312328082},
224 : int64_t{-302949707},
225 : int64_t{-285499304},
226 : int64_t{-125701262},
227 : int64_t{-95139843},
228 : int64_t{-32768},
229 : int64_t{-27542},
230 : int64_t{-23600},
231 : int64_t{-18582},
232 : int64_t{-17770},
233 : int64_t{-9086},
234 : int64_t{-9010},
235 : int64_t{-8244},
236 : int64_t{-2890},
237 : int64_t{-103},
238 : int64_t{-34},
239 : int64_t{-27},
240 : int64_t{-25},
241 : int64_t{-9},
242 : int64_t{-7},
243 : int64_t{0},
244 : int64_t{2},
245 : int64_t{38},
246 : int64_t{58},
247 : int64_t{65},
248 : int64_t{93},
249 : int64_t{111},
250 : int64_t{1003},
251 : int64_t{1267},
252 : int64_t{12797},
253 : int64_t{23122},
254 : int64_t{28200},
255 : int64_t{30888},
256 : int64_t{42648848},
257 : int64_t{116836693},
258 : int64_t{263003643},
259 : int64_t{571039860},
260 : int64_t{1079398689},
261 : int64_t{1145196402},
262 : int64_t{1184846321},
263 : int64_t{1758281648},
264 : int64_t{1859991374},
265 : int64_t{1960251588},
266 : int64_t{2042443199},
267 : int64_t{296220586027987448},
268 : int64_t{1015494173071134726},
269 : int64_t{1151237951914455318},
270 : int64_t{1331941174616854174},
271 : int64_t{2022020418667972654},
272 : int64_t{2450251424374977035},
273 : int64_t{3668393562685561486},
274 : int64_t{4858229301215502171},
275 : int64_t{4919426235170669383},
276 : int64_t{5034286595330341762},
277 : int64_t{5055797915536941182},
278 : int64_t{6072389716149252074},
279 : int64_t{6185309910199801210},
280 : int64_t{6297328311011094138},
281 : int64_t{6932372858072165827},
282 : int64_t{8483640924987737210},
283 : int64_t{8663764179455849203},
284 : int64_t{8877197042645298254},
285 : int64_t{8901543506779157333},
286 : std::numeric_limits<int64_t>::max()};
287 :
288 : const uint32_t kUint32Values[] = {
289 : 0x00000000, 0x00000001, 0xFFFFFFFF, 0x1B09788B, 0x04C5FCE8, 0xCC0DE5BF,
290 : 0x273A798E, 0x187937A3, 0xECE3AF83, 0x5495A16B, 0x0B668ECC, 0x11223344,
291 : 0x0000009E, 0x00000043, 0x0000AF73, 0x0000116B, 0x00658ECC, 0x002B3B4C,
292 : 0x88776655, 0x70000000, 0x07200000, 0x7FFFFFFF, 0x56123761, 0x7FFFFF00,
293 : 0x761C4761, 0x80000000, 0x88888888, 0xA0000000, 0xDDDDDDDD, 0xE0000000,
294 : 0xEEEEEEEE, 0xFFFFFFFD, 0xF0000000, 0x007FFFFF, 0x003FFFFF, 0x001FFFFF,
295 : 0x000FFFFF, 0x0007FFFF, 0x0003FFFF, 0x0001FFFF, 0x0000FFFF, 0x00007FFF,
296 : 0x00003FFF, 0x00001FFF, 0x00000FFF, 0x000007FF, 0x000003FF, 0x000001FF};
297 :
298 : struct ComparisonBinaryOperator {
299 : const Operator* (MachineOperatorBuilder::*constructor)();
300 : const char* constructor_name;
301 : };
302 :
303 :
304 : std::ostream& operator<<(std::ostream& os,
305 : ComparisonBinaryOperator const& cbop) {
306 32 : return os << cbop.constructor_name;
307 : }
308 :
309 :
310 : const ComparisonBinaryOperator kComparisonBinaryOperators[] = {
311 : #define OPCODE(Opcode) \
312 : { &MachineOperatorBuilder::Opcode, #Opcode } \
313 : ,
314 : MACHINE_COMPARE_BINOP_LIST(OPCODE)
315 : #undef OPCODE
316 : };
317 :
318 : // Avoid undefined behavior on signed integer overflow.
319 24680 : int32_t Shl(int32_t x, int32_t y) { return static_cast<uint32_t>(x) << y; }
320 :
321 : } // namespace
322 :
323 :
324 : // -----------------------------------------------------------------------------
325 : // ChangeFloat64ToFloat32
326 :
327 :
328 15374 : TEST_F(MachineOperatorReducerTest, ChangeFloat64ToFloat32WithConstant) {
329 401 : TRACED_FOREACH(float, x, kFloat32Values) {
330 : Reduction reduction = Reduce(graph()->NewNode(
331 300 : machine()->ChangeFloat32ToFloat64(), Float32Constant(x)));
332 100 : ASSERT_TRUE(reduction.Changed());
333 500 : EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq<double>(x)));
334 : }
335 : }
336 :
337 :
338 : // -----------------------------------------------------------------------------
339 : // ChangeFloat64ToInt32
340 :
341 :
342 15374 : TEST_F(MachineOperatorReducerTest,
343 : ChangeFloat64ToInt32WithChangeInt32ToFloat64) {
344 1 : Node* value = Parameter(0);
345 : Reduction reduction = Reduce(graph()->NewNode(
346 : machine()->ChangeFloat64ToInt32(),
347 3 : graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
348 1 : ASSERT_TRUE(reduction.Changed());
349 2 : EXPECT_EQ(value, reduction.replacement());
350 : }
351 :
352 15374 : TEST_F(MachineOperatorReducerTest, ChangeFloat64ToInt32WithConstant) {
353 401 : TRACED_FOREACH(int32_t, x, kInt32Values) {
354 : Reduction reduction = Reduce(graph()->NewNode(
355 300 : machine()->ChangeFloat64ToInt32(), Float64Constant(FastI2D(x))));
356 100 : ASSERT_TRUE(reduction.Changed());
357 500 : EXPECT_THAT(reduction.replacement(), IsInt32Constant(x));
358 : }
359 : }
360 :
361 : // -----------------------------------------------------------------------------
362 : // ChangeFloat64ToInt64
363 :
364 15374 : TEST_F(MachineOperatorReducerTest,
365 : ChangeFloat64ToInt64WithChangeInt64ToFloat64) {
366 1 : Node* value = Parameter(0);
367 : Reduction reduction = Reduce(graph()->NewNode(
368 : machine()->ChangeFloat64ToInt64(),
369 3 : graph()->NewNode(machine()->ChangeInt64ToFloat64(), value)));
370 1 : ASSERT_TRUE(reduction.Changed());
371 2 : EXPECT_EQ(value, reduction.replacement());
372 : }
373 :
374 15374 : TEST_F(MachineOperatorReducerTest, ChangeFloat64ToInt64WithConstant) {
375 401 : TRACED_FOREACH(int32_t, x, kInt32Values) {
376 : Reduction reduction = Reduce(graph()->NewNode(
377 300 : machine()->ChangeFloat64ToInt64(), Float64Constant(FastI2D(x))));
378 100 : ASSERT_TRUE(reduction.Changed());
379 500 : EXPECT_THAT(reduction.replacement(), IsInt64Constant(x));
380 : }
381 : }
382 :
383 : // -----------------------------------------------------------------------------
384 : // ChangeFloat64ToUint32
385 :
386 :
387 15374 : TEST_F(MachineOperatorReducerTest,
388 : ChangeFloat64ToUint32WithChangeUint32ToFloat64) {
389 1 : Node* value = Parameter(0);
390 : Reduction reduction = Reduce(graph()->NewNode(
391 : machine()->ChangeFloat64ToUint32(),
392 3 : graph()->NewNode(machine()->ChangeUint32ToFloat64(), value)));
393 1 : ASSERT_TRUE(reduction.Changed());
394 2 : EXPECT_EQ(value, reduction.replacement());
395 : }
396 :
397 :
398 15374 : TEST_F(MachineOperatorReducerTest, ChangeFloat64ToUint32WithConstant) {
399 193 : TRACED_FOREACH(uint32_t, x, kUint32Values) {
400 : Reduction reduction = Reduce(graph()->NewNode(
401 144 : machine()->ChangeFloat64ToUint32(), Float64Constant(FastUI2D(x))));
402 48 : ASSERT_TRUE(reduction.Changed());
403 240 : EXPECT_THAT(reduction.replacement(), IsInt32Constant(bit_cast<int32_t>(x)));
404 : }
405 : }
406 :
407 :
408 : // -----------------------------------------------------------------------------
409 : // ChangeInt32ToFloat64
410 :
411 :
412 15374 : TEST_F(MachineOperatorReducerTest, ChangeInt32ToFloat64WithConstant) {
413 401 : TRACED_FOREACH(int32_t, x, kInt32Values) {
414 : Reduction reduction = Reduce(
415 300 : graph()->NewNode(machine()->ChangeInt32ToFloat64(), Int32Constant(x)));
416 100 : ASSERT_TRUE(reduction.Changed());
417 600 : EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastI2D(x))));
418 : }
419 : }
420 :
421 :
422 : // -----------------------------------------------------------------------------
423 : // ChangeInt32ToInt64
424 :
425 :
426 15374 : TEST_F(MachineOperatorReducerTest, ChangeInt32ToInt64WithConstant) {
427 401 : TRACED_FOREACH(int32_t, x, kInt32Values) {
428 : Reduction reduction = Reduce(
429 300 : graph()->NewNode(machine()->ChangeInt32ToInt64(), Int32Constant(x)));
430 100 : ASSERT_TRUE(reduction.Changed());
431 500 : EXPECT_THAT(reduction.replacement(), IsInt64Constant(x));
432 : }
433 : }
434 :
435 : // -----------------------------------------------------------------------------
436 : // ChangeInt64ToFloat64
437 :
438 15374 : TEST_F(MachineOperatorReducerTest,
439 : ChangeInt64ToFloat64WithChangeFloat64ToInt64) {
440 1 : Node* value = Parameter(0);
441 : Reduction reduction = Reduce(graph()->NewNode(
442 : machine()->ChangeInt64ToFloat64(),
443 3 : graph()->NewNode(machine()->ChangeFloat64ToInt64(), value)));
444 1 : ASSERT_TRUE(reduction.Changed());
445 2 : EXPECT_EQ(value, reduction.replacement());
446 : }
447 :
448 15374 : TEST_F(MachineOperatorReducerTest, ChangeInt64ToFloat64WithConstant) {
449 401 : TRACED_FOREACH(int32_t, x, kInt32Values) {
450 : Reduction reduction = Reduce(
451 300 : graph()->NewNode(machine()->ChangeInt64ToFloat64(), Int64Constant(x)));
452 100 : ASSERT_TRUE(reduction.Changed());
453 600 : EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastI2D(x))));
454 : }
455 : }
456 :
457 : // -----------------------------------------------------------------------------
458 : // ChangeUint32ToFloat64
459 :
460 :
461 15374 : TEST_F(MachineOperatorReducerTest, ChangeUint32ToFloat64WithConstant) {
462 193 : TRACED_FOREACH(uint32_t, x, kUint32Values) {
463 : Reduction reduction =
464 : Reduce(graph()->NewNode(machine()->ChangeUint32ToFloat64(),
465 144 : Int32Constant(bit_cast<int32_t>(x))));
466 48 : ASSERT_TRUE(reduction.Changed());
467 288 : EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastUI2D(x))));
468 : }
469 : }
470 :
471 :
472 : // -----------------------------------------------------------------------------
473 : // ChangeUint32ToUint64
474 :
475 :
476 15374 : TEST_F(MachineOperatorReducerTest, ChangeUint32ToUint64WithConstant) {
477 193 : TRACED_FOREACH(uint32_t, x, kUint32Values) {
478 : Reduction reduction =
479 : Reduce(graph()->NewNode(machine()->ChangeUint32ToUint64(),
480 144 : Int32Constant(bit_cast<int32_t>(x))));
481 48 : ASSERT_TRUE(reduction.Changed());
482 240 : EXPECT_THAT(reduction.replacement(),
483 0 : IsInt64Constant(bit_cast<int64_t>(static_cast<uint64_t>(x))));
484 : }
485 : }
486 :
487 :
488 : // -----------------------------------------------------------------------------
489 : // TruncateFloat64ToFloat32
490 :
491 :
492 15374 : TEST_F(MachineOperatorReducerTest,
493 : TruncateFloat64ToFloat32WithChangeFloat32ToFloat64) {
494 1 : Node* value = Parameter(0);
495 : Reduction reduction = Reduce(graph()->NewNode(
496 : machine()->TruncateFloat64ToFloat32(),
497 3 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), value)));
498 1 : ASSERT_TRUE(reduction.Changed());
499 2 : EXPECT_EQ(value, reduction.replacement());
500 : }
501 :
502 :
503 15374 : TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) {
504 401 : TRACED_FOREACH(double, x, kFloat64Values) {
505 : Reduction reduction = Reduce(graph()->NewNode(
506 300 : machine()->TruncateFloat64ToFloat32(), Float64Constant(x)));
507 100 : ASSERT_TRUE(reduction.Changed());
508 600 : EXPECT_THAT(reduction.replacement(),
509 0 : IsFloat32Constant(BitEq(DoubleToFloat32(x))));
510 : }
511 : }
512 :
513 :
514 : // -----------------------------------------------------------------------------
515 : // TruncateFloat64ToWord32
516 :
517 15374 : TEST_F(MachineOperatorReducerTest,
518 : TruncateFloat64ToWord32WithChangeInt32ToFloat64) {
519 1 : Node* value = Parameter(0);
520 : Reduction reduction = Reduce(graph()->NewNode(
521 : machine()->TruncateFloat64ToWord32(),
522 3 : graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
523 1 : ASSERT_TRUE(reduction.Changed());
524 2 : EXPECT_EQ(value, reduction.replacement());
525 : }
526 :
527 15374 : TEST_F(MachineOperatorReducerTest, TruncateFloat64ToWord32WithConstant) {
528 401 : TRACED_FOREACH(double, x, kFloat64Values) {
529 : Reduction reduction = Reduce(graph()->NewNode(
530 300 : machine()->TruncateFloat64ToWord32(), Float64Constant(x)));
531 100 : ASSERT_TRUE(reduction.Changed());
532 500 : EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
533 : }
534 : }
535 :
536 :
537 : // -----------------------------------------------------------------------------
538 : // TruncateInt64ToInt32
539 :
540 :
541 15374 : TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithChangeInt32ToInt64) {
542 1 : Node* value = Parameter(0);
543 : Reduction reduction = Reduce(graph()->NewNode(
544 : machine()->TruncateInt64ToInt32(),
545 3 : graph()->NewNode(machine()->ChangeInt32ToInt64(), value)));
546 1 : ASSERT_TRUE(reduction.Changed());
547 2 : EXPECT_EQ(value, reduction.replacement());
548 : }
549 :
550 :
551 15374 : TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithConstant) {
552 401 : TRACED_FOREACH(int64_t, x, kInt64Values) {
553 : Reduction reduction = Reduce(
554 300 : graph()->NewNode(machine()->TruncateInt64ToInt32(), Int64Constant(x)));
555 100 : ASSERT_TRUE(reduction.Changed());
556 500 : EXPECT_THAT(reduction.replacement(),
557 : IsInt32Constant(bit_cast<int32_t>(
558 0 : static_cast<uint32_t>(bit_cast<uint64_t>(x)))));
559 : }
560 : }
561 :
562 :
563 : // -----------------------------------------------------------------------------
564 : // RoundFloat64ToInt32
565 :
566 15374 : TEST_F(MachineOperatorReducerTest,
567 : RoundFloat64ToInt32WithChangeInt32ToFloat64) {
568 1 : Node* value = Parameter(0);
569 : Reduction reduction = Reduce(graph()->NewNode(
570 : machine()->RoundFloat64ToInt32(),
571 3 : graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
572 1 : ASSERT_TRUE(reduction.Changed());
573 2 : EXPECT_EQ(value, reduction.replacement());
574 : }
575 :
576 15374 : TEST_F(MachineOperatorReducerTest, RoundFloat64ToInt32WithConstant) {
577 401 : TRACED_FOREACH(double, x, kFloat64Values) {
578 : Reduction reduction = Reduce(
579 300 : graph()->NewNode(machine()->RoundFloat64ToInt32(), Float64Constant(x)));
580 100 : ASSERT_TRUE(reduction.Changed());
581 500 : EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
582 : }
583 : }
584 :
585 : // -----------------------------------------------------------------------------
586 : // Word32And
587 :
588 15374 : TEST_F(MachineOperatorReducerTest, Word32AndWithWord32ShlWithConstant) {
589 1 : Node* const p0 = Parameter(0);
590 :
591 125 : TRACED_FORRANGE(int32_t, l, 1, 31) {
592 2015 : TRACED_FORRANGE(int32_t, k, 1, l) {
593 : // (x << L) & (-1 << K) => x << L
594 : Reduction const r1 = Reduce(graph()->NewNode(
595 : machine()->Word32And(),
596 : graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l)),
597 1984 : Int32Constant(Shl(-1, k))));
598 496 : ASSERT_TRUE(r1.Changed());
599 3472 : EXPECT_THAT(r1.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
600 :
601 : // (-1 << K) & (x << L) => x << L
602 : Reduction const r2 = Reduce(graph()->NewNode(
603 : machine()->Word32And(), Int32Constant(Shl(-1, k)),
604 1488 : graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l))));
605 496 : ASSERT_TRUE(r2.Changed());
606 3472 : EXPECT_THAT(r2.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
607 : }
608 : }
609 : }
610 :
611 :
612 15374 : TEST_F(MachineOperatorReducerTest, Word32AndWithWord32AndWithConstant) {
613 1 : Node* const p0 = Parameter(0);
614 :
615 401 : TRACED_FOREACH(int32_t, k, kInt32Values) {
616 40100 : TRACED_FOREACH(int32_t, l, kInt32Values) {
617 10000 : if (k == 0 || k == -1 || l == 0 || l == -1) continue;
618 :
619 : // (x & K) & L => x & (K & L)
620 : Reduction const r1 = Reduce(graph()->NewNode(
621 : machine()->Word32And(),
622 : graph()->NewNode(machine()->Word32And(), p0, Int32Constant(k)),
623 39204 : Int32Constant(l)));
624 9801 : ASSERT_TRUE(r1.Changed());
625 67287 : EXPECT_THAT(r1.replacement(),
626 : (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
627 0 : : IsInt32Constant(0));
628 :
629 : // (K & x) & L => x & (K & L)
630 : Reduction const r2 = Reduce(graph()->NewNode(
631 : machine()->Word32And(),
632 : graph()->NewNode(machine()->Word32And(), Int32Constant(k), p0),
633 29403 : Int32Constant(l)));
634 9801 : ASSERT_TRUE(r2.Changed());
635 67287 : EXPECT_THAT(r2.replacement(),
636 : (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
637 0 : : IsInt32Constant(0));
638 : }
639 : }
640 : }
641 :
642 :
643 15374 : TEST_F(MachineOperatorReducerTest, Word32AndWithInt32AddAndConstant) {
644 1 : Node* const p0 = Parameter(0);
645 1 : Node* const p1 = Parameter(1);
646 :
647 125 : TRACED_FORRANGE(int32_t, l, 1, 31) {
648 12431 : TRACED_FOREACH(int32_t, k, kInt32Values) {
649 3100 : if (Shl(k, l) == 0) continue;
650 : // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
651 : Reduction const r = Reduce(graph()->NewNode(
652 : machine()->Word32And(),
653 : graph()->NewNode(machine()->Int32Add(), p0, Int32Constant(Shl(k, l))),
654 11692 : Int32Constant(Shl(-1, l))));
655 2923 : ASSERT_TRUE(r.Changed());
656 29230 : EXPECT_THAT(r.replacement(),
657 : IsInt32Add(IsWord32And(p0, IsInt32Constant(Shl(-1, l))),
658 0 : IsInt32Constant(Shl(k, l))));
659 : }
660 :
661 62 : Node* s1 = graph()->NewNode(machine()->Word32Shl(), p1, Int32Constant(l));
662 :
663 : // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
664 : Reduction const r1 = Reduce(graph()->NewNode(
665 : machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), s1, p0),
666 93 : Int32Constant(Shl(-1, l))));
667 31 : ASSERT_TRUE(r1.Changed());
668 279 : EXPECT_THAT(r1.replacement(),
669 0 : IsInt32Add(IsWord32And(p0, IsInt32Constant(Shl(-1, l))), s1));
670 :
671 : // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
672 : Reduction const r2 = Reduce(graph()->NewNode(
673 : machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), p0, s1),
674 93 : Int32Constant(Shl(-1, l))));
675 31 : ASSERT_TRUE(r2.Changed());
676 279 : EXPECT_THAT(r2.replacement(),
677 0 : IsInt32Add(IsWord32And(p0, IsInt32Constant(Shl(-1, l))), s1));
678 : }
679 : }
680 :
681 :
682 15374 : TEST_F(MachineOperatorReducerTest, Word32AndWithInt32MulAndConstant) {
683 1 : Node* const p0 = Parameter(0);
684 :
685 125 : TRACED_FORRANGE(int32_t, l, 1, 31) {
686 12431 : TRACED_FOREACH(int32_t, k, kInt32Values) {
687 3100 : if (Shl(k, l) == 0) continue;
688 :
689 : // (x * (K << L)) & (-1 << L) => x * (K << L)
690 : Reduction const r1 = Reduce(graph()->NewNode(
691 : machine()->Word32And(),
692 : graph()->NewNode(machine()->Int32Mul(), p0, Int32Constant(Shl(k, l))),
693 11692 : Int32Constant(Shl(-1, l))));
694 2923 : ASSERT_TRUE(r1.Changed());
695 20461 : EXPECT_THAT(r1.replacement(), IsInt32Mul(p0, IsInt32Constant(Shl(k, l))));
696 :
697 : // ((K << L) * x) & (-1 << L) => x * (K << L)
698 : Reduction const r2 = Reduce(graph()->NewNode(
699 : machine()->Word32And(),
700 : graph()->NewNode(machine()->Int32Mul(), Int32Constant(Shl(k, l)), p0),
701 8769 : Int32Constant(Shl(-1, l))));
702 2923 : ASSERT_TRUE(r2.Changed());
703 20461 : EXPECT_THAT(r2.replacement(), IsInt32Mul(p0, IsInt32Constant(Shl(k, l))));
704 : }
705 : }
706 : }
707 :
708 :
709 15374 : TEST_F(MachineOperatorReducerTest,
710 : Word32AndWithInt32AddAndInt32MulAndConstant) {
711 1 : Node* const p0 = Parameter(0);
712 1 : Node* const p1 = Parameter(1);
713 :
714 125 : TRACED_FORRANGE(int32_t, l, 1, 31) {
715 12431 : TRACED_FOREACH(int32_t, k, kInt32Values) {
716 3100 : if (Shl(k, l) == 0) continue;
717 : // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
718 : Reduction const r1 = Reduce(graph()->NewNode(
719 : machine()->Word32And(),
720 : graph()->NewNode(machine()->Int32Add(),
721 : graph()->NewNode(machine()->Int32Mul(), p1,
722 : Int32Constant(Shl(k, l))),
723 : p0),
724 14615 : Int32Constant(Shl(-1, l))));
725 2923 : ASSERT_TRUE(r1.Changed());
726 35076 : EXPECT_THAT(r1.replacement(),
727 : IsInt32Add(IsWord32And(p0, IsInt32Constant(Shl(-1, l))),
728 0 : IsInt32Mul(p1, IsInt32Constant(Shl(k, l)))));
729 :
730 : // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
731 : Reduction const r2 = Reduce(graph()->NewNode(
732 : machine()->Word32And(),
733 : graph()->NewNode(machine()->Int32Add(), p0,
734 : graph()->NewNode(machine()->Int32Mul(), p1,
735 : Int32Constant(Shl(k, l)))),
736 11692 : Int32Constant(Shl(-1, l))));
737 2923 : ASSERT_TRUE(r2.Changed());
738 35076 : EXPECT_THAT(r2.replacement(),
739 : IsInt32Add(IsWord32And(p0, IsInt32Constant(Shl(-1, l))),
740 0 : IsInt32Mul(p1, IsInt32Constant(Shl(k, l)))));
741 : }
742 : }
743 : }
744 :
745 :
746 15374 : TEST_F(MachineOperatorReducerTest, Word32AndWithComparisonAndConstantOne) {
747 1 : Node* const p0 = Parameter(0);
748 1 : Node* const p1 = Parameter(1);
749 65 : TRACED_FOREACH(ComparisonBinaryOperator, cbop, kComparisonBinaryOperators) {
750 32 : Node* cmp = graph()->NewNode((machine()->*cbop.constructor)(), p0, p1);
751 :
752 : // cmp & 1 => cmp
753 : Reduction const r1 =
754 32 : Reduce(graph()->NewNode(machine()->Word32And(), cmp, Int32Constant(1)));
755 16 : ASSERT_TRUE(r1.Changed());
756 32 : EXPECT_EQ(cmp, r1.replacement());
757 :
758 : // 1 & cmp => cmp
759 : Reduction const r2 =
760 32 : Reduce(graph()->NewNode(machine()->Word32And(), Int32Constant(1), cmp));
761 16 : ASSERT_TRUE(r2.Changed());
762 32 : EXPECT_EQ(cmp, r2.replacement());
763 : }
764 : }
765 :
766 :
767 : // -----------------------------------------------------------------------------
768 : // Word32Xor
769 :
770 :
771 15374 : TEST_F(MachineOperatorReducerTest, Word32XorWithWord32XorAndMinusOne) {
772 1 : Node* const p0 = Parameter(0);
773 :
774 : // (x ^ -1) ^ -1 => x
775 : Reduction r1 = Reduce(graph()->NewNode(
776 : machine()->Word32Xor(),
777 : graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1)),
778 4 : Int32Constant(-1)));
779 1 : ASSERT_TRUE(r1.Changed());
780 2 : EXPECT_EQ(r1.replacement(), p0);
781 :
782 : // -1 ^ (x ^ -1) => x
783 : Reduction r2 = Reduce(graph()->NewNode(
784 : machine()->Word32Xor(), Int32Constant(-1),
785 3 : graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1))));
786 1 : ASSERT_TRUE(r2.Changed());
787 2 : EXPECT_EQ(r2.replacement(), p0);
788 :
789 : // (-1 ^ x) ^ -1 => x
790 : Reduction r3 = Reduce(graph()->NewNode(
791 : machine()->Word32Xor(),
792 : graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0),
793 3 : Int32Constant(-1)));
794 1 : ASSERT_TRUE(r3.Changed());
795 2 : EXPECT_EQ(r3.replacement(), p0);
796 :
797 : // -1 ^ (-1 ^ x) => x
798 : Reduction r4 = Reduce(graph()->NewNode(
799 : machine()->Word32Xor(), Int32Constant(-1),
800 3 : graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0)));
801 1 : ASSERT_TRUE(r4.Changed());
802 2 : EXPECT_EQ(r4.replacement(), p0);
803 : }
804 :
805 :
806 : // -----------------------------------------------------------------------------
807 : // Word32Ror
808 :
809 :
810 15374 : TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithParameters) {
811 1 : Node* value = Parameter(0);
812 1 : Node* shift = Parameter(1);
813 2 : Node* sub = graph()->NewNode(machine()->Int32Sub(), Int32Constant(32), shift);
814 :
815 : // Testing rotate left.
816 1 : Node* shl_l = graph()->NewNode(machine()->Word32Shl(), value, shift);
817 1 : Node* shr_l = graph()->NewNode(machine()->Word32Shr(), value, sub);
818 :
819 : // (x << y) | (x >>> (32 - y)) => x ror (32 - y)
820 2 : Node* node1 = graph()->NewNode(machine()->Word32Or(), shl_l, shr_l);
821 1 : Reduction reduction1 = Reduce(node1);
822 1 : EXPECT_TRUE(reduction1.Changed());
823 2 : EXPECT_EQ(reduction1.replacement(), node1);
824 6 : EXPECT_THAT(reduction1.replacement(), IsWord32Ror(value, sub));
825 :
826 : // (x >>> (32 - y)) | (x << y) => x ror (32 - y)
827 2 : Node* node2 = graph()->NewNode(machine()->Word32Or(), shr_l, shl_l);
828 1 : Reduction reduction2 = Reduce(node2);
829 1 : EXPECT_TRUE(reduction2.Changed());
830 2 : EXPECT_EQ(reduction2.replacement(), node2);
831 6 : EXPECT_THAT(reduction2.replacement(), IsWord32Ror(value, sub));
832 :
833 : // (x << y) ^ (x >>> (32 - y)) => x ror (32 - y)
834 2 : Node* node3 = graph()->NewNode(machine()->Word32Xor(), shl_l, shr_l);
835 1 : Reduction reduction3 = Reduce(node3);
836 1 : EXPECT_TRUE(reduction3.Changed());
837 2 : EXPECT_EQ(reduction3.replacement(), node3);
838 6 : EXPECT_THAT(reduction3.replacement(), IsWord32Ror(value, sub));
839 :
840 : // (x >>> (32 - y)) ^ (x << y) => x ror (32 - y)
841 2 : Node* node4 = graph()->NewNode(machine()->Word32Xor(), shr_l, shl_l);
842 1 : Reduction reduction4 = Reduce(node4);
843 1 : EXPECT_TRUE(reduction4.Changed());
844 2 : EXPECT_EQ(reduction4.replacement(), node4);
845 6 : EXPECT_THAT(reduction4.replacement(), IsWord32Ror(value, sub));
846 :
847 : // Testing rotate right.
848 1 : Node* shl_r = graph()->NewNode(machine()->Word32Shl(), value, sub);
849 1 : Node* shr_r = graph()->NewNode(machine()->Word32Shr(), value, shift);
850 :
851 : // (x << (32 - y)) | (x >>> y) => x ror y
852 2 : Node* node5 = graph()->NewNode(machine()->Word32Or(), shl_r, shr_r);
853 1 : Reduction reduction5 = Reduce(node5);
854 1 : EXPECT_TRUE(reduction5.Changed());
855 2 : EXPECT_EQ(reduction5.replacement(), node5);
856 6 : EXPECT_THAT(reduction5.replacement(), IsWord32Ror(value, shift));
857 :
858 : // (x >>> y) | (x << (32 - y)) => x ror y
859 2 : Node* node6 = graph()->NewNode(machine()->Word32Or(), shr_r, shl_r);
860 1 : Reduction reduction6 = Reduce(node6);
861 1 : EXPECT_TRUE(reduction6.Changed());
862 2 : EXPECT_EQ(reduction6.replacement(), node6);
863 6 : EXPECT_THAT(reduction6.replacement(), IsWord32Ror(value, shift));
864 :
865 : // (x << (32 - y)) ^ (x >>> y) => x ror y
866 2 : Node* node7 = graph()->NewNode(machine()->Word32Xor(), shl_r, shr_r);
867 1 : Reduction reduction7 = Reduce(node7);
868 1 : EXPECT_TRUE(reduction7.Changed());
869 2 : EXPECT_EQ(reduction7.replacement(), node7);
870 6 : EXPECT_THAT(reduction7.replacement(), IsWord32Ror(value, shift));
871 :
872 : // (x >>> y) ^ (x << (32 - y)) => x ror y
873 2 : Node* node8 = graph()->NewNode(machine()->Word32Xor(), shr_r, shl_r);
874 1 : Reduction reduction8 = Reduce(node8);
875 1 : EXPECT_TRUE(reduction8.Changed());
876 2 : EXPECT_EQ(reduction8.replacement(), node8);
877 6 : EXPECT_THAT(reduction8.replacement(), IsWord32Ror(value, shift));
878 1 : }
879 :
880 15374 : TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithConstant) {
881 1 : Node* value = Parameter(0);
882 129 : TRACED_FORRANGE(int32_t, k, 0, 31) {
883 : Node* shl =
884 64 : graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(k));
885 : Node* shr =
886 32 : graph()->NewNode(machine()->Word32Shr(), value, Int32Constant(32 - k));
887 :
888 : // (x << K) | (x >>> ((32 - K) - y)) => x ror (32 - K)
889 64 : Node* node1 = graph()->NewNode(machine()->Word32Or(), shl, shr);
890 32 : Reduction reduction1 = Reduce(node1);
891 32 : EXPECT_TRUE(reduction1.Changed());
892 64 : EXPECT_EQ(reduction1.replacement(), node1);
893 224 : EXPECT_THAT(reduction1.replacement(),
894 0 : IsWord32Ror(value, IsInt32Constant(32 - k)));
895 :
896 : // (x >>> (32 - K)) | (x << K) => x ror (32 - K)
897 64 : Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl);
898 32 : Reduction reduction2 = Reduce(node2);
899 32 : EXPECT_TRUE(reduction2.Changed());
900 64 : EXPECT_EQ(reduction2.replacement(), node2);
901 224 : EXPECT_THAT(reduction2.replacement(),
902 0 : IsWord32Ror(value, IsInt32Constant(32 - k)));
903 : }
904 1 : }
905 :
906 :
907 15374 : TEST_F(MachineOperatorReducerTest, Word32RorWithZeroShift) {
908 1 : Node* value = Parameter(0);
909 : Node* node =
910 2 : graph()->NewNode(machine()->Word32Ror(), value, Int32Constant(0));
911 1 : Reduction reduction = Reduce(node);
912 1 : EXPECT_TRUE(reduction.Changed());
913 2 : EXPECT_EQ(reduction.replacement(), value);
914 1 : }
915 :
916 :
917 15374 : TEST_F(MachineOperatorReducerTest, Word32RorWithConstants) {
918 193 : TRACED_FOREACH(int32_t, x, kUint32Values) {
919 6192 : TRACED_FORRANGE(int32_t, y, 0, 31) {
920 3072 : Node* node = graph()->NewNode(machine()->Word32Ror(), Int32Constant(x),
921 : Int32Constant(y));
922 1536 : Reduction reduction = Reduce(node);
923 1536 : EXPECT_TRUE(reduction.Changed());
924 9216 : EXPECT_THAT(reduction.replacement(),
925 0 : IsInt32Constant(base::bits::RotateRight32(x, y)));
926 : }
927 : }
928 1 : }
929 :
930 :
931 : // -----------------------------------------------------------------------------
932 : // Word32Sar
933 :
934 :
935 15374 : TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndComparison) {
936 1 : Node* const p0 = Parameter(0);
937 1 : Node* const p1 = Parameter(1);
938 :
939 65 : TRACED_FOREACH(ComparisonBinaryOperator, cbop, kComparisonBinaryOperators) {
940 16 : Node* cmp = graph()->NewNode((machine()->*cbop.constructor)(), p0, p1);
941 :
942 : // cmp << 31 >> 31 => 0 - cmp
943 : Reduction const r = Reduce(graph()->NewNode(
944 : machine()->Word32Sar(),
945 : graph()->NewNode(machine()->Word32Shl(), cmp, Int32Constant(31)),
946 48 : Int32Constant(31)));
947 16 : ASSERT_TRUE(r.Changed());
948 112 : EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0), cmp));
949 : }
950 : }
951 :
952 :
953 15374 : TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndLoad) {
954 1 : Node* const p0 = Parameter(0);
955 1 : Node* const p1 = Parameter(1);
956 : {
957 1 : Node* const l = graph()->NewNode(machine()->Load(MachineType::Int8()), p0,
958 1 : p1, graph()->start(), graph()->start());
959 : Reduction const r = Reduce(graph()->NewNode(
960 : machine()->Word32Sar(),
961 : graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(24)),
962 3 : Int32Constant(24)));
963 1 : ASSERT_TRUE(r.Changed());
964 2 : EXPECT_EQ(l, r.replacement());
965 : }
966 : {
967 1 : Node* const l = graph()->NewNode(machine()->Load(MachineType::Int16()), p0,
968 1 : p1, graph()->start(), graph()->start());
969 : Reduction const r = Reduce(graph()->NewNode(
970 : machine()->Word32Sar(),
971 : graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(16)),
972 3 : Int32Constant(16)));
973 1 : ASSERT_TRUE(r.Changed());
974 2 : EXPECT_EQ(l, r.replacement());
975 : }
976 : }
977 :
978 :
979 : // -----------------------------------------------------------------------------
980 : // Word32Shr
981 :
982 15374 : TEST_F(MachineOperatorReducerTest, Word32ShrWithWord32And) {
983 1 : Node* const p0 = Parameter(0);
984 125 : TRACED_FORRANGE(int32_t, shift, 1, 31) {
985 : uint32_t mask =
986 : base::SubWithWraparound(base::ShlWithWraparound(1, shift), 1);
987 93 : Node* node = graph()->NewNode(
988 : machine()->Word32Shr(),
989 : graph()->NewNode(machine()->Word32And(), p0, Int32Constant(mask)),
990 : Int32Constant(shift));
991 31 : Reduction r = Reduce(node);
992 31 : ASSERT_TRUE(r.Changed());
993 155 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
994 : }
995 : }
996 :
997 : // -----------------------------------------------------------------------------
998 : // Word32Shl
999 :
1000 15374 : TEST_F(MachineOperatorReducerTest, Word32ShlWithZeroShift) {
1001 1 : Node* p0 = Parameter(0);
1002 2 : Node* node = graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(0));
1003 1 : Reduction r = Reduce(node);
1004 1 : ASSERT_TRUE(r.Changed());
1005 2 : EXPECT_EQ(p0, r.replacement());
1006 : }
1007 :
1008 :
1009 15374 : TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Sar) {
1010 1 : Node* p0 = Parameter(0);
1011 125 : TRACED_FORRANGE(int32_t, x, 1, 31) {
1012 93 : Node* node = graph()->NewNode(
1013 : machine()->Word32Shl(),
1014 : graph()->NewNode(machine()->Word32Sar(), p0, Int32Constant(x)),
1015 : Int32Constant(x));
1016 31 : Reduction r = Reduce(node);
1017 31 : ASSERT_TRUE(r.Changed());
1018 31 : int32_t m = static_cast<int32_t>(~((1U << x) - 1U));
1019 217 : EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
1020 : }
1021 : }
1022 :
1023 :
1024 15374 : TEST_F(MachineOperatorReducerTest,
1025 : Word32ShlWithWord32SarAndInt32AddAndConstant) {
1026 1 : Node* const p0 = Parameter(0);
1027 401 : TRACED_FOREACH(int32_t, k, kInt32Values) {
1028 12500 : TRACED_FORRANGE(int32_t, l, 1, 31) {
1029 3100 : if (Shl(k, l) == 0) continue;
1030 : // (x + (K << L)) >> L << L => (x & (-1 << L)) + (K << L)
1031 : Reduction const r = Reduce(graph()->NewNode(
1032 : machine()->Word32Shl(),
1033 : graph()->NewNode(machine()->Word32Sar(),
1034 : graph()->NewNode(machine()->Int32Add(), p0,
1035 : Int32Constant(Shl(k, l))),
1036 : Int32Constant(l)),
1037 14615 : Int32Constant(l)));
1038 2923 : ASSERT_TRUE(r.Changed());
1039 32153 : EXPECT_THAT(r.replacement(),
1040 : IsInt32Add(IsWord32And(p0, IsInt32Constant(Shl(-1, l))),
1041 0 : IsInt32Constant(Shl(k, l))));
1042 : }
1043 : }
1044 : }
1045 :
1046 :
1047 15374 : TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Shr) {
1048 1 : Node* p0 = Parameter(0);
1049 125 : TRACED_FORRANGE(int32_t, x, 1, 31) {
1050 93 : Node* node = graph()->NewNode(
1051 : machine()->Word32Shl(),
1052 : graph()->NewNode(machine()->Word32Shr(), p0, Int32Constant(x)),
1053 : Int32Constant(x));
1054 31 : Reduction r = Reduce(node);
1055 31 : ASSERT_TRUE(r.Changed());
1056 31 : int32_t m = static_cast<int32_t>(~((1U << x) - 1U));
1057 217 : EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
1058 : }
1059 : }
1060 :
1061 :
1062 : // -----------------------------------------------------------------------------
1063 : // Int32Sub
1064 :
1065 :
1066 15374 : TEST_F(MachineOperatorReducerTest, Int32SubWithConstant) {
1067 1 : Node* const p0 = Parameter(0);
1068 401 : TRACED_FOREACH(int32_t, k, kInt32Values) {
1069 : Reduction const r =
1070 300 : Reduce(graph()->NewNode(machine()->Int32Sub(), p0, Int32Constant(k)));
1071 100 : ASSERT_TRUE(r.Changed());
1072 100 : if (k == 0) {
1073 2 : EXPECT_EQ(p0, r.replacement());
1074 : } else {
1075 792 : EXPECT_THAT(
1076 : r.replacement(),
1077 0 : IsInt32Add(p0, IsInt32Constant(base::NegateWithWraparound(k))));
1078 : }
1079 : }
1080 : }
1081 :
1082 :
1083 : // -----------------------------------------------------------------------------
1084 : // Int32Div
1085 :
1086 :
1087 15374 : TEST_F(MachineOperatorReducerTest, Int32DivWithConstant) {
1088 1 : Node* const p0 = Parameter(0);
1089 : {
1090 : Reduction const r = Reduce(graph()->NewNode(
1091 3 : machine()->Int32Div(), p0, Int32Constant(0), graph()->start()));
1092 1 : ASSERT_TRUE(r.Changed());
1093 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1094 : }
1095 : {
1096 : Reduction const r = Reduce(graph()->NewNode(
1097 2 : machine()->Int32Div(), p0, Int32Constant(1), graph()->start()));
1098 1 : ASSERT_TRUE(r.Changed());
1099 2 : EXPECT_EQ(r.replacement(), p0);
1100 : }
1101 : {
1102 : Reduction const r = Reduce(graph()->NewNode(
1103 2 : machine()->Int32Div(), p0, Int32Constant(-1), graph()->start()));
1104 1 : ASSERT_TRUE(r.Changed());
1105 7 : EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0), p0));
1106 : }
1107 : {
1108 : Reduction const r = Reduce(graph()->NewNode(
1109 2 : machine()->Int32Div(), p0, Int32Constant(2), graph()->start()));
1110 1 : ASSERT_TRUE(r.Changed());
1111 12 : EXPECT_THAT(
1112 : r.replacement(),
1113 : IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
1114 0 : IsInt32Constant(1)));
1115 : }
1116 : {
1117 : Reduction const r = Reduce(graph()->NewNode(
1118 2 : machine()->Int32Div(), p0, Int32Constant(-2), graph()->start()));
1119 1 : ASSERT_TRUE(r.Changed());
1120 15 : EXPECT_THAT(
1121 : r.replacement(),
1122 : IsInt32Sub(
1123 : IsInt32Constant(0),
1124 : IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
1125 0 : IsInt32Constant(1))));
1126 : }
1127 117 : TRACED_FORRANGE(int32_t, shift, 2, 30) {
1128 : Reduction const r =
1129 : Reduce(graph()->NewNode(machine()->Int32Div(), p0,
1130 58 : Int32Constant(1 << shift), graph()->start()));
1131 29 : ASSERT_TRUE(r.Changed());
1132 435 : EXPECT_THAT(
1133 : r.replacement(),
1134 : IsWord32Sar(IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
1135 : IsInt32Constant(32 - shift)),
1136 : p0),
1137 0 : IsInt32Constant(shift)));
1138 : }
1139 121 : TRACED_FORRANGE(int32_t, shift, 2, 31) {
1140 : Reduction const r = Reduce(graph()->NewNode(machine()->Int32Div(), p0,
1141 : Int32Constant(Shl(-1, shift)),
1142 60 : graph()->start()));
1143 30 : ASSERT_TRUE(r.Changed());
1144 540 : EXPECT_THAT(
1145 : r.replacement(),
1146 : IsInt32Sub(
1147 : IsInt32Constant(0),
1148 : IsWord32Sar(
1149 : IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
1150 : IsInt32Constant(32 - shift)),
1151 : p0),
1152 0 : IsInt32Constant(shift))));
1153 : }
1154 401 : TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1155 100 : if (divisor < 0) {
1156 97 : if (divisor == kMinInt || base::bits::IsPowerOfTwo(-divisor)) continue;
1157 : Reduction const r = Reduce(graph()->NewNode(
1158 96 : machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
1159 48 : ASSERT_TRUE(r.Changed());
1160 384 : EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0),
1161 0 : IsTruncatingDiv(p0, -divisor)));
1162 51 : } else if (divisor > 0) {
1163 50 : if (base::bits::IsPowerOfTwo(divisor)) continue;
1164 : Reduction const r = Reduce(graph()->NewNode(
1165 98 : machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
1166 49 : ASSERT_TRUE(r.Changed());
1167 245 : EXPECT_THAT(r.replacement(), IsTruncatingDiv(p0, divisor));
1168 : }
1169 : }
1170 : }
1171 :
1172 :
1173 15374 : TEST_F(MachineOperatorReducerTest, Int32DivWithParameters) {
1174 1 : Node* const p0 = Parameter(0);
1175 : Reduction const r =
1176 2 : Reduce(graph()->NewNode(machine()->Int32Div(), p0, p0, graph()->start()));
1177 1 : ASSERT_TRUE(r.Changed());
1178 10 : EXPECT_THAT(
1179 : r.replacement(),
1180 0 : IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
1181 : }
1182 :
1183 :
1184 : // -----------------------------------------------------------------------------
1185 : // Uint32Div
1186 :
1187 :
1188 15374 : TEST_F(MachineOperatorReducerTest, Uint32DivWithConstant) {
1189 1 : Node* const p0 = Parameter(0);
1190 : {
1191 : Reduction const r = Reduce(graph()->NewNode(
1192 3 : machine()->Uint32Div(), Int32Constant(0), p0, graph()->start()));
1193 1 : ASSERT_TRUE(r.Changed());
1194 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1195 : }
1196 : {
1197 : Reduction const r = Reduce(graph()->NewNode(
1198 2 : machine()->Uint32Div(), p0, Int32Constant(0), graph()->start()));
1199 1 : ASSERT_TRUE(r.Changed());
1200 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1201 : }
1202 : {
1203 : Reduction const r = Reduce(graph()->NewNode(
1204 2 : machine()->Uint32Div(), p0, Int32Constant(1), graph()->start()));
1205 1 : ASSERT_TRUE(r.Changed());
1206 2 : EXPECT_EQ(r.replacement(), p0);
1207 : }
1208 193 : TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1209 9264 : TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1210 : Reduction const r = Reduce(
1211 : graph()->NewNode(machine()->Uint32Div(), Uint32Constant(dividend),
1212 4608 : Uint32Constant(divisor), graph()->start()));
1213 2304 : ASSERT_TRUE(r.Changed());
1214 13824 : EXPECT_THAT(r.replacement(),
1215 : IsInt32Constant(bit_cast<int32_t>(
1216 0 : base::bits::UnsignedDiv32(dividend, divisor))));
1217 : }
1218 : }
1219 125 : TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1220 : Reduction const r =
1221 : Reduce(graph()->NewNode(machine()->Uint32Div(), p0,
1222 93 : Uint32Constant(1u << shift), graph()->start()));
1223 31 : ASSERT_TRUE(r.Changed());
1224 217 : EXPECT_THAT(r.replacement(),
1225 0 : IsWord32Shr(p0, IsInt32Constant(static_cast<int32_t>(shift))));
1226 : }
1227 : }
1228 :
1229 :
1230 15374 : TEST_F(MachineOperatorReducerTest, Uint32DivWithParameters) {
1231 1 : Node* const p0 = Parameter(0);
1232 : Reduction const r = Reduce(
1233 2 : graph()->NewNode(machine()->Uint32Div(), p0, p0, graph()->start()));
1234 1 : ASSERT_TRUE(r.Changed());
1235 10 : EXPECT_THAT(
1236 : r.replacement(),
1237 0 : IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
1238 : }
1239 :
1240 :
1241 : // -----------------------------------------------------------------------------
1242 : // Int32Mod
1243 :
1244 :
1245 15374 : TEST_F(MachineOperatorReducerTest, Int32ModWithConstant) {
1246 1 : Node* const p0 = Parameter(0);
1247 : {
1248 : Reduction const r = Reduce(graph()->NewNode(
1249 3 : machine()->Int32Mod(), Int32Constant(0), p0, graph()->start()));
1250 1 : ASSERT_TRUE(r.Changed());
1251 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1252 : }
1253 : {
1254 : Reduction const r = Reduce(graph()->NewNode(
1255 2 : machine()->Int32Mod(), p0, Int32Constant(0), graph()->start()));
1256 1 : ASSERT_TRUE(r.Changed());
1257 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1258 : }
1259 : {
1260 : Reduction const r = Reduce(graph()->NewNode(
1261 2 : machine()->Int32Mod(), p0, Int32Constant(1), graph()->start()));
1262 1 : ASSERT_TRUE(r.Changed());
1263 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1264 : }
1265 : {
1266 : Reduction const r = Reduce(graph()->NewNode(
1267 2 : machine()->Int32Mod(), p0, Int32Constant(-1), graph()->start()));
1268 1 : ASSERT_TRUE(r.Changed());
1269 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1270 : }
1271 401 : TRACED_FOREACH(int32_t, dividend, kInt32Values) {
1272 40100 : TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1273 : Reduction const r = Reduce(
1274 : graph()->NewNode(machine()->Int32Mod(), Int32Constant(dividend),
1275 20000 : Int32Constant(divisor), graph()->start()));
1276 10000 : ASSERT_TRUE(r.Changed());
1277 50000 : EXPECT_THAT(r.replacement(),
1278 0 : IsInt32Constant(base::bits::SignedMod32(dividend, divisor)));
1279 : }
1280 : }
1281 121 : TRACED_FORRANGE(int32_t, shift, 1, 30) {
1282 : Reduction const r =
1283 : Reduce(graph()->NewNode(machine()->Int32Mod(), p0,
1284 60 : Int32Constant(1 << shift), graph()->start()));
1285 30 : int32_t const mask = (1 << shift) - 1;
1286 30 : ASSERT_TRUE(r.Changed());
1287 1020 : EXPECT_THAT(
1288 : r.replacement(),
1289 : IsPhi(
1290 : MachineRepresentation::kWord32,
1291 : IsInt32Sub(IsInt32Constant(0),
1292 : IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1293 : IsInt32Constant(mask))),
1294 : IsWord32And(p0, IsInt32Constant(mask)),
1295 : IsMerge(IsIfTrue(IsBranch(IsInt32LessThan(p0, IsInt32Constant(0)),
1296 : graph()->start())),
1297 : IsIfFalse(IsBranch(IsInt32LessThan(p0, IsInt32Constant(0)),
1298 0 : graph()->start())))));
1299 : }
1300 125 : TRACED_FORRANGE(int32_t, shift, 1, 31) {
1301 : Reduction const r = Reduce(graph()->NewNode(machine()->Int32Mod(), p0,
1302 : Int32Constant(Shl(-1, shift)),
1303 62 : graph()->start()));
1304 31 : int32_t const mask = static_cast<int32_t>((1U << shift) - 1U);
1305 31 : ASSERT_TRUE(r.Changed());
1306 1054 : EXPECT_THAT(
1307 : r.replacement(),
1308 : IsPhi(
1309 : MachineRepresentation::kWord32,
1310 : IsInt32Sub(IsInt32Constant(0),
1311 : IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1312 : IsInt32Constant(mask))),
1313 : IsWord32And(p0, IsInt32Constant(mask)),
1314 : IsMerge(IsIfTrue(IsBranch(IsInt32LessThan(p0, IsInt32Constant(0)),
1315 : graph()->start())),
1316 : IsIfFalse(IsBranch(IsInt32LessThan(p0, IsInt32Constant(0)),
1317 0 : graph()->start())))));
1318 : }
1319 401 : TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1320 199 : if (divisor == 0 || base::bits::IsPowerOfTwo(Abs(divisor))) continue;
1321 : Reduction const r = Reduce(graph()->NewNode(
1322 194 : machine()->Int32Mod(), p0, Int32Constant(divisor), graph()->start()));
1323 97 : ASSERT_TRUE(r.Changed());
1324 1067 : EXPECT_THAT(r.replacement(),
1325 : IsInt32Sub(p0, IsInt32Mul(IsTruncatingDiv(p0, Abs(divisor)),
1326 0 : IsInt32Constant(Abs(divisor)))));
1327 : }
1328 : }
1329 :
1330 :
1331 15374 : TEST_F(MachineOperatorReducerTest, Int32ModWithParameters) {
1332 1 : Node* const p0 = Parameter(0);
1333 : Reduction const r =
1334 2 : Reduce(graph()->NewNode(machine()->Int32Mod(), p0, p0, graph()->start()));
1335 1 : ASSERT_TRUE(r.Changed());
1336 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1337 : }
1338 :
1339 :
1340 : // -----------------------------------------------------------------------------
1341 : // Uint32Mod
1342 :
1343 :
1344 15374 : TEST_F(MachineOperatorReducerTest, Uint32ModWithConstant) {
1345 1 : Node* const p0 = Parameter(0);
1346 : {
1347 : Reduction const r = Reduce(graph()->NewNode(
1348 3 : machine()->Uint32Mod(), p0, Int32Constant(0), graph()->start()));
1349 1 : ASSERT_TRUE(r.Changed());
1350 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1351 : }
1352 : {
1353 : Reduction const r = Reduce(graph()->NewNode(
1354 2 : machine()->Uint32Mod(), Int32Constant(0), p0, graph()->start()));
1355 1 : ASSERT_TRUE(r.Changed());
1356 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1357 : }
1358 : {
1359 : Reduction const r = Reduce(graph()->NewNode(
1360 2 : machine()->Uint32Mod(), p0, Int32Constant(1), graph()->start()));
1361 1 : ASSERT_TRUE(r.Changed());
1362 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1363 : }
1364 193 : TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1365 9264 : TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1366 : Reduction const r = Reduce(
1367 : graph()->NewNode(machine()->Uint32Mod(), Uint32Constant(dividend),
1368 4608 : Uint32Constant(divisor), graph()->start()));
1369 2304 : ASSERT_TRUE(r.Changed());
1370 13824 : EXPECT_THAT(r.replacement(),
1371 : IsInt32Constant(bit_cast<int32_t>(
1372 0 : base::bits::UnsignedMod32(dividend, divisor))));
1373 : }
1374 : }
1375 125 : TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1376 : Reduction const r =
1377 : Reduce(graph()->NewNode(machine()->Uint32Mod(), p0,
1378 93 : Uint32Constant(1u << shift), graph()->start()));
1379 31 : ASSERT_TRUE(r.Changed());
1380 217 : EXPECT_THAT(r.replacement(),
1381 : IsWord32And(p0, IsInt32Constant(
1382 0 : static_cast<int32_t>((1u << shift) - 1u))));
1383 : }
1384 : }
1385 :
1386 :
1387 15374 : TEST_F(MachineOperatorReducerTest, Uint32ModWithParameters) {
1388 1 : Node* const p0 = Parameter(0);
1389 : Reduction const r = Reduce(
1390 2 : graph()->NewNode(machine()->Uint32Mod(), p0, p0, graph()->start()));
1391 1 : ASSERT_TRUE(r.Changed());
1392 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1393 : }
1394 :
1395 :
1396 : // -----------------------------------------------------------------------------
1397 : // Int32Add
1398 :
1399 :
1400 15374 : TEST_F(MachineOperatorReducerTest, Int32AddWithInt32SubWithConstantZero) {
1401 1 : Node* const p0 = Parameter(0);
1402 1 : Node* const p1 = Parameter(1);
1403 :
1404 : Reduction const r1 = Reduce(graph()->NewNode(
1405 : machine()->Int32Add(),
1406 4 : graph()->NewNode(machine()->Int32Sub(), Int32Constant(0), p0), p1));
1407 1 : ASSERT_TRUE(r1.Changed());
1408 6 : EXPECT_THAT(r1.replacement(), IsInt32Sub(p1, p0));
1409 :
1410 : Reduction const r2 = Reduce(graph()->NewNode(
1411 : machine()->Int32Add(), p0,
1412 3 : graph()->NewNode(machine()->Int32Sub(), Int32Constant(0), p1)));
1413 1 : ASSERT_TRUE(r2.Changed());
1414 6 : EXPECT_THAT(r2.replacement(), IsInt32Sub(p0, p1));
1415 : }
1416 :
1417 :
1418 : // -----------------------------------------------------------------------------
1419 : // Int32AddWithOverflow
1420 :
1421 :
1422 15374 : TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) {
1423 : Node* control = graph()->start();
1424 1 : Node* p0 = Parameter(0);
1425 : {
1426 2 : Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1427 : Int32Constant(0), p0, control);
1428 :
1429 : Reduction r =
1430 2 : Reduce(graph()->NewNode(common()->Projection(1), add, control));
1431 1 : ASSERT_TRUE(r.Changed());
1432 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1433 :
1434 2 : r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1435 1 : ASSERT_TRUE(r.Changed());
1436 2 : EXPECT_EQ(p0, r.replacement());
1437 : }
1438 : {
1439 1 : Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), p0,
1440 : Int32Constant(0), control);
1441 :
1442 : Reduction r =
1443 2 : Reduce(graph()->NewNode(common()->Projection(1), add, control));
1444 1 : ASSERT_TRUE(r.Changed());
1445 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1446 :
1447 2 : r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1448 1 : ASSERT_TRUE(r.Changed());
1449 2 : EXPECT_EQ(p0, r.replacement());
1450 : }
1451 : }
1452 :
1453 :
1454 15374 : TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) {
1455 : Node* control = graph()->start();
1456 401 : TRACED_FOREACH(int32_t, x, kInt32Values) {
1457 40100 : TRACED_FOREACH(int32_t, y, kInt32Values) {
1458 : int32_t z;
1459 20000 : Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1460 : Int32Constant(x), Int32Constant(y), control);
1461 :
1462 : Reduction r =
1463 20000 : Reduce(graph()->NewNode(common()->Projection(1), add, control));
1464 10000 : ASSERT_TRUE(r.Changed());
1465 60000 : EXPECT_THAT(r.replacement(),
1466 0 : IsInt32Constant(base::bits::SignedAddOverflow32(x, y, &z)));
1467 :
1468 20000 : r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1469 10000 : ASSERT_TRUE(r.Changed());
1470 50000 : EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1471 : }
1472 : }
1473 : }
1474 :
1475 :
1476 : // -----------------------------------------------------------------------------
1477 : // Int32SubWithOverflow
1478 :
1479 :
1480 15374 : TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithZero) {
1481 : Node* control = graph()->start();
1482 1 : Node* p0 = Parameter(0);
1483 2 : Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(), p0,
1484 : Int32Constant(0), control);
1485 :
1486 2 : Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add, control));
1487 1 : ASSERT_TRUE(r.Changed());
1488 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1489 :
1490 2 : r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1491 1 : ASSERT_TRUE(r.Changed());
1492 2 : EXPECT_EQ(p0, r.replacement());
1493 : }
1494 :
1495 :
1496 15374 : TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
1497 : Node* control = graph()->start();
1498 401 : TRACED_FOREACH(int32_t, x, kInt32Values) {
1499 40100 : TRACED_FOREACH(int32_t, y, kInt32Values) {
1500 : int32_t z;
1501 20000 : Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(),
1502 : Int32Constant(x), Int32Constant(y), control);
1503 :
1504 : Reduction r =
1505 20000 : Reduce(graph()->NewNode(common()->Projection(1), add, control));
1506 10000 : ASSERT_TRUE(r.Changed());
1507 60000 : EXPECT_THAT(r.replacement(),
1508 0 : IsInt32Constant(base::bits::SignedSubOverflow32(x, y, &z)));
1509 :
1510 20000 : r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1511 10000 : ASSERT_TRUE(r.Changed());
1512 50000 : EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1513 : }
1514 : }
1515 : }
1516 :
1517 :
1518 : // -----------------------------------------------------------------------------
1519 : // Int32MulWithOverflow
1520 :
1521 15374 : TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithZero) {
1522 : Node* control = graph()->start();
1523 1 : Node* p0 = Parameter(0);
1524 : {
1525 2 : Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(),
1526 : Int32Constant(0), p0, control);
1527 :
1528 : Reduction r =
1529 2 : Reduce(graph()->NewNode(common()->Projection(1), mul, control));
1530 1 : ASSERT_TRUE(r.Changed());
1531 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1532 :
1533 2 : r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
1534 1 : ASSERT_TRUE(r.Changed());
1535 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1536 : }
1537 : {
1538 1 : Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
1539 : Int32Constant(0), control);
1540 :
1541 : Reduction r =
1542 2 : Reduce(graph()->NewNode(common()->Projection(1), mul, control));
1543 1 : ASSERT_TRUE(r.Changed());
1544 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1545 :
1546 2 : r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
1547 1 : ASSERT_TRUE(r.Changed());
1548 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1549 : }
1550 : }
1551 :
1552 15374 : TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithOne) {
1553 : Node* control = graph()->start();
1554 1 : Node* p0 = Parameter(0);
1555 : {
1556 2 : Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(),
1557 : Int32Constant(1), p0, control);
1558 :
1559 : Reduction r =
1560 2 : Reduce(graph()->NewNode(common()->Projection(1), mul, control));
1561 1 : ASSERT_TRUE(r.Changed());
1562 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1563 :
1564 2 : r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
1565 1 : ASSERT_TRUE(r.Changed());
1566 2 : EXPECT_EQ(p0, r.replacement());
1567 : }
1568 : {
1569 1 : Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
1570 : Int32Constant(1), control);
1571 :
1572 : Reduction r =
1573 2 : Reduce(graph()->NewNode(common()->Projection(1), mul, control));
1574 1 : ASSERT_TRUE(r.Changed());
1575 5 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1576 :
1577 2 : r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
1578 1 : ASSERT_TRUE(r.Changed());
1579 2 : EXPECT_EQ(p0, r.replacement());
1580 : }
1581 : }
1582 :
1583 15374 : TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithMinusOne) {
1584 : Node* control = graph()->start();
1585 1 : Node* p0 = Parameter(0);
1586 :
1587 : {
1588 : Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(),
1589 3 : Int32Constant(-1), p0, control));
1590 1 : ASSERT_TRUE(r.Changed());
1591 7 : EXPECT_THAT(r.replacement(),
1592 0 : IsInt32SubWithOverflow(IsInt32Constant(0), p0));
1593 : }
1594 :
1595 : {
1596 : Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
1597 2 : Int32Constant(-1), control));
1598 1 : ASSERT_TRUE(r.Changed());
1599 7 : EXPECT_THAT(r.replacement(),
1600 0 : IsInt32SubWithOverflow(IsInt32Constant(0), p0));
1601 : }
1602 : }
1603 :
1604 15374 : TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithTwo) {
1605 : Node* control = graph()->start();
1606 1 : Node* p0 = Parameter(0);
1607 :
1608 : {
1609 : Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(),
1610 3 : Int32Constant(2), p0, control));
1611 1 : ASSERT_TRUE(r.Changed());
1612 6 : EXPECT_THAT(r.replacement(), IsInt32AddWithOverflow(p0, p0));
1613 : }
1614 :
1615 : {
1616 : Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
1617 2 : Int32Constant(2), control));
1618 1 : ASSERT_TRUE(r.Changed());
1619 6 : EXPECT_THAT(r.replacement(), IsInt32AddWithOverflow(p0, p0));
1620 : }
1621 : }
1622 :
1623 15374 : TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithConstant) {
1624 : Node* control = graph()->start();
1625 401 : TRACED_FOREACH(int32_t, x, kInt32Values) {
1626 40100 : TRACED_FOREACH(int32_t, y, kInt32Values) {
1627 : int32_t z;
1628 20000 : Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(),
1629 : Int32Constant(x), Int32Constant(y), control);
1630 :
1631 : Reduction r =
1632 20000 : Reduce(graph()->NewNode(common()->Projection(1), mul, control));
1633 10000 : ASSERT_TRUE(r.Changed());
1634 50000 : EXPECT_THAT(r.replacement(),
1635 0 : IsInt32Constant(base::bits::SignedMulOverflow32(x, y, &z)));
1636 :
1637 20000 : r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
1638 10000 : ASSERT_TRUE(r.Changed());
1639 50000 : EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1640 : }
1641 : }
1642 : }
1643 :
1644 : // -----------------------------------------------------------------------------
1645 : // Int32LessThan
1646 :
1647 15374 : TEST_F(MachineOperatorReducerTest, Int32LessThanWithWord32Or) {
1648 1 : Node* const p0 = Parameter(0);
1649 401 : TRACED_FOREACH(int32_t, x, kInt32Values) {
1650 : Node* word32_or =
1651 200 : graph()->NewNode(machine()->Word32Or(), p0, Int32Constant(x));
1652 100 : Node* less_than = graph()->NewNode(machine()->Int32LessThan(), word32_or,
1653 : Int32Constant(0));
1654 100 : Reduction r = Reduce(less_than);
1655 100 : if (x < 0) {
1656 49 : ASSERT_TRUE(r.Changed());
1657 245 : EXPECT_THAT(r.replacement(), IsInt32Constant(1));
1658 : } else {
1659 102 : ASSERT_FALSE(r.Changed());
1660 : }
1661 : }
1662 : }
1663 :
1664 : // -----------------------------------------------------------------------------
1665 : // Uint32LessThan
1666 :
1667 15374 : TEST_F(MachineOperatorReducerTest, Uint32LessThanWithWord32Sar) {
1668 1 : Node* const p0 = Parameter(0);
1669 13 : TRACED_FORRANGE(uint32_t, shift, 1, 3) {
1670 3 : const uint32_t limit = (kMaxInt >> shift) - 1;
1671 6 : Node* const node = graph()->NewNode(
1672 : machine()->Uint32LessThan(),
1673 : graph()->NewNode(machine()->Word32Sar(), p0, Uint32Constant(shift)),
1674 : Uint32Constant(limit));
1675 :
1676 3 : Reduction r = Reduce(node);
1677 3 : ASSERT_TRUE(r.Changed());
1678 21 : EXPECT_THAT(r.replacement(),
1679 : IsUint32LessThan(
1680 0 : p0, IsInt32Constant(static_cast<int32_t>(limit << shift))));
1681 : }
1682 : }
1683 :
1684 :
1685 : // -----------------------------------------------------------------------------
1686 : // Float64Mul
1687 :
1688 :
1689 15374 : TEST_F(MachineOperatorReducerTest, Float64MulWithMinusOne) {
1690 1 : Node* const p0 = Parameter(0);
1691 : {
1692 : Reduction r = Reduce(
1693 3 : graph()->NewNode(machine()->Float64Mul(), p0, Float64Constant(-1.0)));
1694 1 : ASSERT_TRUE(r.Changed());
1695 7 : EXPECT_THAT(r.replacement(),
1696 0 : IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1697 : }
1698 : {
1699 : Reduction r = Reduce(
1700 2 : graph()->NewNode(machine()->Float64Mul(), Float64Constant(-1.0), p0));
1701 1 : ASSERT_TRUE(r.Changed());
1702 7 : EXPECT_THAT(r.replacement(),
1703 0 : IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1704 : }
1705 : }
1706 :
1707 15374 : TEST_F(MachineOperatorReducerTest, Float64SubMinusZeroMinusX) {
1708 1 : Node* const p0 = Parameter(0);
1709 : {
1710 : Reduction r = Reduce(
1711 3 : graph()->NewNode(machine()->Float64Sub(), Float64Constant(-0.0), p0));
1712 1 : ASSERT_TRUE(r.Changed());
1713 5 : EXPECT_THAT(r.replacement(), IsFloat64Neg(p0));
1714 : }
1715 : }
1716 :
1717 15374 : TEST_F(MachineOperatorReducerTest, Float32SubMinusZeroMinusX) {
1718 1 : Node* const p0 = Parameter(0);
1719 : {
1720 : Reduction r = Reduce(
1721 3 : graph()->NewNode(machine()->Float32Sub(), Float32Constant(-0.0), p0));
1722 1 : ASSERT_TRUE(r.Changed());
1723 5 : EXPECT_THAT(r.replacement(), IsFloat32Neg(p0));
1724 : }
1725 : }
1726 :
1727 15374 : TEST_F(MachineOperatorReducerTest, Float64MulWithTwo) {
1728 1 : Node* const p0 = Parameter(0);
1729 : {
1730 : Reduction r = Reduce(
1731 3 : graph()->NewNode(machine()->Float64Mul(), Float64Constant(2.0), p0));
1732 1 : ASSERT_TRUE(r.Changed());
1733 6 : EXPECT_THAT(r.replacement(), IsFloat64Add(p0, p0));
1734 : }
1735 : {
1736 : Reduction r = Reduce(
1737 2 : graph()->NewNode(machine()->Float64Mul(), p0, Float64Constant(2.0)));
1738 1 : ASSERT_TRUE(r.Changed());
1739 6 : EXPECT_THAT(r.replacement(), IsFloat64Add(p0, p0));
1740 : }
1741 : }
1742 :
1743 : // -----------------------------------------------------------------------------
1744 : // Float64Div
1745 :
1746 15374 : TEST_F(MachineOperatorReducerTest, Float64DivWithMinusOne) {
1747 1 : Node* const p0 = Parameter(0);
1748 : {
1749 : Reduction r = Reduce(
1750 3 : graph()->NewNode(machine()->Float64Div(), p0, Float64Constant(-1.0)));
1751 1 : ASSERT_TRUE(r.Changed());
1752 5 : EXPECT_THAT(r.replacement(), IsFloat64Neg(p0));
1753 : }
1754 : }
1755 :
1756 15374 : TEST_F(MachineOperatorReducerTest, Float64DivWithPowerOfTwo) {
1757 1 : Node* const p0 = Parameter(0);
1758 8185 : TRACED_FORRANGE(uint64_t, exponent, 1, 0x7FE) {
1759 2046 : Double divisor = Double(exponent << Double::kPhysicalSignificandSize);
1760 2046 : if (divisor.value() == 1.0) continue; // Skip x / 1.0 => x.
1761 : Reduction r = Reduce(graph()->NewNode(machine()->Float64Div(), p0,
1762 6135 : Float64Constant(divisor.value())));
1763 2045 : ASSERT_TRUE(r.Changed());
1764 14315 : EXPECT_THAT(r.replacement(),
1765 0 : IsFloat64Mul(p0, IsFloat64Constant(1.0 / divisor.value())));
1766 : }
1767 : }
1768 :
1769 : // -----------------------------------------------------------------------------
1770 : // Float64Acos
1771 :
1772 15374 : TEST_F(MachineOperatorReducerTest, Float64AcosWithConstant) {
1773 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1774 : Reduction const r =
1775 300 : Reduce(graph()->NewNode(machine()->Float64Acos(), Float64Constant(x)));
1776 100 : ASSERT_TRUE(r.Changed());
1777 600 : EXPECT_THAT(
1778 : r.replacement(),
1779 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::acos(x))));
1780 : }
1781 : }
1782 :
1783 : // -----------------------------------------------------------------------------
1784 : // Float64Acosh
1785 :
1786 15374 : TEST_F(MachineOperatorReducerTest, Float64AcoshWithConstant) {
1787 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1788 : Reduction const r =
1789 300 : Reduce(graph()->NewNode(machine()->Float64Acosh(), Float64Constant(x)));
1790 100 : ASSERT_TRUE(r.Changed());
1791 600 : EXPECT_THAT(
1792 : r.replacement(),
1793 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::acosh(x))));
1794 : }
1795 : }
1796 :
1797 : // -----------------------------------------------------------------------------
1798 : // Float64Asin
1799 :
1800 15374 : TEST_F(MachineOperatorReducerTest, Float64AsinWithConstant) {
1801 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1802 : Reduction const r =
1803 300 : Reduce(graph()->NewNode(machine()->Float64Asin(), Float64Constant(x)));
1804 100 : ASSERT_TRUE(r.Changed());
1805 600 : EXPECT_THAT(
1806 : r.replacement(),
1807 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::asin(x))));
1808 : }
1809 : }
1810 :
1811 : // -----------------------------------------------------------------------------
1812 : // Float64Asinh
1813 :
1814 15374 : TEST_F(MachineOperatorReducerTest, Float64AsinhWithConstant) {
1815 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1816 : Reduction const r =
1817 300 : Reduce(graph()->NewNode(machine()->Float64Asinh(), Float64Constant(x)));
1818 100 : ASSERT_TRUE(r.Changed());
1819 600 : EXPECT_THAT(
1820 : r.replacement(),
1821 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::asinh(x))));
1822 : }
1823 : }
1824 :
1825 : // -----------------------------------------------------------------------------
1826 : // Float64Atan
1827 :
1828 15374 : TEST_F(MachineOperatorReducerTest, Float64AtanWithConstant) {
1829 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1830 : Reduction const r =
1831 300 : Reduce(graph()->NewNode(machine()->Float64Atan(), Float64Constant(x)));
1832 100 : ASSERT_TRUE(r.Changed());
1833 600 : EXPECT_THAT(
1834 : r.replacement(),
1835 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::atan(x))));
1836 : }
1837 : }
1838 :
1839 : // -----------------------------------------------------------------------------
1840 : // Float64Atanh
1841 :
1842 15374 : TEST_F(MachineOperatorReducerTest, Float64AtanhWithConstant) {
1843 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1844 : Reduction const r =
1845 300 : Reduce(graph()->NewNode(machine()->Float64Atanh(), Float64Constant(x)));
1846 100 : ASSERT_TRUE(r.Changed());
1847 600 : EXPECT_THAT(
1848 : r.replacement(),
1849 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::atanh(x))));
1850 : }
1851 : }
1852 :
1853 : // -----------------------------------------------------------------------------
1854 : // Float64Atan2
1855 :
1856 15374 : TEST_F(MachineOperatorReducerTest, Float64Atan2WithConstant) {
1857 401 : TRACED_FOREACH(double, y, kFloat64Values) {
1858 40100 : TRACED_FOREACH(double, x, kFloat64Values) {
1859 : Reduction const r = Reduce(graph()->NewNode(
1860 30000 : machine()->Float64Atan2(), Float64Constant(y), Float64Constant(x)));
1861 10000 : ASSERT_TRUE(r.Changed());
1862 60000 : EXPECT_THAT(
1863 : r.replacement(),
1864 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::atan2(y, x))));
1865 : }
1866 : }
1867 : }
1868 :
1869 15374 : TEST_F(MachineOperatorReducerTest, Float64Atan2WithNaN) {
1870 1 : Node* const p0 = Parameter(0);
1871 1 : Node* const nan = Float64Constant(std::numeric_limits<double>::quiet_NaN());
1872 : {
1873 : Reduction const r =
1874 2 : Reduce(graph()->NewNode(machine()->Float64Atan2(), p0, nan));
1875 1 : ASSERT_TRUE(r.Changed());
1876 2 : EXPECT_EQ(nan, r.replacement());
1877 : }
1878 : {
1879 : Reduction const r =
1880 2 : Reduce(graph()->NewNode(machine()->Float64Atan2(), nan, p0));
1881 1 : ASSERT_TRUE(r.Changed());
1882 2 : EXPECT_EQ(nan, r.replacement());
1883 : }
1884 : }
1885 :
1886 : // -----------------------------------------------------------------------------
1887 : // Float64Cos
1888 :
1889 15374 : TEST_F(MachineOperatorReducerTest, Float64CosWithConstant) {
1890 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1891 : Reduction const r =
1892 300 : Reduce(graph()->NewNode(machine()->Float64Cos(), Float64Constant(x)));
1893 100 : ASSERT_TRUE(r.Changed());
1894 600 : EXPECT_THAT(r.replacement(),
1895 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::cos(x))));
1896 : }
1897 : }
1898 :
1899 : // -----------------------------------------------------------------------------
1900 : // Float64Cosh
1901 :
1902 15374 : TEST_F(MachineOperatorReducerTest, Float64CoshWithConstant) {
1903 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1904 : Reduction const r =
1905 300 : Reduce(graph()->NewNode(machine()->Float64Cosh(), Float64Constant(x)));
1906 100 : ASSERT_TRUE(r.Changed());
1907 600 : EXPECT_THAT(
1908 : r.replacement(),
1909 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::cosh(x))));
1910 : }
1911 : }
1912 :
1913 : // -----------------------------------------------------------------------------
1914 : // Float64Exp
1915 :
1916 15374 : TEST_F(MachineOperatorReducerTest, Float64ExpWithConstant) {
1917 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1918 : Reduction const r =
1919 300 : Reduce(graph()->NewNode(machine()->Float64Exp(), Float64Constant(x)));
1920 100 : ASSERT_TRUE(r.Changed());
1921 600 : EXPECT_THAT(r.replacement(),
1922 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::exp(x))));
1923 : }
1924 : }
1925 :
1926 : // -----------------------------------------------------------------------------
1927 : // Float64Log
1928 :
1929 15374 : TEST_F(MachineOperatorReducerTest, Float64LogWithConstant) {
1930 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1931 : Reduction const r =
1932 300 : Reduce(graph()->NewNode(machine()->Float64Log(), Float64Constant(x)));
1933 100 : ASSERT_TRUE(r.Changed());
1934 600 : EXPECT_THAT(r.replacement(),
1935 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::log(x))));
1936 : }
1937 : }
1938 :
1939 : // -----------------------------------------------------------------------------
1940 : // Float64Log1p
1941 :
1942 15374 : TEST_F(MachineOperatorReducerTest, Float64Log1pWithConstant) {
1943 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1944 : Reduction const r =
1945 300 : Reduce(graph()->NewNode(machine()->Float64Log1p(), Float64Constant(x)));
1946 100 : ASSERT_TRUE(r.Changed());
1947 600 : EXPECT_THAT(
1948 : r.replacement(),
1949 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::log1p(x))));
1950 : }
1951 : }
1952 :
1953 : // -----------------------------------------------------------------------------
1954 : // Float64Pow
1955 :
1956 15374 : TEST_F(MachineOperatorReducerTest, Float64PowWithConstant) {
1957 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1958 40100 : TRACED_FOREACH(double, y, kFloat64Values) {
1959 : Reduction const r = Reduce(graph()->NewNode(
1960 30000 : machine()->Float64Pow(), Float64Constant(x), Float64Constant(y)));
1961 10000 : ASSERT_TRUE(r.Changed());
1962 60000 : EXPECT_THAT(
1963 : r.replacement(),
1964 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::pow(x, y))));
1965 : }
1966 : }
1967 : }
1968 :
1969 15374 : TEST_F(MachineOperatorReducerTest, Float64PowWithZeroExponent) {
1970 1 : Node* const p0 = Parameter(0);
1971 : {
1972 : Reduction const r = Reduce(
1973 3 : graph()->NewNode(machine()->Float64Pow(), p0, Float64Constant(-0.0)));
1974 1 : ASSERT_TRUE(r.Changed());
1975 5 : EXPECT_THAT(r.replacement(), IsFloat64Constant(1.0));
1976 : }
1977 : {
1978 : Reduction const r = Reduce(
1979 2 : graph()->NewNode(machine()->Float64Pow(), p0, Float64Constant(0.0)));
1980 1 : ASSERT_TRUE(r.Changed());
1981 5 : EXPECT_THAT(r.replacement(), IsFloat64Constant(1.0));
1982 : }
1983 : }
1984 :
1985 : // -----------------------------------------------------------------------------
1986 : // Float64Sin
1987 :
1988 15374 : TEST_F(MachineOperatorReducerTest, Float64SinWithConstant) {
1989 401 : TRACED_FOREACH(double, x, kFloat64Values) {
1990 : Reduction const r =
1991 300 : Reduce(graph()->NewNode(machine()->Float64Sin(), Float64Constant(x)));
1992 100 : ASSERT_TRUE(r.Changed());
1993 600 : EXPECT_THAT(r.replacement(),
1994 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::sin(x))));
1995 : }
1996 : }
1997 :
1998 : // -----------------------------------------------------------------------------
1999 : // Float64Sinh
2000 :
2001 15374 : TEST_F(MachineOperatorReducerTest, Float64SinhWithConstant) {
2002 401 : TRACED_FOREACH(double, x, kFloat64Values) {
2003 : Reduction const r =
2004 300 : Reduce(graph()->NewNode(machine()->Float64Sinh(), Float64Constant(x)));
2005 100 : ASSERT_TRUE(r.Changed());
2006 600 : EXPECT_THAT(
2007 : r.replacement(),
2008 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::sinh(x))));
2009 : }
2010 : }
2011 :
2012 : // -----------------------------------------------------------------------------
2013 : // Float64Tan
2014 :
2015 15374 : TEST_F(MachineOperatorReducerTest, Float64TanWithConstant) {
2016 401 : TRACED_FOREACH(double, x, kFloat64Values) {
2017 : Reduction const r =
2018 300 : Reduce(graph()->NewNode(machine()->Float64Tan(), Float64Constant(x)));
2019 100 : ASSERT_TRUE(r.Changed());
2020 600 : EXPECT_THAT(r.replacement(),
2021 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::tan(x))));
2022 : }
2023 : }
2024 :
2025 : // -----------------------------------------------------------------------------
2026 : // Float64Tanh
2027 :
2028 15374 : TEST_F(MachineOperatorReducerTest, Float64TanhWithConstant) {
2029 401 : TRACED_FOREACH(double, x, kFloat64Values) {
2030 : Reduction const r =
2031 300 : Reduce(graph()->NewNode(machine()->Float64Tanh(), Float64Constant(x)));
2032 100 : ASSERT_TRUE(r.Changed());
2033 600 : EXPECT_THAT(
2034 : r.replacement(),
2035 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::tanh(x))));
2036 : }
2037 : }
2038 :
2039 : // -----------------------------------------------------------------------------
2040 : // Float64InsertLowWord32
2041 :
2042 15374 : TEST_F(MachineOperatorReducerTest, Float64InsertLowWord32WithConstant) {
2043 401 : TRACED_FOREACH(double, x, kFloat64Values) {
2044 19300 : TRACED_FOREACH(uint32_t, y, kUint32Values) {
2045 : Reduction const r =
2046 : Reduce(graph()->NewNode(machine()->Float64InsertLowWord32(),
2047 19200 : Float64Constant(x), Uint32Constant(y)));
2048 4800 : ASSERT_TRUE(r.Changed());
2049 24000 : EXPECT_THAT(
2050 : r.replacement(),
2051 : IsFloat64Constant(BitEq(bit_cast<double>(
2052 0 : (bit_cast<uint64_t>(x) & uint64_t{0xFFFFFFFF00000000}) | y))));
2053 : }
2054 : }
2055 : }
2056 :
2057 :
2058 : // -----------------------------------------------------------------------------
2059 : // Float64InsertHighWord32
2060 :
2061 :
2062 15374 : TEST_F(MachineOperatorReducerTest, Float64InsertHighWord32WithConstant) {
2063 401 : TRACED_FOREACH(double, x, kFloat64Values) {
2064 19300 : TRACED_FOREACH(uint32_t, y, kUint32Values) {
2065 : Reduction const r =
2066 : Reduce(graph()->NewNode(machine()->Float64InsertHighWord32(),
2067 19200 : Float64Constant(x), Uint32Constant(y)));
2068 4800 : ASSERT_TRUE(r.Changed());
2069 24000 : EXPECT_THAT(r.replacement(),
2070 : IsFloat64Constant(BitEq(bit_cast<double>(
2071 : (bit_cast<uint64_t>(x) & uint64_t{0xFFFFFFFF}) |
2072 0 : (static_cast<uint64_t>(y) << 32)))));
2073 : }
2074 : }
2075 : }
2076 :
2077 :
2078 : // -----------------------------------------------------------------------------
2079 : // Float64Equal
2080 :
2081 15374 : TEST_F(MachineOperatorReducerTest, Float64EqualWithConstant) {
2082 401 : TRACED_FOREACH(double, x, kFloat64Values) {
2083 40100 : TRACED_FOREACH(double, y, kFloat64Values) {
2084 : Reduction const r = Reduce(graph()->NewNode(
2085 30000 : machine()->Float64Equal(), Float64Constant(x), Float64Constant(y)));
2086 10000 : ASSERT_TRUE(r.Changed());
2087 50000 : EXPECT_THAT(r.replacement(), IsInt32Constant(x == y));
2088 : }
2089 : }
2090 : }
2091 :
2092 15374 : TEST_F(MachineOperatorReducerTest, Float64EqualWithFloat32Conversions) {
2093 1 : Node* const p0 = Parameter(0);
2094 1 : Node* const p1 = Parameter(1);
2095 : Reduction const r = Reduce(graph()->NewNode(
2096 : machine()->Float64Equal(),
2097 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2098 4 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p1)));
2099 1 : ASSERT_TRUE(r.Changed());
2100 6 : EXPECT_THAT(r.replacement(), IsFloat32Equal(p0, p1));
2101 : }
2102 :
2103 :
2104 15374 : TEST_F(MachineOperatorReducerTest, Float64EqualWithFloat32Constant) {
2105 1 : Node* const p0 = Parameter(0);
2106 401 : TRACED_FOREACH(float, x, kFloat32Values) {
2107 : Reduction r = Reduce(graph()->NewNode(
2108 : machine()->Float64Equal(),
2109 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2110 400 : Float64Constant(x)));
2111 100 : ASSERT_TRUE(r.Changed());
2112 700 : EXPECT_THAT(r.replacement(), IsFloat32Equal(p0, IsFloat32Constant(x)));
2113 : }
2114 : }
2115 :
2116 :
2117 : // -----------------------------------------------------------------------------
2118 : // Float64LessThan
2119 :
2120 15374 : TEST_F(MachineOperatorReducerTest, Float64LessThanWithConstant) {
2121 401 : TRACED_FOREACH(double, x, kFloat64Values) {
2122 40100 : TRACED_FOREACH(double, y, kFloat64Values) {
2123 : Reduction const r =
2124 : Reduce(graph()->NewNode(machine()->Float64LessThan(),
2125 30000 : Float64Constant(x), Float64Constant(y)));
2126 10000 : ASSERT_TRUE(r.Changed());
2127 50000 : EXPECT_THAT(r.replacement(), IsInt32Constant(x < y));
2128 : }
2129 : }
2130 : }
2131 :
2132 15374 : TEST_F(MachineOperatorReducerTest, Float64LessThanWithFloat32Conversions) {
2133 1 : Node* const p0 = Parameter(0);
2134 1 : Node* const p1 = Parameter(1);
2135 : Reduction const r = Reduce(graph()->NewNode(
2136 : machine()->Float64LessThan(),
2137 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2138 4 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p1)));
2139 1 : ASSERT_TRUE(r.Changed());
2140 6 : EXPECT_THAT(r.replacement(), IsFloat32LessThan(p0, p1));
2141 : }
2142 :
2143 :
2144 15374 : TEST_F(MachineOperatorReducerTest, Float64LessThanWithFloat32Constant) {
2145 1 : Node* const p0 = Parameter(0);
2146 : {
2147 401 : TRACED_FOREACH(float, x, kFloat32Values) {
2148 : Reduction r = Reduce(graph()->NewNode(
2149 : machine()->Float64LessThan(),
2150 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2151 400 : Float64Constant(x)));
2152 100 : ASSERT_TRUE(r.Changed());
2153 700 : EXPECT_THAT(r.replacement(), IsFloat32LessThan(p0, IsFloat32Constant(x)));
2154 : }
2155 : }
2156 : {
2157 401 : TRACED_FOREACH(float, x, kFloat32Values) {
2158 : Reduction r = Reduce(graph()->NewNode(
2159 : machine()->Float64LessThan(), Float64Constant(x),
2160 300 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0)));
2161 100 : ASSERT_TRUE(r.Changed());
2162 700 : EXPECT_THAT(r.replacement(), IsFloat32LessThan(IsFloat32Constant(x), p0));
2163 : }
2164 : }
2165 : }
2166 :
2167 :
2168 : // -----------------------------------------------------------------------------
2169 : // Float64LessThanOrEqual
2170 :
2171 15374 : TEST_F(MachineOperatorReducerTest, Float64LessThanOrEqualWithConstant) {
2172 401 : TRACED_FOREACH(double, x, kFloat64Values) {
2173 40100 : TRACED_FOREACH(double, y, kFloat64Values) {
2174 : Reduction const r =
2175 : Reduce(graph()->NewNode(machine()->Float64LessThanOrEqual(),
2176 30000 : Float64Constant(x), Float64Constant(y)));
2177 10000 : ASSERT_TRUE(r.Changed());
2178 50000 : EXPECT_THAT(r.replacement(), IsInt32Constant(x <= y));
2179 : }
2180 : }
2181 : }
2182 :
2183 15374 : TEST_F(MachineOperatorReducerTest,
2184 : Float64LessThanOrEqualWithFloat32Conversions) {
2185 1 : Node* const p0 = Parameter(0);
2186 1 : Node* const p1 = Parameter(1);
2187 : Reduction const r = Reduce(graph()->NewNode(
2188 : machine()->Float64LessThanOrEqual(),
2189 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2190 4 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p1)));
2191 1 : ASSERT_TRUE(r.Changed());
2192 6 : EXPECT_THAT(r.replacement(), IsFloat32LessThanOrEqual(p0, p1));
2193 : }
2194 :
2195 :
2196 15374 : TEST_F(MachineOperatorReducerTest, Float64LessThanOrEqualWithFloat32Constant) {
2197 1 : Node* const p0 = Parameter(0);
2198 : {
2199 401 : TRACED_FOREACH(float, x, kFloat32Values) {
2200 : Reduction r = Reduce(graph()->NewNode(
2201 : machine()->Float64LessThanOrEqual(),
2202 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2203 400 : Float64Constant(x)));
2204 100 : ASSERT_TRUE(r.Changed());
2205 700 : EXPECT_THAT(r.replacement(),
2206 0 : IsFloat32LessThanOrEqual(p0, IsFloat32Constant(x)));
2207 : }
2208 : }
2209 : {
2210 401 : TRACED_FOREACH(float, x, kFloat32Values) {
2211 : Reduction r = Reduce(graph()->NewNode(
2212 : machine()->Float64LessThanOrEqual(), Float64Constant(x),
2213 300 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0)));
2214 100 : ASSERT_TRUE(r.Changed());
2215 700 : EXPECT_THAT(r.replacement(),
2216 0 : IsFloat32LessThanOrEqual(IsFloat32Constant(x), p0));
2217 : }
2218 : }
2219 : }
2220 :
2221 :
2222 : // -----------------------------------------------------------------------------
2223 : // Float64RoundDown
2224 :
2225 15374 : TEST_F(MachineOperatorReducerTest, Float64RoundDownWithConstant) {
2226 401 : TRACED_FOREACH(double, x, kFloat64Values) {
2227 : Reduction r = Reduce(graph()->NewNode(
2228 300 : machine()->Float64RoundDown().placeholder(), Float64Constant(x)));
2229 100 : ASSERT_TRUE(r.Changed());
2230 500 : EXPECT_THAT(r.replacement(), IsFloat64Constant(std::floor(x)));
2231 : }
2232 : }
2233 :
2234 : // -----------------------------------------------------------------------------
2235 : // Store
2236 :
2237 15374 : TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32And) {
2238 : const StoreRepresentation rep(MachineRepresentation::kWord8, kNoWriteBarrier);
2239 1 : Node* const base = Parameter(0);
2240 1 : Node* const index = Parameter(1);
2241 1 : Node* const value = Parameter(2);
2242 : Node* const effect = graph()->start();
2243 : Node* const control = graph()->start();
2244 193 : TRACED_FOREACH(uint32_t, x, kUint32Values) {
2245 : Node* const node =
2246 144 : graph()->NewNode(machine()->Store(rep), base, index,
2247 : graph()->NewNode(machine()->Word32And(), value,
2248 : Uint32Constant(x | 0xFFu)),
2249 : effect, control);
2250 :
2251 48 : Reduction r = Reduce(node);
2252 48 : ASSERT_TRUE(r.Changed());
2253 480 : EXPECT_THAT(r.replacement(),
2254 0 : IsStore(rep, base, index, value, effect, control));
2255 : }
2256 : }
2257 :
2258 :
2259 15374 : TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32SarAndWord32Shl) {
2260 : const StoreRepresentation rep(MachineRepresentation::kWord8, kNoWriteBarrier);
2261 1 : Node* const base = Parameter(0);
2262 1 : Node* const index = Parameter(1);
2263 1 : Node* const value = Parameter(2);
2264 : Node* const effect = graph()->start();
2265 : Node* const control = graph()->start();
2266 97 : TRACED_FORRANGE(int32_t, x, 1, 24) {
2267 96 : Node* const node = graph()->NewNode(
2268 : machine()->Store(rep), base, index,
2269 : graph()->NewNode(
2270 : machine()->Word32Sar(),
2271 : graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
2272 : Int32Constant(x)),
2273 : effect, control);
2274 :
2275 24 : Reduction r = Reduce(node);
2276 24 : ASSERT_TRUE(r.Changed());
2277 240 : EXPECT_THAT(r.replacement(),
2278 0 : IsStore(rep, base, index, value, effect, control));
2279 : }
2280 : }
2281 :
2282 :
2283 15374 : TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32And) {
2284 : const StoreRepresentation rep(MachineRepresentation::kWord16,
2285 : kNoWriteBarrier);
2286 1 : Node* const base = Parameter(0);
2287 1 : Node* const index = Parameter(1);
2288 1 : Node* const value = Parameter(2);
2289 : Node* const effect = graph()->start();
2290 : Node* const control = graph()->start();
2291 193 : TRACED_FOREACH(uint32_t, x, kUint32Values) {
2292 : Node* const node =
2293 144 : graph()->NewNode(machine()->Store(rep), base, index,
2294 : graph()->NewNode(machine()->Word32And(), value,
2295 : Uint32Constant(x | 0xFFFFu)),
2296 : effect, control);
2297 :
2298 48 : Reduction r = Reduce(node);
2299 48 : ASSERT_TRUE(r.Changed());
2300 480 : EXPECT_THAT(r.replacement(),
2301 0 : IsStore(rep, base, index, value, effect, control));
2302 : }
2303 : }
2304 :
2305 :
2306 15374 : TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32SarAndWord32Shl) {
2307 : const StoreRepresentation rep(MachineRepresentation::kWord16,
2308 : kNoWriteBarrier);
2309 1 : Node* const base = Parameter(0);
2310 1 : Node* const index = Parameter(1);
2311 1 : Node* const value = Parameter(2);
2312 : Node* const effect = graph()->start();
2313 : Node* const control = graph()->start();
2314 65 : TRACED_FORRANGE(int32_t, x, 1, 16) {
2315 64 : Node* const node = graph()->NewNode(
2316 : machine()->Store(rep), base, index,
2317 : graph()->NewNode(
2318 : machine()->Word32Sar(),
2319 : graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
2320 : Int32Constant(x)),
2321 : effect, control);
2322 :
2323 16 : Reduction r = Reduce(node);
2324 16 : ASSERT_TRUE(r.Changed());
2325 160 : EXPECT_THAT(r.replacement(),
2326 0 : IsStore(rep, base, index, value, effect, control));
2327 : }
2328 : }
2329 :
2330 : } // namespace compiler
2331 : } // namespace internal
2332 9222 : } // namespace v8
|