LCOV - code coverage report
Current view: top level - src/compiler - machine-operator-reducer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 686 724 94.8 %
Date: 2019-04-17 Functions: 39 46 84.8 %

          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             : #include <cmath>
       7             : 
       8             : #include "src/base/bits.h"
       9             : #include "src/base/division-by-constant.h"
      10             : #include "src/base/ieee754.h"
      11             : #include "src/base/overflowing-math.h"
      12             : #include "src/compiler/diamond.h"
      13             : #include "src/compiler/graph.h"
      14             : #include "src/compiler/machine-graph.h"
      15             : #include "src/compiler/node-matchers.h"
      16             : #include "src/compiler/node-properties.h"
      17             : #include "src/conversions-inl.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : namespace compiler {
      22             : 
      23     2150104 : MachineOperatorReducer::MachineOperatorReducer(Editor* editor,
      24             :                                                MachineGraph* mcgraph,
      25             :                                                bool allow_signalling_nan)
      26             :     : AdvancedReducer(editor),
      27             :       mcgraph_(mcgraph),
      28     2150104 :       allow_signalling_nan_(allow_signalling_nan) {}
      29             : 
      30             : MachineOperatorReducer::~MachineOperatorReducer() = default;
      31             : 
      32             : 
      33       66860 : Node* MachineOperatorReducer::Float32Constant(volatile float value) {
      34      133720 :   return graph()->NewNode(common()->Float32Constant(value));
      35             : }
      36             : 
      37             : 
      38           0 : Node* MachineOperatorReducer::Float64Constant(volatile double value) {
      39       87566 :   return mcgraph()->Float64Constant(value);
      40             : }
      41             : 
      42             : 
      43           0 : Node* MachineOperatorReducer::Int32Constant(int32_t value) {
      44      533444 :   return mcgraph()->Int32Constant(value);
      45             : }
      46             : 
      47             : 
      48      546835 : Node* MachineOperatorReducer::Int64Constant(int64_t value) {
      49     1093670 :   return graph()->NewNode(common()->Int64Constant(value));
      50             : }
      51             : 
      52           0 : Node* MachineOperatorReducer::Float64Mul(Node* lhs, Node* rhs) {
      53           0 :   return graph()->NewNode(machine()->Float64Mul(), lhs, rhs);
      54             : }
      55             : 
      56           0 : Node* MachineOperatorReducer::Float64PowHalf(Node* value) {
      57             :   value =
      58           0 :       graph()->NewNode(machine()->Float64Add(), Float64Constant(0.0), value);
      59             :   Diamond d(graph(), common(),
      60             :             graph()->NewNode(machine()->Float64LessThanOrEqual(), value,
      61             :                              Float64Constant(-V8_INFINITY)),
      62           0 :             BranchHint::kFalse);
      63           0 :   return d.Phi(MachineRepresentation::kFloat64, Float64Constant(V8_INFINITY),
      64           0 :                graph()->NewNode(machine()->Float64Sqrt(), value));
      65             : }
      66             : 
      67       88604 : Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
      68       88604 :   Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
      69       88604 :   Reduction const reduction = ReduceWord32And(node);
      70       88604 :   return reduction.Changed() ? reduction.replacement() : node;
      71             : }
      72             : 
      73             : 
      74        5526 : Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
      75        5526 :   if (rhs == 0) return lhs;
      76       10730 :   return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
      77             : }
      78             : 
      79             : 
      80        7761 : Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
      81        7761 :   if (rhs == 0) return lhs;
      82       13348 :   return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs));
      83             : }
      84             : 
      85             : 
      86           4 : Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) {
      87           8 :   return graph()->NewNode(machine()->Word32Equal(), lhs, rhs);
      88             : }
      89             : 
      90             : 
      91        6192 : Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
      92        6192 :   Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
      93        6192 :   Reduction const reduction = ReduceInt32Add(node);
      94        6192 :   return reduction.Changed() ? reduction.replacement() : node;
      95             : }
      96             : 
      97             : 
      98        1524 : Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
      99        1524 :   Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
     100        1524 :   Reduction const reduction = ReduceInt32Sub(node);
     101        1524 :   return reduction.Changed() ? reduction.replacement() : node;
     102             : }
     103             : 
     104             : 
     105        3447 : Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
     106        6894 :   return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
     107             : }
     108             : 
     109             : 
     110        4149 : Node* MachineOperatorReducer::Int32Div(Node* dividend, int32_t divisor) {
     111             :   DCHECK_NE(0, divisor);
     112             :   DCHECK_NE(std::numeric_limits<int32_t>::min(), divisor);
     113             :   base::MagicNumbersForDivision<uint32_t> const mag =
     114        4149 :       base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
     115        4149 :   Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
     116             :                                     Uint32Constant(mag.multiplier));
     117        4149 :   if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
     118        1275 :     quotient = Int32Add(quotient, dividend);
     119        2874 :   } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
     120           0 :     quotient = Int32Sub(quotient, dividend);
     121             :   }
     122        4149 :   return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
     123             : }
     124             : 
     125             : 
     126        1422 : Node* MachineOperatorReducer::Uint32Div(Node* dividend, uint32_t divisor) {
     127             :   DCHECK_LT(0u, divisor);
     128             :   // If the divisor is even, we can avoid using the expensive fixup by shifting
     129             :   // the dividend upfront.
     130             :   unsigned const shift = base::bits::CountTrailingZeros(divisor);
     131        1422 :   dividend = Word32Shr(dividend, shift);
     132        1422 :   divisor >>= shift;
     133             :   // Compute the magic number for the (shifted) divisor.
     134             :   base::MagicNumbersForDivision<uint32_t> const mag =
     135        1422 :       base::UnsignedDivisionByConstant(divisor, shift);
     136        1422 :   Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
     137        1422 :                                     Uint32Constant(mag.multiplier));
     138        1422 :   if (mag.add) {
     139             :     DCHECK_LE(1u, mag.shift);
     140          24 :     quotient = Word32Shr(
     141             :         Int32Add(Word32Shr(Int32Sub(dividend, quotient), 1), quotient),
     142          24 :         mag.shift - 1);
     143             :   } else {
     144        1398 :     quotient = Word32Shr(quotient, mag.shift);
     145             :   }
     146        1422 :   return quotient;
     147             : }
     148             : 
     149             : 
     150             : // Perform constant folding and strength reduction on machine operators.
     151   163269373 : Reduction MachineOperatorReducer::Reduce(Node* node) {
     152   163269373 :   switch (node->opcode()) {
     153             :     case IrOpcode::kProjection:
     154      390899 :       return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
     155             :     case IrOpcode::kWord32And:
     156      645360 :       return ReduceWord32And(node);
     157             :     case IrOpcode::kWord32Or:
     158       81303 :       return ReduceWord32Or(node);
     159             :     case IrOpcode::kWord32Xor:
     160       23722 :       return ReduceWord32Xor(node);
     161             :     case IrOpcode::kWord32Shl:
     162       41600 :       return ReduceWord32Shl(node);
     163             :     case IrOpcode::kWord64Shl:
     164      699951 :       return ReduceWord64Shl(node);
     165             :     case IrOpcode::kWord32Shr:
     166       81111 :       return ReduceWord32Shr(node);
     167             :     case IrOpcode::kWord64Shr:
     168       50050 :       return ReduceWord64Shr(node);
     169             :     case IrOpcode::kWord32Sar:
     170       39183 :       return ReduceWord32Sar(node);
     171             :     case IrOpcode::kWord64Sar:
     172      479112 :       return ReduceWord64Sar(node);
     173             :     case IrOpcode::kWord32Ror: {
     174        2261 :       Int32BinopMatcher m(node);
     175        3805 :       if (m.right().Is(0)) return Replace(m.left().node());  // x ror 0 => x
     176        2212 :       if (m.IsFoldable()) {                                  // K ror K => K
     177        1495 :         return ReplaceInt32(base::bits::RotateRight32(m.left().Value(),
     178        2990 :                                                       m.right().Value() & 31));
     179             :       }
     180         717 :       break;
     181             :     }
     182             :     case IrOpcode::kWord32Equal: {
     183     1266737 :       Int32BinopMatcher m(node);
     184     1266737 :       if (m.IsFoldable()) {  // K == K => K
     185       64870 :         return ReplaceBool(m.left().Value() == m.right().Value());
     186             :       }
     187     1236223 :       if (m.left().IsInt32Sub() && m.right().Is(0)) {  // x - y == 0 => x == y
     188         838 :         Int32BinopMatcher msub(m.left().node());
     189         838 :         node->ReplaceInput(0, msub.left().node());
     190         838 :         node->ReplaceInput(1, msub.right().node());
     191             :         return Changed(node);
     192             :       }
     193             :       // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
     194     1233894 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x == x => true
     195     1233872 :       break;
     196             :     }
     197             :     case IrOpcode::kWord64Equal: {
     198     2952591 :       Int64BinopMatcher m(node);
     199     2952592 :       if (m.IsFoldable()) {  // K == K => K
     200       15529 :         return ReplaceBool(m.left().Value() == m.right().Value());
     201             :       }
     202     2957242 :       if (m.left().IsInt64Sub() && m.right().Is(0)) {  // x - y == 0 => x == y
     203         728 :         Int64BinopMatcher msub(m.left().node());
     204         728 :         node->ReplaceInput(0, msub.left().node());
     205         728 :         node->ReplaceInput(1, msub.right().node());
     206             :         return Changed(node);
     207             :       }
     208             :       // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
     209     2949030 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x == x => true
     210     2939897 :       break;
     211             :     }
     212             :     case IrOpcode::kInt32Add:
     213      453967 :       return ReduceInt32Add(node);
     214             :     case IrOpcode::kInt64Add:
     215     1551908 :       return ReduceInt64Add(node);
     216             :     case IrOpcode::kInt32Sub:
     217       62838 :       return ReduceInt32Sub(node);
     218             :     case IrOpcode::kInt64Sub:
     219      313171 :       return ReduceInt64Sub(node);
     220             :     case IrOpcode::kInt32Mul: {
     221       46743 :       Int32BinopMatcher m(node);
     222       67478 :       if (m.right().Is(0)) return Replace(m.right().node());  // x * 0 => 0
     223       46378 :       if (m.right().Is(1)) return Replace(m.left().node());   // x * 1 => x
     224       46077 :       if (m.IsFoldable()) {                                   // K * K => K
     225             :         return ReplaceInt32(
     226       18132 :             base::MulWithWraparound(m.left().Value(), m.right().Value()));
     227             :       }
     228       27945 :       if (m.right().Is(-1)) {  // x * -1 => 0 - x
     229          70 :         node->ReplaceInput(0, Int32Constant(0));
     230          70 :         node->ReplaceInput(1, m.left().node());
     231          70 :         NodeProperties::ChangeOp(node, machine()->Int32Sub());
     232             :         return Changed(node);
     233             :       }
     234       27875 :       if (m.right().IsPowerOf2()) {  // x * 2^n => x << n
     235        3734 :         node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
     236        1867 :         NodeProperties::ChangeOp(node, machine()->Word32Shl());
     237        1867 :         Reduction reduction = ReduceWord32Shl(node);
     238        1867 :         return reduction.Changed() ? reduction : Changed(node);
     239             :       }
     240       26008 :       break;
     241             :     }
     242             :     case IrOpcode::kInt32MulWithOverflow: {
     243        9325 :       Int32BinopMatcher m(node);
     244        9325 :       if (m.right().Is(2)) {
     245         389 :         node->ReplaceInput(1, m.left().node());
     246         389 :         NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
     247        3535 :         return Changed(node);
     248             :       }
     249        8936 :       if (m.right().Is(-1)) {
     250        3146 :         node->ReplaceInput(0, Int32Constant(0));
     251        3146 :         node->ReplaceInput(1, m.left().node());
     252        3146 :         NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
     253             :         return Changed(node);
     254             :       }
     255        5790 :       break;
     256             :     }
     257             :     case IrOpcode::kInt32Div:
     258       20534 :       return ReduceInt32Div(node);
     259             :     case IrOpcode::kUint32Div:
     260       19323 :       return ReduceUint32Div(node);
     261             :     case IrOpcode::kInt32Mod:
     262       30527 :       return ReduceInt32Mod(node);
     263             :     case IrOpcode::kUint32Mod:
     264       21497 :       return ReduceUint32Mod(node);
     265             :     case IrOpcode::kInt32LessThan: {
     266      371033 :       Int32BinopMatcher m(node);
     267      371072 :       if (m.IsFoldable()) {  // K < K => K
     268       40107 :         return ReplaceBool(m.left().Value() < m.right().Value());
     269             :       }
     270      351059 :       if (m.LeftEqualsRight()) return ReplaceBool(false);  // x < x => false
     271      353252 :       if (m.left().IsWord32Or() && m.right().Is(0)) {
     272             :         // (x | K) < 0 => true or (K | x) < 0 => true iff K < 0
     273        2170 :         Int32BinopMatcher mleftmatcher(m.left().node());
     274        4340 :         if (mleftmatcher.left().IsNegative() ||
     275             :             mleftmatcher.right().IsNegative()) {
     276          69 :           return ReplaceBool(true);
     277             :         }
     278             :       }
     279      350978 :       break;
     280             :     }
     281             :     case IrOpcode::kInt32LessThanOrEqual: {
     282       49977 :       Int32BinopMatcher m(node);
     283       49977 :       if (m.IsFoldable()) {  // K <= K => K
     284       35625 :         return ReplaceBool(m.left().Value() <= m.right().Value());
     285             :       }
     286       32167 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x <= x => true
     287       32162 :       break;
     288             :     }
     289             :     case IrOpcode::kUint32LessThan: {
     290      271654 :       Uint32BinopMatcher m(node);
     291      293402 :       if (m.left().Is(kMaxUInt32)) return ReplaceBool(false);  // M < x => false
     292      271342 :       if (m.right().Is(0)) return ReplaceBool(false);          // x < 0 => false
     293      270911 :       if (m.IsFoldable()) {                                    // K < K => K
     294       20557 :         return ReplaceBool(m.left().Value() < m.right().Value());
     295             :       }
     296      250354 :       if (m.LeftEqualsRight()) return ReplaceBool(false);  // x < x => false
     297      250203 :       if (m.left().IsWord32Sar() && m.right().HasValue()) {
     298         363 :         Int32BinopMatcher mleft(m.left().node());
     299         363 :         if (mleft.right().HasValue()) {
     300             :           // (x >> K) < C => x < (C << K)
     301             :           // when C < (M >> K)
     302         363 :           const uint32_t c = m.right().Value();
     303         363 :           const uint32_t k = mleft.right().Value() & 0x1F;
     304         363 :           if (c < static_cast<uint32_t>(kMaxInt >> k)) {
     305         299 :             node->ReplaceInput(0, mleft.left().node());
     306         598 :             node->ReplaceInput(1, Uint32Constant(c << k));
     307         299 :             return Changed(node);
     308             :           }
     309             :           // TODO(turbofan): else the comparison is always true.
     310             :         }
     311             :       }
     312      249904 :       break;
     313             :     }
     314             :     case IrOpcode::kUint32LessThanOrEqual: {
     315       91622 :       Uint32BinopMatcher m(node);
     316      108774 :       if (m.left().Is(0)) return ReplaceBool(true);            // 0 <= x => true
     317       91208 :       if (m.right().Is(kMaxUInt32)) return ReplaceBool(true);  // x <= M => true
     318       90918 :       if (m.IsFoldable()) {                                    // K <= K => K
     319       16442 :         return ReplaceBool(m.left().Value() <= m.right().Value());
     320             :       }
     321       74476 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x <= x => true
     322       74470 :       break;
     323             :     }
     324             :     case IrOpcode::kFloat32Sub: {
     325       66141 :       Float32BinopMatcher m(node);
     326      133432 :       if (allow_signalling_nan_ && m.right().Is(0) &&
     327        1150 :           (std::copysign(1.0, m.right().Value()) > 0)) {
     328       66136 :         return Replace(m.left().node());  // x - 0 => x
     329             :       }
     330       65566 :       if (m.right().IsNaN()) {  // x - NaN => NaN
     331             :         // Do some calculation to make a signalling NaN quiet.
     332        1155 :         return ReplaceFloat32(m.right().Value() - m.right().Value());
     333             :       }
     334       64411 :       if (m.left().IsNaN()) {  // NaN - x => NaN
     335             :         // Do some calculation to make a signalling NaN quiet.
     336        1125 :         return ReplaceFloat32(m.left().Value() - m.left().Value());
     337             :       }
     338       63286 :       if (m.IsFoldable()) {  // L - R => (L - R)
     339       63280 :         return ReplaceFloat32(m.left().Value() - m.right().Value());
     340             :       }
     341           6 :       if (allow_signalling_nan_ && m.left().IsMinusZero()) {
     342             :         // -0.0 - round_down(-0.0 - R) => round_up(R)
     343           1 :         if (machine()->Float32RoundUp().IsSupported() &&
     344             :             m.right().IsFloat32RoundDown()) {
     345           0 :           if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat32Sub) {
     346           0 :             Float32BinopMatcher mright0(m.right().InputAt(0));
     347           0 :             if (mright0.left().IsMinusZero()) {
     348           0 :               return Replace(graph()->NewNode(machine()->Float32RoundUp().op(),
     349             :                                               mright0.right().node()));
     350             :             }
     351             :           }
     352             :         }
     353             :         // -0.0 - R => -R
     354           1 :         node->RemoveInput(0);
     355           1 :         NodeProperties::ChangeOp(node, machine()->Float32Neg());
     356             :         return Changed(node);
     357             :       }
     358           5 :       break;
     359             :     }
     360             :     case IrOpcode::kFloat64Add: {
     361      206342 :       Float64BinopMatcher m(node);
     362      206366 :       if (m.IsFoldable()) {  // K + K => K
     363       22064 :         return ReplaceFloat64(m.left().Value() + m.right().Value());
     364             :       }
     365      195334 :       break;
     366             :     }
     367             :     case IrOpcode::kFloat64Sub: {
     368       39639 :       Float64BinopMatcher m(node);
     369       79793 :       if (allow_signalling_nan_ && m.right().Is(0) &&
     370         515 :           (Double(m.right().Value()).Sign() > 0)) {
     371       20671 :         return Replace(m.left().node());  // x - 0 => x
     372             :       }
     373       39369 :       if (m.right().IsNaN()) {  // x - NaN => NaN
     374             :         // Do some calculation to make a signalling NaN quiet.
     375         509 :         return ReplaceFloat64(m.right().Value() - m.right().Value());
     376             :       }
     377       38860 :       if (m.left().IsNaN()) {  // NaN - x => NaN
     378             :         // Do some calculation to make a signalling NaN quiet.
     379         479 :         return ReplaceFloat64(m.left().Value() - m.left().Value());
     380             :       }
     381       38381 :       if (m.IsFoldable()) {  // L - R => (L - R)
     382       10989 :         return ReplaceFloat64(m.left().Value() - m.right().Value());
     383             :       }
     384       27392 :       if (allow_signalling_nan_ && m.left().IsMinusZero()) {
     385             :         // -0.0 - round_down(-0.0 - R) => round_up(R)
     386       16846 :         if (machine()->Float64RoundUp().IsSupported() &&
     387             :             m.right().IsFloat64RoundDown()) {
     388         630 :           if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub) {
     389           0 :             Float64BinopMatcher mright0(m.right().InputAt(0));
     390           0 :             if (mright0.left().IsMinusZero()) {
     391           0 :               return Replace(graph()->NewNode(machine()->Float64RoundUp().op(),
     392             :                                               mright0.right().node()));
     393             :             }
     394             :           }
     395             :         }
     396             :         // -0.0 - R => -R
     397        8424 :         node->RemoveInput(0);
     398        8424 :         NodeProperties::ChangeOp(node, machine()->Float64Neg());
     399             :         return Changed(node);
     400             :       }
     401       18968 :       break;
     402             :     }
     403             :     case IrOpcode::kFloat64Mul: {
     404       25398 :       Float64BinopMatcher m(node);
     405       50796 :       if (allow_signalling_nan_ && m.right().Is(1))
     406        9321 :         return Replace(m.left().node());  // x * 1.0 => x
     407       25349 :       if (m.right().Is(-1)) {  // x * -1.0 => -0.0 - x
     408        8586 :         node->ReplaceInput(0, Float64Constant(-0.0));
     409        8586 :         node->ReplaceInput(1, m.left().node());
     410        8586 :         NodeProperties::ChangeOp(node, machine()->Float64Sub());
     411             :         return Changed(node);
     412             :       }
     413       16763 :       if (m.right().IsNaN()) {                               // x * NaN => NaN
     414             :         // Do some calculation to make a signalling NaN quiet.
     415           7 :         return ReplaceFloat64(m.right().Value() - m.right().Value());
     416             :       }
     417       16756 :       if (m.IsFoldable()) {  // K * K => K
     418         544 :         return ReplaceFloat64(m.left().Value() * m.right().Value());
     419             :       }
     420       16212 :       if (m.right().Is(2)) {  // x * 2.0 => x + x
     421         135 :         node->ReplaceInput(1, m.left().node());
     422         135 :         NodeProperties::ChangeOp(node, machine()->Float64Add());
     423             :         return Changed(node);
     424             :       }
     425       16077 :       break;
     426             :     }
     427             :     case IrOpcode::kFloat64Div: {
     428       37942 :       Float64BinopMatcher m(node);
     429       75884 :       if (allow_signalling_nan_ && m.right().Is(1))
     430        4897 :         return Replace(m.left().node());  // x / 1.0 => x
     431             :       // TODO(ahaas): We could do x / 1.0 = x if we knew that x is not an sNaN.
     432       37810 :       if (m.right().IsNaN()) {                               // x / NaN => NaN
     433             :         // Do some calculation to make a signalling NaN quiet.
     434           0 :         return ReplaceFloat64(m.right().Value() - m.right().Value());
     435             :       }
     436       37810 :       if (m.left().IsNaN()) {  // NaN / x => NaN
     437             :         // Do some calculation to make a signalling NaN quiet.
     438           0 :         return ReplaceFloat64(m.left().Value() - m.left().Value());
     439             :       }
     440       37810 :       if (m.IsFoldable()) {  // K / K => K
     441             :         return ReplaceFloat64(
     442        1890 :             base::Divide(m.left().Value(), m.right().Value()));
     443             :       }
     444       71840 :       if (allow_signalling_nan_ && m.right().Is(-1)) {  // x / -1.0 => -x
     445          36 :         node->RemoveInput(1);
     446          36 :         NodeProperties::ChangeOp(node, machine()->Float64Neg());
     447             :         return Changed(node);
     448             :       }
     449       35884 :       if (m.right().IsNormal() && m.right().IsPositiveOrNegativePowerOf2()) {
     450             :         // All reciprocals of non-denormal powers of two can be represented
     451             :         // exactly, so division by power of two can be reduced to
     452             :         // multiplication by reciprocal, with the same result.
     453        5678 :         node->ReplaceInput(1, Float64Constant(1.0 / m.right().Value()));
     454        2839 :         NodeProperties::ChangeOp(node, machine()->Float64Mul());
     455             :         return Changed(node);
     456             :       }
     457       33045 :       break;
     458             :     }
     459             :     case IrOpcode::kFloat64Mod: {
     460        2313 :       Float64BinopMatcher m(node);
     461        2313 :       if (m.right().Is(0)) {  // x % 0 => NaN
     462          25 :         return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
     463             :       }
     464        2313 :       if (m.right().IsNaN()) {  // x % NaN => NaN
     465             :         return Replace(m.right().node());
     466             :       }
     467        2313 :       if (m.left().IsNaN()) {  // NaN % x => NaN
     468             :         return Replace(m.left().node());
     469             :       }
     470        2313 :       if (m.IsFoldable()) {  // K % K => K
     471          25 :         return ReplaceFloat64(Modulo(m.left().Value(), m.right().Value()));
     472             :       }
     473        2288 :       break;
     474             :     }
     475             :     case IrOpcode::kFloat64Acos: {
     476             :       Float64Matcher m(node->InputAt(0));
     477         156 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::acos(m.Value()));
     478             :       break;
     479             :     }
     480             :     case IrOpcode::kFloat64Acosh: {
     481             :       Float64Matcher m(node->InputAt(0));
     482         156 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::acosh(m.Value()));
     483             :       break;
     484             :     }
     485             :     case IrOpcode::kFloat64Asin: {
     486             :       Float64Matcher m(node->InputAt(0));
     487         163 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::asin(m.Value()));
     488             :       break;
     489             :     }
     490             :     case IrOpcode::kFloat64Asinh: {
     491             :       Float64Matcher m(node->InputAt(0));
     492         156 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::asinh(m.Value()));
     493             :       break;
     494             :     }
     495             :     case IrOpcode::kFloat64Atan: {
     496             :       Float64Matcher m(node->InputAt(0));
     497         169 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::atan(m.Value()));
     498             :       break;
     499             :     }
     500             :     case IrOpcode::kFloat64Atanh: {
     501             :       Float64Matcher m(node->InputAt(0));
     502         156 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::atanh(m.Value()));
     503             :       break;
     504             :     }
     505             :     case IrOpcode::kFloat64Atan2: {
     506       10068 :       Float64BinopMatcher m(node);
     507       10068 :       if (m.right().IsNaN()) {
     508       10006 :         return Replace(m.right().node());
     509             :       }
     510       10067 :       if (m.left().IsNaN()) {
     511             :         return Replace(m.left().node());
     512             :       }
     513       10066 :       if (m.IsFoldable()) {
     514             :         return ReplaceFloat64(
     515       10004 :             base::ieee754::atan2(m.left().Value(), m.right().Value()));
     516             :       }
     517          62 :       break;
     518             :     }
     519             :     case IrOpcode::kFloat64Cbrt: {
     520             :       Float64Matcher m(node->InputAt(0));
     521          56 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::cbrt(m.Value()));
     522             :       break;
     523             :     }
     524             :     case IrOpcode::kFloat64Cos: {
     525             :       Float64Matcher m(node->InputAt(0));
     526         335 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::cos(m.Value()));
     527             :       break;
     528             :     }
     529             :     case IrOpcode::kFloat64Cosh: {
     530             :       Float64Matcher m(node->InputAt(0));
     531         177 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::cosh(m.Value()));
     532             :       break;
     533             :     }
     534             :     case IrOpcode::kFloat64Exp: {
     535             :       Float64Matcher m(node->InputAt(0));
     536         237 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::exp(m.Value()));
     537             :       break;
     538             :     }
     539             :     case IrOpcode::kFloat64Expm1: {
     540             :       Float64Matcher m(node->InputAt(0));
     541          84 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::expm1(m.Value()));
     542             :       break;
     543             :     }
     544             :     case IrOpcode::kFloat64Log: {
     545             :       Float64Matcher m(node->InputAt(0));
     546         539 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log(m.Value()));
     547             :       break;
     548             :     }
     549             :     case IrOpcode::kFloat64Log1p: {
     550             :       Float64Matcher m(node->InputAt(0));
     551         156 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log1p(m.Value()));
     552             :       break;
     553             :     }
     554             :     case IrOpcode::kFloat64Log10: {
     555             :       Float64Matcher m(node->InputAt(0));
     556          56 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log10(m.Value()));
     557             :       break;
     558             :     }
     559             :     case IrOpcode::kFloat64Log2: {
     560             :       Float64Matcher m(node->InputAt(0));
     561          56 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log2(m.Value()));
     562             :       break;
     563             :     }
     564             :     case IrOpcode::kFloat64Pow: {
     565       11249 :       Float64BinopMatcher m(node);
     566       11249 :       if (m.IsFoldable()) {
     567             :         return ReplaceFloat64(
     568       21550 :             base::ieee754::pow(m.left().Value(), m.right().Value()));
     569         475 :       } else if (m.right().Is(0.0)) {  // x ** +-0.0 => 1.0
     570             :         return ReplaceFloat64(1.0);
     571         473 :       } else if (m.right().Is(-2.0)) {  // x ** -2.0 => 1 / (x * x)
     572           0 :         node->ReplaceInput(0, Float64Constant(1.0));
     573           0 :         node->ReplaceInput(1, Float64Mul(m.left().node(), m.left().node()));
     574           0 :         NodeProperties::ChangeOp(node, machine()->Float64Div());
     575             :         return Changed(node);
     576         473 :       } else if (m.right().Is(2.0)) {  // x ** 2.0 => x * x
     577           0 :         node->ReplaceInput(1, m.left().node());
     578           0 :         NodeProperties::ChangeOp(node, machine()->Float64Mul());
     579             :         return Changed(node);
     580         473 :       } else if (m.right().Is(-0.5)) {
     581             :         // x ** 0.5 => 1 / (if x <= -Infinity then Infinity else sqrt(0.0 + x))
     582           0 :         node->ReplaceInput(0, Float64Constant(1.0));
     583           0 :         node->ReplaceInput(1, Float64PowHalf(m.left().node()));
     584           0 :         NodeProperties::ChangeOp(node, machine()->Float64Div());
     585             :         return Changed(node);
     586         473 :       } else if (m.right().Is(0.5)) {
     587             :         // x ** 0.5 => if x <= -Infinity then Infinity else sqrt(0.0 + x)
     588           0 :         return Replace(Float64PowHalf(m.left().node()));
     589             :       }
     590         473 :       break;
     591             :     }
     592             :     case IrOpcode::kFloat64Sin: {
     593             :       Float64Matcher m(node->InputAt(0));
     594         345 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
     595             :       break;
     596             :     }
     597             :     case IrOpcode::kFloat64Sinh: {
     598             :       Float64Matcher m(node->InputAt(0));
     599         177 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::sinh(m.Value()));
     600             :       break;
     601             :     }
     602             :     case IrOpcode::kFloat64Tan: {
     603             :       Float64Matcher m(node->InputAt(0));
     604         239 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::tan(m.Value()));
     605             :       break;
     606             :     }
     607             :     case IrOpcode::kFloat64Tanh: {
     608             :       Float64Matcher m(node->InputAt(0));
     609         177 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::tanh(m.Value()));
     610             :       break;
     611             :     }
     612             :     case IrOpcode::kChangeFloat32ToFloat64: {
     613             :       Float32Matcher m(node->InputAt(0));
     614       13779 :       if (m.HasValue()) {
     615         160 :         if (!allow_signalling_nan_ && std::isnan(m.Value())) {
     616             :           // Do some calculation to make guarantee the value is a quiet NaN.
     617           0 :           return ReplaceFloat64(m.Value() + m.Value());
     618             :         }
     619         160 :         return ReplaceFloat64(m.Value());
     620             :       }
     621             :       break;
     622             :     }
     623             :     case IrOpcode::kChangeFloat64ToInt32: {
     624             :       Float64Matcher m(node->InputAt(0));
     625        5242 :       if (m.HasValue()) return ReplaceInt32(FastD2IChecked(m.Value()));
     626        5114 :       if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
     627             :       break;
     628             :     }
     629             :     case IrOpcode::kChangeFloat64ToInt64: {
     630             :       Float64Matcher m(node->InputAt(0));
     631         162 :       if (m.HasValue()) return ReplaceInt64(static_cast<int64_t>(m.Value()));
     632          59 :       if (m.IsChangeInt64ToFloat64()) return Replace(m.node()->InputAt(0));
     633             :       break;
     634             :     }
     635             :     case IrOpcode::kChangeFloat64ToUint32: {
     636             :       Float64Matcher m(node->InputAt(0));
     637        1157 :       if (m.HasValue()) return ReplaceInt32(FastD2UI(m.Value()));
     638        1061 :       if (m.IsChangeUint32ToFloat64()) return Replace(m.node()->InputAt(0));
     639             :       break;
     640             :     }
     641             :     case IrOpcode::kChangeInt32ToFloat64: {
     642             :       Int32Matcher m(node->InputAt(0));
     643      388879 :       if (m.HasValue()) return ReplaceFloat64(FastI2D(m.Value()));
     644             :       break;
     645             :     }
     646             :     case IrOpcode::kChangeInt32ToInt64: {
     647             :       Int32Matcher m(node->InputAt(0));
     648      382191 :       if (m.HasValue()) return ReplaceInt64(m.Value());
     649             :       break;
     650             :     }
     651             :     case IrOpcode::kChangeInt64ToFloat64: {
     652             :       Int64Matcher m(node->InputAt(0));
     653         656 :       if (m.HasValue()) return ReplaceFloat64(static_cast<double>(m.Value()));
     654         552 :       if (m.IsChangeFloat64ToInt64()) return Replace(m.node()->InputAt(0));
     655             :       break;
     656             :     }
     657             :     case IrOpcode::kChangeUint32ToFloat64: {
     658             :       Uint32Matcher m(node->InputAt(0));
     659        7012 :       if (m.HasValue()) return ReplaceFloat64(FastUI2D(m.Value()));
     660             :       break;
     661             :     }
     662             :     case IrOpcode::kChangeUint32ToUint64: {
     663             :       Uint32Matcher m(node->InputAt(0));
     664      303496 :       if (m.HasValue()) return ReplaceInt64(static_cast<uint64_t>(m.Value()));
     665             :       break;
     666             :     }
     667             :     case IrOpcode::kTruncateFloat64ToWord32: {
     668             :       Float64Matcher m(node->InputAt(0));
     669       28186 :       if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
     670       27939 :       if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
     671             :       return NoChange();
     672             :     }
     673             :     case IrOpcode::kTruncateInt64ToInt32: {
     674             :       Int64Matcher m(node->InputAt(0));
     675      438131 :       if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
     676      428329 :       if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
     677             :       break;
     678             :     }
     679             :     case IrOpcode::kTruncateFloat64ToFloat32: {
     680             :       Float64Matcher m(node->InputAt(0));
     681        9074 :       if (m.HasValue()) {
     682         680 :         if (!allow_signalling_nan_ && std::isnan(m.Value())) {
     683             :           // Do some calculation to make guarantee the value is a quiet NaN.
     684           0 :           return ReplaceFloat32(DoubleToFloat32(m.Value() + m.Value()));
     685             :         }
     686             :         return ReplaceFloat32(DoubleToFloat32(m.Value()));
     687             :       }
     688        8394 :       if (allow_signalling_nan_ && m.IsChangeFloat32ToFloat64())
     689             :         return Replace(m.node()->InputAt(0));
     690             :       break;
     691             :     }
     692             :     case IrOpcode::kRoundFloat64ToInt32: {
     693             :       Float64Matcher m(node->InputAt(0));
     694      129695 :       if (m.HasValue()) {
     695         132 :         return ReplaceInt32(DoubleToInt32(m.Value()));
     696             :       }
     697      129563 :       if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
     698             :       break;
     699             :     }
     700             :     case IrOpcode::kFloat64InsertLowWord32:
     701        4856 :       return ReduceFloat64InsertLowWord32(node);
     702             :     case IrOpcode::kFloat64InsertHighWord32:
     703        4856 :       return ReduceFloat64InsertHighWord32(node);
     704             :     case IrOpcode::kStore:
     705             :     case IrOpcode::kUnalignedStore:
     706     3256134 :       return ReduceStore(node);
     707             :     case IrOpcode::kFloat64Equal:
     708             :     case IrOpcode::kFloat64LessThan:
     709             :     case IrOpcode::kFloat64LessThanOrEqual:
     710      360752 :       return ReduceFloat64Compare(node);
     711             :     case IrOpcode::kFloat64RoundDown:
     712       81773 :       return ReduceFloat64RoundDown(node);
     713             :     case IrOpcode::kBitcastTaggedToWord: {
     714             :       NodeMatcher m(node->InputAt(0));
     715     1163754 :       if (m.IsBitcastWordToTaggedSigned()) {
     716             :         RelaxEffectsAndControls(node);
     717             :         return Replace(m.InputAt(0));
     718             :       }
     719             :       break;
     720             :     }
     721             :     default:
     722             :       break;
     723             :   }
     724             :   return NoChange();
     725             : }
     726             : 
     727      560930 : Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
     728             :   DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
     729      560930 :   Int32BinopMatcher m(node);
     730      560954 :   if (m.right().Is(0)) return Replace(m.left().node());  // x + 0 => x
     731      537302 :   if (m.IsFoldable()) {                                  // K + K => K
     732             :     return ReplaceInt32(
     733       38157 :         base::AddWithWraparound(m.left().Value(), m.right().Value()));
     734             :   }
     735      499145 :   if (m.left().IsInt32Sub()) {
     736        1479 :     Int32BinopMatcher mleft(m.left().node());
     737        1479 :     if (mleft.left().Is(0)) {  // (0 - x) + y => y - x
     738         122 :       node->ReplaceInput(0, m.right().node());
     739         122 :       node->ReplaceInput(1, mleft.right().node());
     740         122 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     741         122 :       Reduction const reduction = ReduceInt32Sub(node);
     742         122 :       return reduction.Changed() ? reduction : Changed(node);
     743             :     }
     744             :   }
     745      499023 :   if (m.right().IsInt32Sub()) {
     746         453 :     Int32BinopMatcher mright(m.right().node());
     747         453 :     if (mright.left().Is(0)) {  // y + (0 - x) => y - x
     748          42 :       node->ReplaceInput(1, mright.right().node());
     749          42 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     750          42 :       Reduction const reduction = ReduceInt32Sub(node);
     751          42 :       return reduction.Changed() ? reduction : Changed(node);
     752             :     }
     753             :   }
     754             :   return NoChange();
     755             : }
     756             : 
     757     1807085 : Reduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
     758             :   DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
     759     1807085 :   Int64BinopMatcher m(node);
     760     1807085 :   if (m.right().Is(0)) return Replace(m.left().node());  // x + 0 => 0
     761     1794229 :   if (m.IsFoldable()) {
     762             :     return ReplaceInt64(
     763       78381 :         base::AddWithWraparound(m.left().Value(), m.right().Value()));
     764             :   }
     765             :   return NoChange();
     766             : }
     767             : 
     768       64575 : Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
     769             :   DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
     770       64575 :   Int32BinopMatcher m(node);
     771       64575 :   if (m.right().Is(0)) return Replace(m.left().node());  // x - 0 => x
     772       63992 :   if (m.IsFoldable()) {                                  // K - K => K
     773             :     return ReplaceInt32(
     774       19416 :         base::SubWithWraparound(m.left().Value(), m.right().Value()));
     775             :   }
     776       44576 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);  // x - x => 0
     777       44576 :   if (m.right().HasValue()) {                       // x - K => x + -K
     778       13662 :     node->ReplaceInput(
     779       13662 :         1, Int32Constant(base::NegateWithWraparound(m.right().Value())));
     780       13662 :     NodeProperties::ChangeOp(node, machine()->Int32Add());
     781       13662 :     Reduction const reduction = ReduceInt32Add(node);
     782       13662 :     return reduction.Changed() ? reduction : Changed(node);
     783             :   }
     784             :   return NoChange();
     785             : }
     786             : 
     787      313170 : Reduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
     788             :   DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
     789      313170 :   Int64BinopMatcher m(node);
     790      313170 :   if (m.right().Is(0)) return Replace(m.left().node());  // x - 0 => x
     791      306639 :   if (m.IsFoldable()) {                                  // K - K => K
     792             :     return ReplaceInt64(
     793       35260 :         base::SubWithWraparound(m.left().Value(), m.right().Value()));
     794             :   }
     795      271379 :   if (m.LeftEqualsRight()) return Replace(Int64Constant(0));  // x - x => 0
     796      271374 :   if (m.right().HasValue()) {                                 // x - K => x + -K
     797      510354 :     node->ReplaceInput(
     798      255177 :         1, Int64Constant(base::NegateWithWraparound(m.right().Value())));
     799      255178 :     NodeProperties::ChangeOp(node, machine()->Int64Add());
     800      255178 :     Reduction const reduction = ReduceInt64Add(node);
     801      255178 :     return reduction.Changed() ? reduction : Changed(node);
     802             :   }
     803             :   return NoChange();
     804             : }
     805             : 
     806       20534 : Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
     807       20534 :   Int32BinopMatcher m(node);
     808       20534 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 / x => 0
     809       20249 :   if (m.right().Is(0)) return Replace(m.right().node());  // x / 0 => 0
     810       20248 :   if (m.right().Is(1)) return Replace(m.left().node());   // x / 1 => x
     811       19928 :   if (m.IsFoldable()) {                                   // K / K => K
     812             :     return ReplaceInt32(
     813       15960 :         base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
     814             :   }
     815        3968 :   if (m.LeftEqualsRight()) {  // x / x => x != 0
     816             :     Node* const zero = Int32Constant(0);
     817           1 :     return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
     818             :   }
     819        3967 :   if (m.right().Is(-1)) {  // x / -1 => 0 - x
     820          32 :     node->ReplaceInput(0, Int32Constant(0));
     821          32 :     node->ReplaceInput(1, m.left().node());
     822          32 :     node->TrimInputCount(2);
     823          32 :     NodeProperties::ChangeOp(node, machine()->Int32Sub());
     824             :     return Changed(node);
     825             :   }
     826        3935 :   if (m.right().HasValue()) {
     827        2811 :     int32_t const divisor = m.right().Value();
     828             :     Node* const dividend = m.left().node();
     829             :     Node* quotient = dividend;
     830        2811 :     if (base::bits::IsPowerOfTwo(Abs(divisor))) {
     831         744 :       uint32_t const shift = WhichPowerOf2(Abs(divisor));
     832             :       DCHECK_NE(0u, shift);
     833         744 :       if (shift > 1) {
     834         633 :         quotient = Word32Sar(quotient, 31);
     835             :       }
     836         744 :       quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
     837         744 :       quotient = Word32Sar(quotient, shift);
     838             :     } else {
     839        2067 :       quotient = Int32Div(quotient, Abs(divisor));
     840             :     }
     841        2811 :     if (divisor < 0) {
     842        1279 :       node->ReplaceInput(0, Int32Constant(0));
     843        1279 :       node->ReplaceInput(1, quotient);
     844        1279 :       node->TrimInputCount(2);
     845        1279 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     846             :       return Changed(node);
     847             :     }
     848             :     return Replace(quotient);
     849             :   }
     850             :   return NoChange();
     851             : }
     852             : 
     853             : 
     854       19323 : Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
     855       19323 :   Uint32BinopMatcher m(node);
     856       19323 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 / x => 0
     857       18974 :   if (m.right().Is(0)) return Replace(m.right().node());  // x / 0 => 0
     858       18926 :   if (m.right().Is(1)) return Replace(m.left().node());   // x / 1 => x
     859       18583 :   if (m.IsFoldable()) {                                   // K / K => K
     860             :     return ReplaceUint32(
     861       18137 :         base::bits::UnsignedDiv32(m.left().Value(), m.right().Value()));
     862             :   }
     863         446 :   if (m.LeftEqualsRight()) {  // x / x => x != 0
     864             :     Node* const zero = Int32Constant(0);
     865           1 :     return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
     866             :   }
     867         445 :   if (m.right().HasValue()) {
     868             :     Node* const dividend = m.left().node();
     869         273 :     uint32_t const divisor = m.right().Value();
     870         273 :     if (base::bits::IsPowerOfTwo(divisor)) {  // x / 2^n => x >> n
     871         432 :       node->ReplaceInput(1, Uint32Constant(WhichPowerOf2(m.right().Value())));
     872         216 :       node->TrimInputCount(2);
     873         216 :       NodeProperties::ChangeOp(node, machine()->Word32Shr());
     874             :       return Changed(node);
     875             :     } else {
     876          57 :       return Replace(Uint32Div(dividend, divisor));
     877             :     }
     878             :   }
     879             :   return NoChange();
     880             : }
     881             : 
     882             : 
     883       30527 : Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
     884       30527 :   Int32BinopMatcher m(node);
     885       30527 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 % x  => 0
     886       30140 :   if (m.right().Is(0)) return Replace(m.right().node());  // x % 0  => 0
     887       30040 :   if (m.right().Is(1)) return ReplaceInt32(0);            // x % 1  => 0
     888       29728 :   if (m.right().Is(-1)) return ReplaceInt32(0);           // x % -1 => 0
     889       29442 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);        // x % x  => 0
     890       29441 :   if (m.IsFoldable()) {                                   // K % K => K
     891             :     return ReplaceInt32(
     892       25506 :         base::bits::SignedMod32(m.left().Value(), m.right().Value()));
     893             :   }
     894        3935 :   if (m.right().HasValue()) {
     895             :     Node* const dividend = m.left().node();
     896        2832 :     uint32_t const divisor = Abs(m.right().Value());
     897        2832 :     if (base::bits::IsPowerOfTwo(divisor)) {
     898         750 :       uint32_t const mask = divisor - 1;
     899             :       Node* const zero = Int32Constant(0);
     900             :       Diamond d(graph(), common(),
     901             :                 graph()->NewNode(machine()->Int32LessThan(), dividend, zero),
     902        1500 :                 BranchHint::kFalse);
     903             :       return Replace(
     904             :           d.Phi(MachineRepresentation::kWord32,
     905             :                 Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
     906         750 :                 Word32And(dividend, mask)));
     907             :     } else {
     908        2082 :       Node* quotient = Int32Div(dividend, divisor);
     909             :       DCHECK_EQ(dividend, node->InputAt(0));
     910        2082 :       node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
     911        2082 :       node->TrimInputCount(2);
     912        2082 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     913             :     }
     914             :     return Changed(node);
     915             :   }
     916             :   return NoChange();
     917             : }
     918             : 
     919             : 
     920       21497 : Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
     921       21497 :   Uint32BinopMatcher m(node);
     922       21497 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 % x => 0
     923       21117 :   if (m.right().Is(0)) return Replace(m.right().node());  // x % 0 => 0
     924       21069 :   if (m.right().Is(1)) return ReplaceUint32(0);           // x % 1 => 0
     925       20726 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);        // x % x  => 0
     926       20724 :   if (m.IsFoldable()) {                                   // K % K => K
     927             :     return ReplaceUint32(
     928       18186 :         base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
     929             :   }
     930        2538 :   if (m.right().HasValue()) {
     931             :     Node* const dividend = m.left().node();
     932        1895 :     uint32_t const divisor = m.right().Value();
     933        1895 :     if (base::bits::IsPowerOfTwo(divisor)) {  // x % 2^n => x & 2^n-1
     934        1060 :       node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
     935         530 :       node->TrimInputCount(2);
     936         530 :       NodeProperties::ChangeOp(node, machine()->Word32And());
     937             :     } else {
     938        1365 :       Node* quotient = Uint32Div(dividend, divisor);
     939             :       DCHECK_EQ(dividend, node->InputAt(0));
     940        1365 :       node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
     941        1365 :       node->TrimInputCount(2);
     942        1365 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     943             :     }
     944             :     return Changed(node);
     945             :   }
     946             :   return NoChange();
     947             : }
     948             : 
     949             : 
     950     3256133 : Reduction MachineOperatorReducer::ReduceStore(Node* node) {
     951             :   NodeMatcher nm(node);
     952             :   MachineRepresentation rep;
     953             :   int value_input;
     954     3256133 :   if (nm.IsStore()) {
     955     3256133 :     rep = StoreRepresentationOf(node->op()).representation();
     956             :     value_input = 2;
     957             :   } else {
     958             :     DCHECK(nm.IsUnalignedStore());
     959           0 :     rep = UnalignedStoreRepresentationOf(node->op());
     960             :     value_input = 2;
     961             :   }
     962             : 
     963             :   Node* const value = node->InputAt(value_input);
     964             : 
     965     3256132 :   switch (value->opcode()) {
     966             :     case IrOpcode::kWord32And: {
     967        7391 :       Uint32BinopMatcher m(value);
     968       20080 :       if (m.right().HasValue() && ((rep == MachineRepresentation::kWord8 &&
     969        7205 :                                     (m.right().Value() & 0xFF) == 0xFF) ||
     970        1357 :                                    (rep == MachineRepresentation::kWord16 &&
     971        1357 :                                     (m.right().Value() & 0xFFFF) == 0xFFFF))) {
     972        6377 :         node->ReplaceInput(value_input, m.left().node());
     973        6377 :         return Changed(node);
     974             :       }
     975        1014 :       break;
     976             :     }
     977             :     case IrOpcode::kWord32Sar: {
     978         377 :       Int32BinopMatcher m(value);
     979         883 :       if (m.left().IsWord32Shl() && ((rep == MachineRepresentation::kWord8 &&
     980         201 :                                       m.right().IsInRange(1, 24)) ||
     981         193 :                                      (rep == MachineRepresentation::kWord16 &&
     982             :                                       m.right().IsInRange(1, 16)))) {
     983         322 :         Int32BinopMatcher mleft(m.left().node());
     984         322 :         if (mleft.right().Is(m.right().Value())) {
     985         322 :           node->ReplaceInput(value_input, mleft.left().node());
     986         322 :           return Changed(node);
     987             :         }
     988             :       }
     989          55 :       break;
     990             :     }
     991             :     default:
     992             :       break;
     993             :   }
     994             :   return NoChange();
     995             : }
     996             : 
     997             : 
     998      390899 : Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
     999      390899 :   switch (node->opcode()) {
    1000             :     case IrOpcode::kInt32AddWithOverflow: {
    1001             :       DCHECK(index == 0 || index == 1);
    1002      259720 :       Int32BinopMatcher m(node);
    1003      259744 :       if (m.IsFoldable()) {
    1004             :         int32_t val;
    1005       20006 :         bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
    1006             :                                                    m.right().Value(), &val);
    1007       20006 :         return ReplaceInt32(index == 0 ? val : ovf);
    1008             :       }
    1009      239738 :       if (m.right().Is(0)) {
    1010          32 :         return Replace(index == 0 ? m.left().node() : m.right().node());
    1011             :       }
    1012      239706 :       break;
    1013             :     }
    1014             :     case IrOpcode::kInt32SubWithOverflow: {
    1015             :       DCHECK(index == 0 || index == 1);
    1016       67125 :       Int32BinopMatcher m(node);
    1017       67125 :       if (m.IsFoldable()) {
    1018             :         int32_t val;
    1019       20056 :         bool ovf = base::bits::SignedSubOverflow32(m.left().Value(),
    1020             :                                                    m.right().Value(), &val);
    1021       20056 :         return ReplaceInt32(index == 0 ? val : ovf);
    1022             :       }
    1023       47069 :       if (m.right().Is(0)) {
    1024           2 :         return Replace(index == 0 ? m.left().node() : m.right().node());
    1025             :       }
    1026       47067 :       break;
    1027             :     }
    1028             :     case IrOpcode::kInt32MulWithOverflow: {
    1029             :       DCHECK(index == 0 || index == 1);
    1030       31509 :       Int32BinopMatcher m(node);
    1031       31509 :       if (m.IsFoldable()) {
    1032             :         int32_t val;
    1033       20310 :         bool ovf = base::bits::SignedMulOverflow32(m.left().Value(),
    1034       20310 :                                                    m.right().Value(), &val);
    1035       20310 :         return ReplaceInt32(index == 0 ? val : ovf);
    1036             :       }
    1037       11199 :       if (m.right().Is(0)) {
    1038             :         return Replace(m.right().node());
    1039             :       }
    1040       11111 :       if (m.right().Is(1)) {
    1041          72 :         return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
    1042             :       }
    1043       11039 :       break;
    1044             :     }
    1045             :     default:
    1046             :       break;
    1047             :   }
    1048             :   return NoChange();
    1049             : }
    1050             : 
    1051             : 
    1052      116930 : Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
    1053             :   DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
    1054             :          (node->opcode() == IrOpcode::kWord32Shr) ||
    1055             :          (node->opcode() == IrOpcode::kWord32Sar));
    1056      116930 :   if (machine()->Word32ShiftIsSafe()) {
    1057             :     // Remove the explicit 'and' with 0x1F if the shift provided by the machine
    1058             :     // instruction matches that required by JavaScript.
    1059      116615 :     Int32BinopMatcher m(node);
    1060      116615 :     if (m.right().IsWord32And()) {
    1061        1776 :       Int32BinopMatcher mright(m.right().node());
    1062        1776 :       if (mright.right().Is(0x1F)) {
    1063         793 :         node->ReplaceInput(1, mright.left().node());
    1064         793 :         return Changed(node);
    1065             :       }
    1066             :     }
    1067             :   }
    1068             :   return NoChange();
    1069             : }
    1070             : 
    1071             : 
    1072       43467 : Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
    1073             :   DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
    1074       43467 :   Int32BinopMatcher m(node);
    1075       43467 :   if (m.right().Is(0)) return Replace(m.left().node());  // x << 0 => x
    1076       43090 :   if (m.IsFoldable()) {                                  // K << K => K
    1077             :     return ReplaceInt32(
    1078       11801 :         base::ShlWithWraparound(m.left().Value(), m.right().Value()));
    1079             :   }
    1080       31289 :   if (m.right().IsInRange(1, 31)) {
    1081             :     // (x >>> K) << K => x & ~(2^K - 1)
    1082             :     // (x >> K) << K => x & ~(2^K - 1)
    1083       27764 :     if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
    1084        3985 :       Int32BinopMatcher mleft(m.left().node());
    1085        3985 :       if (mleft.right().Is(m.right().Value())) {
    1086        3057 :         node->ReplaceInput(0, mleft.left().node());
    1087        3057 :         node->ReplaceInput(1,
    1088        6114 :                            Uint32Constant(~((1U << m.right().Value()) - 1U)));
    1089        3057 :         NodeProperties::ChangeOp(node, machine()->Word32And());
    1090        3057 :         Reduction reduction = ReduceWord32And(node);
    1091        3057 :         return reduction.Changed() ? reduction : Changed(node);
    1092             :       }
    1093             :     }
    1094             :   }
    1095       28232 :   return ReduceWord32Shifts(node);
    1096             : }
    1097             : 
    1098      699950 : Reduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
    1099             :   DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
    1100      699950 :   Int64BinopMatcher m(node);
    1101      699950 :   if (m.right().Is(0)) return Replace(m.left().node());  // x << 0 => x
    1102      699540 :   if (m.IsFoldable()) {                                  // K << K => K
    1103             :     return ReplaceInt64(
    1104       89513 :         base::ShlWithWraparound(m.left().Value(), m.right().Value()));
    1105             :   }
    1106             :   return NoChange();
    1107             : }
    1108             : 
    1109       81111 : Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
    1110       81111 :   Uint32BinopMatcher m(node);
    1111       81111 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >>> 0 => x
    1112       68481 :   if (m.IsFoldable()) {                                  // K >>> K => K
    1113        9090 :     return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
    1114             :   }
    1115       59391 :   if (m.left().IsWord32And() && m.right().HasValue()) {
    1116       24365 :     Uint32BinopMatcher mleft(m.left().node());
    1117       24365 :     if (mleft.right().HasValue()) {
    1118       24365 :       uint32_t shift = m.right().Value() & 31;
    1119       24365 :       uint32_t mask = mleft.right().Value();
    1120       24365 :       if ((mask >> shift) == 0) {
    1121             :         // (m >>> s) == 0 implies ((x & m) >>> s) == 0
    1122          31 :         return ReplaceInt32(0);
    1123             :       }
    1124             :     }
    1125             :   }
    1126       59360 :   return ReduceWord32Shifts(node);
    1127             : }
    1128             : 
    1129       50050 : Reduction MachineOperatorReducer::ReduceWord64Shr(Node* node) {
    1130             :   DCHECK_EQ(IrOpcode::kWord64Shr, node->opcode());
    1131       50050 :   Uint64BinopMatcher m(node);
    1132       50050 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >>> 0 => x
    1133       49640 :   if (m.IsFoldable()) {                                  // K >> K => K
    1134       25515 :     return ReplaceInt64(m.left().Value() >> (m.right().Value() & 63));
    1135             :   }
    1136             :   return NoChange();
    1137             : }
    1138             : 
    1139       39183 : Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
    1140       39183 :   Int32BinopMatcher m(node);
    1141       39183 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >> 0 => x
    1142       38758 :   if (m.IsFoldable()) {                                  // K >> K => K
    1143        9369 :     return ReplaceInt32(m.left().Value() >> (m.right().Value() & 31));
    1144             :   }
    1145       29389 :   if (m.left().IsWord32Shl()) {
    1146        1248 :     Int32BinopMatcher mleft(m.left().node());
    1147        1248 :     if (mleft.left().IsComparison()) {
    1148          98 :       if (m.right().Is(31) && mleft.right().Is(31)) {
    1149             :         // Comparison << 31 >> 31 => 0 - Comparison
    1150          49 :         node->ReplaceInput(0, Int32Constant(0));
    1151          49 :         node->ReplaceInput(1, mleft.left().node());
    1152          49 :         NodeProperties::ChangeOp(node, machine()->Int32Sub());
    1153          49 :         Reduction const reduction = ReduceInt32Sub(node);
    1154          49 :         return reduction.Changed() ? reduction : Changed(node);
    1155             :       }
    1156        1199 :     } else if (mleft.left().IsLoad()) {
    1157             :       LoadRepresentation const rep =
    1158           2 :           LoadRepresentationOf(mleft.left().node()->op());
    1159           4 :       if (m.right().Is(24) && mleft.right().Is(24) &&
    1160             :           rep == MachineType::Int8()) {
    1161             :         // Load[kMachInt8] << 24 >> 24 => Load[kMachInt8]
    1162             :         return Replace(mleft.left().node());
    1163             :       }
    1164           3 :       if (m.right().Is(16) && mleft.right().Is(16) &&
    1165             :           rep == MachineType::Int16()) {
    1166             :         // Load[kMachInt16] << 16 >> 16 => Load[kMachInt8]
    1167             :         return Replace(mleft.left().node());
    1168             :       }
    1169             :     }
    1170             :   }
    1171       29338 :   return ReduceWord32Shifts(node);
    1172             : }
    1173             : 
    1174      479112 : Reduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
    1175      479112 :   Int64BinopMatcher m(node);
    1176      479112 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >> 0 => x
    1177      478702 :   if (m.IsFoldable()) {
    1178       34327 :     return ReplaceInt64(m.left().Value() >> (m.right().Value() & 63));
    1179             :   }
    1180             :   return NoChange();
    1181             : }
    1182             : 
    1183      756719 : Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
    1184             :   DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
    1185      756719 :   Int32BinopMatcher m(node);
    1186      756719 :   if (m.right().Is(0)) return Replace(m.right().node());  // x & 0  => 0
    1187      755018 :   if (m.right().Is(-1)) return Replace(m.left().node());  // x & -1 => x
    1188      755772 :   if (m.left().IsComparison() && m.right().Is(1)) {       // CMP & 1 => CMP
    1189             :     return Replace(m.left().node());
    1190             :   }
    1191      754422 :   if (m.IsFoldable()) {                                   // K & K  => K
    1192       23288 :     return ReplaceInt32(m.left().Value() & m.right().Value());
    1193             :   }
    1194      731134 :   if (m.LeftEqualsRight()) return Replace(m.left().node());  // x & x => x
    1195      731049 :   if (m.left().IsWord32And() && m.right().HasValue()) {
    1196       22647 :     Int32BinopMatcher mleft(m.left().node());
    1197       22647 :     if (mleft.right().HasValue()) {  // (x & K) & K => x & K
    1198       19698 :       node->ReplaceInput(0, mleft.left().node());
    1199       19698 :       node->ReplaceInput(
    1200       19698 :           1, Int32Constant(m.right().Value() & mleft.right().Value()));
    1201       19698 :       Reduction const reduction = ReduceWord32And(node);
    1202       19698 :       return reduction.Changed() ? reduction : Changed(node);
    1203             :     }
    1204             :   }
    1205      711351 :   if (m.right().IsNegativePowerOf2()) {
    1206      254023 :     int32_t const mask = m.right().Value();
    1207             :     int32_t const neg_mask = base::NegateWithWraparound(mask);
    1208      254023 :     if (m.left().IsWord32Shl()) {
    1209        2142 :       Uint32BinopMatcher mleft(m.left().node());
    1210        4284 :       if (mleft.right().HasValue() &&
    1211        2142 :           (mleft.right().Value() & 0x1F) >=
    1212             :               base::bits::CountTrailingZeros(mask)) {
    1213             :         // (x << L) & (-1 << K) => x << L iff L >= K
    1214        2140 :         return Replace(mleft.node());
    1215             :       }
    1216      251881 :     } else if (m.left().IsInt32Add()) {
    1217       94806 :       Int32BinopMatcher mleft(m.left().node());
    1218      169547 :       if (mleft.right().HasValue() &&
    1219       74741 :           (mleft.right().Value() & mask) == mleft.right().Value()) {
    1220             :         // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
    1221       74582 :         node->ReplaceInput(0, Word32And(mleft.left().node(), m.right().node()));
    1222       74582 :         node->ReplaceInput(1, mleft.right().node());
    1223       74582 :         NodeProperties::ChangeOp(node, machine()->Int32Add());
    1224       74582 :         Reduction const reduction = ReduceInt32Add(node);
    1225       74582 :         return reduction.Changed() ? reduction : Changed(node);
    1226             :       }
    1227       20224 :       if (mleft.left().IsInt32Mul()) {
    1228        2924 :         Int32BinopMatcher mleftleft(mleft.left().node());
    1229        2924 :         if (mleftleft.right().IsMultipleOf(neg_mask)) {
    1230             :           // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
    1231        2923 :           node->ReplaceInput(0,
    1232        2923 :                              Word32And(mleft.right().node(), m.right().node()));
    1233        2923 :           node->ReplaceInput(1, mleftleft.node());
    1234        2923 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1235        2923 :           Reduction const reduction = ReduceInt32Add(node);
    1236        2923 :           return reduction.Changed() ? reduction : Changed(node);
    1237             :         }
    1238             :       }
    1239       17301 :       if (mleft.right().IsInt32Mul()) {
    1240        7153 :         Int32BinopMatcher mleftright(mleft.right().node());
    1241        7153 :         if (mleftright.right().IsMultipleOf(neg_mask)) {
    1242             :           // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
    1243        7143 :           node->ReplaceInput(0,
    1244        7143 :                              Word32And(mleft.left().node(), m.right().node()));
    1245        7143 :           node->ReplaceInput(1, mleftright.node());
    1246        7143 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1247        7143 :           Reduction const reduction = ReduceInt32Add(node);
    1248        7143 :           return reduction.Changed() ? reduction : Changed(node);
    1249             :         }
    1250             :       }
    1251       10158 :       if (mleft.left().IsWord32Shl()) {
    1252          36 :         Int32BinopMatcher mleftleft(mleft.left().node());
    1253          72 :         if (mleftleft.right().Is(base::bits::CountTrailingZeros(mask))) {
    1254             :           // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
    1255          31 :           node->ReplaceInput(0,
    1256          31 :                              Word32And(mleft.right().node(), m.right().node()));
    1257          31 :           node->ReplaceInput(1, mleftleft.node());
    1258          31 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1259          31 :           Reduction const reduction = ReduceInt32Add(node);
    1260          31 :           return reduction.Changed() ? reduction : Changed(node);
    1261             :         }
    1262             :       }
    1263       10127 :       if (mleft.right().IsWord32Shl()) {
    1264        6360 :         Int32BinopMatcher mleftright(mleft.right().node());
    1265       12720 :         if (mleftright.right().Is(base::bits::CountTrailingZeros(mask))) {
    1266             :           // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
    1267        2425 :           node->ReplaceInput(0,
    1268        2425 :                              Word32And(mleft.left().node(), m.right().node()));
    1269        2425 :           node->ReplaceInput(1, mleftright.node());
    1270        2425 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1271        2425 :           Reduction const reduction = ReduceInt32Add(node);
    1272        2425 :           return reduction.Changed() ? reduction : Changed(node);
    1273             :         }
    1274             :       }
    1275      157075 :     } else if (m.left().IsInt32Mul()) {
    1276        5892 :       Int32BinopMatcher mleft(m.left().node());
    1277        5892 :       if (mleft.right().IsMultipleOf(neg_mask)) {
    1278             :         // (x * (K << L)) & (-1 << L) => x * (K << L)
    1279        5892 :         return Replace(mleft.node());
    1280             :       }
    1281             :     }
    1282             :   }
    1283             :   return NoChange();
    1284             : }
    1285             : 
    1286       53470 : Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
    1287             :   DCHECK(IrOpcode::kWord32Or == node->opcode() ||
    1288             :          IrOpcode::kWord32Xor == node->opcode());
    1289       53470 :   Int32BinopMatcher m(node);
    1290             :   Node* shl = nullptr;
    1291             :   Node* shr = nullptr;
    1292             :   // Recognize rotation, we are matching:
    1293             :   //  * x << y | x >>> (32 - y) => x ror (32 - y), i.e  x rol y
    1294             :   //  * x << (32 - y) | x >>> y => x ror y
    1295             :   //  * x << y ^ x >>> (32 - y) => x ror (32 - y), i.e. x rol y
    1296             :   //  * x << (32 - y) ^ x >>> y => x ror y
    1297             :   // as well as their commuted form.
    1298       60393 :   if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
    1299             :     shl = m.left().node();
    1300             :     shr = m.right().node();
    1301       52994 :   } else if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
    1302             :     shl = m.right().node();
    1303             :     shr = m.left().node();
    1304             :   } else {
    1305             :     return NoChange();
    1306             :   }
    1307             : 
    1308         937 :   Int32BinopMatcher mshl(shl);
    1309         937 :   Int32BinopMatcher mshr(shr);
    1310         937 :   if (mshl.left().node() != mshr.left().node()) return NoChange();
    1311             : 
    1312         636 :   if (mshl.right().HasValue() && mshr.right().HasValue()) {
    1313             :     // Case where y is a constant.
    1314         382 :     if (mshl.right().Value() + mshr.right().Value() != 32) return NoChange();
    1315             :   } else {
    1316             :     Node* sub = nullptr;
    1317             :     Node* y = nullptr;
    1318         254 :     if (mshl.right().IsInt32Sub()) {
    1319             :       sub = mshl.right().node();
    1320             :       y = mshr.right().node();
    1321         211 :     } else if (mshr.right().IsInt32Sub()) {
    1322             :       sub = mshr.right().node();
    1323             :       y = mshl.right().node();
    1324             :     } else {
    1325         182 :       return NoChange();
    1326             :     }
    1327             : 
    1328         128 :     Int32BinopMatcher msub(sub);
    1329         256 :     if (!msub.left().Is(32) || msub.right().node() != y) return NoChange();
    1330             :   }
    1331             : 
    1332         454 :   node->ReplaceInput(0, mshl.left().node());
    1333         454 :   node->ReplaceInput(1, mshr.right().node());
    1334         454 :   NodeProperties::ChangeOp(node, machine()->Word32Ror());
    1335             :   return Changed(node);
    1336             : }
    1337             : 
    1338       81303 : Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
    1339             :   DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
    1340       81303 :   Int32BinopMatcher m(node);
    1341       81303 :   if (m.right().Is(0)) return Replace(m.left().node());    // x | 0  => x
    1342       66461 :   if (m.right().Is(-1)) return Replace(m.right().node());  // x | -1 => -1
    1343       63059 :   if (m.IsFoldable()) {                                    // K | K  => K
    1344       16315 :     return ReplaceInt32(m.left().Value() | m.right().Value());
    1345             :   }
    1346       46744 :   if (m.LeftEqualsRight()) return Replace(m.left().node());  // x | x => x
    1347             : 
    1348       46713 :   return TryMatchWord32Ror(node);
    1349             : }
    1350             : 
    1351       23722 : Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
    1352             :   DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
    1353       23722 :   Int32BinopMatcher m(node);
    1354       23722 :   if (m.right().Is(0)) return Replace(m.left().node());  // x ^ 0 => x
    1355       23397 :   if (m.IsFoldable()) {                                  // K ^ K => K
    1356       16615 :     return ReplaceInt32(m.left().Value() ^ m.right().Value());
    1357             :   }
    1358        6782 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);  // x ^ x => 0
    1359        7071 :   if (m.left().IsWord32Xor() && m.right().Is(-1)) {
    1360          20 :     Int32BinopMatcher mleft(m.left().node());
    1361          20 :     if (mleft.right().Is(-1)) {  // (x ^ -1) ^ -1 => x
    1362          20 :       return Replace(mleft.left().node());
    1363             :     }
    1364             :   }
    1365             : 
    1366        6757 :   return TryMatchWord32Ror(node);
    1367             : }
    1368             : 
    1369        4856 : Reduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) {
    1370             :   DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode());
    1371             :   Float64Matcher mlhs(node->InputAt(0));
    1372             :   Uint32Matcher mrhs(node->InputAt(1));
    1373        4856 :   if (mlhs.HasValue() && mrhs.HasValue()) {
    1374             :     return ReplaceFloat64(bit_cast<double>(
    1375        4800 :         (bit_cast<uint64_t>(mlhs.Value()) & uint64_t{0xFFFFFFFF00000000}) |
    1376             :         mrhs.Value()));
    1377             :   }
    1378             :   return NoChange();
    1379             : }
    1380             : 
    1381             : 
    1382        4856 : Reduction MachineOperatorReducer::ReduceFloat64InsertHighWord32(Node* node) {
    1383             :   DCHECK_EQ(IrOpcode::kFloat64InsertHighWord32, node->opcode());
    1384             :   Float64Matcher mlhs(node->InputAt(0));
    1385             :   Uint32Matcher mrhs(node->InputAt(1));
    1386        4856 :   if (mlhs.HasValue() && mrhs.HasValue()) {
    1387             :     return ReplaceFloat64(bit_cast<double>(
    1388        9600 :         (bit_cast<uint64_t>(mlhs.Value()) & uint64_t{0xFFFFFFFF}) |
    1389        4800 :         (static_cast<uint64_t>(mrhs.Value()) << 32)));
    1390             :   }
    1391             :   return NoChange();
    1392             : }
    1393             : 
    1394             : 
    1395             : namespace {
    1396             : 
    1397             : bool IsFloat64RepresentableAsFloat32(const Float64Matcher& m) {
    1398      328492 :   if (m.HasValue()) {
    1399      104513 :     double v = m.Value();
    1400      104513 :     return DoubleToFloat32(v) == v;
    1401             :   }
    1402             :   return false;
    1403             : }
    1404             : 
    1405             : }  // namespace
    1406             : 
    1407             : 
    1408      360751 : Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
    1409             :   DCHECK(IrOpcode::kFloat64Equal == node->opcode() ||
    1410             :          IrOpcode::kFloat64LessThan == node->opcode() ||
    1411             :          IrOpcode::kFloat64LessThanOrEqual == node->opcode());
    1412      360751 :   Float64BinopMatcher m(node);
    1413      360751 :   if (m.IsFoldable()) {
    1414       32513 :     switch (node->opcode()) {
    1415             :       case IrOpcode::kFloat64Equal:
    1416       11685 :         return ReplaceBool(m.left().Value() == m.right().Value());
    1417             :       case IrOpcode::kFloat64LessThan:
    1418       10701 :         return ReplaceBool(m.left().Value() < m.right().Value());
    1419             :       case IrOpcode::kFloat64LessThanOrEqual:
    1420       10127 :         return ReplaceBool(m.left().Value() <= m.right().Value());
    1421             :       default:
    1422           0 :         UNREACHABLE();
    1423             :     }
    1424      329926 :   } else if ((m.left().IsChangeFloat32ToFloat64() &&
    1425      327711 :               m.right().IsChangeFloat32ToFloat64()) ||
    1426        1161 :              (m.left().IsChangeFloat32ToFloat64() &&
    1427      655569 :               IsFloat64RepresentableAsFloat32(m.right())) ||
    1428      104027 :              (IsFloat64RepresentableAsFloat32(m.left()) &&
    1429             :               m.right().IsChangeFloat32ToFloat64())) {
    1430             :     // As all Float32 values have an exact representation in Float64, comparing
    1431             :     // two Float64 values both converted from Float32 is equivalent to comparing
    1432             :     // the original Float32s, so we can ignore the conversions. We can also
    1433             :     // reduce comparisons of converted Float64 values against constants that
    1434             :     // can be represented exactly as Float32.
    1435        1147 :     switch (node->opcode()) {
    1436             :       case IrOpcode::kFloat64Equal:
    1437         288 :         NodeProperties::ChangeOp(node, machine()->Float32Equal());
    1438         288 :         break;
    1439             :       case IrOpcode::kFloat64LessThan:
    1440         583 :         NodeProperties::ChangeOp(node, machine()->Float32LessThan());
    1441         583 :         break;
    1442             :       case IrOpcode::kFloat64LessThanOrEqual:
    1443         276 :         NodeProperties::ChangeOp(node, machine()->Float32LessThanOrEqual());
    1444         276 :         break;
    1445             :       default:
    1446           0 :         UNREACHABLE();
    1447             :     }
    1448        1387 :     node->ReplaceInput(
    1449             :         0, m.left().HasValue()
    1450         240 :                ? Float32Constant(static_cast<float>(m.left().Value()))
    1451        1147 :                : m.left().InputAt(0));
    1452        1527 :     node->ReplaceInput(
    1453             :         1, m.right().HasValue()
    1454         380 :                ? Float32Constant(static_cast<float>(m.right().Value()))
    1455        1147 :                : m.right().InputAt(0));
    1456             :     return Changed(node);
    1457             :   }
    1458             :   return NoChange();
    1459             : }
    1460             : 
    1461       81773 : Reduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
    1462             :   DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
    1463             :   Float64Matcher m(node->InputAt(0));
    1464       81773 :   if (m.HasValue()) {
    1465         345 :     return ReplaceFloat64(std::floor(m.Value()));
    1466             :   }
    1467             :   return NoChange();
    1468             : }
    1469             : 
    1470           0 : CommonOperatorBuilder* MachineOperatorReducer::common() const {
    1471           0 :   return mcgraph()->common();
    1472             : }
    1473             : 
    1474             : 
    1475           0 : MachineOperatorBuilder* MachineOperatorReducer::machine() const {
    1476           0 :   return mcgraph()->machine();
    1477             : }
    1478             : 
    1479           0 : Graph* MachineOperatorReducer::graph() const { return mcgraph()->graph(); }
    1480             : 
    1481             : }  // namespace compiler
    1482             : }  // namespace internal
    1483      122004 : }  // namespace v8

Generated by: LCOV version 1.10