LCOV - code coverage report
Current view: top level - test/cctest/compiler - test-machine-operator-reducer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 508 512 99.2 %
Date: 2017-10-20 Functions: 56 60 93.3 %

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

Generated by: LCOV version 1.10