LCOV - code coverage report
Current view: top level - src/compiler - machine-operator-reducer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 672 705 95.3 %
Date: 2017-10-20 Functions: 39 47 83.0 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/machine-operator-reducer.h"
       6             : 
       7             : #include "src/base/bits.h"
       8             : #include "src/base/division-by-constant.h"
       9             : #include "src/base/ieee754.h"
      10             : #include "src/compiler/diamond.h"
      11             : #include "src/compiler/graph.h"
      12             : #include "src/compiler/js-graph.h"
      13             : #include "src/compiler/node-matchers.h"
      14             : #include "src/conversions-inl.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : namespace compiler {
      19             : 
      20     1650655 : MachineOperatorReducer::MachineOperatorReducer(JSGraph* jsgraph,
      21             :                                                bool allow_signalling_nan)
      22     1650655 :     : jsgraph_(jsgraph), allow_signalling_nan_(allow_signalling_nan) {}
      23             : 
      24     3301288 : MachineOperatorReducer::~MachineOperatorReducer() {}
      25             : 
      26             : 
      27       80229 : Node* MachineOperatorReducer::Float32Constant(volatile float value) {
      28      240687 :   return graph()->NewNode(common()->Float32Constant(value));
      29             : }
      30             : 
      31             : 
      32      113802 : Node* MachineOperatorReducer::Float64Constant(volatile double value) {
      33      227604 :   return jsgraph()->Float64Constant(value);
      34             : }
      35             : 
      36             : 
      37      571776 : Node* MachineOperatorReducer::Int32Constant(int32_t value) {
      38      571776 :   return jsgraph()->Int32Constant(value);
      39             : }
      40             : 
      41             : 
      42      550477 : Node* MachineOperatorReducer::Int64Constant(int64_t value) {
      43     1100955 :   return graph()->NewNode(common()->Int64Constant(value));
      44             : }
      45             : 
      46           0 : Node* MachineOperatorReducer::Float64Mul(Node* lhs, Node* rhs) {
      47           0 :   return graph()->NewNode(machine()->Float64Mul(), lhs, rhs);
      48             : }
      49             : 
      50           0 : Node* MachineOperatorReducer::Float64PowHalf(Node* value) {
      51             :   value =
      52           0 :       graph()->NewNode(machine()->Float64Add(), Float64Constant(0.0), value);
      53             :   Diamond d(graph(), common(),
      54             :             graph()->NewNode(machine()->Float64LessThanOrEqual(), value,
      55             :                              Float64Constant(-V8_INFINITY)),
      56           0 :             BranchHint::kFalse);
      57             :   return d.Phi(MachineRepresentation::kFloat64, Float64Constant(V8_INFINITY),
      58           0 :                graph()->NewNode(machine()->Float64Sqrt(), value));
      59             : }
      60             : 
      61      115010 : Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
      62      115010 :   Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
      63      115010 :   Reduction const reduction = ReduceWord32And(node);
      64      115010 :   return reduction.Changed() ? reduction.replacement() : node;
      65             : }
      66             : 
      67             : 
      68        6829 : Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
      69        6829 :   if (rhs == 0) return lhs;
      70       13278 :   return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
      71             : }
      72             : 
      73             : 
      74        6804 : Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
      75        6804 :   if (rhs == 0) return lhs;
      76       13184 :   return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs));
      77             : }
      78             : 
      79             : 
      80          12 : Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) {
      81          24 :   return graph()->NewNode(machine()->Word32Equal(), lhs, rhs);
      82             : }
      83             : 
      84             : 
      85        7618 : Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
      86        7618 :   Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
      87        7618 :   Reduction const reduction = ReduceInt32Add(node);
      88        7618 :   return reduction.Changed() ? reduction.replacement() : node;
      89             : }
      90             : 
      91             : 
      92        2262 : Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
      93        2262 :   Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
      94        2262 :   Reduction const reduction = ReduceInt32Sub(node);
      95        2262 :   return reduction.Changed() ? reduction.replacement() : node;
      96             : }
      97             : 
      98             : 
      99        3352 : Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
     100        6704 :   return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
     101             : }
     102             : 
     103             : 
     104        5248 : Node* MachineOperatorReducer::Int32Div(Node* dividend, int32_t divisor) {
     105             :   DCHECK_NE(0, divisor);
     106             :   DCHECK_NE(std::numeric_limits<int32_t>::min(), divisor);
     107             :   base::MagicNumbersForDivision<uint32_t> const mag =
     108        5248 :       base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
     109             :   Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
     110        5248 :                                     Uint32Constant(mag.multiplier));
     111       10496 :   if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
     112        1454 :     quotient = Int32Add(quotient, dividend);
     113        3794 :   } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
     114           0 :     quotient = Int32Sub(quotient, dividend);
     115             :   }
     116        5248 :   return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
     117             : }
     118             : 
     119             : 
     120         320 : Node* MachineOperatorReducer::Uint32Div(Node* dividend, uint32_t divisor) {
     121             :   DCHECK_LT(0u, divisor);
     122             :   // If the divisor is even, we can avoid using the expensive fixup by shifting
     123             :   // the dividend upfront.
     124             :   unsigned const shift = base::bits::CountTrailingZeros32(divisor);
     125         320 :   dividend = Word32Shr(dividend, shift);
     126         320 :   divisor >>= shift;
     127             :   // Compute the magic number for the (shifted) divisor.
     128             :   base::MagicNumbersForDivision<uint32_t> const mag =
     129         320 :       base::UnsignedDivisionByConstant(divisor, shift);
     130             :   Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
     131         640 :                                     Uint32Constant(mag.multiplier));
     132         320 :   if (mag.add) {
     133             :     DCHECK_LE(1u, mag.shift);
     134             :     quotient = Word32Shr(
     135             :         Int32Add(Word32Shr(Int32Sub(dividend, quotient), 1), quotient),
     136          34 :         mag.shift - 1);
     137             :   } else {
     138         286 :     quotient = Word32Shr(quotient, mag.shift);
     139             :   }
     140         320 :   return quotient;
     141             : }
     142             : 
     143             : 
     144             : // Perform constant folding and strength reduction on machine operators.
     145    90748364 : Reduction MachineOperatorReducer::Reduce(Node* node) {
     146    90748364 :   switch (node->opcode()) {
     147             :     case IrOpcode::kProjection:
     148      256815 :       return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
     149             :     case IrOpcode::kWord32And:
     150      382915 :       return ReduceWord32And(node);
     151             :     case IrOpcode::kWord32Or:
     152       55869 :       return ReduceWord32Or(node);
     153             :     case IrOpcode::kWord32Xor:
     154       25034 :       return ReduceWord32Xor(node);
     155             :     case IrOpcode::kWord32Shl:
     156       39597 :       return ReduceWord32Shl(node);
     157             :     case IrOpcode::kWord64Shl:
     158      217353 :       return ReduceWord64Shl(node);
     159             :     case IrOpcode::kWord32Shr:
     160       47454 :       return ReduceWord32Shr(node);
     161             :     case IrOpcode::kWord64Shr:
     162       31116 :       return ReduceWord64Shr(node);
     163             :     case IrOpcode::kWord32Sar:
     164       35950 :       return ReduceWord32Sar(node);
     165             :     case IrOpcode::kWord64Sar:
     166      197762 :       return ReduceWord64Sar(node);
     167             :     case IrOpcode::kWord32Ror: {
     168        1879 :       Int32BinopMatcher m(node);
     169        3416 :       if (m.right().Is(0)) return Replace(m.left().node());  // x ror 0 => x
     170        1830 :       if (m.IsFoldable()) {                                  // K ror K => K
     171             :         return ReplaceInt32(
     172        2976 :             base::bits::RotateRight32(m.left().Value(), m.right().Value()));
     173             :       }
     174         342 :       break;
     175             :     }
     176             :     case IrOpcode::kWord32Equal: {
     177      383976 :       Int32BinopMatcher m(node);
     178      383976 :       if (m.IsFoldable()) {  // K == K => K
     179       79315 :         return ReplaceBool(m.left().Value() == m.right().Value());
     180             :       }
     181      345787 :       if (m.left().IsInt32Sub() && m.right().Is(0)) {  // x - y == 0 => x == y
     182         871 :         Int32BinopMatcher msub(m.left().node());
     183         871 :         node->ReplaceInput(0, msub.left().node());
     184         871 :         node->ReplaceInput(1, msub.right().node());
     185             :         return Changed(node);
     186             :       }
     187             :       // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
     188      343992 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x == x => true
     189      343774 :       break;
     190             :     }
     191             :     case IrOpcode::kWord64Equal: {
     192     1203322 :       Int64BinopMatcher m(node);
     193     1203319 :       if (m.IsFoldable()) {  // K == K => K
     194        7171 :         return ReplaceBool(m.left().Value() == m.right().Value());
     195             :       }
     196     1203319 :       if (m.left().IsInt64Sub() && m.right().Is(0)) {  // x - y == 0 => x == y
     197           0 :         Int64BinopMatcher msub(m.left().node());
     198           0 :         node->ReplaceInput(0, msub.left().node());
     199           0 :         node->ReplaceInput(1, msub.right().node());
     200             :         return Changed(node);
     201             :       }
     202             :       // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
     203     1203319 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x == x => true
     204     1196148 :       break;
     205             :     }
     206             :     case IrOpcode::kInt32Add:
     207      377921 :       return ReduceInt32Add(node);
     208             :     case IrOpcode::kInt64Add:
     209      620539 :       return ReduceInt64Add(node);
     210             :     case IrOpcode::kInt32Sub:
     211       64326 :       return ReduceInt32Sub(node);
     212             :     case IrOpcode::kInt64Sub:
     213      161573 :       return ReduceInt64Sub(node);
     214             :     case IrOpcode::kInt32Mul: {
     215       31882 :       Int32BinopMatcher m(node);
     216       53206 :       if (m.right().Is(0)) return Replace(m.right().node());  // x * 0 => 0
     217       31442 :       if (m.right().Is(1)) return Replace(m.left().node());   // x * 1 => x
     218       31059 :       if (m.IsFoldable()) {                                   // K * K => K
     219       19685 :         return ReplaceInt32(m.left().Value() * m.right().Value());
     220             :       }
     221       11374 :       if (m.right().Is(-1)) {  // x * -1 => 0 - x
     222          92 :         node->ReplaceInput(0, Int32Constant(0));
     223          92 :         node->ReplaceInput(1, m.left().node());
     224          92 :         NodeProperties::ChangeOp(node, machine()->Int32Sub());
     225             :         return Changed(node);
     226             :       }
     227       11282 :       if (m.right().IsPowerOf2()) {  // x * 2^n => x << n
     228        1448 :         node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
     229         724 :         NodeProperties::ChangeOp(node, machine()->Word32Shl());
     230         724 :         Reduction reduction = ReduceWord32Shl(node);
     231         724 :         return reduction.Changed() ? reduction : Changed(node);
     232             :       }
     233       10558 :       break;
     234             :     }
     235             :     case IrOpcode::kInt32MulWithOverflow: {
     236        6544 :       Int32BinopMatcher m(node);
     237        6544 :       if (m.right().Is(2)) {
     238         212 :         node->ReplaceInput(1, m.left().node());
     239         212 :         NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
     240        3290 :         return Changed(node);
     241             :       }
     242        6332 :       if (m.right().Is(-1)) {
     243        3078 :         node->ReplaceInput(0, Int32Constant(0));
     244        3078 :         node->ReplaceInput(1, m.left().node());
     245        3078 :         NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
     246             :         return Changed(node);
     247             :       }
     248        3254 :       break;
     249             :     }
     250             :     case IrOpcode::kInt32Div:
     251       23532 :       return ReduceInt32Div(node);
     252             :     case IrOpcode::kUint32Div:
     253       22741 :       return ReduceUint32Div(node);
     254             :     case IrOpcode::kInt32Mod:
     255       34882 :       return ReduceInt32Mod(node);
     256             :     case IrOpcode::kUint32Mod:
     257       22928 :       return ReduceUint32Mod(node);
     258             :     case IrOpcode::kInt32LessThan: {
     259      221386 :       Int32BinopMatcher m(node);
     260      221395 :       if (m.IsFoldable()) {  // K < K => K
     261       47913 :         return ReplaceBool(m.left().Value() < m.right().Value());
     262             :       }
     263      197483 :       if (m.LeftEqualsRight()) return ReplaceBool(false);  // x < x => false
     264      198738 :       if (m.left().IsWord32Or() && m.right().Is(0)) {
     265             :         // (x | K) < 0 => true or (K | x) < 0 => true iff K < 0
     266        1219 :         Int32BinopMatcher mleftmatcher(m.left().node());
     267        2438 :         if (mleftmatcher.left().IsNegative() ||
     268             :             mleftmatcher.right().IsNegative()) {
     269          75 :           return ReplaceBool(true);
     270             :         }
     271             :       }
     272      197394 :       break;
     273             :     }
     274             :     case IrOpcode::kInt32LessThanOrEqual: {
     275       26598 :       Int32BinopMatcher m(node);
     276       26598 :       if (m.IsFoldable()) {  // K <= K => K
     277       42226 :         return ReplaceBool(m.left().Value() <= m.right().Value());
     278             :       }
     279        5488 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x <= x => true
     280        5482 :       break;
     281             :     }
     282             :     case IrOpcode::kUint32LessThan: {
     283      117433 :       Uint32BinopMatcher m(node);
     284      146623 :       if (m.left().Is(kMaxUInt32)) return ReplaceBool(false);  // M < x => false
     285      117067 :       if (m.right().Is(0)) return ReplaceBool(false);          // x < 0 => false
     286      116347 :       if (m.IsFoldable()) {                                    // K < K => K
     287       27244 :         return ReplaceBool(m.left().Value() < m.right().Value());
     288             :       }
     289       89103 :       if (m.LeftEqualsRight()) return ReplaceBool(false);  // x < x => false
     290       88529 :       if (m.left().IsWord32Sar() && m.right().HasValue()) {
     291         286 :         Int32BinopMatcher mleft(m.left().node());
     292         286 :         if (mleft.right().HasValue()) {
     293             :           // (x >> K) < C => x < (C << K)
     294             :           // when C < (M >> K)
     295         286 :           const uint32_t c = m.right().Value();
     296         286 :           const uint32_t k = mleft.right().Value() & 0x1f;
     297         286 :           if (c < static_cast<uint32_t>(kMaxInt >> k)) {
     298         286 :             node->ReplaceInput(0, mleft.left().node());
     299         572 :             node->ReplaceInput(1, Uint32Constant(c << k));
     300         286 :             return Changed(node);
     301             :           }
     302             :           // TODO(turbofan): else the comparison is always true.
     303             :         }
     304             :       }
     305       88243 :       break;
     306             :     }
     307             :     case IrOpcode::kUint32LessThanOrEqual: {
     308       50708 :       Uint32BinopMatcher m(node);
     309       71362 :       if (m.left().Is(0)) return ReplaceBool(true);            // 0 <= x => true
     310       50096 :       if (m.right().Is(kMaxUInt32)) return ReplaceBool(true);  // x <= M => true
     311       49748 :       if (m.IsFoldable()) {                                    // K <= K => K
     312       19687 :         return ReplaceBool(m.left().Value() <= m.right().Value());
     313             :       }
     314       30061 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x <= x => true
     315       30054 :       break;
     316             :     }
     317             :     case IrOpcode::kFloat32Sub: {
     318       79370 :       Float32BinopMatcher m(node);
     319      160120 :       if (allow_signalling_nan_ && m.right().Is(0) &&
     320        1380 :           (copysign(1.0, m.right().Value()) > 0)) {
     321       79363 :         return Replace(m.left().node());  // x - 0 => x
     322             :       }
     323       78680 :       if (m.right().IsNaN()) {  // x - NaN => NaN
     324             :         // Do some calculation to make a signalling NaN quiet.
     325        1386 :         return ReplaceFloat32(m.right().Value() - m.right().Value());
     326             :       }
     327       77294 :       if (m.left().IsNaN()) {  // NaN - x => NaN
     328             :         // Do some calculation to make a signalling NaN quiet.
     329        1350 :         return ReplaceFloat32(m.left().Value() - m.left().Value());
     330             :       }
     331       75944 :       if (m.IsFoldable()) {  // L - R => (L - R)
     332       75936 :         return ReplaceFloat32(m.left().Value() - m.right().Value());
     333             :       }
     334           8 :       if (allow_signalling_nan_ && m.left().IsMinusZero()) {
     335             :         // -0.0 - round_down(-0.0 - R) => round_up(R)
     336           1 :         if (machine()->Float32RoundUp().IsSupported() &&
     337             :             m.right().IsFloat32RoundDown()) {
     338           0 :           if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat32Sub) {
     339           0 :             Float32BinopMatcher mright0(m.right().InputAt(0));
     340           0 :             if (mright0.left().IsMinusZero()) {
     341             :               return Replace(graph()->NewNode(machine()->Float32RoundUp().op(),
     342           0 :                                               mright0.right().node()));
     343             :             }
     344             :           }
     345             :         }
     346             :         // -0.0 - R => -R
     347           1 :         node->RemoveInput(0);
     348           1 :         NodeProperties::ChangeOp(node, machine()->Float32Neg());
     349             :         return Changed(node);
     350             :       }
     351           7 :       break;
     352             :     }
     353             :     case IrOpcode::kFloat64Add: {
     354      126268 :       Float64BinopMatcher m(node);
     355      126276 :       if (m.right().IsNaN()) {  // x + NaN => NaN
     356             :         // Do some calculation to make a signalling NaN quiet.
     357       17589 :         return ReplaceFloat64(m.right().Value() - m.right().Value());
     358             :       }
     359      126229 :       if (m.IsFoldable()) {  // K + K => K
     360       17495 :         return ReplaceFloat64(m.left().Value() + m.right().Value());
     361             :       }
     362      108734 :       break;
     363             :     }
     364             :     case IrOpcode::kFloat64Sub: {
     365       69260 :       Float64BinopMatcher m(node);
     366      139305 :       if (allow_signalling_nan_ && m.right().Is(0) &&
     367         785 :           (Double(m.right().Value()).Sign() > 0)) {
     368       32400 :         return Replace(m.left().node());  // x - 0 => x
     369             :       }
     370       68777 :       if (m.right().IsNaN()) {  // x - NaN => NaN
     371             :         // Do some calculation to make a signalling NaN quiet.
     372         624 :         return ReplaceFloat64(m.right().Value() - m.right().Value());
     373             :       }
     374       68153 :       if (m.left().IsNaN()) {  // NaN - x => NaN
     375             :         // Do some calculation to make a signalling NaN quiet.
     376         598 :         return ReplaceFloat64(m.left().Value() - m.left().Value());
     377             :       }
     378       67555 :       if (m.IsFoldable()) {  // L - R => (L - R)
     379       22139 :         return ReplaceFloat64(m.left().Value() - m.right().Value());
     380             :       }
     381       45416 :       if (allow_signalling_nan_ && m.left().IsMinusZero()) {
     382             :         // -0.0 - round_down(-0.0 - R) => round_up(R)
     383       17111 :         if (machine()->Float64RoundUp().IsSupported() &&
     384             :             m.right().IsFloat64RoundDown()) {
     385        1260 :           if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub) {
     386           0 :             Float64BinopMatcher mright0(m.right().InputAt(0));
     387           0 :             if (mright0.left().IsMinusZero()) {
     388             :               return Replace(graph()->NewNode(machine()->Float64RoundUp().op(),
     389           0 :                                               mright0.right().node()));
     390             :             }
     391             :           }
     392             :         }
     393             :         // -0.0 - R => -R
     394        8556 :         node->RemoveInput(0);
     395        8556 :         NodeProperties::ChangeOp(node, machine()->Float64Neg());
     396             :         return Changed(node);
     397             :       }
     398       36860 :       break;
     399             :     }
     400             :     case IrOpcode::kFloat64Mul: {
     401       26129 :       Float64BinopMatcher m(node);
     402       52257 :       if (allow_signalling_nan_ && m.right().Is(1))
     403       10884 :         return Replace(m.left().node());  // x * 1.0 => x
     404       26031 :       if (m.right().Is(-1)) {  // x * -1.0 => -0.0 - x
     405        8750 :         node->ReplaceInput(0, Float64Constant(-0.0));
     406        8750 :         node->ReplaceInput(1, m.left().node());
     407        8750 :         NodeProperties::ChangeOp(node, machine()->Float64Sub());
     408             :         return Changed(node);
     409             :       }
     410       17281 :       if (m.right().IsNaN()) {                               // x * NaN => NaN
     411             :         // Do some calculation to make a signalling NaN quiet.
     412          33 :         return ReplaceFloat64(m.right().Value() - m.right().Value());
     413             :       }
     414       17248 :       if (m.IsFoldable()) {  // K * K => K
     415        1801 :         return ReplaceFloat64(m.left().Value() * m.right().Value());
     416             :       }
     417       15447 :       if (m.right().Is(2)) {  // x * 2.0 => x + x
     418         203 :         node->ReplaceInput(1, m.left().node());
     419         203 :         NodeProperties::ChangeOp(node, machine()->Float64Add());
     420             :         return Changed(node);
     421             :       }
     422       15244 :       break;
     423             :     }
     424             :     case IrOpcode::kFloat64Div: {
     425       30476 :       Float64BinopMatcher m(node);
     426       60952 :       if (allow_signalling_nan_ && m.right().Is(1))
     427        6778 :         return Replace(m.left().node());  // x / 1.0 => x
     428             :       // TODO(ahaas): We could do x / 1.0 = x if we knew that x is not an sNaN.
     429       30321 :       if (m.right().IsNaN()) {                               // x / NaN => NaN
     430             :         // Do some calculation to make a signalling NaN quiet.
     431          30 :         return ReplaceFloat64(m.right().Value() - m.right().Value());
     432             :       }
     433       30291 :       if (m.left().IsNaN()) {  // NaN / x => NaN
     434             :         // Do some calculation to make a signalling NaN quiet.
     435          46 :         return ReplaceFloat64(m.left().Value() - m.left().Value());
     436             :       }
     437       30245 :       if (m.IsFoldable()) {  // K / K => K
     438        3653 :         return ReplaceFloat64(m.left().Value() / m.right().Value());
     439             :       }
     440       53184 :       if (allow_signalling_nan_ && m.right().Is(-1)) {  // x / -1.0 => -x
     441          40 :         node->RemoveInput(1);
     442          40 :         NodeProperties::ChangeOp(node, machine()->Float64Neg());
     443             :         return Changed(node);
     444             :       }
     445       26552 :       if (m.right().IsNormal() && m.right().IsPositiveOrNegativePowerOf2()) {
     446             :         // All reciprocals of non-denormal powers of two can be represented
     447             :         // exactly, so division by power of two can be reduced to
     448             :         // multiplication by reciprocal, with the same result.
     449        5708 :         node->ReplaceInput(1, Float64Constant(1.0 / m.right().Value()));
     450        2854 :         NodeProperties::ChangeOp(node, machine()->Float64Mul());
     451             :         return Changed(node);
     452             :       }
     453       23698 :       break;
     454             :     }
     455             :     case IrOpcode::kFloat64Mod: {
     456        2815 :       Float64BinopMatcher m(node);
     457        2815 :       if (m.right().Is(0)) {  // x % 0 => NaN
     458        1256 :         return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
     459             :       }
     460        2664 :       if (m.right().IsNaN()) {  // x % NaN => NaN
     461             :         return Replace(m.right().node());
     462             :       }
     463        2627 :       if (m.left().IsNaN()) {  // NaN % x => NaN
     464             :         return Replace(m.left().node());
     465             :       }
     466        2600 :       if (m.IsFoldable()) {  // K % K => K
     467        1041 :         return ReplaceFloat64(Modulo(m.left().Value(), m.right().Value()));
     468             :       }
     469        1559 :       break;
     470             :     }
     471             :     case IrOpcode::kFloat64Acos: {
     472             :       Float64Matcher m(node->InputAt(0));
     473         102 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::acos(m.Value()));
     474             :       break;
     475             :     }
     476             :     case IrOpcode::kFloat64Acosh: {
     477             :       Float64Matcher m(node->InputAt(0));
     478         100 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::acosh(m.Value()));
     479             :       break;
     480             :     }
     481             :     case IrOpcode::kFloat64Asin: {
     482             :       Float64Matcher m(node->InputAt(0));
     483         102 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::asin(m.Value()));
     484             :       break;
     485             :     }
     486             :     case IrOpcode::kFloat64Asinh: {
     487             :       Float64Matcher m(node->InputAt(0));
     488         100 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::asinh(m.Value()));
     489             :       break;
     490             :     }
     491             :     case IrOpcode::kFloat64Atan: {
     492             :       Float64Matcher m(node->InputAt(0));
     493         121 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::atan(m.Value()));
     494             :       break;
     495             :     }
     496             :     case IrOpcode::kFloat64Atanh: {
     497             :       Float64Matcher m(node->InputAt(0));
     498         100 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::atanh(m.Value()));
     499             :       break;
     500             :     }
     501             :     case IrOpcode::kFloat64Atan2: {
     502       10049 :       Float64BinopMatcher m(node);
     503       10049 :       if (m.right().IsNaN()) {
     504       10008 :         return Replace(m.right().node());
     505             :       }
     506       10048 :       if (m.left().IsNaN()) {
     507             :         return Replace(m.left().node());
     508             :       }
     509       10047 :       if (m.IsFoldable()) {
     510             :         return ReplaceFloat64(
     511       10006 :             base::ieee754::atan2(m.left().Value(), m.right().Value()));
     512             :       }
     513          41 :       break;
     514             :     }
     515             :     case IrOpcode::kFloat64Cbrt: {
     516             :       Float64Matcher m(node->InputAt(0));
     517           0 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::cbrt(m.Value()));
     518             :       break;
     519             :     }
     520             :     case IrOpcode::kFloat64Cos: {
     521             :       Float64Matcher m(node->InputAt(0));
     522         296 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::cos(m.Value()));
     523             :       break;
     524             :     }
     525             :     case IrOpcode::kFloat64Cosh: {
     526             :       Float64Matcher m(node->InputAt(0));
     527         116 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::cosh(m.Value()));
     528             :       break;
     529             :     }
     530             :     case IrOpcode::kFloat64Exp: {
     531             :       Float64Matcher m(node->InputAt(0));
     532         151 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::exp(m.Value()));
     533             :       break;
     534             :     }
     535             :     case IrOpcode::kFloat64Expm1: {
     536             :       Float64Matcher m(node->InputAt(0));
     537           0 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::expm1(m.Value()));
     538             :       break;
     539             :     }
     540             :     case IrOpcode::kFloat64Log: {
     541             :       Float64Matcher m(node->InputAt(0));
     542         443 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log(m.Value()));
     543             :       break;
     544             :     }
     545             :     case IrOpcode::kFloat64Log1p: {
     546             :       Float64Matcher m(node->InputAt(0));
     547         100 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log1p(m.Value()));
     548             :       break;
     549             :     }
     550             :     case IrOpcode::kFloat64Log10: {
     551             :       Float64Matcher m(node->InputAt(0));
     552           0 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log10(m.Value()));
     553             :       break;
     554             :     }
     555             :     case IrOpcode::kFloat64Log2: {
     556             :       Float64Matcher m(node->InputAt(0));
     557           0 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log2(m.Value()));
     558             :       break;
     559             :     }
     560             :     case IrOpcode::kFloat64Pow: {
     561       11042 :       Float64BinopMatcher m(node);
     562       11042 :       if (m.IsFoldable()) {
     563       21722 :         return ReplaceFloat64(Pow(m.left().Value(), m.right().Value()));
     564         182 :       } else if (m.right().Is(0.0)) {  // x ** +-0.0 => 1.0
     565             :         return ReplaceFloat64(1.0);
     566         180 :       } else if (m.right().Is(-2.0)) {  // x ** -2.0 => 1 / (x * x)
     567           0 :         node->ReplaceInput(0, Float64Constant(1.0));
     568           0 :         node->ReplaceInput(1, Float64Mul(m.left().node(), m.left().node()));
     569           0 :         NodeProperties::ChangeOp(node, machine()->Float64Div());
     570             :         return Changed(node);
     571         180 :       } else if (m.right().Is(2.0)) {  // x ** 2.0 => x * x
     572           0 :         node->ReplaceInput(1, m.left().node());
     573           0 :         NodeProperties::ChangeOp(node, machine()->Float64Mul());
     574             :         return Changed(node);
     575         180 :       } else if (m.right().Is(-0.5)) {
     576             :         // x ** 0.5 => 1 / (if x <= -Infinity then Infinity else sqrt(0.0 + x))
     577           0 :         node->ReplaceInput(0, Float64Constant(1.0));
     578           0 :         node->ReplaceInput(1, Float64PowHalf(m.left().node()));
     579           0 :         NodeProperties::ChangeOp(node, machine()->Float64Div());
     580             :         return Changed(node);
     581         180 :       } else if (m.right().Is(0.5)) {
     582             :         // x ** 0.5 => if x <= -Infinity then Infinity else sqrt(0.0 + x)
     583           0 :         return Replace(Float64PowHalf(m.left().node()));
     584             :       }
     585         180 :       break;
     586             :     }
     587             :     case IrOpcode::kFloat64Sin: {
     588             :       Float64Matcher m(node->InputAt(0));
     589         321 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
     590             :       break;
     591             :     }
     592             :     case IrOpcode::kFloat64Sinh: {
     593             :       Float64Matcher m(node->InputAt(0));
     594         116 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::sinh(m.Value()));
     595             :       break;
     596             :     }
     597             :     case IrOpcode::kFloat64Tan: {
     598             :       Float64Matcher m(node->InputAt(0));
     599         121 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::tan(m.Value()));
     600             :       break;
     601             :     }
     602             :     case IrOpcode::kFloat64Tanh: {
     603             :       Float64Matcher m(node->InputAt(0));
     604         116 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::tanh(m.Value()));
     605             :       break;
     606             :     }
     607             :     case IrOpcode::kChangeFloat32ToFloat64: {
     608             :       Float32Matcher m(node->InputAt(0));
     609       12162 :       if (m.HasValue()) {
     610         174 :         if (!allow_signalling_nan_ && std::isnan(m.Value())) {
     611             :           // Do some calculation to make guarantee the value is a quiet NaN.
     612           0 :           return ReplaceFloat64(m.Value() + m.Value());
     613             :         }
     614         174 :         return ReplaceFloat64(m.Value());
     615             :       }
     616             :       break;
     617             :     }
     618             :     case IrOpcode::kChangeFloat64ToInt32: {
     619             :       Float64Matcher m(node->InputAt(0));
     620       13921 :       if (m.HasValue()) return ReplaceInt32(FastD2I(m.Value()));
     621        8562 :       if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
     622             :       break;
     623             :     }
     624             :     case IrOpcode::kChangeFloat64ToUint32: {
     625             :       Float64Matcher m(node->InputAt(0));
     626         392 :       if (m.HasValue()) return ReplaceInt32(FastD2UI(m.Value()));
     627         278 :       if (m.IsChangeUint32ToFloat64()) return Replace(m.node()->InputAt(0));
     628             :       break;
     629             :     }
     630             :     case IrOpcode::kChangeInt32ToFloat64: {
     631             :       Int32Matcher m(node->InputAt(0));
     632      197733 :       if (m.HasValue()) return ReplaceFloat64(FastI2D(m.Value()));
     633             :       break;
     634             :     }
     635             :     case IrOpcode::kChangeInt32ToInt64: {
     636             :       Int32Matcher m(node->InputAt(0));
     637      228244 :       if (m.HasValue()) return ReplaceInt64(m.Value());
     638             :       break;
     639             :     }
     640             :     case IrOpcode::kChangeUint32ToFloat64: {
     641             :       Uint32Matcher m(node->InputAt(0));
     642        2008 :       if (m.HasValue()) return ReplaceFloat64(FastUI2D(m.Value()));
     643             :       break;
     644             :     }
     645             :     case IrOpcode::kChangeUint32ToUint64: {
     646             :       Uint32Matcher m(node->InputAt(0));
     647      225217 :       if (m.HasValue()) return ReplaceInt64(static_cast<uint64_t>(m.Value()));
     648             :       break;
     649             :     }
     650             :     case IrOpcode::kTruncateFloat64ToWord32: {
     651             :       Float64Matcher m(node->InputAt(0));
     652       14512 :       if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
     653       11012 :       if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
     654             :       return NoChange();
     655             :     }
     656             :     case IrOpcode::kTruncateInt64ToInt32: {
     657             :       Int64Matcher m(node->InputAt(0));
     658      159685 :       if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
     659      159577 :       if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
     660             :       break;
     661             :     }
     662             :     case IrOpcode::kTruncateFloat64ToFloat32: {
     663             :       Float64Matcher m(node->InputAt(0));
     664        6902 :       if (m.HasValue()) {
     665         912 :         if (!allow_signalling_nan_ && std::isnan(m.Value())) {
     666             :           // Do some calculation to make guarantee the value is a quiet NaN.
     667           0 :           return ReplaceFloat32(DoubleToFloat32(m.Value() + m.Value()));
     668             :         }
     669             :         return ReplaceFloat32(DoubleToFloat32(m.Value()));
     670             :       }
     671        5990 :       if (allow_signalling_nan_ && m.IsChangeFloat32ToFloat64())
     672             :         return Replace(m.node()->InputAt(0));
     673             :       break;
     674             :     }
     675             :     case IrOpcode::kRoundFloat64ToInt32: {
     676             :       Float64Matcher m(node->InputAt(0));
     677       47857 :       if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
     678       47545 :       if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
     679             :       break;
     680             :     }
     681             :     case IrOpcode::kFloat64InsertLowWord32:
     682        4800 :       return ReduceFloat64InsertLowWord32(node);
     683             :     case IrOpcode::kFloat64InsertHighWord32:
     684        4800 :       return ReduceFloat64InsertHighWord32(node);
     685             :     case IrOpcode::kStore:
     686             :     case IrOpcode::kUnalignedStore:
     687             :     case IrOpcode::kCheckedStore:
     688     1525464 :       return ReduceStore(node);
     689             :     case IrOpcode::kFloat64Equal:
     690             :     case IrOpcode::kFloat64LessThan:
     691             :     case IrOpcode::kFloat64LessThanOrEqual:
     692      167910 :       return ReduceFloat64Compare(node);
     693             :     case IrOpcode::kFloat64RoundDown:
     694       18166 :       return ReduceFloat64RoundDown(node);
     695             :     default:
     696             :       break;
     697             :   }
     698             :   return NoChange();
     699             : }
     700             : 
     701      512091 : Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
     702             :   DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
     703      512091 :   Int32BinopMatcher m(node);
     704      512092 :   if (m.right().Is(0)) return Replace(m.left().node());  // x + 0 => x
     705      484859 :   if (m.IsFoldable()) {                                  // K + K => K
     706             :     return ReplaceUint32(bit_cast<uint32_t>(m.left().Value()) +
     707       38569 :                          bit_cast<uint32_t>(m.right().Value()));
     708             :   }
     709      446290 :   if (m.left().IsInt32Sub()) {
     710        1414 :     Int32BinopMatcher mleft(m.left().node());
     711        1414 :     if (mleft.left().Is(0)) {  // (0 - x) + y => y - x
     712          13 :       node->ReplaceInput(0, m.right().node());
     713          13 :       node->ReplaceInput(1, mleft.right().node());
     714          13 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     715          13 :       Reduction const reduction = ReduceInt32Sub(node);
     716          13 :       return reduction.Changed() ? reduction : Changed(node);
     717             :     }
     718             :   }
     719      446277 :   if (m.right().IsInt32Sub()) {
     720         618 :     Int32BinopMatcher mright(m.right().node());
     721         618 :     if (mright.left().Is(0)) {  // y + (0 - x) => y - x
     722          54 :       node->ReplaceInput(1, mright.right().node());
     723          54 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     724          54 :       Reduction const reduction = ReduceInt32Sub(node);
     725          54 :       return reduction.Changed() ? reduction : Changed(node);
     726             :     }
     727             :   }
     728             :   return NoChange();
     729             : }
     730             : 
     731      738261 : Reduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
     732             :   DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
     733      738261 :   Int64BinopMatcher m(node);
     734      738261 :   if (m.right().Is(0)) return Replace(m.left().node());  // x + 0 => 0
     735      737277 :   if (m.IsFoldable()) {
     736             :     return Replace(Uint64Constant(bit_cast<uint64_t>(m.left().Value()) +
     737       79934 :                                   bit_cast<uint64_t>(m.right().Value())));
     738             :   }
     739             :   return NoChange();
     740             : }
     741             : 
     742       66714 : Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
     743             :   DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
     744       66714 :   Int32BinopMatcher m(node);
     745       66715 :   if (m.right().Is(0)) return Replace(m.left().node());  // x - 0 => x
     746       66021 :   if (m.IsFoldable()) {                                  // K - K => K
     747       30291 :     return ReplaceInt32(static_cast<uint32_t>(m.left().Value()) -
     748       30291 :                         static_cast<uint32_t>(m.right().Value()));
     749             :   }
     750       35730 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);  // x - x => 0
     751       35728 :   if (m.right().HasValue()) {                       // x - K => x + -K
     752       27540 :     node->ReplaceInput(1, Int32Constant(-m.right().Value()));
     753       13770 :     NodeProperties::ChangeOp(node, machine()->Int32Add());
     754       13770 :     Reduction const reduction = ReduceInt32Add(node);
     755       13770 :     return reduction.Changed() ? reduction : Changed(node);
     756             :   }
     757             :   return NoChange();
     758             : }
     759             : 
     760      161572 : Reduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
     761             :   DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
     762      161572 :   Int64BinopMatcher m(node);
     763      161571 :   if (m.right().Is(0)) return Replace(m.left().node());  // x - 0 => x
     764      160593 :   if (m.IsFoldable()) {                                  // K - K => K
     765             :     return Replace(Uint64Constant(bit_cast<uint64_t>(m.left().Value()) -
     766       38394 :                                   bit_cast<uint64_t>(m.right().Value())));
     767             :   }
     768      122199 :   if (m.LeftEqualsRight()) return Replace(Int64Constant(0));  // x - x => 0
     769      122193 :   if (m.right().HasValue()) {                                 // x - K => x + -K
     770      117720 :     node->ReplaceInput(1, Int64Constant(-m.right().Value()));
     771      117722 :     NodeProperties::ChangeOp(node, machine()->Int64Add());
     772      117721 :     Reduction const reduction = ReduceInt64Add(node);
     773      117721 :     return reduction.Changed() ? reduction : Changed(node);
     774             :   }
     775             :   return NoChange();
     776             : }
     777             : 
     778       23532 : Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
     779       23532 :   Int32BinopMatcher m(node);
     780       23532 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 / x => 0
     781       23181 :   if (m.right().Is(0)) return Replace(m.right().node());  // x / 0 => 0
     782       23180 :   if (m.right().Is(1)) return Replace(m.left().node());   // x / 1 => x
     783       22783 :   if (m.IsFoldable()) {                                   // K / K => K
     784             :     return ReplaceInt32(
     785       19206 :         base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
     786             :   }
     787        3577 :   if (m.LeftEqualsRight()) {  // x / x => x != 0
     788             :     Node* const zero = Int32Constant(0);
     789           5 :     return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
     790             :   }
     791        3572 :   if (m.right().Is(-1)) {  // x / -1 => 0 - x
     792          34 :     node->ReplaceInput(0, Int32Constant(0));
     793          34 :     node->ReplaceInput(1, m.left().node());
     794          34 :     node->TrimInputCount(2);
     795          34 :     NodeProperties::ChangeOp(node, machine()->Int32Sub());
     796             :     return Changed(node);
     797             :   }
     798        3538 :   if (m.right().HasValue()) {
     799        3019 :     int32_t const divisor = m.right().Value();
     800             :     Node* const dividend = m.left().node();
     801             :     Node* quotient = dividend;
     802        3019 :     if (base::bits::IsPowerOfTwo(Abs(divisor))) {
     803         882 :       uint32_t const shift = WhichPowerOf2(Abs(divisor));
     804             :       DCHECK_NE(0u, shift);
     805         882 :       if (shift > 1) {
     806         699 :         quotient = Word32Sar(quotient, 31);
     807             :       }
     808         882 :       quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
     809         882 :       quotient = Word32Sar(quotient, shift);
     810             :     } else {
     811        2137 :       quotient = Int32Div(quotient, Abs(divisor));
     812             :     }
     813        3019 :     if (divisor < 0) {
     814        1297 :       node->ReplaceInput(0, Int32Constant(0));
     815        1297 :       node->ReplaceInput(1, quotient);
     816        1297 :       node->TrimInputCount(2);
     817        1297 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     818             :       return Changed(node);
     819             :     }
     820             :     return Replace(quotient);
     821             :   }
     822             :   return NoChange();
     823             : }
     824             : 
     825             : 
     826       22741 : Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
     827       22741 :   Uint32BinopMatcher m(node);
     828       22741 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 / x => 0
     829       22329 :   if (m.right().Is(0)) return Replace(m.right().node());  // x / 0 => 0
     830       22281 :   if (m.right().Is(1)) return Replace(m.left().node());   // x / 1 => x
     831       21878 :   if (m.IsFoldable()) {                                   // K / K => K
     832             :     return ReplaceUint32(
     833       21340 :         base::bits::UnsignedDiv32(m.left().Value(), m.right().Value()));
     834             :   }
     835         538 :   if (m.LeftEqualsRight()) {  // x / x => x != 0
     836             :     Node* const zero = Int32Constant(0);
     837           1 :     return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
     838             :   }
     839         537 :   if (m.right().HasValue()) {
     840             :     Node* const dividend = m.left().node();
     841         366 :     uint32_t const divisor = m.right().Value();
     842         366 :     if (base::bits::IsPowerOfTwo(divisor)) {  // x / 2^n => x >> n
     843         574 :       node->ReplaceInput(1, Uint32Constant(WhichPowerOf2(m.right().Value())));
     844         287 :       node->TrimInputCount(2);
     845         287 :       NodeProperties::ChangeOp(node, machine()->Word32Shr());
     846             :       return Changed(node);
     847             :     } else {
     848          79 :       return Replace(Uint32Div(dividend, divisor));
     849             :     }
     850             :   }
     851             :   return NoChange();
     852             : }
     853             : 
     854             : 
     855       34882 : Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
     856       34882 :   Int32BinopMatcher m(node);
     857       34882 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 % x  => 0
     858       34422 :   if (m.right().Is(0)) return Replace(m.right().node());  // x % 0  => 0
     859       34322 :   if (m.right().Is(1)) return ReplaceInt32(0);            // x % 1  => 0
     860       33947 :   if (m.right().Is(-1)) return ReplaceInt32(0);           // x % -1 => 0
     861       33604 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);        // x % x  => 0
     862       33593 :   if (m.IsFoldable()) {                                   // K % K => K
     863             :     return ReplaceInt32(
     864       28697 :         base::bits::SignedMod32(m.left().Value(), m.right().Value()));
     865             :   }
     866        4896 :   if (m.right().HasValue()) {
     867             :     Node* const dividend = m.left().node();
     868        4225 :     uint32_t const divisor = Abs(m.right().Value());
     869        4225 :     if (base::bits::IsPowerOfTwo(divisor)) {
     870        1114 :       uint32_t const mask = divisor - 1;
     871             :       Node* const zero = Int32Constant(0);
     872             :       Diamond d(graph(), common(),
     873             :                 graph()->NewNode(machine()->Int32LessThan(), dividend, zero),
     874        2228 :                 BranchHint::kFalse);
     875             :       return Replace(
     876             :           d.Phi(MachineRepresentation::kWord32,
     877             :                 Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
     878        1114 :                 Word32And(dividend, mask)));
     879             :     } else {
     880        3111 :       Node* quotient = Int32Div(dividend, divisor);
     881             :       DCHECK_EQ(dividend, node->InputAt(0));
     882        3111 :       node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
     883        3111 :       node->TrimInputCount(2);
     884        3111 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     885             :     }
     886             :     return Changed(node);
     887             :   }
     888             :   return NoChange();
     889             : }
     890             : 
     891             : 
     892       22928 : Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
     893       22928 :   Uint32BinopMatcher m(node);
     894       22928 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 % x => 0
     895       22482 :   if (m.right().Is(0)) return Replace(m.right().node());  // x % 0 => 0
     896       22434 :   if (m.right().Is(1)) return ReplaceUint32(0);           // x % 1 => 0
     897       22031 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);        // x % x  => 0
     898       22029 :   if (m.IsFoldable()) {                                   // K % K => K
     899             :     return ReplaceUint32(
     900       21382 :         base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
     901             :   }
     902         647 :   if (m.right().HasValue()) {
     903             :     Node* const dividend = m.left().node();
     904         511 :     uint32_t const divisor = m.right().Value();
     905         511 :     if (base::bits::IsPowerOfTwo(divisor)) {  // x % 2^n => x & 2^n-1
     906         540 :       node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
     907         270 :       node->TrimInputCount(2);
     908         270 :       NodeProperties::ChangeOp(node, machine()->Word32And());
     909             :     } else {
     910         241 :       Node* quotient = Uint32Div(dividend, divisor);
     911             :       DCHECK_EQ(dividend, node->InputAt(0));
     912         241 :       node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
     913         241 :       node->TrimInputCount(2);
     914         241 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     915             :     }
     916             :     return Changed(node);
     917             :   }
     918             :   return NoChange();
     919             : }
     920             : 
     921             : 
     922     1525464 : Reduction MachineOperatorReducer::ReduceStore(Node* node) {
     923             :   NodeMatcher nm(node);
     924             :   MachineRepresentation rep;
     925             :   int value_input;
     926     1525464 :   if (nm.IsCheckedStore()) {
     927       55186 :     rep = CheckedStoreRepresentationOf(node->op());
     928             :     value_input = 3;
     929     1470278 :   } else if (nm.IsStore()) {
     930     1470278 :     rep = StoreRepresentationOf(node->op()).representation();
     931             :     value_input = 2;
     932             :   } else {
     933             :     DCHECK(nm.IsUnalignedStore());
     934           0 :     rep = UnalignedStoreRepresentationOf(node->op());
     935             :     value_input = 2;
     936             :   }
     937             : 
     938     1525464 :   Node* const value = node->InputAt(value_input);
     939             : 
     940     1525464 :   switch (value->opcode()) {
     941             :     case IrOpcode::kWord32And: {
     942        1837 :       Uint32BinopMatcher m(value);
     943        4268 :       if (m.right().HasValue() && ((rep == MachineRepresentation::kWord8 &&
     944        1475 :                                     (m.right().Value() & 0xff) == 0xff) ||
     945         244 :                                    (rep == MachineRepresentation::kWord16 &&
     946         244 :                                     (m.right().Value() & 0xffff) == 0xffff))) {
     947         653 :         node->ReplaceInput(value_input, m.left().node());
     948         653 :         return Changed(node);
     949             :       }
     950        1184 :       break;
     951             :     }
     952             :     case IrOpcode::kWord32Sar: {
     953         485 :       Int32BinopMatcher m(value);
     954        1141 :       if (m.left().IsWord32Shl() && ((rep == MachineRepresentation::kWord8 &&
     955         268 :                                       m.right().IsInRange(1, 24)) ||
     956         259 :                                      (rep == MachineRepresentation::kWord16 &&
     957             :                                       m.right().IsInRange(1, 16)))) {
     958         430 :         Int32BinopMatcher mleft(m.left().node());
     959         430 :         if (mleft.right().Is(m.right().Value())) {
     960         430 :           node->ReplaceInput(value_input, mleft.left().node());
     961         430 :           return Changed(node);
     962             :         }
     963             :       }
     964          55 :       break;
     965             :     }
     966             :     default:
     967             :       break;
     968             :   }
     969             :   return NoChange();
     970             : }
     971             : 
     972             : 
     973      256815 : Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
     974      256815 :   switch (node->opcode()) {
     975             :     case IrOpcode::kInt32AddWithOverflow: {
     976             :       DCHECK(index == 0 || index == 1);
     977      111785 :       Int32BinopMatcher m(node);
     978      111786 :       if (m.IsFoldable()) {
     979             :         int32_t val;
     980             :         bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
     981       20016 :                                                    m.right().Value(), &val);
     982       20016 :         return ReplaceInt32(index == 0 ? val : ovf);
     983             :       }
     984       91770 :       if (m.right().Is(0)) {
     985          32 :         return Replace(index == 0 ? m.left().node() : m.right().node());
     986             :       }
     987       91738 :       break;
     988             :     }
     989             :     case IrOpcode::kInt32SubWithOverflow: {
     990             :       DCHECK(index == 0 || index == 1);
     991      116966 :       Int32BinopMatcher m(node);
     992      116966 :       if (m.IsFoldable()) {
     993             :         int32_t val;
     994             :         bool ovf = base::bits::SignedSubOverflow32(m.left().Value(),
     995       20042 :                                                    m.right().Value(), &val);
     996       20042 :         return ReplaceInt32(index == 0 ? val : ovf);
     997             :       }
     998       96924 :       if (m.right().Is(0)) {
     999           2 :         return Replace(index == 0 ? m.left().node() : m.right().node());
    1000             :       }
    1001       96922 :       break;
    1002             :     }
    1003             :     case IrOpcode::kInt32MulWithOverflow: {
    1004             :       DCHECK(index == 0 || index == 1);
    1005       26354 :       Int32BinopMatcher m(node);
    1006       26354 :       if (m.IsFoldable()) {
    1007             :         int32_t val;
    1008             :         bool ovf = base::bits::SignedMulOverflow32(m.left().Value(),
    1009       20316 :                                                    m.right().Value(), &val);
    1010       20316 :         return ReplaceInt32(index == 0 ? val : ovf);
    1011             :       }
    1012        6038 :       if (m.right().Is(0)) {
    1013             :         return Replace(m.right().node());
    1014             :       }
    1015        5962 :       if (m.right().Is(1)) {
    1016          76 :         return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
    1017             :       }
    1018        5886 :       break;
    1019             :     }
    1020             :     default:
    1021             :       break;
    1022             :   }
    1023             :   return NoChange();
    1024             : }
    1025             : 
    1026             : 
    1027       65395 : Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
    1028             :   DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
    1029             :          (node->opcode() == IrOpcode::kWord32Shr) ||
    1030             :          (node->opcode() == IrOpcode::kWord32Sar));
    1031       65395 :   if (machine()->Word32ShiftIsSafe()) {
    1032             :     // Remove the explicit 'and' with 0x1f if the shift provided by the machine
    1033             :     // instruction matches that required by JavaScript.
    1034       65017 :     Int32BinopMatcher m(node);
    1035       65017 :     if (m.right().IsWord32And()) {
    1036        2453 :       Int32BinopMatcher mright(m.right().node());
    1037        2453 :       if (mright.right().Is(0x1f)) {
    1038        1075 :         node->ReplaceInput(1, mright.left().node());
    1039        1075 :         return Changed(node);
    1040             :       }
    1041             :     }
    1042             :   }
    1043             :   return NoChange();
    1044             : }
    1045             : 
    1046             : 
    1047       40321 : Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
    1048             :   DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
    1049       40321 :   Int32BinopMatcher m(node);
    1050       40321 :   if (m.right().Is(0)) return Replace(m.left().node());  // x << 0 => x
    1051       39530 :   if (m.IsFoldable()) {                                  // K << K => K
    1052       11997 :     return ReplaceInt32(m.left().Value() << m.right().Value());
    1053             :   }
    1054       27533 :   if (m.right().IsInRange(1, 31)) {
    1055             :     // (x >>> K) << K => x & ~(2^K - 1)
    1056             :     // (x >> K) << K => x & ~(2^K - 1)
    1057       23726 :     if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
    1058        4207 :       Int32BinopMatcher mleft(m.left().node());
    1059        4207 :       if (mleft.right().Is(m.right().Value())) {
    1060        3233 :         node->ReplaceInput(0, mleft.left().node());
    1061             :         node->ReplaceInput(1,
    1062        6466 :                            Uint32Constant(~((1U << m.right().Value()) - 1U)));
    1063        3233 :         NodeProperties::ChangeOp(node, machine()->Word32And());
    1064        3233 :         Reduction reduction = ReduceWord32And(node);
    1065        3233 :         return reduction.Changed() ? reduction : Changed(node);
    1066             :       }
    1067             :     }
    1068             :   }
    1069       24300 :   return ReduceWord32Shifts(node);
    1070             : }
    1071             : 
    1072      217351 : Reduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
    1073             :   DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
    1074      217351 :   Int64BinopMatcher m(node);
    1075      217352 :   if (m.right().Is(0)) return Replace(m.left().node());  // x << 0 => x
    1076      216860 :   if (m.IsFoldable()) {                                  // K << K => K
    1077       76385 :     return ReplaceInt64(m.left().Value() << m.right().Value());
    1078             :   }
    1079             :   return NoChange();
    1080             : }
    1081             : 
    1082       47454 : Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
    1083       47454 :   Uint32BinopMatcher m(node);
    1084       47454 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >>> 0 => x
    1085       29921 :   if (m.IsFoldable()) {                                  // K >>> K => K
    1086       11758 :     return ReplaceInt32(m.left().Value() >> m.right().Value());
    1087             :   }
    1088       18163 :   if (m.left().IsWord32And() && m.right().HasValue()) {
    1089         261 :     Uint32BinopMatcher mleft(m.left().node());
    1090         261 :     if (mleft.right().HasValue()) {
    1091         258 :       uint32_t shift = m.right().Value() & 0x1f;
    1092         258 :       uint32_t mask = mleft.right().Value();
    1093         258 :       if ((mask >> shift) == 0) {
    1094             :         // (m >>> s) == 0 implies ((x & m) >>> s) == 0
    1095          31 :         return ReplaceInt32(0);
    1096             :       }
    1097             :     }
    1098             :   }
    1099       18132 :   return ReduceWord32Shifts(node);
    1100             : }
    1101             : 
    1102       31116 : Reduction MachineOperatorReducer::ReduceWord64Shr(Node* node) {
    1103             :   DCHECK_EQ(IrOpcode::kWord64Shr, node->opcode());
    1104       31116 :   Uint64BinopMatcher m(node);
    1105       31116 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >>> 0 => x
    1106       30624 :   if (m.IsFoldable()) {                                  // K >> K => K
    1107       30618 :     return ReplaceInt64(m.left().Value() >> m.right().Value());
    1108             :   }
    1109             :   return NoChange();
    1110             : }
    1111             : 
    1112       35950 : Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
    1113       35950 :   Int32BinopMatcher m(node);
    1114       35950 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >> 0 => x
    1115       35059 :   if (m.IsFoldable()) {                                  // K >> K => K
    1116       12033 :     return ReplaceInt32(m.left().Value() >> m.right().Value());
    1117             :   }
    1118       23026 :   if (m.left().IsWord32Shl()) {
    1119        1651 :     Int32BinopMatcher mleft(m.left().node());
    1120        1651 :     if (mleft.left().IsComparison()) {
    1121         122 :       if (m.right().Is(31) && mleft.right().Is(31)) {
    1122             :         // Comparison << 31 >> 31 => 0 - Comparison
    1123          61 :         node->ReplaceInput(0, Int32Constant(0));
    1124          61 :         node->ReplaceInput(1, mleft.left().node());
    1125          61 :         NodeProperties::ChangeOp(node, machine()->Int32Sub());
    1126          61 :         Reduction const reduction = ReduceInt32Sub(node);
    1127          61 :         return reduction.Changed() ? reduction : Changed(node);
    1128             :       }
    1129        1590 :     } else if (mleft.left().IsLoad()) {
    1130             :       LoadRepresentation const rep =
    1131           2 :           LoadRepresentationOf(mleft.left().node()->op());
    1132           4 :       if (m.right().Is(24) && mleft.right().Is(24) &&
    1133             :           rep == MachineType::Int8()) {
    1134             :         // Load[kMachInt8] << 24 >> 24 => Load[kMachInt8]
    1135             :         return Replace(mleft.left().node());
    1136             :       }
    1137           3 :       if (m.right().Is(16) && mleft.right().Is(16) &&
    1138             :           rep == MachineType::Int16()) {
    1139             :         // Load[kMachInt16] << 16 >> 16 => Load[kMachInt8]
    1140             :         return Replace(mleft.left().node());
    1141             :       }
    1142             :     }
    1143             :   }
    1144       22963 :   return ReduceWord32Shifts(node);
    1145             : }
    1146             : 
    1147      197762 : Reduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
    1148      197762 :   Int64BinopMatcher m(node);
    1149      197762 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >> 0 => x
    1150      197270 :   if (m.IsFoldable()) {
    1151       30626 :     return ReplaceInt64(m.left().Value() >> m.right().Value());
    1152             :   }
    1153             :   return NoChange();
    1154             : }
    1155             : 
    1156      520904 : Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
    1157             :   DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
    1158      520904 :   Int32BinopMatcher m(node);
    1159      520904 :   if (m.right().Is(0)) return Replace(m.right().node());  // x & 0  => 0
    1160      518943 :   if (m.right().Is(-1)) return Replace(m.left().node());  // x & -1 => x
    1161      520637 :   if (m.left().IsComparison() && m.right().Is(1)) {       // CMP & 1 => CMP
    1162             :     return Replace(m.left().node());
    1163             :   }
    1164      518231 :   if (m.IsFoldable()) {                                   // K & K  => K
    1165       33234 :     return ReplaceInt32(m.left().Value() & m.right().Value());
    1166             :   }
    1167      484997 :   if (m.LeftEqualsRight()) return Replace(m.left().node());  // x & x => x
    1168      484974 :   if (m.left().IsWord32And() && m.right().HasValue()) {
    1169       19762 :     Int32BinopMatcher mleft(m.left().node());
    1170       19762 :     if (mleft.right().HasValue()) {  // (x & K) & K => x & K
    1171       19746 :       node->ReplaceInput(0, mleft.left().node());
    1172             :       node->ReplaceInput(
    1173       39492 :           1, Int32Constant(m.right().Value() & mleft.right().Value()));
    1174       19746 :       Reduction const reduction = ReduceWord32And(node);
    1175       19746 :       return reduction.Changed() ? reduction : Changed(node);
    1176             :     }
    1177             :   }
    1178      465228 :   if (m.right().IsNegativePowerOf2()) {
    1179      328424 :     int32_t const mask = m.right().Value();
    1180      328424 :     if (m.left().IsWord32Shl()) {
    1181        2578 :       Uint32BinopMatcher mleft(m.left().node());
    1182        5156 :       if (mleft.right().HasValue() &&
    1183        2578 :           (mleft.right().Value() & 0x1f) >=
    1184        2578 :               base::bits::CountTrailingZeros32(mask)) {
    1185             :         // (x << L) & (-1 << K) => x << L iff L >= K
    1186        2576 :         return Replace(mleft.node());
    1187             :       }
    1188      325846 :     } else if (m.left().IsInt32Add()) {
    1189      123584 :       Int32BinopMatcher mleft(m.left().node());
    1190      221577 :       if (mleft.right().HasValue() &&
    1191       97993 :           (mleft.right().Value() & mask) == mleft.right().Value()) {
    1192             :         // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
    1193       97758 :         node->ReplaceInput(0, Word32And(mleft.left().node(), m.right().node()));
    1194       97758 :         node->ReplaceInput(1, mleft.right().node());
    1195       97758 :         NodeProperties::ChangeOp(node, machine()->Int32Add());
    1196       97758 :         Reduction const reduction = ReduceInt32Add(node);
    1197       97758 :         return reduction.Changed() ? reduction : Changed(node);
    1198             :       }
    1199       25826 :       if (mleft.left().IsInt32Mul()) {
    1200        2924 :         Int32BinopMatcher mleftleft(mleft.left().node());
    1201        5848 :         if (mleftleft.right().IsMultipleOf(-mask)) {
    1202             :           // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
    1203             :           node->ReplaceInput(0,
    1204        2923 :                              Word32And(mleft.right().node(), m.right().node()));
    1205        2923 :           node->ReplaceInput(1, mleftleft.node());
    1206        2923 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1207        2923 :           Reduction const reduction = ReduceInt32Add(node);
    1208        2923 :           return reduction.Changed() ? reduction : Changed(node);
    1209             :         }
    1210             :       }
    1211       22903 :       if (mleft.right().IsInt32Mul()) {
    1212        8797 :         Int32BinopMatcher mleftright(mleft.right().node());
    1213       17594 :         if (mleftright.right().IsMultipleOf(-mask)) {
    1214             :           // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
    1215             :           node->ReplaceInput(0,
    1216        8783 :                              Word32And(mleft.left().node(), m.right().node()));
    1217        8783 :           node->ReplaceInput(1, mleftright.node());
    1218        8783 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1219        8783 :           Reduction const reduction = ReduceInt32Add(node);
    1220        8783 :           return reduction.Changed() ? reduction : Changed(node);
    1221             :         }
    1222             :       }
    1223       14120 :       if (mleft.left().IsWord32Shl()) {
    1224          38 :         Int32BinopMatcher mleftleft(mleft.left().node());
    1225         114 :         if (mleftleft.right().Is(base::bits::CountTrailingZeros32(mask))) {
    1226             :           // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
    1227             :           node->ReplaceInput(0,
    1228          31 :                              Word32And(mleft.right().node(), m.right().node()));
    1229          31 :           node->ReplaceInput(1, mleftleft.node());
    1230          31 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1231          31 :           Reduction const reduction = ReduceInt32Add(node);
    1232          31 :           return reduction.Changed() ? reduction : Changed(node);
    1233             :         }
    1234             :       }
    1235       14089 :       if (mleft.right().IsWord32Shl()) {
    1236        8645 :         Int32BinopMatcher mleftright(mleft.right().node());
    1237       25935 :         if (mleftright.right().Is(base::bits::CountTrailingZeros32(mask))) {
    1238             :           // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
    1239             :           node->ReplaceInput(0,
    1240        3287 :                              Word32And(mleft.left().node(), m.right().node()));
    1241        3287 :           node->ReplaceInput(1, mleftright.node());
    1242        3287 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1243        3287 :           Reduction const reduction = ReduceInt32Add(node);
    1244        3287 :           return reduction.Changed() ? reduction : Changed(node);
    1245             :         }
    1246             :       }
    1247      202262 :     } else if (m.left().IsInt32Mul()) {
    1248        5953 :       Int32BinopMatcher mleft(m.left().node());
    1249       11906 :       if (mleft.right().IsMultipleOf(-mask)) {
    1250             :         // (x * (K << L)) & (-1 << L) => x * (K << L)
    1251        5904 :         return Replace(mleft.node());
    1252             :       }
    1253             :     }
    1254             :   }
    1255             :   return NoChange();
    1256             : }
    1257             : 
    1258       19204 : Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
    1259             :   DCHECK(IrOpcode::kWord32Or == node->opcode() ||
    1260             :          IrOpcode::kWord32Xor == node->opcode());
    1261       19204 :   Int32BinopMatcher m(node);
    1262             :   Node* shl = nullptr;
    1263             :   Node* shr = nullptr;
    1264             :   // Recognize rotation, we are matching:
    1265             :   //  * x << y | x >>> (32 - y) => x ror (32 - y), i.e  x rol y
    1266             :   //  * x << (32 - y) | x >>> y => x ror y
    1267             :   //  * x << y ^ x >>> (32 - y) => x ror (32 - y), i.e. x rol y
    1268             :   //  * x << (32 - y) ^ x >>> y => x ror y
    1269             :   // as well as their commuted form.
    1270       23753 :   if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
    1271             :     shl = m.left().node();
    1272             :     shr = m.right().node();
    1273       18947 :   } else if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
    1274             :     shl = m.right().node();
    1275             :     shr = m.left().node();
    1276             :   } else {
    1277             :     return NoChange();
    1278             :   }
    1279             : 
    1280         693 :   Int32BinopMatcher mshl(shl);
    1281         693 :   Int32BinopMatcher mshr(shr);
    1282         693 :   if (mshl.left().node() != mshr.left().node()) return NoChange();
    1283             : 
    1284         504 :   if (mshl.right().HasValue() && mshr.right().HasValue()) {
    1285             :     // Case where y is a constant.
    1286         370 :     if (mshl.right().Value() + mshr.right().Value() != 32) return NoChange();
    1287             :   } else {
    1288             :     Node* sub = nullptr;
    1289             :     Node* y = nullptr;
    1290         134 :     if (mshl.right().IsInt32Sub()) {
    1291             :       sub = mshl.right().node();
    1292             :       y = mshr.right().node();
    1293         124 :     } else if (mshr.right().IsInt32Sub()) {
    1294             :       sub = mshr.right().node();
    1295             :       y = mshl.right().node();
    1296             :     } else {
    1297          74 :       return NoChange();
    1298             :     }
    1299             : 
    1300          60 :     Int32BinopMatcher msub(sub);
    1301         120 :     if (!msub.left().Is(32) || msub.right().node() != y) return NoChange();
    1302             :   }
    1303             : 
    1304         430 :   node->ReplaceInput(0, mshl.left().node());
    1305         430 :   node->ReplaceInput(1, mshr.right().node());
    1306         430 :   NodeProperties::ChangeOp(node, machine()->Word32Ror());
    1307             :   return Changed(node);
    1308             : }
    1309             : 
    1310       55869 : Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
    1311             :   DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
    1312       55869 :   Int32BinopMatcher m(node);
    1313       55870 :   if (m.right().Is(0)) return Replace(m.left().node());    // x | 0  => x
    1314       39881 :   if (m.right().Is(-1)) return Replace(m.right().node());  // x | -1 => -1
    1315       36469 :   if (m.IsFoldable()) {                                    // K | K  => K
    1316       20621 :     return ReplaceInt32(m.left().Value() | m.right().Value());
    1317             :   }
    1318       15848 :   if (m.LeftEqualsRight()) return Replace(m.left().node());  // x | x => x
    1319             : 
    1320       15785 :   return TryMatchWord32Ror(node);
    1321             : }
    1322             : 
    1323       25034 : Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
    1324             :   DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
    1325       25034 :   Int32BinopMatcher m(node);
    1326       25034 :   if (m.right().Is(0)) return Replace(m.left().node());  // x ^ 0 => x
    1327       24436 :   if (m.IsFoldable()) {                                  // K ^ K => K
    1328       20988 :     return ReplaceInt32(m.left().Value() ^ m.right().Value());
    1329             :   }
    1330        3448 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);  // x ^ x => 0
    1331        3642 :   if (m.left().IsWord32Xor() && m.right().Is(-1)) {
    1332          11 :     Int32BinopMatcher mleft(m.left().node());
    1333          11 :     if (mleft.right().Is(-1)) {  // (x ^ -1) ^ -1 => x
    1334          11 :       return Replace(mleft.left().node());
    1335             :     }
    1336             :   }
    1337             : 
    1338        3419 :   return TryMatchWord32Ror(node);
    1339             : }
    1340             : 
    1341        4800 : Reduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) {
    1342             :   DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode());
    1343             :   Float64Matcher mlhs(node->InputAt(0));
    1344             :   Uint32Matcher mrhs(node->InputAt(1));
    1345        4800 :   if (mlhs.HasValue() && mrhs.HasValue()) {
    1346             :     return ReplaceFloat64(bit_cast<double>(
    1347        4800 :         (bit_cast<uint64_t>(mlhs.Value()) & V8_UINT64_C(0xFFFFFFFF00000000)) |
    1348             :         mrhs.Value()));
    1349             :   }
    1350             :   return NoChange();
    1351             : }
    1352             : 
    1353             : 
    1354        4800 : Reduction MachineOperatorReducer::ReduceFloat64InsertHighWord32(Node* node) {
    1355             :   DCHECK_EQ(IrOpcode::kFloat64InsertHighWord32, node->opcode());
    1356             :   Float64Matcher mlhs(node->InputAt(0));
    1357             :   Uint32Matcher mrhs(node->InputAt(1));
    1358        4800 :   if (mlhs.HasValue() && mrhs.HasValue()) {
    1359             :     return ReplaceFloat64(bit_cast<double>(
    1360        9600 :         (bit_cast<uint64_t>(mlhs.Value()) & V8_UINT64_C(0xFFFFFFFF)) |
    1361        4800 :         (static_cast<uint64_t>(mrhs.Value()) << 32)));
    1362             :   }
    1363             :   return NoChange();
    1364             : }
    1365             : 
    1366             : 
    1367             : namespace {
    1368             : 
    1369             : bool IsFloat64RepresentableAsFloat32(const Float64Matcher& m) {
    1370      167528 :   if (m.HasValue()) {
    1371       74084 :     double v = m.Value();
    1372       74084 :     float fv = static_cast<float>(v);
    1373       74084 :     return static_cast<double>(fv) == v;
    1374             :   }
    1375             :   return false;
    1376             : }
    1377             : 
    1378             : }  // namespace
    1379             : 
    1380             : 
    1381      169242 : Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
    1382             :   DCHECK((IrOpcode::kFloat64Equal == node->opcode()) ||
    1383             :          (IrOpcode::kFloat64LessThan == node->opcode()) ||
    1384             :          (IrOpcode::kFloat64LessThanOrEqual == node->opcode()));
    1385             :   // As all Float32 values have an exact representation in Float64, comparing
    1386             :   // two Float64 values both converted from Float32 is equivalent to comparing
    1387             :   // the original Float32s, so we can ignore the conversions. We can also reduce
    1388             :   // comparisons of converted Float64 values against constants that can be
    1389             :   // represented exactly as Float32.
    1390      167910 :   Float64BinopMatcher m(node);
    1391      169291 :   if ((m.left().IsChangeFloat32ToFloat64() &&
    1392      167224 :        m.right().IsChangeFloat32ToFloat64()) ||
    1393         693 :       (m.left().IsChangeFloat32ToFloat64() &&
    1394      334746 :        IsFloat64RepresentableAsFloat32(m.right())) ||
    1395       71788 :       (IsFloat64RepresentableAsFloat32(m.left()) &&
    1396             :        m.right().IsChangeFloat32ToFloat64())) {
    1397        1332 :     switch (node->opcode()) {
    1398             :       case IrOpcode::kFloat64Equal:
    1399         312 :         NodeProperties::ChangeOp(node, machine()->Float32Equal());
    1400         312 :         break;
    1401             :       case IrOpcode::kFloat64LessThan:
    1402         720 :         NodeProperties::ChangeOp(node, machine()->Float32LessThan());
    1403         720 :         break;
    1404             :       case IrOpcode::kFloat64LessThanOrEqual:
    1405         300 :         NodeProperties::ChangeOp(node, machine()->Float32LessThanOrEqual());
    1406         300 :         break;
    1407             :       default:
    1408             :         return NoChange();
    1409             :     }
    1410             :     node->ReplaceInput(
    1411        1332 :         0, m.left().HasValue()
    1412         256 :                ? Float32Constant(static_cast<float>(m.left().Value()))
    1413        2920 :                : m.left().InputAt(0));
    1414             :     node->ReplaceInput(
    1415        1332 :         1, m.right().HasValue()
    1416         389 :                ? Float32Constant(static_cast<float>(m.right().Value()))
    1417        3053 :                : m.right().InputAt(0));
    1418             :     return Changed(node);
    1419             :   }
    1420             :   return NoChange();
    1421             : }
    1422             : 
    1423       18166 : Reduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
    1424             :   DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
    1425             :   Float64Matcher m(node->InputAt(0));
    1426       18166 :   if (m.HasValue()) {
    1427             :     return ReplaceFloat64(Floor(m.Value()));
    1428             :   }
    1429             :   return NoChange();
    1430             : }
    1431             : 
    1432      631820 : CommonOperatorBuilder* MachineOperatorReducer::common() const {
    1433      631820 :   return jsgraph()->common();
    1434             : }
    1435             : 
    1436             : 
    1437      501266 : MachineOperatorBuilder* MachineOperatorReducer::machine() const {
    1438      501266 :   return jsgraph()->machine();
    1439             : }
    1440             : 
    1441             : 
    1442      779989 : Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); }
    1443             : 
    1444             : }  // namespace compiler
    1445             : }  // namespace internal
    1446             : }  // namespace v8

Generated by: LCOV version 1.10