Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / v8 / test / cctest / compiler / test-machine-operator-reducer.cc
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 "test/cctest/cctest.h"
6
7 #include "src/base/utils/random-number-generator.h"
8 #include "src/codegen.h"
9 #include "src/compiler/graph-inl.h"
10 #include "src/compiler/js-graph.h"
11 #include "src/compiler/machine-operator-reducer.h"
12 #include "src/compiler/operator-properties.h"
13 #include "src/compiler/operator-properties-inl.h"
14 #include "src/compiler/typer.h"
15 #include "test/cctest/compiler/value-helper.h"
16
17 using namespace v8::internal;
18 using namespace v8::internal::compiler;
19
20 template <typename T>
21 const Operator* NewConstantOperator(CommonOperatorBuilder* common,
22                                     volatile T value);
23
24 template <>
25 const Operator* NewConstantOperator<int32_t>(CommonOperatorBuilder* common,
26                                              volatile int32_t value) {
27   return common->Int32Constant(value);
28 }
29
30 template <>
31 const Operator* NewConstantOperator<double>(CommonOperatorBuilder* common,
32                                             volatile double value) {
33   return common->Float64Constant(value);
34 }
35
36
37 template <typename T>
38 T ValueOfOperator(const Operator* op);
39
40 template <>
41 int32_t ValueOfOperator<int32_t>(const Operator* op) {
42   CHECK_EQ(IrOpcode::kInt32Constant, op->opcode());
43   return OpParameter<int32_t>(op);
44 }
45
46 template <>
47 double ValueOfOperator<double>(const Operator* op) {
48   CHECK_EQ(IrOpcode::kFloat64Constant, op->opcode());
49   return OpParameter<double>(op);
50 }
51
52
53 class ReducerTester : public HandleAndZoneScope {
54  public:
55   explicit ReducerTester(int num_parameters = 0)
56       : isolate(main_isolate()),
57         binop(NULL),
58         unop(NULL),
59         common(main_zone()),
60         graph(main_zone()),
61         javascript(main_zone()),
62         typer(&graph, MaybeHandle<Context>()),
63         jsgraph(&graph, &common, &javascript, &machine),
64         maxuint32(Constant<int32_t>(kMaxUInt32)) {
65     Node* s = graph.NewNode(common.Start(num_parameters));
66     graph.SetStart(s);
67   }
68
69   Isolate* isolate;
70   const Operator* binop;
71   const Operator* unop;
72   MachineOperatorBuilder machine;
73   CommonOperatorBuilder common;
74   Graph graph;
75   JSOperatorBuilder javascript;
76   Typer typer;
77   JSGraph jsgraph;
78   Node* maxuint32;
79
80   template <typename T>
81   Node* Constant(volatile T value) {
82     return graph.NewNode(NewConstantOperator<T>(&common, value));
83   }
84
85   template <typename T>
86   const T ValueOf(const Operator* op) {
87     return ValueOfOperator<T>(op);
88   }
89
90   // Check that the reduction of this binop applied to constants {a} and {b}
91   // yields the {expect} value.
92   template <typename T>
93   void CheckFoldBinop(volatile T expect, volatile T a, volatile T b) {
94     CheckFoldBinop<T>(expect, Constant<T>(a), Constant<T>(b));
95   }
96
97   // Check that the reduction of this binop applied to {a} and {b} yields
98   // the {expect} value.
99   template <typename T>
100   void CheckFoldBinop(volatile T expect, Node* a, Node* b) {
101     CHECK_NE(NULL, binop);
102     Node* n = CreateBinopNode(a, b);
103     MachineOperatorReducer reducer(&jsgraph);
104     Reduction reduction = reducer.Reduce(n);
105     CHECK(reduction.Changed());
106     CHECK_NE(n, reduction.replacement());
107     CHECK_EQ(expect, ValueOf<T>(reduction.replacement()->op()));
108   }
109
110   // Check that the reduction of this binop applied to {a} and {b} yields
111   // the {expect} node.
112   void CheckBinop(Node* expect, Node* a, Node* b) {
113     CHECK_NE(NULL, binop);
114     Node* n = CreateBinopNode(a, b);
115     MachineOperatorReducer reducer(&jsgraph);
116     Reduction reduction = reducer.Reduce(n);
117     CHECK(reduction.Changed());
118     CHECK_EQ(expect, reduction.replacement());
119   }
120
121   // Check that the reduction of this binop applied to {left} and {right} yields
122   // this binop applied to {left_expect} and {right_expect}.
123   void CheckFoldBinop(Node* left_expect, Node* right_expect, Node* left,
124                       Node* right) {
125     CHECK_NE(NULL, binop);
126     Node* n = CreateBinopNode(left, right);
127     MachineOperatorReducer reducer(&jsgraph);
128     Reduction reduction = reducer.Reduce(n);
129     CHECK(reduction.Changed());
130     CHECK_EQ(binop, reduction.replacement()->op());
131     CHECK_EQ(left_expect, reduction.replacement()->InputAt(0));
132     CHECK_EQ(right_expect, reduction.replacement()->InputAt(1));
133   }
134
135   // Check that the reduction of this binop applied to {left} and {right} yields
136   // the {op_expect} applied to {left_expect} and {right_expect}.
137   template <typename T>
138   void CheckFoldBinop(volatile T left_expect, const Operator* op_expect,
139                       Node* right_expect, Node* left, Node* right) {
140     CHECK_NE(NULL, binop);
141     Node* n = CreateBinopNode(left, right);
142     MachineOperatorReducer reducer(&jsgraph);
143     Reduction r = reducer.Reduce(n);
144     CHECK(r.Changed());
145     CHECK_EQ(op_expect->opcode(), r.replacement()->op()->opcode());
146     CHECK_EQ(left_expect, ValueOf<T>(r.replacement()->InputAt(0)->op()));
147     CHECK_EQ(right_expect, r.replacement()->InputAt(1));
148   }
149
150   // Check that the reduction of this binop applied to {left} and {right} yields
151   // the {op_expect} applied to {left_expect} and {right_expect}.
152   template <typename T>
153   void CheckFoldBinop(Node* left_expect, const Operator* op_expect,
154                       volatile T right_expect, Node* left, Node* right) {
155     CHECK_NE(NULL, binop);
156     Node* n = CreateBinopNode(left, right);
157     MachineOperatorReducer reducer(&jsgraph);
158     Reduction r = reducer.Reduce(n);
159     CHECK(r.Changed());
160     CHECK_EQ(op_expect->opcode(), r.replacement()->op()->opcode());
161     CHECK_EQ(OperatorProperties::GetTotalInputCount(op_expect),
162              r.replacement()->InputCount());
163     CHECK_EQ(left_expect, r.replacement()->InputAt(0));
164     CHECK_EQ(right_expect, ValueOf<T>(r.replacement()->InputAt(1)->op()));
165   }
166
167   // Check that if the given constant appears on the left, the reducer will
168   // swap it to be on the right.
169   template <typename T>
170   void CheckPutConstantOnRight(volatile T constant) {
171     // TODO(titzer): CHECK(binop->HasProperty(Operator::kCommutative));
172     Node* p = Parameter();
173     Node* k = Constant<T>(constant);
174     {
175       Node* n = CreateBinopNode(k, p);
176       MachineOperatorReducer reducer(&jsgraph);
177       Reduction reduction = reducer.Reduce(n);
178       CHECK(!reduction.Changed() || reduction.replacement() == n);
179       CHECK_EQ(p, n->InputAt(0));
180       CHECK_EQ(k, n->InputAt(1));
181     }
182     {
183       Node* n = CreateBinopNode(p, k);
184       MachineOperatorReducer reducer(&jsgraph);
185       Reduction reduction = reducer.Reduce(n);
186       CHECK(!reduction.Changed());
187       CHECK_EQ(p, n->InputAt(0));
188       CHECK_EQ(k, n->InputAt(1));
189     }
190   }
191
192   // Check that if the given constant appears on the left, the reducer will
193   // *NOT* swap it to be on the right.
194   template <typename T>
195   void CheckDontPutConstantOnRight(volatile T constant) {
196     CHECK(!binop->HasProperty(Operator::kCommutative));
197     Node* p = Parameter();
198     Node* k = Constant<T>(constant);
199     Node* n = CreateBinopNode(k, p);
200     MachineOperatorReducer reducer(&jsgraph);
201     Reduction reduction = reducer.Reduce(n);
202     CHECK(!reduction.Changed());
203     CHECK_EQ(k, n->InputAt(0));
204     CHECK_EQ(p, n->InputAt(1));
205   }
206
207   Node* Parameter(int32_t index = 0) {
208     return graph.NewNode(common.Parameter(index), graph.start());
209   }
210
211  private:
212   Node* CreateBinopNode(Node* left, Node* right) {
213     if (binop->ControlInputCount() > 0) {
214       return graph.NewNode(binop, left, right, graph.start());
215     } else {
216       return graph.NewNode(binop, left, right);
217     }
218   }
219 };
220
221
222 TEST(ReduceWord32And) {
223   ReducerTester R;
224   R.binop = R.machine.Word32And();
225
226   FOR_INT32_INPUTS(pl) {
227     FOR_INT32_INPUTS(pr) {
228       int32_t x = *pl, y = *pr;
229       R.CheckFoldBinop<int32_t>(x & y, x, y);
230     }
231   }
232
233   R.CheckPutConstantOnRight(33);
234   R.CheckPutConstantOnRight(44000);
235
236   Node* x = R.Parameter();
237   Node* zero = R.Constant<int32_t>(0);
238   Node* minus_1 = R.Constant<int32_t>(-1);
239
240   R.CheckBinop(zero, x, zero);  // x  & 0  => 0
241   R.CheckBinop(zero, zero, x);  // 0  & x  => 0
242   R.CheckBinop(x, x, minus_1);  // x  & -1 => 0
243   R.CheckBinop(x, minus_1, x);  // -1 & x  => 0
244   R.CheckBinop(x, x, x);        // x  & x  => x
245 }
246
247
248 TEST(ReduceWord32Or) {
249   ReducerTester R;
250   R.binop = R.machine.Word32Or();
251
252   FOR_INT32_INPUTS(pl) {
253     FOR_INT32_INPUTS(pr) {
254       int32_t x = *pl, y = *pr;
255       R.CheckFoldBinop<int32_t>(x | y, x, y);
256     }
257   }
258
259   R.CheckPutConstantOnRight(36);
260   R.CheckPutConstantOnRight(44001);
261
262   Node* x = R.Parameter();
263   Node* zero = R.Constant<int32_t>(0);
264   Node* minus_1 = R.Constant<int32_t>(-1);
265
266   R.CheckBinop(x, x, zero);           // x  & 0  => x
267   R.CheckBinop(x, zero, x);           // 0  & x  => x
268   R.CheckBinop(minus_1, x, minus_1);  // x  & -1 => -1
269   R.CheckBinop(minus_1, minus_1, x);  // -1 & x  => -1
270   R.CheckBinop(x, x, x);              // x  & x  => x
271 }
272
273
274 TEST(ReduceWord32Xor) {
275   ReducerTester R;
276   R.binop = R.machine.Word32Xor();
277
278   FOR_INT32_INPUTS(pl) {
279     FOR_INT32_INPUTS(pr) {
280       int32_t x = *pl, y = *pr;
281       R.CheckFoldBinop<int32_t>(x ^ y, x, y);
282     }
283   }
284
285   R.CheckPutConstantOnRight(39);
286   R.CheckPutConstantOnRight(4403);
287
288   Node* x = R.Parameter();
289   Node* zero = R.Constant<int32_t>(0);
290
291   R.CheckBinop(x, x, zero);            // x ^ 0  => x
292   R.CheckBinop(x, zero, x);            // 0 ^ x  => x
293   R.CheckFoldBinop<int32_t>(0, x, x);  // x ^ x  => 0
294 }
295
296
297 TEST(ReduceWord32Shl) {
298   ReducerTester R;
299   R.binop = R.machine.Word32Shl();
300
301   // TODO(titzer): out of range shifts
302   FOR_INT32_INPUTS(i) {
303     for (int y = 0; y < 32; y++) {
304       int32_t x = *i;
305       R.CheckFoldBinop<int32_t>(x << y, x, y);
306     }
307   }
308
309   R.CheckDontPutConstantOnRight(44);
310
311   Node* x = R.Parameter();
312   Node* zero = R.Constant<int32_t>(0);
313
314   R.CheckBinop(x, x, zero);  // x << 0  => x
315 }
316
317
318 TEST(ReduceWord32Shr) {
319   ReducerTester R;
320   R.binop = R.machine.Word32Shr();
321
322   // TODO(titzer): test out of range shifts
323   FOR_UINT32_INPUTS(i) {
324     for (uint32_t y = 0; y < 32; y++) {
325       uint32_t x = *i;
326       R.CheckFoldBinop<int32_t>(x >> y, x, y);
327     }
328   }
329
330   R.CheckDontPutConstantOnRight(44);
331
332   Node* x = R.Parameter();
333   Node* zero = R.Constant<int32_t>(0);
334
335   R.CheckBinop(x, x, zero);  // x >>> 0  => x
336 }
337
338
339 TEST(ReduceWord32Sar) {
340   ReducerTester R;
341   R.binop = R.machine.Word32Sar();
342
343   // TODO(titzer): test out of range shifts
344   FOR_INT32_INPUTS(i) {
345     for (int32_t y = 0; y < 32; y++) {
346       int32_t x = *i;
347       R.CheckFoldBinop<int32_t>(x >> y, x, y);
348     }
349   }
350
351   R.CheckDontPutConstantOnRight(44);
352
353   Node* x = R.Parameter();
354   Node* zero = R.Constant<int32_t>(0);
355
356   R.CheckBinop(x, x, zero);  // x >> 0  => x
357 }
358
359
360 TEST(ReduceWord32Equal) {
361   ReducerTester R;
362   R.binop = R.machine.Word32Equal();
363
364   FOR_INT32_INPUTS(pl) {
365     FOR_INT32_INPUTS(pr) {
366       int32_t x = *pl, y = *pr;
367       R.CheckFoldBinop<int32_t>(x == y ? 1 : 0, x, y);
368     }
369   }
370
371   R.CheckPutConstantOnRight(48);
372   R.CheckPutConstantOnRight(-48);
373
374   Node* x = R.Parameter(0);
375   Node* y = R.Parameter(1);
376   Node* zero = R.Constant<int32_t>(0);
377   Node* sub = R.graph.NewNode(R.machine.Int32Sub(), x, y);
378
379   R.CheckFoldBinop<int32_t>(1, x, x);  // x == x  => 1
380   R.CheckFoldBinop(x, y, sub, zero);   // x - y == 0  => x == y
381   R.CheckFoldBinop(x, y, zero, sub);   // 0 == x - y  => x == y
382 }
383
384
385 TEST(ReduceInt32Add) {
386   ReducerTester R;
387   R.binop = R.machine.Int32Add();
388
389   FOR_INT32_INPUTS(pl) {
390     FOR_INT32_INPUTS(pr) {
391       int32_t x = *pl, y = *pr;
392       R.CheckFoldBinop<int32_t>(x + y, x, y);  // TODO(titzer): signed overflow
393     }
394   }
395
396   R.CheckPutConstantOnRight(41);
397   R.CheckPutConstantOnRight(4407);
398
399   Node* x = R.Parameter();
400   Node* zero = R.Constant<int32_t>(0);
401
402   R.CheckBinop(x, x, zero);  // x + 0  => x
403   R.CheckBinop(x, zero, x);  // 0 + x  => x
404 }
405
406
407 TEST(ReduceInt32Sub) {
408   ReducerTester R;
409   R.binop = R.machine.Int32Sub();
410
411   FOR_INT32_INPUTS(pl) {
412     FOR_INT32_INPUTS(pr) {
413       int32_t x = *pl, y = *pr;
414       R.CheckFoldBinop<int32_t>(x - y, x, y);
415     }
416   }
417
418   R.CheckDontPutConstantOnRight(412);
419
420   Node* x = R.Parameter();
421   Node* zero = R.Constant<int32_t>(0);
422
423   R.CheckBinop(x, x, zero);  // x - 0  => x
424 }
425
426
427 TEST(ReduceInt32Mul) {
428   ReducerTester R;
429   R.binop = R.machine.Int32Mul();
430
431   FOR_INT32_INPUTS(pl) {
432     FOR_INT32_INPUTS(pr) {
433       int32_t x = *pl, y = *pr;
434       R.CheckFoldBinop<int32_t>(x * y, x, y);  // TODO(titzer): signed overflow
435     }
436   }
437
438   R.CheckPutConstantOnRight(4111);
439   R.CheckPutConstantOnRight(-4407);
440
441   Node* x = R.Parameter();
442   Node* zero = R.Constant<int32_t>(0);
443   Node* one = R.Constant<int32_t>(1);
444   Node* minus_one = R.Constant<int32_t>(-1);
445
446   R.CheckBinop(zero, x, zero);  // x * 0  => 0
447   R.CheckBinop(zero, zero, x);  // 0 * x  => 0
448   R.CheckBinop(x, x, one);      // x * 1  => x
449   R.CheckBinop(x, one, x);      // 1 * x  => x
450   R.CheckFoldBinop<int32_t>(0, R.machine.Int32Sub(), x, minus_one,
451                             x);  // -1 * x  => 0 - x
452   R.CheckFoldBinop<int32_t>(0, R.machine.Int32Sub(), x, x,
453                             minus_one);  // x * -1  => 0 - x
454
455   for (int32_t n = 1; n < 31; ++n) {
456     Node* multiplier = R.Constant<int32_t>(1 << n);
457     R.CheckFoldBinop<int32_t>(x, R.machine.Word32Shl(), n, x,
458                               multiplier);  // x * 2^n => x << n
459     R.CheckFoldBinop<int32_t>(x, R.machine.Word32Shl(), n, multiplier,
460                               x);  // 2^n * x => x << n
461   }
462 }
463
464
465 TEST(ReduceInt32Div) {
466   ReducerTester R;
467   R.binop = R.machine.Int32Div();
468
469   FOR_INT32_INPUTS(pl) {
470     FOR_INT32_INPUTS(pr) {
471       int32_t x = *pl, y = *pr;
472       if (y == 0) continue;              // TODO(titzer): test / 0
473       int32_t r = y == -1 ? -x : x / y;  // INT_MIN / -1 may explode in C
474       R.CheckFoldBinop<int32_t>(r, x, y);
475     }
476   }
477
478   R.CheckDontPutConstantOnRight(41111);
479   R.CheckDontPutConstantOnRight(-44071);
480
481   Node* x = R.Parameter();
482   Node* one = R.Constant<int32_t>(1);
483   Node* minus_one = R.Constant<int32_t>(-1);
484
485   R.CheckBinop(x, x, one);  // x / 1  => x
486   // TODO(titzer):                          // 0 / x  => 0 if x != 0
487   // TODO(titzer):                          // x / 2^n => x >> n and round
488   R.CheckFoldBinop<int32_t>(0, R.machine.Int32Sub(), x, x,
489                             minus_one);  // x / -1  => 0 - x
490 }
491
492
493 TEST(ReduceUint32Div) {
494   ReducerTester R;
495   R.binop = R.machine.Uint32Div();
496
497   FOR_UINT32_INPUTS(pl) {
498     FOR_UINT32_INPUTS(pr) {
499       uint32_t x = *pl, y = *pr;
500       if (y == 0) continue;  // TODO(titzer): test / 0
501       R.CheckFoldBinop<int32_t>(x / y, x, y);
502     }
503   }
504
505   R.CheckDontPutConstantOnRight(41311);
506   R.CheckDontPutConstantOnRight(-44371);
507
508   Node* x = R.Parameter();
509   Node* one = R.Constant<int32_t>(1);
510
511   R.CheckBinop(x, x, one);  // x / 1  => x
512   // TODO(titzer):                            // 0 / x  => 0 if x != 0
513
514   for (uint32_t n = 1; n < 32; ++n) {
515     Node* divisor = R.Constant<int32_t>(1u << n);
516     R.CheckFoldBinop<int32_t>(x, R.machine.Word32Shr(), n, x,
517                               divisor);  // x / 2^n => x >> n
518   }
519 }
520
521
522 TEST(ReduceInt32Mod) {
523   ReducerTester R;
524   R.binop = R.machine.Int32Mod();
525
526   FOR_INT32_INPUTS(pl) {
527     FOR_INT32_INPUTS(pr) {
528       int32_t x = *pl, y = *pr;
529       if (y == 0) continue;             // TODO(titzer): test % 0
530       int32_t r = y == -1 ? 0 : x % y;  // INT_MIN % -1 may explode in C
531       R.CheckFoldBinop<int32_t>(r, x, y);
532     }
533   }
534
535   R.CheckDontPutConstantOnRight(413);
536   R.CheckDontPutConstantOnRight(-4401);
537
538   Node* x = R.Parameter();
539   Node* one = R.Constant<int32_t>(1);
540
541   R.CheckFoldBinop<int32_t>(0, x, one);  // x % 1  => 0
542   // TODO(titzer):                       // x % 2^n => x & 2^n-1 and round
543 }
544
545
546 TEST(ReduceUint32Mod) {
547   ReducerTester R;
548   R.binop = R.machine.Uint32Mod();
549
550   FOR_INT32_INPUTS(pl) {
551     FOR_INT32_INPUTS(pr) {
552       uint32_t x = *pl, y = *pr;
553       if (y == 0) continue;  // TODO(titzer): test x % 0
554       R.CheckFoldBinop<int32_t>(x % y, x, y);
555     }
556   }
557
558   R.CheckDontPutConstantOnRight(417);
559   R.CheckDontPutConstantOnRight(-4371);
560
561   Node* x = R.Parameter();
562   Node* one = R.Constant<int32_t>(1);
563
564   R.CheckFoldBinop<int32_t>(0, x, one);  // x % 1  => 0
565
566   for (uint32_t n = 1; n < 32; ++n) {
567     Node* divisor = R.Constant<int32_t>(1u << n);
568     R.CheckFoldBinop<int32_t>(x, R.machine.Word32And(), (1u << n) - 1, x,
569                               divisor);  // x % 2^n => x & 2^n-1
570   }
571 }
572
573
574 TEST(ReduceInt32LessThan) {
575   ReducerTester R;
576   R.binop = R.machine.Int32LessThan();
577
578   FOR_INT32_INPUTS(pl) {
579     FOR_INT32_INPUTS(pr) {
580       int32_t x = *pl, y = *pr;
581       R.CheckFoldBinop<int32_t>(x < y ? 1 : 0, x, y);
582     }
583   }
584
585   R.CheckDontPutConstantOnRight(41399);
586   R.CheckDontPutConstantOnRight(-440197);
587
588   Node* x = R.Parameter(0);
589   Node* y = R.Parameter(1);
590   Node* zero = R.Constant<int32_t>(0);
591   Node* sub = R.graph.NewNode(R.machine.Int32Sub(), x, y);
592
593   R.CheckFoldBinop<int32_t>(0, x, x);  // x < x  => 0
594   R.CheckFoldBinop(x, y, sub, zero);   // x - y < 0 => x < y
595   R.CheckFoldBinop(y, x, zero, sub);   // 0 < x - y => y < x
596 }
597
598
599 TEST(ReduceInt32LessThanOrEqual) {
600   ReducerTester R;
601   R.binop = R.machine.Int32LessThanOrEqual();
602
603   FOR_INT32_INPUTS(pl) {
604     FOR_INT32_INPUTS(pr) {
605       int32_t x = *pl, y = *pr;
606       R.CheckFoldBinop<int32_t>(x <= y ? 1 : 0, x, y);
607     }
608   }
609
610   FOR_INT32_INPUTS(i) { R.CheckDontPutConstantOnRight<int32_t>(*i); }
611
612   Node* x = R.Parameter(0);
613   Node* y = R.Parameter(1);
614   Node* zero = R.Constant<int32_t>(0);
615   Node* sub = R.graph.NewNode(R.machine.Int32Sub(), x, y);
616
617   R.CheckFoldBinop<int32_t>(1, x, x);  // x <= x => 1
618   R.CheckFoldBinop(x, y, sub, zero);   // x - y <= 0 => x <= y
619   R.CheckFoldBinop(y, x, zero, sub);   // 0 <= x - y => y <= x
620 }
621
622
623 TEST(ReduceUint32LessThan) {
624   ReducerTester R;
625   R.binop = R.machine.Uint32LessThan();
626
627   FOR_UINT32_INPUTS(pl) {
628     FOR_UINT32_INPUTS(pr) {
629       uint32_t x = *pl, y = *pr;
630       R.CheckFoldBinop<int32_t>(x < y ? 1 : 0, x, y);
631     }
632   }
633
634   R.CheckDontPutConstantOnRight(41399);
635   R.CheckDontPutConstantOnRight(-440197);
636
637   Node* x = R.Parameter();
638   Node* max = R.maxuint32;
639   Node* zero = R.Constant<int32_t>(0);
640
641   R.CheckFoldBinop<int32_t>(0, max, x);   // M < x  => 0
642   R.CheckFoldBinop<int32_t>(0, x, zero);  // x < 0  => 0
643   R.CheckFoldBinop<int32_t>(0, x, x);     // x < x  => 0
644 }
645
646
647 TEST(ReduceUint32LessThanOrEqual) {
648   ReducerTester R;
649   R.binop = R.machine.Uint32LessThanOrEqual();
650
651   FOR_UINT32_INPUTS(pl) {
652     FOR_UINT32_INPUTS(pr) {
653       uint32_t x = *pl, y = *pr;
654       R.CheckFoldBinop<int32_t>(x <= y ? 1 : 0, x, y);
655     }
656   }
657
658   R.CheckDontPutConstantOnRight(41399);
659   R.CheckDontPutConstantOnRight(-440197);
660
661   Node* x = R.Parameter();
662   Node* max = R.maxuint32;
663   Node* zero = R.Constant<int32_t>(0);
664
665   R.CheckFoldBinop<int32_t>(1, x, max);   // x <= M  => 1
666   R.CheckFoldBinop<int32_t>(1, zero, x);  // 0 <= x  => 1
667   R.CheckFoldBinop<int32_t>(1, x, x);     // x <= x  => 1
668 }
669
670
671 TEST(ReduceLoadStore) {
672   ReducerTester R;
673
674   Node* base = R.Constant<int32_t>(11);
675   Node* index = R.Constant<int32_t>(4);
676   Node* load = R.graph.NewNode(R.machine.Load(kMachInt32), base, index);
677
678   {
679     MachineOperatorReducer reducer(&R.jsgraph);
680     Reduction reduction = reducer.Reduce(load);
681     CHECK(!reduction.Changed());  // loads should not be reduced.
682   }
683
684   {
685     Node* store = R.graph.NewNode(
686         R.machine.Store(StoreRepresentation(kMachInt32, kNoWriteBarrier)), base,
687         index, load);
688     MachineOperatorReducer reducer(&R.jsgraph);
689     Reduction reduction = reducer.Reduce(store);
690     CHECK(!reduction.Changed());  // stores should not be reduced.
691   }
692 }
693
694
695 static void CheckNans(ReducerTester* R) {
696   Node* x = R->Parameter();
697   std::vector<double> nans = ValueHelper::nan_vector();
698   for (std::vector<double>::const_iterator pl = nans.begin(); pl != nans.end();
699        ++pl) {
700     for (std::vector<double>::const_iterator pr = nans.begin();
701          pr != nans.end(); ++pr) {
702       Node* nan1 = R->Constant<double>(*pl);
703       Node* nan2 = R->Constant<double>(*pr);
704       R->CheckBinop(nan1, x, nan1);     // x op NaN => NaN
705       R->CheckBinop(nan1, nan1, x);     // NaN op x => NaN
706       R->CheckBinop(nan1, nan2, nan1);  // NaN op NaN => NaN
707     }
708   }
709 }
710
711
712 TEST(ReduceFloat64Add) {
713   ReducerTester R;
714   R.binop = R.machine.Float64Add();
715
716   FOR_FLOAT64_INPUTS(pl) {
717     FOR_FLOAT64_INPUTS(pr) {
718       double x = *pl, y = *pr;
719       R.CheckFoldBinop<double>(x + y, x, y);
720     }
721   }
722
723   FOR_FLOAT64_INPUTS(i) {
724     Double tmp(*i);
725     if (!tmp.IsSpecial() || tmp.IsInfinite()) {
726       // Don't check NaNs as they are reduced more.
727       R.CheckPutConstantOnRight(*i);
728     }
729   }
730
731   CheckNans(&R);
732 }
733
734
735 TEST(ReduceFloat64Sub) {
736   ReducerTester R;
737   R.binop = R.machine.Float64Sub();
738
739   FOR_FLOAT64_INPUTS(pl) {
740     FOR_FLOAT64_INPUTS(pr) {
741       double x = *pl, y = *pr;
742       R.CheckFoldBinop<double>(x - y, x, y);
743     }
744   }
745
746   Node* zero = R.Constant<double>(0.0);
747   Node* x = R.Parameter();
748
749   R.CheckBinop(x, x, zero);  // x - 0.0 => x
750
751   CheckNans(&R);
752 }
753
754
755 TEST(ReduceFloat64Mul) {
756   ReducerTester R;
757   R.binop = R.machine.Float64Mul();
758
759   FOR_FLOAT64_INPUTS(pl) {
760     FOR_FLOAT64_INPUTS(pr) {
761       double x = *pl, y = *pr;
762       R.CheckFoldBinop<double>(x * y, x, y);
763     }
764   }
765
766   double inf = V8_INFINITY;
767   R.CheckPutConstantOnRight(-inf);
768   R.CheckPutConstantOnRight(-0.1);
769   R.CheckPutConstantOnRight(0.1);
770   R.CheckPutConstantOnRight(inf);
771
772   Node* x = R.Parameter();
773   Node* one = R.Constant<double>(1.0);
774
775   R.CheckBinop(x, x, one);  // x * 1.0 => x
776   R.CheckBinop(x, one, x);  // 1.0 * x => x
777
778   CheckNans(&R);
779 }
780
781
782 TEST(ReduceFloat64Div) {
783   ReducerTester R;
784   R.binop = R.machine.Float64Div();
785
786   FOR_FLOAT64_INPUTS(pl) {
787     FOR_FLOAT64_INPUTS(pr) {
788       double x = *pl, y = *pr;
789       R.CheckFoldBinop<double>(x / y, x, y);
790     }
791   }
792
793   Node* x = R.Parameter();
794   Node* one = R.Constant<double>(1.0);
795
796   R.CheckBinop(x, x, one);  // x / 1.0 => x
797
798   CheckNans(&R);
799 }
800
801
802 TEST(ReduceFloat64Mod) {
803   ReducerTester R;
804   R.binop = R.machine.Float64Mod();
805
806   FOR_FLOAT64_INPUTS(pl) {
807     FOR_FLOAT64_INPUTS(pr) {
808       double x = *pl, y = *pr;
809       R.CheckFoldBinop<double>(modulo(x, y), x, y);
810     }
811   }
812
813   Node* x = R.Parameter();
814   Node* zero = R.Constant<double>(0.0);
815
816   R.CheckFoldBinop<double>(v8::base::OS::nan_value(), x, zero);
817
818   CheckNans(&R);
819 }
820
821
822 // TODO(titzer): test MachineOperatorReducer for Word64And
823 // TODO(titzer): test MachineOperatorReducer for Word64Or
824 // TODO(titzer): test MachineOperatorReducer for Word64Xor
825 // TODO(titzer): test MachineOperatorReducer for Word64Shl
826 // TODO(titzer): test MachineOperatorReducer for Word64Shr
827 // TODO(titzer): test MachineOperatorReducer for Word64Sar
828 // TODO(titzer): test MachineOperatorReducer for Word64Equal
829 // TODO(titzer): test MachineOperatorReducer for Word64Not
830 // TODO(titzer): test MachineOperatorReducer for Int64Add
831 // TODO(titzer): test MachineOperatorReducer for Int64Sub
832 // TODO(titzer): test MachineOperatorReducer for Int64Mul
833 // TODO(titzer): test MachineOperatorReducer for Int64UMul
834 // TODO(titzer): test MachineOperatorReducer for Int64Div
835 // TODO(titzer): test MachineOperatorReducer for Uint64Div
836 // TODO(titzer): test MachineOperatorReducer for Int64Mod
837 // TODO(titzer): test MachineOperatorReducer for Uint64Mod
838 // TODO(titzer): test MachineOperatorReducer for Int64Neg
839 // TODO(titzer): test MachineOperatorReducer for ChangeInt32ToFloat64
840 // TODO(titzer): test MachineOperatorReducer for ChangeFloat64ToInt32
841 // TODO(titzer): test MachineOperatorReducer for Float64Compare