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