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