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 180224 : MachineOperatorReducer reducer(&graph_reducer_, &jsgraph);
44 180224 : 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 : 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 : } // namespace
319 :
320 :
321 : // -----------------------------------------------------------------------------
322 : // ChangeFloat64ToFloat32
323 :
324 :
325 15129 : TEST_F(MachineOperatorReducerTest, ChangeFloat64ToFloat32WithConstant) {
326 601 : TRACED_FOREACH(float, x, kFloat32Values) {
327 : Reduction reduction = Reduce(graph()->NewNode(
328 200 : machine()->ChangeFloat32ToFloat64(), Float32Constant(x)));
329 101 : ASSERT_TRUE(reduction.Changed());
330 400 : EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq<double>(x)));
331 100 : }
332 : }
333 :
334 :
335 : // -----------------------------------------------------------------------------
336 : // ChangeFloat64ToInt32
337 :
338 :
339 15129 : TEST_F(MachineOperatorReducerTest,
340 : ChangeFloat64ToInt32WithChangeInt32ToFloat64) {
341 1 : Node* value = Parameter(0);
342 : Reduction reduction = Reduce(graph()->NewNode(
343 : machine()->ChangeFloat64ToInt32(),
344 3 : graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
345 2 : ASSERT_TRUE(reduction.Changed());
346 2 : EXPECT_EQ(value, reduction.replacement());
347 : }
348 :
349 15129 : TEST_F(MachineOperatorReducerTest, ChangeFloat64ToInt32WithConstant) {
350 601 : TRACED_FOREACH(int32_t, x, kInt32Values) {
351 : Reduction reduction = Reduce(graph()->NewNode(
352 200 : machine()->ChangeFloat64ToInt32(), Float64Constant(FastI2D(x))));
353 101 : ASSERT_TRUE(reduction.Changed());
354 400 : EXPECT_THAT(reduction.replacement(), IsInt32Constant(x));
355 100 : }
356 : }
357 :
358 : // -----------------------------------------------------------------------------
359 : // ChangeFloat64ToInt64
360 :
361 15129 : TEST_F(MachineOperatorReducerTest,
362 : ChangeFloat64ToInt64WithChangeInt64ToFloat64) {
363 1 : Node* value = Parameter(0);
364 : Reduction reduction = Reduce(graph()->NewNode(
365 : machine()->ChangeFloat64ToInt64(),
366 3 : graph()->NewNode(machine()->ChangeInt64ToFloat64(), value)));
367 2 : ASSERT_TRUE(reduction.Changed());
368 2 : EXPECT_EQ(value, reduction.replacement());
369 : }
370 :
371 15129 : TEST_F(MachineOperatorReducerTest, ChangeFloat64ToInt64WithConstant) {
372 601 : TRACED_FOREACH(int32_t, x, kInt32Values) {
373 : Reduction reduction = Reduce(graph()->NewNode(
374 200 : machine()->ChangeFloat64ToInt64(), Float64Constant(FastI2D(x))));
375 101 : ASSERT_TRUE(reduction.Changed());
376 400 : EXPECT_THAT(reduction.replacement(), IsInt64Constant(x));
377 100 : }
378 : }
379 :
380 : // -----------------------------------------------------------------------------
381 : // ChangeFloat64ToUint32
382 :
383 :
384 15129 : TEST_F(MachineOperatorReducerTest,
385 : ChangeFloat64ToUint32WithChangeUint32ToFloat64) {
386 1 : Node* value = Parameter(0);
387 : Reduction reduction = Reduce(graph()->NewNode(
388 : machine()->ChangeFloat64ToUint32(),
389 3 : graph()->NewNode(machine()->ChangeUint32ToFloat64(), value)));
390 2 : ASSERT_TRUE(reduction.Changed());
391 2 : EXPECT_EQ(value, reduction.replacement());
392 : }
393 :
394 :
395 15129 : TEST_F(MachineOperatorReducerTest, ChangeFloat64ToUint32WithConstant) {
396 289 : TRACED_FOREACH(uint32_t, x, kUint32Values) {
397 : Reduction reduction = Reduce(graph()->NewNode(
398 96 : machine()->ChangeFloat64ToUint32(), Float64Constant(FastUI2D(x))));
399 49 : ASSERT_TRUE(reduction.Changed());
400 240 : EXPECT_THAT(reduction.replacement(), IsInt32Constant(bit_cast<int32_t>(x)));
401 48 : }
402 : }
403 :
404 :
405 : // -----------------------------------------------------------------------------
406 : // ChangeInt32ToFloat64
407 :
408 :
409 15129 : TEST_F(MachineOperatorReducerTest, ChangeInt32ToFloat64WithConstant) {
410 601 : TRACED_FOREACH(int32_t, x, kInt32Values) {
411 : Reduction reduction = Reduce(
412 200 : graph()->NewNode(machine()->ChangeInt32ToFloat64(), Int32Constant(x)));
413 101 : ASSERT_TRUE(reduction.Changed());
414 500 : EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastI2D(x))));
415 100 : }
416 : }
417 :
418 :
419 : // -----------------------------------------------------------------------------
420 : // ChangeInt32ToInt64
421 :
422 :
423 15129 : TEST_F(MachineOperatorReducerTest, ChangeInt32ToInt64WithConstant) {
424 601 : TRACED_FOREACH(int32_t, x, kInt32Values) {
425 : Reduction reduction = Reduce(
426 200 : graph()->NewNode(machine()->ChangeInt32ToInt64(), Int32Constant(x)));
427 101 : ASSERT_TRUE(reduction.Changed());
428 400 : EXPECT_THAT(reduction.replacement(), IsInt64Constant(x));
429 100 : }
430 : }
431 :
432 : // -----------------------------------------------------------------------------
433 : // ChangeInt64ToFloat64
434 :
435 15129 : TEST_F(MachineOperatorReducerTest,
436 : ChangeInt64ToFloat64WithChangeFloat64ToInt64) {
437 1 : Node* value = Parameter(0);
438 : Reduction reduction = Reduce(graph()->NewNode(
439 : machine()->ChangeInt64ToFloat64(),
440 3 : graph()->NewNode(machine()->ChangeFloat64ToInt64(), value)));
441 2 : ASSERT_TRUE(reduction.Changed());
442 2 : EXPECT_EQ(value, reduction.replacement());
443 : }
444 :
445 15129 : TEST_F(MachineOperatorReducerTest, ChangeInt64ToFloat64WithConstant) {
446 601 : TRACED_FOREACH(int32_t, x, kInt32Values) {
447 : Reduction reduction = Reduce(
448 200 : graph()->NewNode(machine()->ChangeInt64ToFloat64(), Int64Constant(x)));
449 101 : ASSERT_TRUE(reduction.Changed());
450 500 : EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastI2D(x))));
451 100 : }
452 : }
453 :
454 : // -----------------------------------------------------------------------------
455 : // ChangeUint32ToFloat64
456 :
457 :
458 15129 : TEST_F(MachineOperatorReducerTest, ChangeUint32ToFloat64WithConstant) {
459 289 : TRACED_FOREACH(uint32_t, x, kUint32Values) {
460 : Reduction reduction =
461 : Reduce(graph()->NewNode(machine()->ChangeUint32ToFloat64(),
462 96 : Int32Constant(bit_cast<int32_t>(x))));
463 49 : ASSERT_TRUE(reduction.Changed());
464 240 : EXPECT_THAT(reduction.replacement(), IsFloat64Constant(BitEq(FastUI2D(x))));
465 48 : }
466 : }
467 :
468 :
469 : // -----------------------------------------------------------------------------
470 : // ChangeUint32ToUint64
471 :
472 :
473 15129 : TEST_F(MachineOperatorReducerTest, ChangeUint32ToUint64WithConstant) {
474 289 : TRACED_FOREACH(uint32_t, x, kUint32Values) {
475 : Reduction reduction =
476 : Reduce(graph()->NewNode(machine()->ChangeUint32ToUint64(),
477 96 : Int32Constant(bit_cast<int32_t>(x))));
478 49 : ASSERT_TRUE(reduction.Changed());
479 240 : EXPECT_THAT(reduction.replacement(),
480 0 : IsInt64Constant(bit_cast<int64_t>(static_cast<uint64_t>(x))));
481 48 : }
482 : }
483 :
484 :
485 : // -----------------------------------------------------------------------------
486 : // TruncateFloat64ToFloat32
487 :
488 :
489 15129 : TEST_F(MachineOperatorReducerTest,
490 : TruncateFloat64ToFloat32WithChangeFloat32ToFloat64) {
491 1 : Node* value = Parameter(0);
492 : Reduction reduction = Reduce(graph()->NewNode(
493 : machine()->TruncateFloat64ToFloat32(),
494 3 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), value)));
495 2 : ASSERT_TRUE(reduction.Changed());
496 2 : EXPECT_EQ(value, reduction.replacement());
497 : }
498 :
499 :
500 15129 : TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) {
501 601 : TRACED_FOREACH(double, x, kFloat64Values) {
502 : Reduction reduction = Reduce(graph()->NewNode(
503 200 : machine()->TruncateFloat64ToFloat32(), Float64Constant(x)));
504 101 : ASSERT_TRUE(reduction.Changed());
505 500 : EXPECT_THAT(reduction.replacement(),
506 0 : IsFloat32Constant(BitEq(DoubleToFloat32(x))));
507 100 : }
508 : }
509 :
510 :
511 : // -----------------------------------------------------------------------------
512 : // TruncateFloat64ToWord32
513 :
514 15129 : TEST_F(MachineOperatorReducerTest,
515 : TruncateFloat64ToWord32WithChangeInt32ToFloat64) {
516 1 : Node* value = Parameter(0);
517 : Reduction reduction = Reduce(graph()->NewNode(
518 : machine()->TruncateFloat64ToWord32(),
519 3 : graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
520 2 : ASSERT_TRUE(reduction.Changed());
521 2 : EXPECT_EQ(value, reduction.replacement());
522 : }
523 :
524 15129 : TEST_F(MachineOperatorReducerTest, TruncateFloat64ToWord32WithConstant) {
525 601 : TRACED_FOREACH(double, x, kFloat64Values) {
526 : Reduction reduction = Reduce(graph()->NewNode(
527 200 : machine()->TruncateFloat64ToWord32(), Float64Constant(x)));
528 101 : ASSERT_TRUE(reduction.Changed());
529 400 : EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
530 100 : }
531 : }
532 :
533 :
534 : // -----------------------------------------------------------------------------
535 : // TruncateInt64ToInt32
536 :
537 :
538 15129 : TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithChangeInt32ToInt64) {
539 1 : Node* value = Parameter(0);
540 : Reduction reduction = Reduce(graph()->NewNode(
541 : machine()->TruncateInt64ToInt32(),
542 3 : graph()->NewNode(machine()->ChangeInt32ToInt64(), value)));
543 2 : ASSERT_TRUE(reduction.Changed());
544 2 : EXPECT_EQ(value, reduction.replacement());
545 : }
546 :
547 :
548 15129 : TEST_F(MachineOperatorReducerTest, TruncateInt64ToInt32WithConstant) {
549 601 : TRACED_FOREACH(int64_t, x, kInt64Values) {
550 : Reduction reduction = Reduce(
551 200 : graph()->NewNode(machine()->TruncateInt64ToInt32(), Int64Constant(x)));
552 101 : ASSERT_TRUE(reduction.Changed());
553 600 : EXPECT_THAT(reduction.replacement(),
554 : IsInt32Constant(bit_cast<int32_t>(
555 0 : static_cast<uint32_t>(bit_cast<uint64_t>(x)))));
556 100 : }
557 : }
558 :
559 :
560 : // -----------------------------------------------------------------------------
561 : // RoundFloat64ToInt32
562 :
563 15129 : TEST_F(MachineOperatorReducerTest,
564 : RoundFloat64ToInt32WithChangeInt32ToFloat64) {
565 1 : Node* value = Parameter(0);
566 : Reduction reduction = Reduce(graph()->NewNode(
567 : machine()->RoundFloat64ToInt32(),
568 3 : graph()->NewNode(machine()->ChangeInt32ToFloat64(), value)));
569 2 : ASSERT_TRUE(reduction.Changed());
570 2 : EXPECT_EQ(value, reduction.replacement());
571 : }
572 :
573 15129 : TEST_F(MachineOperatorReducerTest, RoundFloat64ToInt32WithConstant) {
574 601 : TRACED_FOREACH(double, x, kFloat64Values) {
575 : Reduction reduction = Reduce(
576 200 : graph()->NewNode(machine()->RoundFloat64ToInt32(), Float64Constant(x)));
577 101 : ASSERT_TRUE(reduction.Changed());
578 400 : EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x)));
579 100 : }
580 : }
581 :
582 : // -----------------------------------------------------------------------------
583 : // Word32And
584 :
585 15129 : TEST_F(MachineOperatorReducerTest, Word32AndWithWord32ShlWithConstant) {
586 1 : Node* const p0 = Parameter(0);
587 :
588 187 : TRACED_FORRANGE(int32_t, l, 1, 31) {
589 3472 : TRACED_FORRANGE(int32_t, k, 1, l) {
590 : // (x << L) & (-1 << K) => x << L
591 : Reduction const r1 = Reduce(graph()->NewNode(
592 : machine()->Word32And(),
593 : graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l)),
594 1488 : Int32Constant(-1 << k)));
595 496 : ASSERT_TRUE(r1.Changed());
596 2976 : EXPECT_THAT(r1.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
597 :
598 : // (-1 << K) & (x << L) => x << L
599 : Reduction const r2 = Reduce(graph()->NewNode(
600 : machine()->Word32And(), Int32Constant(-1 << k),
601 1488 : graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(l))));
602 496 : ASSERT_TRUE(r2.Changed());
603 2976 : EXPECT_THAT(r2.replacement(), IsWord32Shl(p0, IsInt32Constant(l)));
604 496 : }
605 31 : }
606 : }
607 :
608 :
609 15129 : TEST_F(MachineOperatorReducerTest, Word32AndWithWord32AndWithConstant) {
610 1 : Node* const p0 = Parameter(0);
611 :
612 601 : TRACED_FOREACH(int32_t, k, kInt32Values) {
613 70000 : TRACED_FOREACH(int32_t, l, kInt32Values) {
614 10000 : if (k == 0 || k == -1 || l == 0 || l == -1) continue;
615 :
616 : // (x & K) & L => x & (K & L)
617 : Reduction const r1 = Reduce(graph()->NewNode(
618 : machine()->Word32And(),
619 : graph()->NewNode(machine()->Word32And(), p0, Int32Constant(k)),
620 29403 : Int32Constant(l)));
621 9801 : ASSERT_TRUE(r1.Changed());
622 57486 : EXPECT_THAT(r1.replacement(),
623 : (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
624 0 : : IsInt32Constant(0));
625 :
626 : // (K & x) & L => x & (K & L)
627 : Reduction const r2 = Reduce(graph()->NewNode(
628 : machine()->Word32And(),
629 : graph()->NewNode(machine()->Word32And(), Int32Constant(k), p0),
630 29403 : Int32Constant(l)));
631 9801 : ASSERT_TRUE(r2.Changed());
632 57486 : EXPECT_THAT(r2.replacement(),
633 : (k & l) ? IsWord32And(p0, IsInt32Constant(k & l))
634 0 : : IsInt32Constant(0));
635 10000 : }
636 100 : }
637 : }
638 :
639 :
640 15129 : TEST_F(MachineOperatorReducerTest, Word32AndWithInt32AddAndConstant) {
641 1 : Node* const p0 = Parameter(0);
642 1 : Node* const p1 = Parameter(1);
643 :
644 187 : TRACED_FORRANGE(int32_t, l, 1, 31) {
645 21700 : TRACED_FOREACH(int32_t, k, kInt32Values) {
646 3100 : if ((k << l) == 0) continue;
647 : // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
648 : Reduction const r = Reduce(graph()->NewNode(
649 : machine()->Word32And(),
650 : graph()->NewNode(machine()->Int32Add(), p0, Int32Constant(k << l)),
651 8769 : Int32Constant(-1 << l)));
652 2923 : ASSERT_TRUE(r.Changed());
653 26307 : EXPECT_THAT(r.replacement(),
654 : IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
655 0 : IsInt32Constant(k << l)));
656 3100 : }
657 :
658 31 : Node* s1 = graph()->NewNode(machine()->Word32Shl(), p1, Int32Constant(l));
659 :
660 : // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
661 : Reduction const r1 = Reduce(graph()->NewNode(
662 : machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), s1, p0),
663 93 : Int32Constant(-1 << l)));
664 31 : ASSERT_TRUE(r1.Changed());
665 248 : EXPECT_THAT(r1.replacement(),
666 0 : IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)), s1));
667 :
668 : // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
669 : Reduction const r2 = Reduce(graph()->NewNode(
670 : machine()->Word32And(), graph()->NewNode(machine()->Int32Add(), p0, s1),
671 93 : Int32Constant(-1 << l)));
672 31 : ASSERT_TRUE(r2.Changed());
673 248 : EXPECT_THAT(r2.replacement(),
674 0 : IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)), s1));
675 31 : }
676 : }
677 :
678 :
679 15129 : TEST_F(MachineOperatorReducerTest, Word32AndWithInt32MulAndConstant) {
680 1 : Node* const p0 = Parameter(0);
681 :
682 187 : TRACED_FORRANGE(int32_t, l, 1, 31) {
683 21700 : TRACED_FOREACH(int32_t, k, kInt32Values) {
684 3100 : if ((k << l) == 0) continue;
685 :
686 : // (x * (K << L)) & (-1 << L) => x * (K << L)
687 : Reduction const r1 = Reduce(graph()->NewNode(
688 : machine()->Word32And(),
689 : graph()->NewNode(machine()->Int32Mul(), p0, Int32Constant(k << l)),
690 8769 : Int32Constant(-1 << l)));
691 2923 : ASSERT_TRUE(r1.Changed());
692 17538 : EXPECT_THAT(r1.replacement(), IsInt32Mul(p0, IsInt32Constant(k << l)));
693 :
694 : // ((K << L) * x) & (-1 << L) => x * (K << L)
695 : Reduction const r2 = Reduce(graph()->NewNode(
696 : machine()->Word32And(),
697 : graph()->NewNode(machine()->Int32Mul(), Int32Constant(k << l), p0),
698 8769 : Int32Constant(-1 << l)));
699 2923 : ASSERT_TRUE(r2.Changed());
700 17538 : EXPECT_THAT(r2.replacement(), IsInt32Mul(p0, IsInt32Constant(k << l)));
701 3100 : }
702 31 : }
703 : }
704 :
705 :
706 15129 : TEST_F(MachineOperatorReducerTest,
707 : Word32AndWithInt32AddAndInt32MulAndConstant) {
708 1 : Node* const p0 = Parameter(0);
709 1 : Node* const p1 = Parameter(1);
710 :
711 187 : TRACED_FORRANGE(int32_t, l, 1, 31) {
712 21700 : TRACED_FOREACH(int32_t, k, kInt32Values) {
713 3100 : if ((k << l) == 0) continue;
714 : // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
715 : Reduction const r1 = Reduce(graph()->NewNode(
716 : machine()->Word32And(),
717 : graph()->NewNode(machine()->Int32Add(),
718 : graph()->NewNode(machine()->Int32Mul(), p1,
719 : Int32Constant(k << l)),
720 : p0),
721 11692 : Int32Constant(-1 << l)));
722 2923 : ASSERT_TRUE(r1.Changed());
723 32153 : EXPECT_THAT(r1.replacement(),
724 : IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
725 0 : IsInt32Mul(p1, IsInt32Constant(k << l))));
726 :
727 : // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
728 : Reduction const r2 = Reduce(graph()->NewNode(
729 : machine()->Word32And(),
730 : graph()->NewNode(machine()->Int32Add(), p0,
731 : graph()->NewNode(machine()->Int32Mul(), p1,
732 : Int32Constant(k << l))),
733 11692 : Int32Constant(-1 << l)));
734 2923 : ASSERT_TRUE(r2.Changed());
735 32153 : EXPECT_THAT(r2.replacement(),
736 : IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
737 0 : IsInt32Mul(p1, IsInt32Constant(k << l))));
738 3100 : }
739 31 : }
740 : }
741 :
742 :
743 15129 : TEST_F(MachineOperatorReducerTest, Word32AndWithComparisonAndConstantOne) {
744 1 : Node* const p0 = Parameter(0);
745 1 : Node* const p1 = Parameter(1);
746 97 : TRACED_FOREACH(ComparisonBinaryOperator, cbop, kComparisonBinaryOperators) {
747 32 : Node* cmp = graph()->NewNode((machine()->*cbop.constructor)(), p0, p1);
748 :
749 : // cmp & 1 => cmp
750 : Reduction const r1 =
751 32 : Reduce(graph()->NewNode(machine()->Word32And(), cmp, Int32Constant(1)));
752 16 : ASSERT_TRUE(r1.Changed());
753 32 : EXPECT_EQ(cmp, r1.replacement());
754 :
755 : // 1 & cmp => cmp
756 : Reduction const r2 =
757 32 : Reduce(graph()->NewNode(machine()->Word32And(), Int32Constant(1), cmp));
758 16 : ASSERT_TRUE(r2.Changed());
759 32 : EXPECT_EQ(cmp, r2.replacement());
760 16 : }
761 : }
762 :
763 :
764 : // -----------------------------------------------------------------------------
765 : // Word32Xor
766 :
767 :
768 15129 : TEST_F(MachineOperatorReducerTest, Word32XorWithWord32XorAndMinusOne) {
769 1 : Node* const p0 = Parameter(0);
770 :
771 : // (x ^ -1) ^ -1 => x
772 : Reduction r1 = Reduce(graph()->NewNode(
773 : machine()->Word32Xor(),
774 : graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1)),
775 3 : Int32Constant(-1)));
776 1 : ASSERT_TRUE(r1.Changed());
777 2 : EXPECT_EQ(r1.replacement(), p0);
778 :
779 : // -1 ^ (x ^ -1) => x
780 : Reduction r2 = Reduce(graph()->NewNode(
781 : machine()->Word32Xor(), Int32Constant(-1),
782 3 : graph()->NewNode(machine()->Word32Xor(), p0, Int32Constant(-1))));
783 1 : ASSERT_TRUE(r2.Changed());
784 2 : EXPECT_EQ(r2.replacement(), p0);
785 :
786 : // (-1 ^ x) ^ -1 => x
787 : Reduction r3 = Reduce(graph()->NewNode(
788 : machine()->Word32Xor(),
789 : graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0),
790 3 : Int32Constant(-1)));
791 1 : ASSERT_TRUE(r3.Changed());
792 2 : EXPECT_EQ(r3.replacement(), p0);
793 :
794 : // -1 ^ (-1 ^ x) => x
795 : Reduction r4 = Reduce(graph()->NewNode(
796 : machine()->Word32Xor(), Int32Constant(-1),
797 3 : graph()->NewNode(machine()->Word32Xor(), Int32Constant(-1), p0)));
798 1 : ASSERT_TRUE(r4.Changed());
799 2 : EXPECT_EQ(r4.replacement(), p0);
800 : }
801 :
802 :
803 : // -----------------------------------------------------------------------------
804 : // Word32Ror
805 :
806 :
807 15129 : TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithParameters) {
808 1 : Node* value = Parameter(0);
809 1 : Node* shift = Parameter(1);
810 1 : Node* sub = graph()->NewNode(machine()->Int32Sub(), Int32Constant(32), shift);
811 :
812 : // Testing rotate left.
813 1 : Node* shl_l = graph()->NewNode(machine()->Word32Shl(), value, shift);
814 1 : Node* shr_l = graph()->NewNode(machine()->Word32Shr(), value, sub);
815 :
816 : // (x << y) | (x >>> (32 - y)) => x ror (32 - y)
817 2 : Node* node1 = graph()->NewNode(machine()->Word32Or(), shl_l, shr_l);
818 1 : Reduction reduction1 = Reduce(node1);
819 1 : EXPECT_TRUE(reduction1.Changed());
820 2 : EXPECT_EQ(reduction1.replacement(), node1);
821 5 : EXPECT_THAT(reduction1.replacement(), IsWord32Ror(value, sub));
822 :
823 : // (x >>> (32 - y)) | (x << y) => x ror (32 - y)
824 2 : Node* node2 = graph()->NewNode(machine()->Word32Or(), shr_l, shl_l);
825 1 : Reduction reduction2 = Reduce(node2);
826 1 : EXPECT_TRUE(reduction2.Changed());
827 2 : EXPECT_EQ(reduction2.replacement(), node2);
828 5 : EXPECT_THAT(reduction2.replacement(), IsWord32Ror(value, sub));
829 :
830 : // (x << y) ^ (x >>> (32 - y)) => x ror (32 - y)
831 2 : Node* node3 = graph()->NewNode(machine()->Word32Xor(), shl_l, shr_l);
832 1 : Reduction reduction3 = Reduce(node3);
833 1 : EXPECT_TRUE(reduction3.Changed());
834 2 : EXPECT_EQ(reduction3.replacement(), node3);
835 5 : EXPECT_THAT(reduction3.replacement(), IsWord32Ror(value, sub));
836 :
837 : // (x >>> (32 - y)) ^ (x << y) => x ror (32 - y)
838 2 : Node* node4 = graph()->NewNode(machine()->Word32Xor(), shr_l, shl_l);
839 1 : Reduction reduction4 = Reduce(node4);
840 1 : EXPECT_TRUE(reduction4.Changed());
841 2 : EXPECT_EQ(reduction4.replacement(), node4);
842 5 : EXPECT_THAT(reduction4.replacement(), IsWord32Ror(value, sub));
843 :
844 : // Testing rotate right.
845 1 : Node* shl_r = graph()->NewNode(machine()->Word32Shl(), value, sub);
846 1 : Node* shr_r = graph()->NewNode(machine()->Word32Shr(), value, shift);
847 :
848 : // (x << (32 - y)) | (x >>> y) => x ror y
849 2 : Node* node5 = graph()->NewNode(machine()->Word32Or(), shl_r, shr_r);
850 1 : Reduction reduction5 = Reduce(node5);
851 1 : EXPECT_TRUE(reduction5.Changed());
852 2 : EXPECT_EQ(reduction5.replacement(), node5);
853 5 : EXPECT_THAT(reduction5.replacement(), IsWord32Ror(value, shift));
854 :
855 : // (x >>> y) | (x << (32 - y)) => x ror y
856 2 : Node* node6 = graph()->NewNode(machine()->Word32Or(), shr_r, shl_r);
857 1 : Reduction reduction6 = Reduce(node6);
858 1 : EXPECT_TRUE(reduction6.Changed());
859 2 : EXPECT_EQ(reduction6.replacement(), node6);
860 5 : EXPECT_THAT(reduction6.replacement(), IsWord32Ror(value, shift));
861 :
862 : // (x << (32 - y)) ^ (x >>> y) => x ror y
863 2 : Node* node7 = graph()->NewNode(machine()->Word32Xor(), shl_r, shr_r);
864 1 : Reduction reduction7 = Reduce(node7);
865 1 : EXPECT_TRUE(reduction7.Changed());
866 2 : EXPECT_EQ(reduction7.replacement(), node7);
867 5 : EXPECT_THAT(reduction7.replacement(), IsWord32Ror(value, shift));
868 :
869 : // (x >>> y) ^ (x << (32 - y)) => x ror y
870 2 : Node* node8 = graph()->NewNode(machine()->Word32Xor(), shr_r, shl_r);
871 1 : Reduction reduction8 = Reduce(node8);
872 1 : EXPECT_TRUE(reduction8.Changed());
873 2 : EXPECT_EQ(reduction8.replacement(), node8);
874 5 : EXPECT_THAT(reduction8.replacement(), IsWord32Ror(value, shift));
875 1 : }
876 :
877 15129 : TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithConstant) {
878 1 : Node* value = Parameter(0);
879 193 : TRACED_FORRANGE(int32_t, k, 0, 31) {
880 : Node* shl =
881 32 : graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(k));
882 : Node* shr =
883 32 : graph()->NewNode(machine()->Word32Shr(), value, Int32Constant(32 - k));
884 :
885 : // (x << K) | (x >>> ((32 - K) - y)) => x ror (32 - K)
886 64 : Node* node1 = graph()->NewNode(machine()->Word32Or(), shl, shr);
887 32 : Reduction reduction1 = Reduce(node1);
888 32 : EXPECT_TRUE(reduction1.Changed());
889 64 : EXPECT_EQ(reduction1.replacement(), node1);
890 192 : EXPECT_THAT(reduction1.replacement(),
891 0 : IsWord32Ror(value, IsInt32Constant(32 - k)));
892 :
893 : // (x >>> (32 - K)) | (x << K) => x ror (32 - K)
894 64 : Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl);
895 32 : Reduction reduction2 = Reduce(node2);
896 32 : EXPECT_TRUE(reduction2.Changed());
897 64 : EXPECT_EQ(reduction2.replacement(), node2);
898 192 : EXPECT_THAT(reduction2.replacement(),
899 0 : IsWord32Ror(value, IsInt32Constant(32 - k)));
900 32 : }
901 1 : }
902 :
903 :
904 15129 : TEST_F(MachineOperatorReducerTest, Word32RorWithZeroShift) {
905 1 : Node* value = Parameter(0);
906 : Node* node =
907 1 : graph()->NewNode(machine()->Word32Ror(), value, Int32Constant(0));
908 1 : Reduction reduction = Reduce(node);
909 1 : EXPECT_TRUE(reduction.Changed());
910 2 : EXPECT_EQ(reduction.replacement(), value);
911 1 : }
912 :
913 :
914 15129 : TEST_F(MachineOperatorReducerTest, Word32RorWithConstants) {
915 289 : TRACED_FOREACH(int32_t, x, kUint32Values) {
916 10752 : TRACED_FORRANGE(int32_t, y, 0, 31) {
917 : Node* node = graph()->NewNode(machine()->Word32Ror(), Int32Constant(x),
918 1536 : Int32Constant(y));
919 1536 : Reduction reduction = Reduce(node);
920 1536 : EXPECT_TRUE(reduction.Changed());
921 7680 : EXPECT_THAT(reduction.replacement(),
922 0 : IsInt32Constant(base::bits::RotateRight32(x, y)));
923 1536 : }
924 48 : }
925 1 : }
926 :
927 :
928 : // -----------------------------------------------------------------------------
929 : // Word32Sar
930 :
931 :
932 15129 : TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndComparison) {
933 1 : Node* const p0 = Parameter(0);
934 1 : Node* const p1 = Parameter(1);
935 :
936 97 : TRACED_FOREACH(ComparisonBinaryOperator, cbop, kComparisonBinaryOperators) {
937 16 : Node* cmp = graph()->NewNode((machine()->*cbop.constructor)(), p0, p1);
938 :
939 : // cmp << 31 >> 31 => 0 - cmp
940 : Reduction const r = Reduce(graph()->NewNode(
941 : machine()->Word32Sar(),
942 : graph()->NewNode(machine()->Word32Shl(), cmp, Int32Constant(31)),
943 48 : Int32Constant(31)));
944 17 : ASSERT_TRUE(r.Changed());
945 96 : EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0), cmp));
946 16 : }
947 : }
948 :
949 :
950 15129 : TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndLoad) {
951 1 : Node* const p0 = Parameter(0);
952 1 : Node* const p1 = Parameter(1);
953 : {
954 : Node* const l = graph()->NewNode(machine()->Load(MachineType::Int8()), p0,
955 2 : p1, graph()->start(), graph()->start());
956 : Reduction const r = Reduce(graph()->NewNode(
957 : machine()->Word32Sar(),
958 : graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(24)),
959 3 : Int32Constant(24)));
960 1 : ASSERT_TRUE(r.Changed());
961 2 : EXPECT_EQ(l, r.replacement());
962 : }
963 : {
964 : Node* const l = graph()->NewNode(machine()->Load(MachineType::Int16()), p0,
965 2 : p1, graph()->start(), graph()->start());
966 : Reduction const r = Reduce(graph()->NewNode(
967 : machine()->Word32Sar(),
968 : graph()->NewNode(machine()->Word32Shl(), l, Int32Constant(16)),
969 3 : Int32Constant(16)));
970 1 : ASSERT_TRUE(r.Changed());
971 2 : EXPECT_EQ(l, r.replacement());
972 : }
973 : }
974 :
975 :
976 : // -----------------------------------------------------------------------------
977 : // Word32Shr
978 :
979 15129 : TEST_F(MachineOperatorReducerTest, Word32ShrWithWord32And) {
980 1 : Node* const p0 = Parameter(0);
981 187 : TRACED_FORRANGE(int32_t, shift, 1, 31) {
982 : uint32_t mask =
983 : base::SubWithWraparound(base::ShlWithWraparound(1, shift), 1);
984 : Node* node = graph()->NewNode(
985 : machine()->Word32Shr(),
986 : graph()->NewNode(machine()->Word32And(), p0, Int32Constant(mask)),
987 62 : Int32Constant(shift));
988 31 : Reduction r = Reduce(node);
989 32 : ASSERT_TRUE(r.Changed());
990 124 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
991 31 : }
992 : }
993 :
994 : // -----------------------------------------------------------------------------
995 : // Word32Shl
996 :
997 15129 : TEST_F(MachineOperatorReducerTest, Word32ShlWithZeroShift) {
998 1 : Node* p0 = Parameter(0);
999 1 : Node* node = graph()->NewNode(machine()->Word32Shl(), p0, Int32Constant(0));
1000 1 : Reduction r = Reduce(node);
1001 2 : ASSERT_TRUE(r.Changed());
1002 2 : EXPECT_EQ(p0, r.replacement());
1003 : }
1004 :
1005 :
1006 15129 : TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Sar) {
1007 1 : Node* p0 = Parameter(0);
1008 187 : TRACED_FORRANGE(int32_t, x, 1, 31) {
1009 : Node* node = graph()->NewNode(
1010 : machine()->Word32Shl(),
1011 : graph()->NewNode(machine()->Word32Sar(), p0, Int32Constant(x)),
1012 62 : Int32Constant(x));
1013 31 : Reduction r = Reduce(node);
1014 32 : ASSERT_TRUE(r.Changed());
1015 31 : int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
1016 186 : EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
1017 31 : }
1018 : }
1019 :
1020 :
1021 15129 : TEST_F(MachineOperatorReducerTest,
1022 : Word32ShlWithWord32SarAndInt32AddAndConstant) {
1023 1 : Node* const p0 = Parameter(0);
1024 601 : TRACED_FOREACH(int32_t, k, kInt32Values) {
1025 21700 : TRACED_FORRANGE(int32_t, l, 1, 31) {
1026 3100 : if ((k << l) == 0) continue;
1027 : // (x + (K << L)) >> L << L => (x & (-1 << L)) + (K << L)
1028 : Reduction const r = Reduce(graph()->NewNode(
1029 : machine()->Word32Shl(),
1030 : graph()->NewNode(machine()->Word32Sar(),
1031 : graph()->NewNode(machine()->Int32Add(), p0,
1032 : Int32Constant(k << l)),
1033 : Int32Constant(l)),
1034 11692 : Int32Constant(l)));
1035 2924 : ASSERT_TRUE(r.Changed());
1036 26307 : EXPECT_THAT(r.replacement(),
1037 : IsInt32Add(IsWord32And(p0, IsInt32Constant(-1 << l)),
1038 0 : IsInt32Constant(k << l)));
1039 3100 : }
1040 100 : }
1041 : }
1042 :
1043 :
1044 15129 : TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Shr) {
1045 1 : Node* p0 = Parameter(0);
1046 187 : TRACED_FORRANGE(int32_t, x, 1, 31) {
1047 : Node* node = graph()->NewNode(
1048 : machine()->Word32Shl(),
1049 : graph()->NewNode(machine()->Word32Shr(), p0, Int32Constant(x)),
1050 62 : Int32Constant(x));
1051 31 : Reduction r = Reduce(node);
1052 32 : ASSERT_TRUE(r.Changed());
1053 31 : int32_t m = bit_cast<int32_t>(~((1U << x) - 1U));
1054 186 : EXPECT_THAT(r.replacement(), IsWord32And(p0, IsInt32Constant(m)));
1055 31 : }
1056 : }
1057 :
1058 :
1059 : // -----------------------------------------------------------------------------
1060 : // Int32Sub
1061 :
1062 :
1063 15129 : TEST_F(MachineOperatorReducerTest, Int32SubWithConstant) {
1064 1 : Node* const p0 = Parameter(0);
1065 601 : TRACED_FOREACH(int32_t, k, kInt32Values) {
1066 : Reduction const r =
1067 200 : Reduce(graph()->NewNode(machine()->Int32Sub(), p0, Int32Constant(k)));
1068 101 : ASSERT_TRUE(r.Changed());
1069 100 : if (k == 0) {
1070 2 : EXPECT_EQ(p0, r.replacement());
1071 : } else {
1072 693 : EXPECT_THAT(
1073 : r.replacement(),
1074 0 : IsInt32Add(p0, IsInt32Constant(base::NegateWithWraparound(k))));
1075 : }
1076 100 : }
1077 : }
1078 :
1079 :
1080 : // -----------------------------------------------------------------------------
1081 : // Int32Div
1082 :
1083 :
1084 15129 : TEST_F(MachineOperatorReducerTest, Int32DivWithConstant) {
1085 1 : Node* const p0 = Parameter(0);
1086 : {
1087 : Reduction const r = Reduce(graph()->NewNode(
1088 2 : machine()->Int32Div(), p0, Int32Constant(0), graph()->start()));
1089 1 : ASSERT_TRUE(r.Changed());
1090 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1091 : }
1092 : {
1093 : Reduction const r = Reduce(graph()->NewNode(
1094 2 : machine()->Int32Div(), p0, Int32Constant(1), graph()->start()));
1095 1 : ASSERT_TRUE(r.Changed());
1096 2 : EXPECT_EQ(r.replacement(), p0);
1097 : }
1098 : {
1099 : Reduction const r = Reduce(graph()->NewNode(
1100 2 : machine()->Int32Div(), p0, Int32Constant(-1), graph()->start()));
1101 1 : ASSERT_TRUE(r.Changed());
1102 6 : EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0), p0));
1103 : }
1104 : {
1105 : Reduction const r = Reduce(graph()->NewNode(
1106 2 : machine()->Int32Div(), p0, Int32Constant(2), graph()->start()));
1107 1 : ASSERT_TRUE(r.Changed());
1108 11 : EXPECT_THAT(
1109 : r.replacement(),
1110 : IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
1111 0 : IsInt32Constant(1)));
1112 : }
1113 : {
1114 : Reduction const r = Reduce(graph()->NewNode(
1115 2 : machine()->Int32Div(), p0, Int32Constant(-2), graph()->start()));
1116 1 : ASSERT_TRUE(r.Changed());
1117 14 : EXPECT_THAT(
1118 : r.replacement(),
1119 : IsInt32Sub(
1120 : IsInt32Constant(0),
1121 : IsWord32Sar(IsInt32Add(IsWord32Shr(p0, IsInt32Constant(31)), p0),
1122 0 : IsInt32Constant(1))));
1123 : }
1124 175 : TRACED_FORRANGE(int32_t, shift, 2, 30) {
1125 : Reduction const r =
1126 : Reduce(graph()->NewNode(machine()->Int32Div(), p0,
1127 58 : Int32Constant(1 << shift), graph()->start()));
1128 29 : ASSERT_TRUE(r.Changed());
1129 406 : EXPECT_THAT(
1130 : r.replacement(),
1131 : IsWord32Sar(IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
1132 : IsInt32Constant(32 - shift)),
1133 : p0),
1134 0 : IsInt32Constant(shift)));
1135 29 : }
1136 210 : TRACED_FORRANGE(int32_t, shift, 2, 31) {
1137 : Reduction const r = Reduce(graph()->NewNode(
1138 : machine()->Int32Div(), p0,
1139 : Uint32Constant(bit_cast<uint32_t, int32_t>(-1) << shift),
1140 90 : graph()->start()));
1141 30 : ASSERT_TRUE(r.Changed());
1142 510 : EXPECT_THAT(
1143 : r.replacement(),
1144 : IsInt32Sub(
1145 : IsInt32Constant(0),
1146 : IsWord32Sar(
1147 : IsInt32Add(IsWord32Shr(IsWord32Sar(p0, IsInt32Constant(31)),
1148 : IsInt32Constant(32 - shift)),
1149 : p0),
1150 0 : IsInt32Constant(shift))));
1151 30 : }
1152 700 : TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1153 100 : if (divisor < 0) {
1154 97 : if (divisor == kMinInt || base::bits::IsPowerOfTwo(-divisor)) continue;
1155 : Reduction const r = Reduce(graph()->NewNode(
1156 96 : machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
1157 48 : ASSERT_TRUE(r.Changed());
1158 336 : EXPECT_THAT(r.replacement(), IsInt32Sub(IsInt32Constant(0),
1159 0 : IsTruncatingDiv(p0, -divisor)));
1160 51 : } else if (divisor > 0) {
1161 50 : if (base::bits::IsPowerOfTwo(divisor)) continue;
1162 : Reduction const r = Reduce(graph()->NewNode(
1163 98 : machine()->Int32Div(), p0, Int32Constant(divisor), graph()->start()));
1164 49 : ASSERT_TRUE(r.Changed());
1165 196 : EXPECT_THAT(r.replacement(), IsTruncatingDiv(p0, divisor));
1166 : }
1167 100 : }
1168 : }
1169 :
1170 :
1171 15129 : TEST_F(MachineOperatorReducerTest, Int32DivWithParameters) {
1172 1 : Node* const p0 = Parameter(0);
1173 : Reduction const r =
1174 2 : Reduce(graph()->NewNode(machine()->Int32Div(), p0, p0, graph()->start()));
1175 2 : ASSERT_TRUE(r.Changed());
1176 9 : EXPECT_THAT(
1177 : r.replacement(),
1178 0 : IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
1179 : }
1180 :
1181 :
1182 : // -----------------------------------------------------------------------------
1183 : // Uint32Div
1184 :
1185 :
1186 15129 : TEST_F(MachineOperatorReducerTest, Uint32DivWithConstant) {
1187 1 : Node* const p0 = Parameter(0);
1188 : {
1189 : Reduction const r = Reduce(graph()->NewNode(
1190 2 : machine()->Uint32Div(), Int32Constant(0), p0, graph()->start()));
1191 1 : ASSERT_TRUE(r.Changed());
1192 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1193 : }
1194 : {
1195 : Reduction const r = Reduce(graph()->NewNode(
1196 2 : machine()->Uint32Div(), p0, Int32Constant(0), graph()->start()));
1197 1 : ASSERT_TRUE(r.Changed());
1198 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1199 : }
1200 : {
1201 : Reduction const r = Reduce(graph()->NewNode(
1202 2 : machine()->Uint32Div(), p0, Int32Constant(1), graph()->start()));
1203 1 : ASSERT_TRUE(r.Changed());
1204 2 : EXPECT_EQ(r.replacement(), p0);
1205 : }
1206 289 : TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1207 16128 : TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1208 : Reduction const r = Reduce(
1209 : graph()->NewNode(machine()->Uint32Div(), Uint32Constant(dividend),
1210 6912 : Uint32Constant(divisor), graph()->start()));
1211 2304 : ASSERT_TRUE(r.Changed());
1212 11520 : EXPECT_THAT(r.replacement(),
1213 : IsInt32Constant(bit_cast<int32_t>(
1214 0 : base::bits::UnsignedDiv32(dividend, divisor))));
1215 2304 : }
1216 48 : }
1217 217 : TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1218 : Reduction const r =
1219 : Reduce(graph()->NewNode(machine()->Uint32Div(), p0,
1220 93 : Uint32Constant(1u << shift), graph()->start()));
1221 31 : ASSERT_TRUE(r.Changed());
1222 186 : EXPECT_THAT(r.replacement(),
1223 0 : IsWord32Shr(p0, IsInt32Constant(bit_cast<int32_t>(shift))));
1224 31 : }
1225 : }
1226 :
1227 :
1228 15129 : TEST_F(MachineOperatorReducerTest, Uint32DivWithParameters) {
1229 1 : Node* const p0 = Parameter(0);
1230 : Reduction const r = Reduce(
1231 2 : graph()->NewNode(machine()->Uint32Div(), p0, p0, graph()->start()));
1232 2 : ASSERT_TRUE(r.Changed());
1233 9 : EXPECT_THAT(
1234 : r.replacement(),
1235 0 : IsWord32Equal(IsWord32Equal(p0, IsInt32Constant(0)), IsInt32Constant(0)));
1236 : }
1237 :
1238 :
1239 : // -----------------------------------------------------------------------------
1240 : // Int32Mod
1241 :
1242 :
1243 15129 : TEST_F(MachineOperatorReducerTest, Int32ModWithConstant) {
1244 1 : Node* const p0 = Parameter(0);
1245 : {
1246 : Reduction const r = Reduce(graph()->NewNode(
1247 2 : machine()->Int32Mod(), Int32Constant(0), p0, graph()->start()));
1248 1 : ASSERT_TRUE(r.Changed());
1249 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1250 : }
1251 : {
1252 : Reduction const r = Reduce(graph()->NewNode(
1253 2 : machine()->Int32Mod(), p0, Int32Constant(0), graph()->start()));
1254 1 : ASSERT_TRUE(r.Changed());
1255 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1256 : }
1257 : {
1258 : Reduction const r = Reduce(graph()->NewNode(
1259 2 : machine()->Int32Mod(), p0, Int32Constant(1), graph()->start()));
1260 1 : ASSERT_TRUE(r.Changed());
1261 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1262 : }
1263 : {
1264 : Reduction const r = Reduce(graph()->NewNode(
1265 2 : machine()->Int32Mod(), p0, Int32Constant(-1), graph()->start()));
1266 1 : ASSERT_TRUE(r.Changed());
1267 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1268 : }
1269 601 : TRACED_FOREACH(int32_t, dividend, kInt32Values) {
1270 70000 : TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1271 : Reduction const r = Reduce(
1272 : graph()->NewNode(machine()->Int32Mod(), Int32Constant(dividend),
1273 20000 : Int32Constant(divisor), graph()->start()));
1274 10000 : ASSERT_TRUE(r.Changed());
1275 40000 : EXPECT_THAT(r.replacement(),
1276 0 : IsInt32Constant(base::bits::SignedMod32(dividend, divisor)));
1277 10000 : }
1278 100 : }
1279 210 : TRACED_FORRANGE(int32_t, shift, 1, 30) {
1280 : Reduction const r =
1281 : Reduce(graph()->NewNode(machine()->Int32Mod(), p0,
1282 60 : Int32Constant(1 << shift), graph()->start()));
1283 30 : int32_t const mask = (1 << shift) - 1;
1284 30 : ASSERT_TRUE(r.Changed());
1285 990 : EXPECT_THAT(
1286 : r.replacement(),
1287 : IsPhi(
1288 : MachineRepresentation::kWord32,
1289 : IsInt32Sub(IsInt32Constant(0),
1290 : IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1291 : IsInt32Constant(mask))),
1292 : IsWord32And(p0, IsInt32Constant(mask)),
1293 : IsMerge(IsIfTrue(IsBranch(IsInt32LessThan(p0, IsInt32Constant(0)),
1294 : graph()->start())),
1295 : IsIfFalse(IsBranch(IsInt32LessThan(p0, IsInt32Constant(0)),
1296 0 : graph()->start())))));
1297 30 : }
1298 217 : TRACED_FORRANGE(int32_t, shift, 1, 31) {
1299 : Reduction const r = Reduce(graph()->NewNode(
1300 : machine()->Int32Mod(), p0,
1301 : Uint32Constant(bit_cast<uint32_t, int32_t>(-1) << shift),
1302 93 : graph()->start()));
1303 31 : int32_t const mask = bit_cast<int32_t, uint32_t>((1U << shift) - 1);
1304 31 : ASSERT_TRUE(r.Changed());
1305 1023 : EXPECT_THAT(
1306 : r.replacement(),
1307 : IsPhi(
1308 : MachineRepresentation::kWord32,
1309 : IsInt32Sub(IsInt32Constant(0),
1310 : IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
1311 : IsInt32Constant(mask))),
1312 : IsWord32And(p0, IsInt32Constant(mask)),
1313 : IsMerge(IsIfTrue(IsBranch(IsInt32LessThan(p0, IsInt32Constant(0)),
1314 : graph()->start())),
1315 : IsIfFalse(IsBranch(IsInt32LessThan(p0, IsInt32Constant(0)),
1316 0 : graph()->start())))));
1317 31 : }
1318 700 : TRACED_FOREACH(int32_t, divisor, kInt32Values) {
1319 199 : if (divisor == 0 || base::bits::IsPowerOfTwo(Abs(divisor))) continue;
1320 : Reduction const r = Reduce(graph()->NewNode(
1321 194 : machine()->Int32Mod(), p0, Int32Constant(divisor), graph()->start()));
1322 97 : ASSERT_TRUE(r.Changed());
1323 970 : EXPECT_THAT(r.replacement(),
1324 : IsInt32Sub(p0, IsInt32Mul(IsTruncatingDiv(p0, Abs(divisor)),
1325 0 : IsInt32Constant(Abs(divisor)))));
1326 100 : }
1327 : }
1328 :
1329 :
1330 15129 : TEST_F(MachineOperatorReducerTest, Int32ModWithParameters) {
1331 1 : Node* const p0 = Parameter(0);
1332 : Reduction const r =
1333 2 : Reduce(graph()->NewNode(machine()->Int32Mod(), p0, p0, graph()->start()));
1334 2 : ASSERT_TRUE(r.Changed());
1335 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1336 : }
1337 :
1338 :
1339 : // -----------------------------------------------------------------------------
1340 : // Uint32Mod
1341 :
1342 :
1343 15129 : TEST_F(MachineOperatorReducerTest, Uint32ModWithConstant) {
1344 1 : Node* const p0 = Parameter(0);
1345 : {
1346 : Reduction const r = Reduce(graph()->NewNode(
1347 2 : machine()->Uint32Mod(), p0, Int32Constant(0), graph()->start()));
1348 1 : ASSERT_TRUE(r.Changed());
1349 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1350 : }
1351 : {
1352 : Reduction const r = Reduce(graph()->NewNode(
1353 2 : machine()->Uint32Mod(), Int32Constant(0), p0, graph()->start()));
1354 1 : ASSERT_TRUE(r.Changed());
1355 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1356 : }
1357 : {
1358 : Reduction const r = Reduce(graph()->NewNode(
1359 2 : machine()->Uint32Mod(), p0, Int32Constant(1), graph()->start()));
1360 1 : ASSERT_TRUE(r.Changed());
1361 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1362 : }
1363 289 : TRACED_FOREACH(uint32_t, dividend, kUint32Values) {
1364 16128 : TRACED_FOREACH(uint32_t, divisor, kUint32Values) {
1365 : Reduction const r = Reduce(
1366 : graph()->NewNode(machine()->Uint32Mod(), Uint32Constant(dividend),
1367 6912 : Uint32Constant(divisor), graph()->start()));
1368 2304 : ASSERT_TRUE(r.Changed());
1369 11520 : EXPECT_THAT(r.replacement(),
1370 : IsInt32Constant(bit_cast<int32_t>(
1371 0 : base::bits::UnsignedMod32(dividend, divisor))));
1372 2304 : }
1373 48 : }
1374 217 : TRACED_FORRANGE(uint32_t, shift, 1, 31) {
1375 : Reduction const r =
1376 : Reduce(graph()->NewNode(machine()->Uint32Mod(), p0,
1377 93 : Uint32Constant(1u << shift), graph()->start()));
1378 31 : ASSERT_TRUE(r.Changed());
1379 217 : EXPECT_THAT(r.replacement(),
1380 : IsWord32And(p0, IsInt32Constant(
1381 0 : bit_cast<int32_t>((1u << shift) - 1u))));
1382 31 : }
1383 : }
1384 :
1385 :
1386 15129 : TEST_F(MachineOperatorReducerTest, Uint32ModWithParameters) {
1387 1 : Node* const p0 = Parameter(0);
1388 : Reduction const r = Reduce(
1389 2 : graph()->NewNode(machine()->Uint32Mod(), p0, p0, graph()->start()));
1390 2 : ASSERT_TRUE(r.Changed());
1391 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1392 : }
1393 :
1394 :
1395 : // -----------------------------------------------------------------------------
1396 : // Int32Add
1397 :
1398 :
1399 15129 : TEST_F(MachineOperatorReducerTest, Int32AddWithInt32SubWithConstantZero) {
1400 1 : Node* const p0 = Parameter(0);
1401 1 : Node* const p1 = Parameter(1);
1402 :
1403 : Reduction const r1 = Reduce(graph()->NewNode(
1404 : machine()->Int32Add(),
1405 3 : graph()->NewNode(machine()->Int32Sub(), Int32Constant(0), p0), p1));
1406 1 : ASSERT_TRUE(r1.Changed());
1407 5 : EXPECT_THAT(r1.replacement(), IsInt32Sub(p1, p0));
1408 :
1409 : Reduction const r2 = Reduce(graph()->NewNode(
1410 : machine()->Int32Add(), p0,
1411 3 : graph()->NewNode(machine()->Int32Sub(), Int32Constant(0), p1)));
1412 1 : ASSERT_TRUE(r2.Changed());
1413 5 : EXPECT_THAT(r2.replacement(), IsInt32Sub(p0, p1));
1414 : }
1415 :
1416 :
1417 : // -----------------------------------------------------------------------------
1418 : // Int32AddWithOverflow
1419 :
1420 :
1421 15129 : TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithZero) {
1422 1 : Node* control = graph()->start();
1423 1 : Node* p0 = Parameter(0);
1424 : {
1425 : Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1426 1 : Int32Constant(0), p0, control);
1427 :
1428 : Reduction r =
1429 2 : Reduce(graph()->NewNode(common()->Projection(1), add, control));
1430 1 : ASSERT_TRUE(r.Changed());
1431 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1432 :
1433 2 : r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1434 1 : ASSERT_TRUE(r.Changed());
1435 2 : EXPECT_EQ(p0, r.replacement());
1436 : }
1437 : {
1438 : Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), p0,
1439 1 : Int32Constant(0), control);
1440 :
1441 : Reduction r =
1442 2 : Reduce(graph()->NewNode(common()->Projection(1), add, control));
1443 1 : ASSERT_TRUE(r.Changed());
1444 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1445 :
1446 2 : r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1447 1 : ASSERT_TRUE(r.Changed());
1448 2 : EXPECT_EQ(p0, r.replacement());
1449 : }
1450 : }
1451 :
1452 :
1453 15129 : TEST_F(MachineOperatorReducerTest, Int32AddWithOverflowWithConstant) {
1454 1 : Node* control = graph()->start();
1455 601 : TRACED_FOREACH(int32_t, x, kInt32Values) {
1456 70000 : TRACED_FOREACH(int32_t, y, kInt32Values) {
1457 : int32_t z;
1458 : Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(),
1459 10000 : Int32Constant(x), Int32Constant(y), control);
1460 :
1461 : Reduction r =
1462 20000 : Reduce(graph()->NewNode(common()->Projection(1), add, control));
1463 10000 : ASSERT_TRUE(r.Changed());
1464 50000 : EXPECT_THAT(r.replacement(),
1465 0 : IsInt32Constant(base::bits::SignedAddOverflow32(x, y, &z)));
1466 :
1467 20000 : r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1468 10000 : ASSERT_TRUE(r.Changed());
1469 40000 : EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1470 10000 : }
1471 100 : }
1472 : }
1473 :
1474 :
1475 : // -----------------------------------------------------------------------------
1476 : // Int32SubWithOverflow
1477 :
1478 :
1479 15129 : TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithZero) {
1480 1 : Node* control = graph()->start();
1481 1 : Node* p0 = Parameter(0);
1482 : Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(), p0,
1483 1 : Int32Constant(0), control);
1484 :
1485 2 : Reduction r = Reduce(graph()->NewNode(common()->Projection(1), add, control));
1486 1 : ASSERT_TRUE(r.Changed());
1487 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1488 :
1489 2 : r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1490 1 : ASSERT_TRUE(r.Changed());
1491 2 : EXPECT_EQ(p0, r.replacement());
1492 : }
1493 :
1494 :
1495 15129 : TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
1496 1 : Node* control = graph()->start();
1497 601 : TRACED_FOREACH(int32_t, x, kInt32Values) {
1498 70000 : TRACED_FOREACH(int32_t, y, kInt32Values) {
1499 : int32_t z;
1500 : Node* add = graph()->NewNode(machine()->Int32SubWithOverflow(),
1501 10000 : Int32Constant(x), Int32Constant(y), control);
1502 :
1503 : Reduction r =
1504 20000 : Reduce(graph()->NewNode(common()->Projection(1), add, control));
1505 10000 : ASSERT_TRUE(r.Changed());
1506 50000 : EXPECT_THAT(r.replacement(),
1507 0 : IsInt32Constant(base::bits::SignedSubOverflow32(x, y, &z)));
1508 :
1509 20000 : r = Reduce(graph()->NewNode(common()->Projection(0), add, control));
1510 10000 : ASSERT_TRUE(r.Changed());
1511 40000 : EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1512 10000 : }
1513 100 : }
1514 : }
1515 :
1516 :
1517 : // -----------------------------------------------------------------------------
1518 : // Int32MulWithOverflow
1519 :
1520 15129 : TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithZero) {
1521 1 : Node* control = graph()->start();
1522 1 : Node* p0 = Parameter(0);
1523 : {
1524 : Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(),
1525 1 : Int32Constant(0), p0, control);
1526 :
1527 : Reduction r =
1528 2 : Reduce(graph()->NewNode(common()->Projection(1), mul, control));
1529 1 : ASSERT_TRUE(r.Changed());
1530 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1531 :
1532 2 : r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
1533 1 : ASSERT_TRUE(r.Changed());
1534 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1535 : }
1536 : {
1537 : Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
1538 1 : Int32Constant(0), control);
1539 :
1540 : Reduction r =
1541 2 : Reduce(graph()->NewNode(common()->Projection(1), mul, control));
1542 1 : ASSERT_TRUE(r.Changed());
1543 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1544 :
1545 2 : r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
1546 1 : ASSERT_TRUE(r.Changed());
1547 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1548 : }
1549 : }
1550 :
1551 15129 : TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithOne) {
1552 1 : Node* control = graph()->start();
1553 1 : Node* p0 = Parameter(0);
1554 : {
1555 : Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(),
1556 1 : Int32Constant(1), p0, control);
1557 :
1558 : Reduction r =
1559 2 : Reduce(graph()->NewNode(common()->Projection(1), mul, control));
1560 1 : ASSERT_TRUE(r.Changed());
1561 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1562 :
1563 2 : r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
1564 1 : ASSERT_TRUE(r.Changed());
1565 2 : EXPECT_EQ(p0, r.replacement());
1566 : }
1567 : {
1568 : Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
1569 1 : Int32Constant(1), control);
1570 :
1571 : Reduction r =
1572 2 : Reduce(graph()->NewNode(common()->Projection(1), mul, control));
1573 1 : ASSERT_TRUE(r.Changed());
1574 4 : EXPECT_THAT(r.replacement(), IsInt32Constant(0));
1575 :
1576 2 : r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
1577 1 : ASSERT_TRUE(r.Changed());
1578 2 : EXPECT_EQ(p0, r.replacement());
1579 : }
1580 : }
1581 :
1582 15129 : TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithMinusOne) {
1583 1 : Node* control = graph()->start();
1584 1 : Node* p0 = Parameter(0);
1585 :
1586 : {
1587 : Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(),
1588 2 : Int32Constant(-1), p0, control));
1589 1 : ASSERT_TRUE(r.Changed());
1590 6 : EXPECT_THAT(r.replacement(),
1591 0 : IsInt32SubWithOverflow(IsInt32Constant(0), p0));
1592 : }
1593 :
1594 : {
1595 : Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
1596 2 : Int32Constant(-1), control));
1597 1 : ASSERT_TRUE(r.Changed());
1598 6 : EXPECT_THAT(r.replacement(),
1599 0 : IsInt32SubWithOverflow(IsInt32Constant(0), p0));
1600 : }
1601 : }
1602 :
1603 15129 : TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithTwo) {
1604 1 : Node* control = graph()->start();
1605 1 : Node* p0 = Parameter(0);
1606 :
1607 : {
1608 : Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(),
1609 2 : Int32Constant(2), p0, control));
1610 1 : ASSERT_TRUE(r.Changed());
1611 5 : EXPECT_THAT(r.replacement(), IsInt32AddWithOverflow(p0, p0));
1612 : }
1613 :
1614 : {
1615 : Reduction r = Reduce(graph()->NewNode(machine()->Int32MulWithOverflow(), p0,
1616 2 : Int32Constant(2), control));
1617 1 : ASSERT_TRUE(r.Changed());
1618 5 : EXPECT_THAT(r.replacement(), IsInt32AddWithOverflow(p0, p0));
1619 : }
1620 : }
1621 :
1622 15129 : TEST_F(MachineOperatorReducerTest, Int32MulWithOverflowWithConstant) {
1623 1 : Node* control = graph()->start();
1624 601 : TRACED_FOREACH(int32_t, x, kInt32Values) {
1625 70000 : TRACED_FOREACH(int32_t, y, kInt32Values) {
1626 : int32_t z;
1627 : Node* mul = graph()->NewNode(machine()->Int32MulWithOverflow(),
1628 10000 : Int32Constant(x), Int32Constant(y), control);
1629 :
1630 : Reduction r =
1631 20000 : Reduce(graph()->NewNode(common()->Projection(1), mul, control));
1632 10000 : ASSERT_TRUE(r.Changed());
1633 40000 : EXPECT_THAT(r.replacement(),
1634 0 : IsInt32Constant(base::bits::SignedMulOverflow32(x, y, &z)));
1635 :
1636 20000 : r = Reduce(graph()->NewNode(common()->Projection(0), mul, control));
1637 10000 : ASSERT_TRUE(r.Changed());
1638 40000 : EXPECT_THAT(r.replacement(), IsInt32Constant(z));
1639 10000 : }
1640 100 : }
1641 : }
1642 :
1643 : // -----------------------------------------------------------------------------
1644 : // Int32LessThan
1645 :
1646 15129 : TEST_F(MachineOperatorReducerTest, Int32LessThanWithWord32Or) {
1647 1 : Node* const p0 = Parameter(0);
1648 601 : TRACED_FOREACH(int32_t, x, kInt32Values) {
1649 : Node* word32_or =
1650 100 : graph()->NewNode(machine()->Word32Or(), p0, Int32Constant(x));
1651 : Node* less_than = graph()->NewNode(machine()->Int32LessThan(), word32_or,
1652 100 : Int32Constant(0));
1653 100 : Reduction r = Reduce(less_than);
1654 100 : if (x < 0) {
1655 49 : ASSERT_TRUE(r.Changed());
1656 196 : EXPECT_THAT(r.replacement(), IsInt32Constant(1));
1657 : } else {
1658 102 : ASSERT_FALSE(r.Changed());
1659 : }
1660 100 : }
1661 : }
1662 :
1663 : // -----------------------------------------------------------------------------
1664 : // Uint32LessThan
1665 :
1666 15129 : TEST_F(MachineOperatorReducerTest, Uint32LessThanWithWord32Sar) {
1667 1 : Node* const p0 = Parameter(0);
1668 19 : TRACED_FORRANGE(uint32_t, shift, 1, 3) {
1669 3 : const uint32_t limit = (kMaxInt >> shift) - 1;
1670 : Node* const node = graph()->NewNode(
1671 : machine()->Uint32LessThan(),
1672 : graph()->NewNode(machine()->Word32Sar(), p0, Uint32Constant(shift)),
1673 6 : Uint32Constant(limit));
1674 :
1675 3 : Reduction r = Reduce(node);
1676 4 : ASSERT_TRUE(r.Changed());
1677 21 : EXPECT_THAT(r.replacement(),
1678 : IsUint32LessThan(
1679 0 : p0, IsInt32Constant(bit_cast<int32_t>(limit << shift))));
1680 3 : }
1681 : }
1682 :
1683 :
1684 : // -----------------------------------------------------------------------------
1685 : // Float64Mul
1686 :
1687 :
1688 15129 : TEST_F(MachineOperatorReducerTest, Float64MulWithMinusOne) {
1689 1 : Node* const p0 = Parameter(0);
1690 : {
1691 : Reduction r = Reduce(
1692 2 : graph()->NewNode(machine()->Float64Mul(), p0, Float64Constant(-1.0)));
1693 1 : ASSERT_TRUE(r.Changed());
1694 6 : EXPECT_THAT(r.replacement(),
1695 0 : IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1696 : }
1697 : {
1698 : Reduction r = Reduce(
1699 2 : graph()->NewNode(machine()->Float64Mul(), Float64Constant(-1.0), p0));
1700 1 : ASSERT_TRUE(r.Changed());
1701 6 : EXPECT_THAT(r.replacement(),
1702 0 : IsFloat64Sub(IsFloat64Constant(BitEq(-0.0)), p0));
1703 : }
1704 : }
1705 :
1706 15129 : TEST_F(MachineOperatorReducerTest, Float64SubMinusZeroMinusX) {
1707 1 : Node* const p0 = Parameter(0);
1708 : {
1709 : Reduction r = Reduce(
1710 2 : graph()->NewNode(machine()->Float64Sub(), Float64Constant(-0.0), p0));
1711 2 : ASSERT_TRUE(r.Changed());
1712 4 : EXPECT_THAT(r.replacement(), IsFloat64Neg(p0));
1713 : }
1714 : }
1715 :
1716 15129 : TEST_F(MachineOperatorReducerTest, Float32SubMinusZeroMinusX) {
1717 1 : Node* const p0 = Parameter(0);
1718 : {
1719 : Reduction r = Reduce(
1720 2 : graph()->NewNode(machine()->Float32Sub(), Float32Constant(-0.0), p0));
1721 2 : ASSERT_TRUE(r.Changed());
1722 4 : EXPECT_THAT(r.replacement(), IsFloat32Neg(p0));
1723 : }
1724 : }
1725 :
1726 15129 : TEST_F(MachineOperatorReducerTest, Float64MulWithTwo) {
1727 1 : Node* const p0 = Parameter(0);
1728 : {
1729 : Reduction r = Reduce(
1730 2 : graph()->NewNode(machine()->Float64Mul(), Float64Constant(2.0), p0));
1731 1 : ASSERT_TRUE(r.Changed());
1732 5 : EXPECT_THAT(r.replacement(), IsFloat64Add(p0, p0));
1733 : }
1734 : {
1735 : Reduction r = Reduce(
1736 2 : graph()->NewNode(machine()->Float64Mul(), p0, Float64Constant(2.0)));
1737 1 : ASSERT_TRUE(r.Changed());
1738 5 : EXPECT_THAT(r.replacement(), IsFloat64Add(p0, p0));
1739 : }
1740 : }
1741 :
1742 : // -----------------------------------------------------------------------------
1743 : // Float64Div
1744 :
1745 15129 : TEST_F(MachineOperatorReducerTest, Float64DivWithMinusOne) {
1746 1 : Node* const p0 = Parameter(0);
1747 : {
1748 : Reduction r = Reduce(
1749 2 : graph()->NewNode(machine()->Float64Div(), p0, Float64Constant(-1.0)));
1750 2 : ASSERT_TRUE(r.Changed());
1751 4 : EXPECT_THAT(r.replacement(), IsFloat64Neg(p0));
1752 : }
1753 : }
1754 :
1755 15129 : TEST_F(MachineOperatorReducerTest, Float64DivWithPowerOfTwo) {
1756 1 : Node* const p0 = Parameter(0);
1757 12277 : TRACED_FORRANGE(uint64_t, exponent, 1, 0x7FE) {
1758 2046 : Double divisor = Double(exponent << Double::kPhysicalSignificandSize);
1759 2046 : if (divisor.value() == 1.0) continue; // Skip x / 1.0 => x.
1760 : Reduction r = Reduce(graph()->NewNode(machine()->Float64Div(), p0,
1761 4090 : Float64Constant(divisor.value())));
1762 2046 : ASSERT_TRUE(r.Changed());
1763 12270 : EXPECT_THAT(r.replacement(),
1764 0 : IsFloat64Mul(p0, IsFloat64Constant(1.0 / divisor.value())));
1765 2046 : }
1766 : }
1767 :
1768 : // -----------------------------------------------------------------------------
1769 : // Float64Acos
1770 :
1771 15129 : TEST_F(MachineOperatorReducerTest, Float64AcosWithConstant) {
1772 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1773 : Reduction const r =
1774 200 : Reduce(graph()->NewNode(machine()->Float64Acos(), Float64Constant(x)));
1775 101 : ASSERT_TRUE(r.Changed());
1776 500 : EXPECT_THAT(
1777 : r.replacement(),
1778 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::acos(x))));
1779 100 : }
1780 : }
1781 :
1782 : // -----------------------------------------------------------------------------
1783 : // Float64Acosh
1784 :
1785 15129 : TEST_F(MachineOperatorReducerTest, Float64AcoshWithConstant) {
1786 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1787 : Reduction const r =
1788 200 : Reduce(graph()->NewNode(machine()->Float64Acosh(), Float64Constant(x)));
1789 101 : ASSERT_TRUE(r.Changed());
1790 500 : EXPECT_THAT(
1791 : r.replacement(),
1792 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::acosh(x))));
1793 100 : }
1794 : }
1795 :
1796 : // -----------------------------------------------------------------------------
1797 : // Float64Asin
1798 :
1799 15129 : TEST_F(MachineOperatorReducerTest, Float64AsinWithConstant) {
1800 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1801 : Reduction const r =
1802 200 : Reduce(graph()->NewNode(machine()->Float64Asin(), Float64Constant(x)));
1803 101 : ASSERT_TRUE(r.Changed());
1804 500 : EXPECT_THAT(
1805 : r.replacement(),
1806 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::asin(x))));
1807 100 : }
1808 : }
1809 :
1810 : // -----------------------------------------------------------------------------
1811 : // Float64Asinh
1812 :
1813 15129 : TEST_F(MachineOperatorReducerTest, Float64AsinhWithConstant) {
1814 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1815 : Reduction const r =
1816 200 : Reduce(graph()->NewNode(machine()->Float64Asinh(), Float64Constant(x)));
1817 101 : ASSERT_TRUE(r.Changed());
1818 500 : EXPECT_THAT(
1819 : r.replacement(),
1820 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::asinh(x))));
1821 100 : }
1822 : }
1823 :
1824 : // -----------------------------------------------------------------------------
1825 : // Float64Atan
1826 :
1827 15129 : TEST_F(MachineOperatorReducerTest, Float64AtanWithConstant) {
1828 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1829 : Reduction const r =
1830 200 : Reduce(graph()->NewNode(machine()->Float64Atan(), Float64Constant(x)));
1831 101 : ASSERT_TRUE(r.Changed());
1832 500 : EXPECT_THAT(
1833 : r.replacement(),
1834 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::atan(x))));
1835 100 : }
1836 : }
1837 :
1838 : // -----------------------------------------------------------------------------
1839 : // Float64Atanh
1840 :
1841 15129 : TEST_F(MachineOperatorReducerTest, Float64AtanhWithConstant) {
1842 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1843 : Reduction const r =
1844 200 : Reduce(graph()->NewNode(machine()->Float64Atanh(), Float64Constant(x)));
1845 101 : ASSERT_TRUE(r.Changed());
1846 500 : EXPECT_THAT(
1847 : r.replacement(),
1848 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::atanh(x))));
1849 100 : }
1850 : }
1851 :
1852 : // -----------------------------------------------------------------------------
1853 : // Float64Atan2
1854 :
1855 15129 : TEST_F(MachineOperatorReducerTest, Float64Atan2WithConstant) {
1856 601 : TRACED_FOREACH(double, y, kFloat64Values) {
1857 70000 : TRACED_FOREACH(double, x, kFloat64Values) {
1858 : Reduction const r = Reduce(graph()->NewNode(
1859 20000 : machine()->Float64Atan2(), Float64Constant(y), Float64Constant(x)));
1860 10001 : ASSERT_TRUE(r.Changed());
1861 50000 : EXPECT_THAT(
1862 : r.replacement(),
1863 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::atan2(y, x))));
1864 10000 : }
1865 100 : }
1866 : }
1867 :
1868 15129 : TEST_F(MachineOperatorReducerTest, Float64Atan2WithNaN) {
1869 1 : Node* const p0 = Parameter(0);
1870 1 : Node* const nan = Float64Constant(std::numeric_limits<double>::quiet_NaN());
1871 : {
1872 : Reduction const r =
1873 2 : Reduce(graph()->NewNode(machine()->Float64Atan2(), p0, nan));
1874 1 : ASSERT_TRUE(r.Changed());
1875 2 : EXPECT_EQ(nan, r.replacement());
1876 : }
1877 : {
1878 : Reduction const r =
1879 2 : Reduce(graph()->NewNode(machine()->Float64Atan2(), nan, p0));
1880 1 : ASSERT_TRUE(r.Changed());
1881 2 : EXPECT_EQ(nan, r.replacement());
1882 : }
1883 : }
1884 :
1885 : // -----------------------------------------------------------------------------
1886 : // Float64Cos
1887 :
1888 15129 : TEST_F(MachineOperatorReducerTest, Float64CosWithConstant) {
1889 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1890 : Reduction const r =
1891 200 : Reduce(graph()->NewNode(machine()->Float64Cos(), Float64Constant(x)));
1892 101 : ASSERT_TRUE(r.Changed());
1893 500 : EXPECT_THAT(r.replacement(),
1894 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::cos(x))));
1895 100 : }
1896 : }
1897 :
1898 : // -----------------------------------------------------------------------------
1899 : // Float64Cosh
1900 :
1901 15129 : TEST_F(MachineOperatorReducerTest, Float64CoshWithConstant) {
1902 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1903 : Reduction const r =
1904 200 : Reduce(graph()->NewNode(machine()->Float64Cosh(), Float64Constant(x)));
1905 101 : ASSERT_TRUE(r.Changed());
1906 500 : EXPECT_THAT(
1907 : r.replacement(),
1908 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::cosh(x))));
1909 100 : }
1910 : }
1911 :
1912 : // -----------------------------------------------------------------------------
1913 : // Float64Exp
1914 :
1915 15129 : TEST_F(MachineOperatorReducerTest, Float64ExpWithConstant) {
1916 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1917 : Reduction const r =
1918 200 : Reduce(graph()->NewNode(machine()->Float64Exp(), Float64Constant(x)));
1919 101 : ASSERT_TRUE(r.Changed());
1920 500 : EXPECT_THAT(r.replacement(),
1921 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::exp(x))));
1922 100 : }
1923 : }
1924 :
1925 : // -----------------------------------------------------------------------------
1926 : // Float64Log
1927 :
1928 15129 : TEST_F(MachineOperatorReducerTest, Float64LogWithConstant) {
1929 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1930 : Reduction const r =
1931 200 : Reduce(graph()->NewNode(machine()->Float64Log(), Float64Constant(x)));
1932 101 : ASSERT_TRUE(r.Changed());
1933 500 : EXPECT_THAT(r.replacement(),
1934 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::log(x))));
1935 100 : }
1936 : }
1937 :
1938 : // -----------------------------------------------------------------------------
1939 : // Float64Log1p
1940 :
1941 15129 : TEST_F(MachineOperatorReducerTest, Float64Log1pWithConstant) {
1942 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1943 : Reduction const r =
1944 200 : Reduce(graph()->NewNode(machine()->Float64Log1p(), Float64Constant(x)));
1945 101 : ASSERT_TRUE(r.Changed());
1946 500 : EXPECT_THAT(
1947 : r.replacement(),
1948 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::log1p(x))));
1949 100 : }
1950 : }
1951 :
1952 : // -----------------------------------------------------------------------------
1953 : // Float64Pow
1954 :
1955 15129 : TEST_F(MachineOperatorReducerTest, Float64PowWithConstant) {
1956 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1957 70000 : TRACED_FOREACH(double, y, kFloat64Values) {
1958 : Reduction const r = Reduce(graph()->NewNode(
1959 20000 : machine()->Float64Pow(), Float64Constant(x), Float64Constant(y)));
1960 10001 : ASSERT_TRUE(r.Changed());
1961 50000 : EXPECT_THAT(r.replacement(),
1962 0 : IsFloat64Constant(NanSensitiveDoubleEq(Pow(x, y))));
1963 10000 : }
1964 100 : }
1965 : }
1966 :
1967 15129 : TEST_F(MachineOperatorReducerTest, Float64PowWithZeroExponent) {
1968 1 : Node* const p0 = Parameter(0);
1969 : {
1970 : Reduction const r = Reduce(
1971 2 : graph()->NewNode(machine()->Float64Pow(), p0, Float64Constant(-0.0)));
1972 1 : ASSERT_TRUE(r.Changed());
1973 4 : EXPECT_THAT(r.replacement(), IsFloat64Constant(1.0));
1974 : }
1975 : {
1976 : Reduction const r = Reduce(
1977 2 : graph()->NewNode(machine()->Float64Pow(), p0, Float64Constant(0.0)));
1978 1 : ASSERT_TRUE(r.Changed());
1979 4 : EXPECT_THAT(r.replacement(), IsFloat64Constant(1.0));
1980 : }
1981 : }
1982 :
1983 : // -----------------------------------------------------------------------------
1984 : // Float64Sin
1985 :
1986 15129 : TEST_F(MachineOperatorReducerTest, Float64SinWithConstant) {
1987 601 : TRACED_FOREACH(double, x, kFloat64Values) {
1988 : Reduction const r =
1989 200 : Reduce(graph()->NewNode(machine()->Float64Sin(), Float64Constant(x)));
1990 101 : ASSERT_TRUE(r.Changed());
1991 500 : EXPECT_THAT(r.replacement(),
1992 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::sin(x))));
1993 100 : }
1994 : }
1995 :
1996 : // -----------------------------------------------------------------------------
1997 : // Float64Sinh
1998 :
1999 15129 : TEST_F(MachineOperatorReducerTest, Float64SinhWithConstant) {
2000 601 : TRACED_FOREACH(double, x, kFloat64Values) {
2001 : Reduction const r =
2002 200 : Reduce(graph()->NewNode(machine()->Float64Sinh(), Float64Constant(x)));
2003 101 : ASSERT_TRUE(r.Changed());
2004 500 : EXPECT_THAT(
2005 : r.replacement(),
2006 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::sinh(x))));
2007 100 : }
2008 : }
2009 :
2010 : // -----------------------------------------------------------------------------
2011 : // Float64Tan
2012 :
2013 15129 : TEST_F(MachineOperatorReducerTest, Float64TanWithConstant) {
2014 601 : TRACED_FOREACH(double, x, kFloat64Values) {
2015 : Reduction const r =
2016 200 : Reduce(graph()->NewNode(machine()->Float64Tan(), Float64Constant(x)));
2017 101 : ASSERT_TRUE(r.Changed());
2018 500 : EXPECT_THAT(r.replacement(),
2019 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::tan(x))));
2020 100 : }
2021 : }
2022 :
2023 : // -----------------------------------------------------------------------------
2024 : // Float64Tanh
2025 :
2026 15129 : TEST_F(MachineOperatorReducerTest, Float64TanhWithConstant) {
2027 601 : TRACED_FOREACH(double, x, kFloat64Values) {
2028 : Reduction const r =
2029 200 : Reduce(graph()->NewNode(machine()->Float64Tanh(), Float64Constant(x)));
2030 101 : ASSERT_TRUE(r.Changed());
2031 500 : EXPECT_THAT(
2032 : r.replacement(),
2033 0 : IsFloat64Constant(NanSensitiveDoubleEq(base::ieee754::tanh(x))));
2034 100 : }
2035 : }
2036 :
2037 : // -----------------------------------------------------------------------------
2038 : // Float64InsertLowWord32
2039 :
2040 15129 : TEST_F(MachineOperatorReducerTest, Float64InsertLowWord32WithConstant) {
2041 601 : TRACED_FOREACH(double, x, kFloat64Values) {
2042 33600 : TRACED_FOREACH(uint32_t, y, kUint32Values) {
2043 : Reduction const r =
2044 : Reduce(graph()->NewNode(machine()->Float64InsertLowWord32(),
2045 14400 : Float64Constant(x), Uint32Constant(y)));
2046 4801 : ASSERT_TRUE(r.Changed());
2047 28800 : EXPECT_THAT(
2048 : r.replacement(),
2049 : IsFloat64Constant(BitEq(bit_cast<double>(
2050 0 : (bit_cast<uint64_t>(x) & uint64_t{0xFFFFFFFF00000000}) | y))));
2051 4800 : }
2052 100 : }
2053 : }
2054 :
2055 :
2056 : // -----------------------------------------------------------------------------
2057 : // Float64InsertHighWord32
2058 :
2059 :
2060 15129 : TEST_F(MachineOperatorReducerTest, Float64InsertHighWord32WithConstant) {
2061 601 : TRACED_FOREACH(double, x, kFloat64Values) {
2062 33600 : TRACED_FOREACH(uint32_t, y, kUint32Values) {
2063 : Reduction const r =
2064 : Reduce(graph()->NewNode(machine()->Float64InsertHighWord32(),
2065 14400 : Float64Constant(x), Uint32Constant(y)));
2066 4801 : ASSERT_TRUE(r.Changed());
2067 28800 : EXPECT_THAT(r.replacement(),
2068 : IsFloat64Constant(BitEq(bit_cast<double>(
2069 : (bit_cast<uint64_t>(x) & uint64_t{0xFFFFFFFF}) |
2070 0 : (static_cast<uint64_t>(y) << 32)))));
2071 4800 : }
2072 100 : }
2073 : }
2074 :
2075 :
2076 : // -----------------------------------------------------------------------------
2077 : // Float64Equal
2078 :
2079 15129 : TEST_F(MachineOperatorReducerTest, Float64EqualWithConstant) {
2080 601 : TRACED_FOREACH(double, x, kFloat64Values) {
2081 70000 : TRACED_FOREACH(double, y, kFloat64Values) {
2082 : Reduction const r = Reduce(graph()->NewNode(
2083 20000 : machine()->Float64Equal(), Float64Constant(x), Float64Constant(y)));
2084 10001 : ASSERT_TRUE(r.Changed());
2085 40000 : EXPECT_THAT(r.replacement(), IsInt32Constant(x == y));
2086 10000 : }
2087 100 : }
2088 : }
2089 :
2090 15129 : TEST_F(MachineOperatorReducerTest, Float64EqualWithFloat32Conversions) {
2091 1 : Node* const p0 = Parameter(0);
2092 1 : Node* const p1 = Parameter(1);
2093 : Reduction const r = Reduce(graph()->NewNode(
2094 : machine()->Float64Equal(),
2095 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2096 4 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p1)));
2097 2 : ASSERT_TRUE(r.Changed());
2098 5 : EXPECT_THAT(r.replacement(), IsFloat32Equal(p0, p1));
2099 : }
2100 :
2101 :
2102 15129 : TEST_F(MachineOperatorReducerTest, Float64EqualWithFloat32Constant) {
2103 1 : Node* const p0 = Parameter(0);
2104 601 : TRACED_FOREACH(float, x, kFloat32Values) {
2105 : Reduction r = Reduce(graph()->NewNode(
2106 : machine()->Float64Equal(),
2107 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2108 300 : Float64Constant(x)));
2109 101 : ASSERT_TRUE(r.Changed());
2110 600 : EXPECT_THAT(r.replacement(), IsFloat32Equal(p0, IsFloat32Constant(x)));
2111 100 : }
2112 : }
2113 :
2114 :
2115 : // -----------------------------------------------------------------------------
2116 : // Float64LessThan
2117 :
2118 15129 : TEST_F(MachineOperatorReducerTest, Float64LessThanWithConstant) {
2119 601 : TRACED_FOREACH(double, x, kFloat64Values) {
2120 70000 : TRACED_FOREACH(double, y, kFloat64Values) {
2121 : Reduction const r =
2122 : Reduce(graph()->NewNode(machine()->Float64LessThan(),
2123 20000 : Float64Constant(x), Float64Constant(y)));
2124 10001 : ASSERT_TRUE(r.Changed());
2125 40000 : EXPECT_THAT(r.replacement(), IsInt32Constant(x < y));
2126 10000 : }
2127 100 : }
2128 : }
2129 :
2130 15129 : TEST_F(MachineOperatorReducerTest, Float64LessThanWithFloat32Conversions) {
2131 1 : Node* const p0 = Parameter(0);
2132 1 : Node* const p1 = Parameter(1);
2133 : Reduction const r = Reduce(graph()->NewNode(
2134 : machine()->Float64LessThan(),
2135 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2136 4 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p1)));
2137 2 : ASSERT_TRUE(r.Changed());
2138 5 : EXPECT_THAT(r.replacement(), IsFloat32LessThan(p0, p1));
2139 : }
2140 :
2141 :
2142 15129 : TEST_F(MachineOperatorReducerTest, Float64LessThanWithFloat32Constant) {
2143 1 : Node* const p0 = Parameter(0);
2144 : {
2145 601 : TRACED_FOREACH(float, x, kFloat32Values) {
2146 : Reduction r = Reduce(graph()->NewNode(
2147 : machine()->Float64LessThan(),
2148 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2149 300 : Float64Constant(x)));
2150 100 : ASSERT_TRUE(r.Changed());
2151 600 : EXPECT_THAT(r.replacement(), IsFloat32LessThan(p0, IsFloat32Constant(x)));
2152 100 : }
2153 : }
2154 : {
2155 700 : TRACED_FOREACH(float, x, kFloat32Values) {
2156 : Reduction r = Reduce(graph()->NewNode(
2157 : machine()->Float64LessThan(), Float64Constant(x),
2158 300 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0)));
2159 100 : ASSERT_TRUE(r.Changed());
2160 600 : EXPECT_THAT(r.replacement(), IsFloat32LessThan(IsFloat32Constant(x), p0));
2161 100 : }
2162 : }
2163 : }
2164 :
2165 :
2166 : // -----------------------------------------------------------------------------
2167 : // Float64LessThanOrEqual
2168 :
2169 15129 : TEST_F(MachineOperatorReducerTest, Float64LessThanOrEqualWithConstant) {
2170 601 : TRACED_FOREACH(double, x, kFloat64Values) {
2171 70000 : TRACED_FOREACH(double, y, kFloat64Values) {
2172 : Reduction const r =
2173 : Reduce(graph()->NewNode(machine()->Float64LessThanOrEqual(),
2174 20000 : Float64Constant(x), Float64Constant(y)));
2175 10001 : ASSERT_TRUE(r.Changed());
2176 40000 : EXPECT_THAT(r.replacement(), IsInt32Constant(x <= y));
2177 10000 : }
2178 100 : }
2179 : }
2180 :
2181 15129 : TEST_F(MachineOperatorReducerTest,
2182 : Float64LessThanOrEqualWithFloat32Conversions) {
2183 1 : Node* const p0 = Parameter(0);
2184 1 : Node* const p1 = Parameter(1);
2185 : Reduction const r = Reduce(graph()->NewNode(
2186 : machine()->Float64LessThanOrEqual(),
2187 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2188 4 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p1)));
2189 2 : ASSERT_TRUE(r.Changed());
2190 5 : EXPECT_THAT(r.replacement(), IsFloat32LessThanOrEqual(p0, p1));
2191 : }
2192 :
2193 :
2194 15129 : TEST_F(MachineOperatorReducerTest, Float64LessThanOrEqualWithFloat32Constant) {
2195 1 : Node* const p0 = Parameter(0);
2196 : {
2197 601 : TRACED_FOREACH(float, x, kFloat32Values) {
2198 : Reduction r = Reduce(graph()->NewNode(
2199 : machine()->Float64LessThanOrEqual(),
2200 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
2201 300 : Float64Constant(x)));
2202 100 : ASSERT_TRUE(r.Changed());
2203 600 : EXPECT_THAT(r.replacement(),
2204 0 : IsFloat32LessThanOrEqual(p0, IsFloat32Constant(x)));
2205 100 : }
2206 : }
2207 : {
2208 700 : TRACED_FOREACH(float, x, kFloat32Values) {
2209 : Reduction r = Reduce(graph()->NewNode(
2210 : machine()->Float64LessThanOrEqual(), Float64Constant(x),
2211 300 : graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0)));
2212 100 : ASSERT_TRUE(r.Changed());
2213 600 : EXPECT_THAT(r.replacement(),
2214 0 : IsFloat32LessThanOrEqual(IsFloat32Constant(x), p0));
2215 100 : }
2216 : }
2217 : }
2218 :
2219 :
2220 : // -----------------------------------------------------------------------------
2221 : // Float64RoundDown
2222 :
2223 15129 : TEST_F(MachineOperatorReducerTest, Float64RoundDownWithConstant) {
2224 601 : TRACED_FOREACH(double, x, kFloat64Values) {
2225 : Reduction r = Reduce(graph()->NewNode(
2226 200 : machine()->Float64RoundDown().placeholder(), Float64Constant(x)));
2227 101 : ASSERT_TRUE(r.Changed());
2228 500 : EXPECT_THAT(r.replacement(), IsFloat64Constant(Floor(x)));
2229 100 : }
2230 : }
2231 :
2232 : // -----------------------------------------------------------------------------
2233 : // Store
2234 :
2235 15129 : TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32And) {
2236 : const StoreRepresentation rep(MachineRepresentation::kWord8, kNoWriteBarrier);
2237 1 : Node* const base = Parameter(0);
2238 1 : Node* const index = Parameter(1);
2239 1 : Node* const value = Parameter(2);
2240 1 : Node* const effect = graph()->start();
2241 : Node* const control = graph()->start();
2242 289 : TRACED_FOREACH(uint32_t, x, kUint32Values) {
2243 : Node* const node =
2244 : graph()->NewNode(machine()->Store(rep), base, index,
2245 : graph()->NewNode(machine()->Word32And(), value,
2246 : Uint32Constant(x | 0xFFu)),
2247 144 : effect, control);
2248 :
2249 48 : Reduction r = Reduce(node);
2250 49 : ASSERT_TRUE(r.Changed());
2251 432 : EXPECT_THAT(r.replacement(),
2252 0 : IsStore(rep, base, index, value, effect, control));
2253 48 : }
2254 : }
2255 :
2256 :
2257 15129 : TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32SarAndWord32Shl) {
2258 : const StoreRepresentation rep(MachineRepresentation::kWord8, kNoWriteBarrier);
2259 1 : Node* const base = Parameter(0);
2260 1 : Node* const index = Parameter(1);
2261 1 : Node* const value = Parameter(2);
2262 1 : Node* const effect = graph()->start();
2263 : Node* const control = graph()->start();
2264 145 : TRACED_FORRANGE(int32_t, x, 1, 24) {
2265 : Node* const node = graph()->NewNode(
2266 : machine()->Store(rep), base, index,
2267 : graph()->NewNode(
2268 : machine()->Word32Sar(),
2269 : graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
2270 : Int32Constant(x)),
2271 72 : effect, control);
2272 :
2273 24 : Reduction r = Reduce(node);
2274 25 : ASSERT_TRUE(r.Changed());
2275 216 : EXPECT_THAT(r.replacement(),
2276 0 : IsStore(rep, base, index, value, effect, control));
2277 24 : }
2278 : }
2279 :
2280 :
2281 15129 : TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32And) {
2282 : const StoreRepresentation rep(MachineRepresentation::kWord16,
2283 : kNoWriteBarrier);
2284 1 : Node* const base = Parameter(0);
2285 1 : Node* const index = Parameter(1);
2286 1 : Node* const value = Parameter(2);
2287 1 : Node* const effect = graph()->start();
2288 : Node* const control = graph()->start();
2289 289 : TRACED_FOREACH(uint32_t, x, kUint32Values) {
2290 : Node* const node =
2291 : graph()->NewNode(machine()->Store(rep), base, index,
2292 : graph()->NewNode(machine()->Word32And(), value,
2293 : Uint32Constant(x | 0xFFFFu)),
2294 144 : effect, control);
2295 :
2296 48 : Reduction r = Reduce(node);
2297 49 : ASSERT_TRUE(r.Changed());
2298 432 : EXPECT_THAT(r.replacement(),
2299 0 : IsStore(rep, base, index, value, effect, control));
2300 48 : }
2301 : }
2302 :
2303 :
2304 15129 : TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32SarAndWord32Shl) {
2305 : const StoreRepresentation rep(MachineRepresentation::kWord16,
2306 : kNoWriteBarrier);
2307 1 : Node* const base = Parameter(0);
2308 1 : Node* const index = Parameter(1);
2309 1 : Node* const value = Parameter(2);
2310 1 : Node* const effect = graph()->start();
2311 : Node* const control = graph()->start();
2312 97 : TRACED_FORRANGE(int32_t, x, 1, 16) {
2313 : Node* const node = graph()->NewNode(
2314 : machine()->Store(rep), base, index,
2315 : graph()->NewNode(
2316 : machine()->Word32Sar(),
2317 : graph()->NewNode(machine()->Word32Shl(), value, Int32Constant(x)),
2318 : Int32Constant(x)),
2319 48 : effect, control);
2320 :
2321 16 : Reduction r = Reduce(node);
2322 17 : ASSERT_TRUE(r.Changed());
2323 144 : EXPECT_THAT(r.replacement(),
2324 0 : IsStore(rep, base, index, value, effect, control));
2325 16 : }
2326 : }
2327 :
2328 : } // namespace compiler
2329 : } // namespace internal
2330 9075 : } // namespace v8
|