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