LCOV - code coverage report
Current view: top level - src/compiler - machine-operator-reducer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 673 705 95.5 %
Date: 2017-04-26 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/codegen.h"
      11             : #include "src/compiler/diamond.h"
      12             : #include "src/compiler/graph.h"
      13             : #include "src/compiler/js-graph.h"
      14             : #include "src/compiler/node-matchers.h"
      15             : #include "src/objects-inl.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : namespace compiler {
      20             : 
      21     1649988 : MachineOperatorReducer::MachineOperatorReducer(JSGraph* jsgraph,
      22             :                                                bool allow_signalling_nan)
      23     1649988 :     : jsgraph_(jsgraph), allow_signalling_nan_(allow_signalling_nan) {}
      24             : 
      25     3299828 : MachineOperatorReducer::~MachineOperatorReducer() {}
      26             : 
      27             : 
      28       93389 : Node* MachineOperatorReducer::Float32Constant(volatile float value) {
      29      280167 :   return graph()->NewNode(common()->Float32Constant(value));
      30             : }
      31             : 
      32             : 
      33      112648 : Node* MachineOperatorReducer::Float64Constant(volatile double value) {
      34      225296 :   return jsgraph()->Float64Constant(value);
      35             : }
      36             : 
      37             : 
      38      598367 : Node* MachineOperatorReducer::Int32Constant(int32_t value) {
      39      598367 :   return jsgraph()->Int32Constant(value);
      40             : }
      41             : 
      42             : 
      43      921633 : Node* MachineOperatorReducer::Int64Constant(int64_t value) {
      44     1843268 :   return graph()->NewNode(common()->Int64Constant(value));
      45             : }
      46             : 
      47           0 : Node* MachineOperatorReducer::Float64Mul(Node* lhs, Node* rhs) {
      48           0 :   return graph()->NewNode(machine()->Float64Mul(), lhs, rhs);
      49             : }
      50             : 
      51           0 : Node* MachineOperatorReducer::Float64PowHalf(Node* value) {
      52             :   value =
      53           0 :       graph()->NewNode(machine()->Float64Add(), Float64Constant(0.0), value);
      54             :   Diamond d(graph(), common(),
      55             :             graph()->NewNode(machine()->Float64LessThanOrEqual(), value,
      56             :                              Float64Constant(-V8_INFINITY)),
      57           0 :             BranchHint::kFalse);
      58             :   return d.Phi(MachineRepresentation::kFloat64, Float64Constant(V8_INFINITY),
      59           0 :                graph()->NewNode(machine()->Float64Sqrt(), value));
      60             : }
      61             : 
      62      114257 : Node* MachineOperatorReducer::Word32And(Node* lhs, Node* rhs) {
      63      114257 :   Node* const node = graph()->NewNode(machine()->Word32And(), lhs, rhs);
      64      114257 :   Reduction const reduction = ReduceWord32And(node);
      65      114257 :   return reduction.Changed() ? reduction.replacement() : node;
      66             : }
      67             : 
      68             : 
      69        7638 : Node* MachineOperatorReducer::Word32Sar(Node* lhs, uint32_t rhs) {
      70        7638 :   if (rhs == 0) return lhs;
      71       14826 :   return graph()->NewNode(machine()->Word32Sar(), lhs, Uint32Constant(rhs));
      72             : }
      73             : 
      74             : 
      75        7936 : Node* MachineOperatorReducer::Word32Shr(Node* lhs, uint32_t rhs) {
      76        7936 :   if (rhs == 0) return lhs;
      77       15116 :   return graph()->NewNode(machine()->Word32Shr(), lhs, Uint32Constant(rhs));
      78             : }
      79             : 
      80             : 
      81          12 : Node* MachineOperatorReducer::Word32Equal(Node* lhs, Node* rhs) {
      82          24 :   return graph()->NewNode(machine()->Word32Equal(), lhs, rhs);
      83             : }
      84             : 
      85             : 
      86        8467 : Node* MachineOperatorReducer::Int32Add(Node* lhs, Node* rhs) {
      87        8467 :   Node* const node = graph()->NewNode(machine()->Int32Add(), lhs, rhs);
      88        8467 :   Reduction const reduction = ReduceInt32Add(node);
      89        8467 :   return reduction.Changed() ? reduction.replacement() : node;
      90             : }
      91             : 
      92             : 
      93        2537 : Node* MachineOperatorReducer::Int32Sub(Node* lhs, Node* rhs) {
      94        2537 :   Node* const node = graph()->NewNode(machine()->Int32Sub(), lhs, rhs);
      95        2537 :   Reduction const reduction = ReduceInt32Sub(node);
      96        2537 :   return reduction.Changed() ? reduction.replacement() : node;
      97             : }
      98             : 
      99             : 
     100        3914 : Node* MachineOperatorReducer::Int32Mul(Node* lhs, Node* rhs) {
     101        7828 :   return graph()->NewNode(machine()->Int32Mul(), lhs, rhs);
     102             : }
     103             : 
     104             : 
     105        5869 : Node* MachineOperatorReducer::Int32Div(Node* dividend, int32_t divisor) {
     106             :   DCHECK_NE(0, divisor);
     107             :   DCHECK_NE(std::numeric_limits<int32_t>::min(), divisor);
     108             :   base::MagicNumbersForDivision<uint32_t> const mag =
     109        5869 :       base::SignedDivisionByConstant(bit_cast<uint32_t>(divisor));
     110             :   Node* quotient = graph()->NewNode(machine()->Int32MulHigh(), dividend,
     111        5870 :                                     Uint32Constant(mag.multiplier));
     112       11740 :   if (divisor > 0 && bit_cast<int32_t>(mag.multiplier) < 0) {
     113        1567 :     quotient = Int32Add(quotient, dividend);
     114        4303 :   } else if (divisor < 0 && bit_cast<int32_t>(mag.multiplier) > 0) {
     115           0 :     quotient = Int32Sub(quotient, dividend);
     116             :   }
     117        5870 :   return Int32Add(Word32Sar(quotient, mag.shift), Word32Shr(dividend, 31));
     118             : }
     119             : 
     120             : 
     121         518 : Node* MachineOperatorReducer::Uint32Div(Node* dividend, uint32_t divisor) {
     122             :   DCHECK_LT(0u, divisor);
     123             :   // If the divisor is even, we can avoid using the expensive fixup by shifting
     124             :   // the dividend upfront.
     125             :   unsigned const shift = base::bits::CountTrailingZeros32(divisor);
     126         518 :   dividend = Word32Shr(dividend, shift);
     127         518 :   divisor >>= shift;
     128             :   // Compute the magic number for the (shifted) divisor.
     129             :   base::MagicNumbersForDivision<uint32_t> const mag =
     130         518 :       base::UnsignedDivisionByConstant(divisor, shift);
     131             :   Node* quotient = graph()->NewNode(machine()->Uint32MulHigh(), dividend,
     132        1036 :                                     Uint32Constant(mag.multiplier));
     133         518 :   if (mag.add) {
     134             :     DCHECK_LE(1u, mag.shift);
     135             :     quotient = Word32Shr(
     136             :         Int32Add(Word32Shr(Int32Sub(dividend, quotient), 1), quotient),
     137          57 :         mag.shift - 1);
     138             :   } else {
     139         461 :     quotient = Word32Shr(quotient, mag.shift);
     140             :   }
     141         518 :   return quotient;
     142             : }
     143             : 
     144             : 
     145             : // Perform constant folding and strength reduction on machine operators.
     146    89472453 : Reduction MachineOperatorReducer::Reduce(Node* node) {
     147    89472453 :   switch (node->opcode()) {
     148             :     case IrOpcode::kProjection:
     149      227643 :       return ReduceProjection(ProjectionIndexOf(node->op()), node->InputAt(0));
     150             :     case IrOpcode::kWord32And:
     151      402081 :       return ReduceWord32And(node);
     152             :     case IrOpcode::kWord32Or:
     153       79843 :       return ReduceWord32Or(node);
     154             :     case IrOpcode::kWord32Xor:
     155       32122 :       return ReduceWord32Xor(node);
     156             :     case IrOpcode::kWord32Shl:
     157       55480 :       return ReduceWord32Shl(node);
     158             :     case IrOpcode::kWord64Shl:
     159      337056 :       return ReduceWord64Shl(node);
     160             :     case IrOpcode::kWord32Shr:
     161       45261 :       return ReduceWord32Shr(node);
     162             :     case IrOpcode::kWord64Shr:
     163       34789 :       return ReduceWord64Shr(node);
     164             :     case IrOpcode::kWord32Sar:
     165       48378 :       return ReduceWord32Sar(node);
     166             :     case IrOpcode::kWord64Sar:
     167      215313 :       return ReduceWord64Sar(node);
     168             :     case IrOpcode::kWord32Ror: {
     169        1900 :       Int32BinopMatcher m(node);
     170        3465 :       if (m.right().Is(0)) return Replace(m.left().node());  // x ror 0 => x
     171        1851 :       if (m.IsFoldable()) {                                  // K ror K => K
     172             :         return ReplaceInt32(
     173        3032 :             base::bits::RotateRight32(m.left().Value(), m.right().Value()));
     174             :       }
     175         335 :       break;
     176             :     }
     177             :     case IrOpcode::kWord32Equal: {
     178      487139 :       Int32BinopMatcher m(node);
     179      487139 :       if (m.IsFoldable()) {  // K == K => K
     180       78768 :         return ReplaceBool(m.left().Value() == m.right().Value());
     181             :       }
     182      450870 :       if (m.left().IsInt32Sub() && m.right().Is(0)) {  // x - y == 0 => x == y
     183        1008 :         Int32BinopMatcher msub(m.left().node());
     184        1008 :         node->ReplaceInput(0, msub.left().node());
     185        1008 :         node->ReplaceInput(1, msub.right().node());
     186             :         return Changed(node);
     187             :       }
     188             :       // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
     189      448802 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x == x => true
     190      445700 :       break;
     191             :     }
     192             :     case IrOpcode::kWord64Equal: {
     193     1449882 :       Int64BinopMatcher m(node);
     194     1449881 :       if (m.IsFoldable()) {  // K == K => K
     195        5947 :         return ReplaceBool(m.left().Value() == m.right().Value());
     196             :       }
     197     1449739 :       if (m.left().IsInt64Sub() && m.right().Is(0)) {  // x - y == 0 => x == y
     198           0 :         Int64BinopMatcher msub(m.left().node());
     199           0 :         node->ReplaceInput(0, msub.left().node());
     200           0 :         node->ReplaceInput(1, msub.right().node());
     201             :         return Changed(node);
     202             :       }
     203             :       // TODO(turbofan): fold HeapConstant, ExternalReference, pointer compares
     204     1449739 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x == x => true
     205     1444076 :       break;
     206             :     }
     207             :     case IrOpcode::kInt32Add:
     208      390775 :       return ReduceInt32Add(node);
     209             :     case IrOpcode::kInt64Add:
     210      738282 :       return ReduceInt64Add(node);
     211             :     case IrOpcode::kInt32Sub:
     212       75404 :       return ReduceInt32Sub(node);
     213             :     case IrOpcode::kInt64Sub:
     214      156718 :       return ReduceInt64Sub(node);
     215             :     case IrOpcode::kInt32Mul: {
     216       35753 :       Int32BinopMatcher m(node);
     217       57550 :       if (m.right().Is(0)) return Replace(m.right().node());  // x * 0 => 0
     218       35292 :       if (m.right().Is(1)) return Replace(m.left().node());   // x * 1 => x
     219       34653 :       if (m.IsFoldable()) {                                   // K * K => K
     220       19844 :         return ReplaceInt32(m.left().Value() * m.right().Value());
     221             :       }
     222       14809 :       if (m.right().Is(-1)) {  // x * -1 => 0 - x
     223         117 :         node->ReplaceInput(0, Int32Constant(0));
     224         117 :         node->ReplaceInput(1, m.left().node());
     225         117 :         NodeProperties::ChangeOp(node, machine()->Int32Sub());
     226             :         return Changed(node);
     227             :       }
     228       14692 :       if (m.right().IsPowerOf2()) {  // x * 2^n => x << n
     229        1468 :         node->ReplaceInput(1, Int32Constant(WhichPowerOf2(m.right().Value())));
     230         734 :         NodeProperties::ChangeOp(node, machine()->Word32Shl());
     231         734 :         Reduction reduction = ReduceWord32Shl(node);
     232         734 :         return reduction.Changed() ? reduction : Changed(node);
     233             :       }
     234       13958 :       break;
     235             :     }
     236             :     case IrOpcode::kInt32MulWithOverflow: {
     237        7361 :       Int32BinopMatcher m(node);
     238        7361 :       if (m.right().Is(2)) {
     239         206 :         node->ReplaceInput(1, m.left().node());
     240         206 :         NodeProperties::ChangeOp(node, machine()->Int32AddWithOverflow());
     241        3448 :         return Changed(node);
     242             :       }
     243        7155 :       if (m.right().Is(-1)) {
     244        3242 :         node->ReplaceInput(0, Int32Constant(0));
     245        3242 :         node->ReplaceInput(1, m.left().node());
     246        3242 :         NodeProperties::ChangeOp(node, machine()->Int32SubWithOverflow());
     247             :         return Changed(node);
     248             :       }
     249        3913 :       break;
     250             :     }
     251             :     case IrOpcode::kInt32Div:
     252       23902 :       return ReduceInt32Div(node);
     253             :     case IrOpcode::kUint32Div:
     254       23216 :       return ReduceUint32Div(node);
     255             :     case IrOpcode::kInt32Mod:
     256       35682 :       return ReduceInt32Mod(node);
     257             :     case IrOpcode::kUint32Mod:
     258       23412 :       return ReduceUint32Mod(node);
     259             :     case IrOpcode::kInt32LessThan: {
     260      237947 :       Int32BinopMatcher m(node);
     261      237950 :       if (m.IsFoldable()) {  // K < K => K
     262       48776 :         return ReplaceBool(m.left().Value() < m.right().Value());
     263             :       }
     264      213605 :       if (m.LeftEqualsRight()) return ReplaceBool(false);  // x < x => false
     265      214707 :       if (m.left().IsWord32Or() && m.right().Is(0)) {
     266             :         // (x | K) < 0 => true or (K | x) < 0 => true iff K < 0
     267        1056 :         Int32BinopMatcher mleftmatcher(m.left().node());
     268        2112 :         if (mleftmatcher.left().IsNegative() ||
     269             :             mleftmatcher.right().IsNegative()) {
     270          71 :           return ReplaceBool(true);
     271             :         }
     272             :       }
     273      213519 :       break;
     274             :     }
     275             :     case IrOpcode::kInt32LessThanOrEqual: {
     276       27901 :       Int32BinopMatcher m(node);
     277       27901 :       if (m.IsFoldable()) {  // K <= K => K
     278       44023 :         return ReplaceBool(m.left().Value() <= m.right().Value());
     279             :       }
     280        5893 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x <= x => true
     281        5886 :       break;
     282             :     }
     283             :     case IrOpcode::kUint32LessThan: {
     284      114933 :       Uint32BinopMatcher m(node);
     285      143574 :       if (m.left().Is(kMaxUInt32)) return ReplaceBool(false);  // M < x => false
     286      114523 :       if (m.right().Is(0)) return ReplaceBool(false);          // x < 0 => false
     287      113946 :       if (m.IsFoldable()) {                                    // K < K => K
     288       25860 :         return ReplaceBool(m.left().Value() < m.right().Value());
     289             :       }
     290       88086 :       if (m.LeftEqualsRight()) return ReplaceBool(false);  // x < x => false
     291       86593 :       if (m.left().IsWord32Sar() && m.right().HasValue()) {
     292         338 :         Int32BinopMatcher mleft(m.left().node());
     293         338 :         if (mleft.right().HasValue()) {
     294             :           // (x >> K) < C => x < (C << K)
     295             :           // when C < (M >> K)
     296         338 :           const uint32_t c = m.right().Value();
     297         338 :           const uint32_t k = mleft.right().Value() & 0x1f;
     298         338 :           if (c < static_cast<uint32_t>(kMaxInt >> k)) {
     299         301 :             node->ReplaceInput(0, mleft.left().node());
     300         602 :             node->ReplaceInput(1, Uint32Constant(c << k));
     301         301 :             return Changed(node);
     302             :           }
     303             :           // TODO(turbofan): else the comparison is always true.
     304             :         }
     305             :       }
     306       86292 :       break;
     307             :     }
     308             :     case IrOpcode::kUint32LessThanOrEqual: {
     309       64225 :       Uint32BinopMatcher m(node);
     310       85121 :       if (m.left().Is(0)) return ReplaceBool(true);            // 0 <= x => true
     311       63661 :       if (m.right().Is(kMaxUInt32)) return ReplaceBool(true);  // x <= M => true
     312       63283 :       if (m.IsFoldable()) {                                    // K <= K => K
     313       19947 :         return ReplaceBool(m.left().Value() <= m.right().Value());
     314             :       }
     315       43336 :       if (m.LeftEqualsRight()) return ReplaceBool(true);  // x <= x => true
     316       43329 :       break;
     317             :     }
     318             :     case IrOpcode::kFloat32Sub: {
     319       92693 :       Float32BinopMatcher m(node);
     320      186902 :       if (allow_signalling_nan_ && m.right().Is(0) &&
     321        1610 :           (copysign(1.0, m.right().Value()) > 0)) {
     322       92629 :         return Replace(m.left().node());  // x - 0 => x
     323             :       }
     324       91888 :       if (m.right().IsNaN()) {  // x - NaN => NaN
     325             :         // Do some calculation to make a signalling NaN quiet.
     326        1633 :         return ReplaceFloat32(m.right().Value() - m.right().Value());
     327             :       }
     328       90255 :       if (m.left().IsNaN()) {  // NaN - x => NaN
     329             :         // Do some calculation to make a signalling NaN quiet.
     330        1591 :         return ReplaceFloat32(m.left().Value() - m.left().Value());
     331             :       }
     332       88664 :       if (m.IsFoldable()) {  // L - R => (L - R)
     333       88599 :         return ReplaceFloat32(m.left().Value() - m.right().Value());
     334             :       }
     335          65 :       if (allow_signalling_nan_ && m.left().IsMinusZero()) {
     336             :         // -0.0 - round_down(-0.0 - R) => round_up(R)
     337           1 :         if (machine()->Float32RoundUp().IsSupported() &&
     338             :             m.right().IsFloat32RoundDown()) {
     339           0 :           if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat32Sub) {
     340           0 :             Float32BinopMatcher mright0(m.right().InputAt(0));
     341           0 :             if (mright0.left().IsMinusZero()) {
     342             :               return Replace(graph()->NewNode(machine()->Float32RoundUp().op(),
     343           0 :                                               mright0.right().node()));
     344             :             }
     345             :           }
     346             :         }
     347             :         // -0.0 - R => -R
     348           1 :         node->RemoveInput(0);
     349           1 :         NodeProperties::ChangeOp(node, machine()->Float32Neg());
     350             :         return Changed(node);
     351             :       }
     352          64 :       break;
     353             :     }
     354             :     case IrOpcode::kFloat64Add: {
     355      115379 :       Float64BinopMatcher m(node);
     356      115383 :       if (m.right().IsNaN()) {  // x + NaN => NaN
     357             :         // Do some calculation to make a signalling NaN quiet.
     358       14903 :         return ReplaceFloat64(m.right().Value() - m.right().Value());
     359             :       }
     360      115305 :       if (m.IsFoldable()) {  // K + K => K
     361       14747 :         return ReplaceFloat64(m.left().Value() + m.right().Value());
     362             :       }
     363      100558 :       break;
     364             :     }
     365             :     case IrOpcode::kFloat64Sub: {
     366       79670 :       Float64BinopMatcher m(node);
     367      160120 :       if (allow_signalling_nan_ && m.right().Is(0) &&
     368         873 :           (Double(m.right().Value()).Sign() > 0)) {
     369       36005 :         return Replace(m.left().node());  // x - 0 => x
     370             :       }
     371       79148 :       if (m.right().IsNaN()) {  // x - NaN => NaN
     372             :         // Do some calculation to make a signalling NaN quiet.
     373         739 :         return ReplaceFloat64(m.right().Value() - m.right().Value());
     374             :       }
     375       78409 :       if (m.left().IsNaN()) {  // NaN - x => NaN
     376             :         // Do some calculation to make a signalling NaN quiet.
     377         700 :         return ReplaceFloat64(m.left().Value() - m.left().Value());
     378             :       }
     379       77709 :       if (m.IsFoldable()) {  // L - R => (L - R)
     380       24512 :         return ReplaceFloat64(m.left().Value() - m.right().Value());
     381             :       }
     382       53197 :       if (allow_signalling_nan_ && m.left().IsMinusZero()) {
     383             :         // -0.0 - round_down(-0.0 - R) => round_up(R)
     384       19065 :         if (machine()->Float64RoundUp().IsSupported() &&
     385             :             m.right().IsFloat64RoundDown()) {
     386        1314 :           if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub) {
     387           0 :             Float64BinopMatcher mright0(m.right().InputAt(0));
     388           0 :             if (mright0.left().IsMinusZero()) {
     389             :               return Replace(graph()->NewNode(machine()->Float64RoundUp().op(),
     390           0 :                                               mright0.right().node()));
     391             :             }
     392             :           }
     393             :         }
     394             :         // -0.0 - R => -R
     395        9532 :         node->RemoveInput(0);
     396        9533 :         NodeProperties::ChangeOp(node, machine()->Float64Neg());
     397             :         return Changed(node);
     398             :       }
     399       43665 :       break;
     400             :     }
     401             :     case IrOpcode::kFloat64Mul: {
     402       43107 :       Float64BinopMatcher m(node);
     403       86147 :       if (allow_signalling_nan_ && m.right().Is(1))
     404       22718 :         return Replace(m.left().node());  // x * 1.0 => x
     405       32919 :       if (m.right().Is(-1)) {  // x * -1.0 => -0.0 - x
     406       10214 :         node->ReplaceInput(0, Float64Constant(-0.0));
     407       10214 :         node->ReplaceInput(1, m.left().node());
     408       10213 :         NodeProperties::ChangeOp(node, machine()->Float64Sub());
     409             :         return Changed(node);
     410             :       }
     411       22706 :       if (m.right().IsNaN()) {                               // x * NaN => NaN
     412             :         // Do some calculation to make a signalling NaN quiet.
     413          42 :         return ReplaceFloat64(m.right().Value() - m.right().Value());
     414             :       }
     415       22664 :       if (m.IsFoldable()) {  // K * K => K
     416        1989 :         return ReplaceFloat64(m.left().Value() * m.right().Value());
     417             :       }
     418       20675 :       if (m.right().Is(2)) {  // x * 2.0 => x + x
     419         286 :         node->ReplaceInput(1, m.left().node());
     420         286 :         NodeProperties::ChangeOp(node, machine()->Float64Add());
     421             :         return Changed(node);
     422             :       }
     423       20389 :       break;
     424             :     }
     425             :     case IrOpcode::kFloat64Div: {
     426       34474 :       Float64BinopMatcher m(node);
     427       68853 :       if (allow_signalling_nan_ && m.right().Is(1))
     428        7451 :         return Replace(m.left().node());  // x / 1.0 => x
     429             :       // TODO(ahaas): We could do x / 1.0 = x if we knew that x is not an sNaN.
     430       33900 :       if (m.right().IsNaN()) {                               // x / NaN => NaN
     431             :         // Do some calculation to make a signalling NaN quiet.
     432         175 :         return ReplaceFloat64(m.right().Value() - m.right().Value());
     433             :       }
     434       33725 :       if (m.left().IsNaN()) {  // NaN / x => NaN
     435             :         // Do some calculation to make a signalling NaN quiet.
     436          62 :         return ReplaceFloat64(m.left().Value() - m.left().Value());
     437             :       }
     438       33663 :       if (m.IsFoldable()) {  // K / K => K
     439        3787 :         return ReplaceFloat64(m.left().Value() / m.right().Value());
     440             :       }
     441       59696 :       if (allow_signalling_nan_ && m.right().Is(-1)) {  // x / -1.0 => -x
     442          65 :         node->RemoveInput(1);
     443          65 :         NodeProperties::ChangeOp(node, machine()->Float64Neg());
     444             :         return Changed(node);
     445             :       }
     446       29811 :       if (m.right().IsNormal() && m.right().IsPositiveOrNegativePowerOf2()) {
     447             :         // All reciprocals of non-denormal powers of two can be represented
     448             :         // exactly, so division by power of two can be reduced to
     449             :         // multiplication by reciprocal, with the same result.
     450        5576 :         node->ReplaceInput(1, Float64Constant(1.0 / m.right().Value()));
     451        2788 :         NodeProperties::ChangeOp(node, machine()->Float64Mul());
     452             :         return Changed(node);
     453             :       }
     454       27023 :       break;
     455             :     }
     456             :     case IrOpcode::kFloat64Mod: {
     457        2657 :       Float64BinopMatcher m(node);
     458        2657 :       if (m.right().Is(0)) {  // x % 0 => NaN
     459        1248 :         return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN());
     460             :       }
     461        2506 :       if (m.right().IsNaN()) {  // x % NaN => NaN
     462             :         return Replace(m.right().node());
     463             :       }
     464        2469 :       if (m.left().IsNaN()) {  // NaN % x => NaN
     465             :         return Replace(m.left().node());
     466             :       }
     467        2442 :       if (m.IsFoldable()) {  // K % K => K
     468        1033 :         return ReplaceFloat64(modulo(m.left().Value(), m.right().Value()));
     469             :       }
     470        1409 :       break;
     471             :     }
     472             :     case IrOpcode::kFloat64Acos: {
     473             :       Float64Matcher m(node->InputAt(0));
     474         102 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::acos(m.Value()));
     475             :       break;
     476             :     }
     477             :     case IrOpcode::kFloat64Acosh: {
     478             :       Float64Matcher m(node->InputAt(0));
     479         100 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::acosh(m.Value()));
     480             :       break;
     481             :     }
     482             :     case IrOpcode::kFloat64Asin: {
     483             :       Float64Matcher m(node->InputAt(0));
     484         102 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::asin(m.Value()));
     485             :       break;
     486             :     }
     487             :     case IrOpcode::kFloat64Asinh: {
     488             :       Float64Matcher m(node->InputAt(0));
     489         100 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::asinh(m.Value()));
     490             :       break;
     491             :     }
     492             :     case IrOpcode::kFloat64Atan: {
     493             :       Float64Matcher m(node->InputAt(0));
     494         125 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::atan(m.Value()));
     495             :       break;
     496             :     }
     497             :     case IrOpcode::kFloat64Atanh: {
     498             :       Float64Matcher m(node->InputAt(0));
     499         100 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::atanh(m.Value()));
     500             :       break;
     501             :     }
     502             :     case IrOpcode::kFloat64Atan2: {
     503       10048 :       Float64BinopMatcher m(node);
     504       10048 :       if (m.right().IsNaN()) {
     505       10009 :         return Replace(m.right().node());
     506             :       }
     507       10047 :       if (m.left().IsNaN()) {
     508             :         return Replace(m.left().node());
     509             :       }
     510       10046 :       if (m.IsFoldable()) {
     511             :         return ReplaceFloat64(
     512       10007 :             base::ieee754::atan2(m.left().Value(), m.right().Value()));
     513             :       }
     514          39 :       break;
     515             :     }
     516             :     case IrOpcode::kFloat64Cbrt: {
     517             :       Float64Matcher m(node->InputAt(0));
     518           0 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::cbrt(m.Value()));
     519             :       break;
     520             :     }
     521             :     case IrOpcode::kFloat64Cos: {
     522             :       Float64Matcher m(node->InputAt(0));
     523         386 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::cos(m.Value()));
     524             :       break;
     525             :     }
     526             :     case IrOpcode::kFloat64Cosh: {
     527             :       Float64Matcher m(node->InputAt(0));
     528         118 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::cosh(m.Value()));
     529             :       break;
     530             :     }
     531             :     case IrOpcode::kFloat64Exp: {
     532             :       Float64Matcher m(node->InputAt(0));
     533         149 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::exp(m.Value()));
     534             :       break;
     535             :     }
     536             :     case IrOpcode::kFloat64Expm1: {
     537             :       Float64Matcher m(node->InputAt(0));
     538           0 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::expm1(m.Value()));
     539             :       break;
     540             :     }
     541             :     case IrOpcode::kFloat64Log: {
     542             :       Float64Matcher m(node->InputAt(0));
     543         345 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log(m.Value()));
     544             :       break;
     545             :     }
     546             :     case IrOpcode::kFloat64Log1p: {
     547             :       Float64Matcher m(node->InputAt(0));
     548         100 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log1p(m.Value()));
     549             :       break;
     550             :     }
     551             :     case IrOpcode::kFloat64Log10: {
     552             :       Float64Matcher m(node->InputAt(0));
     553           0 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log10(m.Value()));
     554             :       break;
     555             :     }
     556             :     case IrOpcode::kFloat64Log2: {
     557             :       Float64Matcher m(node->InputAt(0));
     558           0 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::log2(m.Value()));
     559             :       break;
     560             :     }
     561             :     case IrOpcode::kFloat64Pow: {
     562       10975 :       Float64BinopMatcher m(node);
     563       10975 :       if (m.IsFoldable()) {
     564       21698 :         return ReplaceFloat64(Pow(m.left().Value(), m.right().Value()));
     565         127 :       } else if (m.right().Is(0.0)) {  // x ** +-0.0 => 1.0
     566             :         return ReplaceFloat64(1.0);
     567         125 :       } else if (m.right().Is(-2.0)) {  // x ** -2.0 => 1 / (x * x)
     568           0 :         node->ReplaceInput(0, Float64Constant(1.0));
     569           0 :         node->ReplaceInput(1, Float64Mul(m.left().node(), m.left().node()));
     570           0 :         NodeProperties::ChangeOp(node, machine()->Float64Div());
     571             :         return Changed(node);
     572         125 :       } else if (m.right().Is(2.0)) {  // x ** 2.0 => x * x
     573           0 :         node->ReplaceInput(1, m.left().node());
     574           0 :         NodeProperties::ChangeOp(node, machine()->Float64Mul());
     575             :         return Changed(node);
     576         125 :       } else if (m.right().Is(-0.5)) {
     577             :         // x ** 0.5 => 1 / (if x <= -Infinity then Infinity else sqrt(0.0 + x))
     578           0 :         node->ReplaceInput(0, Float64Constant(1.0));
     579           0 :         node->ReplaceInput(1, Float64PowHalf(m.left().node()));
     580           0 :         NodeProperties::ChangeOp(node, machine()->Float64Div());
     581             :         return Changed(node);
     582         125 :       } else if (m.right().Is(0.5)) {
     583             :         // x ** 0.5 => if x <= -Infinity then Infinity else sqrt(0.0 + x)
     584           0 :         return Replace(Float64PowHalf(m.left().node()));
     585             :       }
     586         125 :       break;
     587             :     }
     588             :     case IrOpcode::kFloat64Sin: {
     589             :       Float64Matcher m(node->InputAt(0));
     590         411 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::sin(m.Value()));
     591             :       break;
     592             :     }
     593             :     case IrOpcode::kFloat64Sinh: {
     594             :       Float64Matcher m(node->InputAt(0));
     595         118 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::sinh(m.Value()));
     596             :       break;
     597             :     }
     598             :     case IrOpcode::kFloat64Tan: {
     599             :       Float64Matcher m(node->InputAt(0));
     600         125 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::tan(m.Value()));
     601             :       break;
     602             :     }
     603             :     case IrOpcode::kFloat64Tanh: {
     604             :       Float64Matcher m(node->InputAt(0));
     605         118 :       if (m.HasValue()) return ReplaceFloat64(base::ieee754::tanh(m.Value()));
     606             :       break;
     607             :     }
     608             :     case IrOpcode::kChangeFloat32ToFloat64: {
     609             :       Float32Matcher m(node->InputAt(0));
     610       15707 :       if (m.HasValue()) {
     611         199 :         if (!allow_signalling_nan_ && std::isnan(m.Value())) {
     612             :           // Do some calculation to make guarantee the value is a quiet NaN.
     613          16 :           return ReplaceFloat64(m.Value() + m.Value());
     614             :         }
     615         183 :         return ReplaceFloat64(m.Value());
     616             :       }
     617             :       break;
     618             :     }
     619             :     case IrOpcode::kChangeFloat64ToInt32: {
     620             :       Float64Matcher m(node->InputAt(0));
     621       12956 :       if (m.HasValue()) return ReplaceInt32(FastD2I(m.Value()));
     622        8320 :       if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
     623             :       break;
     624             :     }
     625             :     case IrOpcode::kChangeFloat64ToUint32: {
     626             :       Float64Matcher m(node->InputAt(0));
     627         608 :       if (m.HasValue()) return ReplaceInt32(FastD2UI(m.Value()));
     628         494 :       if (m.IsChangeUint32ToFloat64()) return Replace(m.node()->InputAt(0));
     629             :       break;
     630             :     }
     631             :     case IrOpcode::kChangeInt32ToFloat64: {
     632             :       Int32Matcher m(node->InputAt(0));
     633      193978 :       if (m.HasValue()) return ReplaceFloat64(FastI2D(m.Value()));
     634             :       break;
     635             :     }
     636             :     case IrOpcode::kChangeInt32ToInt64: {
     637             :       Int32Matcher m(node->InputAt(0));
     638      216931 :       if (m.HasValue()) return ReplaceInt64(m.Value());
     639             :       break;
     640             :     }
     641             :     case IrOpcode::kChangeUint32ToFloat64: {
     642             :       Uint32Matcher m(node->InputAt(0));
     643        2083 :       if (m.HasValue()) return ReplaceFloat64(FastUI2D(m.Value()));
     644             :       break;
     645             :     }
     646             :     case IrOpcode::kChangeUint32ToUint64: {
     647             :       Uint32Matcher m(node->InputAt(0));
     648      204313 :       if (m.HasValue()) return ReplaceInt64(static_cast<uint64_t>(m.Value()));
     649             :       break;
     650             :     }
     651             :     case IrOpcode::kTruncateFloat64ToWord32: {
     652             :       Float64Matcher m(node->InputAt(0));
     653       25881 :       if (m.HasValue()) return ReplaceInt32(DoubleToInt32(m.Value()));
     654       22336 :       if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
     655             :       return NoChange();
     656             :     }
     657             :     case IrOpcode::kTruncateInt64ToInt32: {
     658             :       Int64Matcher m(node->InputAt(0));
     659      172241 :       if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
     660      171468 :       if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
     661             :       break;
     662             :     }
     663             :     case IrOpcode::kTruncateFloat64ToFloat32: {
     664             :       Float64Matcher m(node->InputAt(0));
     665        7998 :       if (m.HasValue()) {
     666         875 :         if (!allow_signalling_nan_ && std::isnan(m.Value())) {
     667             :           // Do some calculation to make guarantee the value is a quiet NaN.
     668          16 :           return ReplaceFloat32(DoubleToFloat32(m.Value() + m.Value()));
     669             :         }
     670             :         return ReplaceFloat32(DoubleToFloat32(m.Value()));
     671             :       }
     672        7123 :       if (allow_signalling_nan_ && m.IsChangeFloat32ToFloat64())
     673             :         return Replace(m.node()->InputAt(0));
     674             :       break;
     675             :     }
     676             :     case IrOpcode::kRoundFloat64ToInt32: {
     677             :       Float64Matcher m(node->InputAt(0));
     678       55394 :       if (m.HasValue()) return ReplaceInt32(static_cast<int32_t>(m.Value()));
     679       55087 :       if (m.IsChangeInt32ToFloat64()) return Replace(m.node()->InputAt(0));
     680             :       break;
     681             :     }
     682             :     case IrOpcode::kFloat64InsertLowWord32:
     683        4800 :       return ReduceFloat64InsertLowWord32(node);
     684             :     case IrOpcode::kFloat64InsertHighWord32:
     685        4800 :       return ReduceFloat64InsertHighWord32(node);
     686             :     case IrOpcode::kStore:
     687             :     case IrOpcode::kUnalignedStore:
     688             :     case IrOpcode::kCheckedStore:
     689     1454432 :       return ReduceStore(node);
     690             :     case IrOpcode::kFloat64Equal:
     691             :     case IrOpcode::kFloat64LessThan:
     692             :     case IrOpcode::kFloat64LessThanOrEqual:
     693      191628 :       return ReduceFloat64Compare(node);
     694             :     case IrOpcode::kFloat64RoundDown:
     695       18064 :       return ReduceFloat64RoundDown(node);
     696             :     default:
     697             :       break;
     698             :   }
     699             :   return NoChange();
     700             : }
     701             : 
     702      536046 : Reduction MachineOperatorReducer::ReduceInt32Add(Node* node) {
     703             :   DCHECK_EQ(IrOpcode::kInt32Add, node->opcode());
     704      536046 :   Int32BinopMatcher m(node);
     705      536061 :   if (m.right().Is(0)) return Replace(m.left().node());  // x + 0 => x
     706      513189 :   if (m.IsFoldable()) {                                  // K + K => K
     707             :     return ReplaceUint32(bit_cast<uint32_t>(m.left().Value()) +
     708       39734 :                          bit_cast<uint32_t>(m.right().Value()));
     709             :   }
     710      473455 :   if (m.left().IsInt32Sub()) {
     711        1504 :     Int32BinopMatcher mleft(m.left().node());
     712        1504 :     if (mleft.left().Is(0)) {  // (0 - x) + y => y - x
     713          12 :       node->ReplaceInput(0, m.right().node());
     714          12 :       node->ReplaceInput(1, mleft.right().node());
     715          12 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     716          12 :       Reduction const reduction = ReduceInt32Sub(node);
     717          12 :       return reduction.Changed() ? reduction : Changed(node);
     718             :     }
     719             :   }
     720      473443 :   if (m.right().IsInt32Sub()) {
     721         732 :     Int32BinopMatcher mright(m.right().node());
     722         732 :     if (mright.left().Is(0)) {  // y + (0 - x) => y - x
     723          50 :       node->ReplaceInput(1, mright.right().node());
     724          50 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     725          50 :       Reduction const reduction = ReduceInt32Sub(node);
     726          50 :       return reduction.Changed() ? reduction : Changed(node);
     727             :     }
     728             :   }
     729             :   return NoChange();
     730             : }
     731             : 
     732      852814 : Reduction MachineOperatorReducer::ReduceInt64Add(Node* node) {
     733             :   DCHECK_EQ(IrOpcode::kInt64Add, node->opcode());
     734      852814 :   Int64BinopMatcher m(node);
     735      852815 :   if (m.right().Is(0)) return Replace(m.left().node());  // x + 0 => 0
     736      851723 :   if (m.IsFoldable()) {
     737             :     return Replace(Uint64Constant(bit_cast<uint64_t>(m.left().Value()) +
     738      205863 :                                   bit_cast<uint64_t>(m.right().Value())));
     739             :   }
     740             :   return NoChange();
     741             : }
     742             : 
     743       78061 : Reduction MachineOperatorReducer::ReduceInt32Sub(Node* node) {
     744             :   DCHECK_EQ(IrOpcode::kInt32Sub, node->opcode());
     745       78061 :   Int32BinopMatcher m(node);
     746       78081 :   if (m.right().Is(0)) return Replace(m.left().node());  // x - 0 => x
     747       77284 :   if (m.IsFoldable()) {                                  // K - K => K
     748       29301 :     return ReplaceInt32(static_cast<uint32_t>(m.left().Value()) -
     749       29301 :                         static_cast<uint32_t>(m.right().Value()));
     750             :   }
     751       47983 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);  // x - x => 0
     752       47981 :   if (m.right().HasValue()) {                       // x - K => x + -K
     753       50064 :     node->ReplaceInput(1, Int32Constant(-m.right().Value()));
     754       25030 :     NodeProperties::ChangeOp(node, machine()->Int32Add());
     755       25032 :     Reduction const reduction = ReduceInt32Add(node);
     756       25016 :     return reduction.Changed() ? reduction : Changed(node);
     757             :   }
     758             :   return NoChange();
     759             : }
     760             : 
     761      156717 : Reduction MachineOperatorReducer::ReduceInt64Sub(Node* node) {
     762             :   DCHECK_EQ(IrOpcode::kInt64Sub, node->opcode());
     763      156717 :   Int64BinopMatcher m(node);
     764      156717 :   if (m.right().Is(0)) return Replace(m.left().node());  // x - 0 => x
     765      155632 :   if (m.IsFoldable()) {                                  // K - K => K
     766             :     return Replace(Uint64Constant(bit_cast<uint64_t>(m.left().Value()) -
     767       40454 :                                   bit_cast<uint64_t>(m.right().Value())));
     768             :   }
     769      115178 :   if (m.LeftEqualsRight()) return Replace(Int64Constant(0));  // x - x => 0
     770      115171 :   if (m.right().HasValue()) {                                 // x - K => x + -K
     771      114533 :     node->ReplaceInput(1, Int64Constant(-m.right().Value()));
     772      114532 :     NodeProperties::ChangeOp(node, machine()->Int64Add());
     773      114532 :     Reduction const reduction = ReduceInt64Add(node);
     774      114532 :     return reduction.Changed() ? reduction : Changed(node);
     775             :   }
     776             :   return NoChange();
     777             : }
     778             : 
     779       23901 : Reduction MachineOperatorReducer::ReduceInt32Div(Node* node) {
     780       23901 :   Int32BinopMatcher m(node);
     781       23902 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 / x => 0
     782       23525 :   if (m.right().Is(0)) return Replace(m.right().node());  // x / 0 => 0
     783       23517 :   if (m.right().Is(1)) return Replace(m.left().node());   // x / 1 => x
     784       23078 :   if (m.IsFoldable()) {                                   // K / K => K
     785             :     return ReplaceInt32(
     786       19353 :         base::bits::SignedDiv32(m.left().Value(), m.right().Value()));
     787             :   }
     788        3725 :   if (m.LeftEqualsRight()) {  // x / x => x != 0
     789             :     Node* const zero = Int32Constant(0);
     790           5 :     return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
     791             :   }
     792        3720 :   if (m.right().Is(-1)) {  // x / -1 => 0 - x
     793          41 :     node->ReplaceInput(0, Int32Constant(0));
     794          41 :     node->ReplaceInput(1, m.left().node());
     795          41 :     node->TrimInputCount(2);
     796          41 :     NodeProperties::ChangeOp(node, machine()->Int32Sub());
     797             :     return Changed(node);
     798             :   }
     799        3679 :   if (m.right().HasValue()) {
     800        3306 :     int32_t const divisor = m.right().Value();
     801             :     Node* const dividend = m.left().node();
     802             :     Node* quotient = dividend;
     803        6612 :     if (base::bits::IsPowerOfTwo32(Abs(divisor))) {
     804         973 :       uint32_t const shift = WhichPowerOf2Abs(divisor);
     805             :       DCHECK_NE(0u, shift);
     806         973 :       if (shift > 1) {
     807         795 :         quotient = Word32Sar(quotient, 31);
     808             :       }
     809         973 :       quotient = Int32Add(Word32Shr(quotient, 32u - shift), dividend);
     810         973 :       quotient = Word32Sar(quotient, shift);
     811             :     } else {
     812        2333 :       quotient = Int32Div(quotient, Abs(divisor));
     813             :     }
     814        3306 :     if (divisor < 0) {
     815        1462 :       node->ReplaceInput(0, Int32Constant(0));
     816        1462 :       node->ReplaceInput(1, quotient);
     817        1462 :       node->TrimInputCount(2);
     818        1462 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     819             :       return Changed(node);
     820             :     }
     821             :     return Replace(quotient);
     822             :   }
     823             :   return NoChange();
     824             : }
     825             : 
     826             : 
     827       23216 : Reduction MachineOperatorReducer::ReduceUint32Div(Node* node) {
     828       23216 :   Uint32BinopMatcher m(node);
     829       23216 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 / x => 0
     830       22770 :   if (m.right().Is(0)) return Replace(m.right().node());  // x / 0 => 0
     831       22707 :   if (m.right().Is(1)) return Replace(m.left().node());   // x / 1 => x
     832       22266 :   if (m.IsFoldable()) {                                   // K / K => K
     833             :     return ReplaceUint32(
     834       21516 :         base::bits::UnsignedDiv32(m.left().Value(), m.right().Value()));
     835             :   }
     836         750 :   if (m.LeftEqualsRight()) {  // x / x => x != 0
     837             :     Node* const zero = Int32Constant(0);
     838           1 :     return Replace(Word32Equal(Word32Equal(m.left().node(), zero), zero));
     839             :   }
     840         749 :   if (m.right().HasValue()) {
     841             :     Node* const dividend = m.left().node();
     842         513 :     uint32_t const divisor = m.right().Value();
     843         513 :     if (base::bits::IsPowerOfTwo32(divisor)) {  // x / 2^n => x >> n
     844         744 :       node->ReplaceInput(1, Uint32Constant(WhichPowerOf2(m.right().Value())));
     845         372 :       node->TrimInputCount(2);
     846         372 :       NodeProperties::ChangeOp(node, machine()->Word32Shr());
     847             :       return Changed(node);
     848             :     } else {
     849         141 :       return Replace(Uint32Div(dividend, divisor));
     850             :     }
     851             :   }
     852             :   return NoChange();
     853             : }
     854             : 
     855             : 
     856       35682 : Reduction MachineOperatorReducer::ReduceInt32Mod(Node* node) {
     857       35682 :   Int32BinopMatcher m(node);
     858       35682 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 % x  => 0
     859       35193 :   if (m.right().Is(0)) return Replace(m.right().node());  // x % 0  => 0
     860       35093 :   if (m.right().Is(1)) return ReplaceInt32(0);            // x % 1  => 0
     861       34698 :   if (m.right().Is(-1)) return ReplaceInt32(0);           // x % -1 => 0
     862       34326 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);        // x % x  => 0
     863       34308 :   if (m.IsFoldable()) {                                   // K % K => K
     864             :     return ReplaceInt32(
     865       28810 :         base::bits::SignedMod32(m.left().Value(), m.right().Value()));
     866             :   }
     867        5498 :   if (m.right().HasValue()) {
     868             :     Node* const dividend = m.left().node();
     869        4777 :     int32_t const divisor = Abs(m.right().Value());
     870        9554 :     if (base::bits::IsPowerOfTwo32(divisor)) {
     871        1240 :       uint32_t const mask = divisor - 1;
     872             :       Node* const zero = Int32Constant(0);
     873             :       Diamond d(graph(), common(),
     874             :                 graph()->NewNode(machine()->Int32LessThan(), dividend, zero),
     875        2480 :                 BranchHint::kFalse);
     876             :       return Replace(
     877             :           d.Phi(MachineRepresentation::kWord32,
     878             :                 Int32Sub(zero, Word32And(Int32Sub(zero, dividend), mask)),
     879        1240 :                 Word32And(dividend, mask)));
     880             :     } else {
     881        3537 :       Node* quotient = Int32Div(dividend, divisor);
     882             :       DCHECK_EQ(dividend, node->InputAt(0));
     883        3537 :       node->ReplaceInput(1, Int32Mul(quotient, Int32Constant(divisor)));
     884        3537 :       node->TrimInputCount(2);
     885        3537 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     886             :     }
     887             :     return Changed(node);
     888             :   }
     889             :   return NoChange();
     890             : }
     891             : 
     892             : 
     893       23412 : Reduction MachineOperatorReducer::ReduceUint32Mod(Node* node) {
     894       23412 :   Uint32BinopMatcher m(node);
     895       23412 :   if (m.left().Is(0)) return Replace(m.left().node());    // 0 % x => 0
     896       22941 :   if (m.right().Is(0)) return Replace(m.right().node());  // x % 0 => 0
     897       22878 :   if (m.right().Is(1)) return ReplaceUint32(0);           // x % 1 => 0
     898       22451 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);        // x % x  => 0
     899       22449 :   if (m.IsFoldable()) {                                   // K % K => K
     900             :     return ReplaceUint32(
     901       21526 :         base::bits::UnsignedMod32(m.left().Value(), m.right().Value()));
     902             :   }
     903         923 :   if (m.right().HasValue()) {
     904             :     Node* const dividend = m.left().node();
     905         729 :     uint32_t const divisor = m.right().Value();
     906         729 :     if (base::bits::IsPowerOfTwo32(divisor)) {  // x % 2^n => x & 2^n-1
     907         704 :       node->ReplaceInput(1, Uint32Constant(m.right().Value() - 1));
     908         352 :       node->TrimInputCount(2);
     909         352 :       NodeProperties::ChangeOp(node, machine()->Word32And());
     910             :     } else {
     911         377 :       Node* quotient = Uint32Div(dividend, divisor);
     912             :       DCHECK_EQ(dividend, node->InputAt(0));
     913         377 :       node->ReplaceInput(1, Int32Mul(quotient, Uint32Constant(divisor)));
     914         377 :       node->TrimInputCount(2);
     915         377 :       NodeProperties::ChangeOp(node, machine()->Int32Sub());
     916             :     }
     917             :     return Changed(node);
     918             :   }
     919             :   return NoChange();
     920             : }
     921             : 
     922             : 
     923     1454431 : Reduction MachineOperatorReducer::ReduceStore(Node* node) {
     924             :   NodeMatcher nm(node);
     925             :   MachineRepresentation rep;
     926             :   int value_input;
     927     1454431 :   if (nm.IsCheckedStore()) {
     928       64147 :     rep = CheckedStoreRepresentationOf(node->op());
     929             :     value_input = 3;
     930     1390284 :   } else if (nm.IsStore()) {
     931     1390284 :     rep = StoreRepresentationOf(node->op()).representation();
     932             :     value_input = 2;
     933             :   } else {
     934             :     DCHECK(nm.IsUnalignedStore());
     935           0 :     rep = UnalignedStoreRepresentationOf(node->op());
     936             :     value_input = 2;
     937             :   }
     938             : 
     939     1454431 :   Node* const value = node->InputAt(value_input);
     940             : 
     941     1454431 :   switch (value->opcode()) {
     942             :     case IrOpcode::kWord32And: {
     943        2021 :       Uint32BinopMatcher m(value);
     944        4628 :       if (m.right().HasValue() && ((rep == MachineRepresentation::kWord8 &&
     945        1570 :                                     (m.right().Value() & 0xff) == 0xff) ||
     946         311 :                                    (rep == MachineRepresentation::kWord16 &&
     947         311 :                                     (m.right().Value() & 0xffff) == 0xffff))) {
     948         720 :         node->ReplaceInput(value_input, m.left().node());
     949         720 :         return Changed(node);
     950             :       }
     951        1301 :       break;
     952             :     }
     953             :     case IrOpcode::kWord32Sar: {
     954         438 :       Int32BinopMatcher m(value);
     955        1047 :       if (m.left().IsWord32Shl() && ((rep == MachineRepresentation::kWord8 &&
     956         267 :                                       m.right().IsInRange(1, 24)) ||
     957         267 :                                      (rep == MachineRepresentation::kWord16 &&
     958             :                                       m.right().IsInRange(1, 16)))) {
     959         438 :         Int32BinopMatcher mleft(m.left().node());
     960         438 :         if (mleft.right().Is(m.right().Value())) {
     961         438 :           node->ReplaceInput(value_input, mleft.left().node());
     962         438 :           return Changed(node);
     963             :         }
     964             :       }
     965           0 :       break;
     966             :     }
     967             :     default:
     968             :       break;
     969             :   }
     970             :   return NoChange();
     971             : }
     972             : 
     973             : 
     974      227643 : Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
     975      227643 :   switch (node->opcode()) {
     976             :     case IrOpcode::kInt32AddWithOverflow: {
     977             :       DCHECK(index == 0 || index == 1);
     978      111786 :       Int32BinopMatcher m(node);
     979      111786 :       if (m.IsFoldable()) {
     980             :         int32_t val;
     981             :         bool ovf = base::bits::SignedAddOverflow32(m.left().Value(),
     982       20038 :                                                    m.right().Value(), &val);
     983       20038 :         return ReplaceInt32(index == 0 ? val : ovf);
     984             :       }
     985       91748 :       if (m.right().Is(0)) {
     986          32 :         return Replace(index == 0 ? m.left().node() : m.right().node());
     987             :       }
     988       91716 :       break;
     989             :     }
     990             :     case IrOpcode::kInt32SubWithOverflow: {
     991             :       DCHECK(index == 0 || index == 1);
     992       74836 :       Int32BinopMatcher m(node);
     993       74836 :       if (m.IsFoldable()) {
     994             :         int32_t val;
     995             :         bool ovf = base::bits::SignedSubOverflow32(m.left().Value(),
     996       20024 :                                                    m.right().Value(), &val);
     997       20024 :         return ReplaceInt32(index == 0 ? val : ovf);
     998             :       }
     999       54812 :       if (m.right().Is(0)) {
    1000           2 :         return Replace(index == 0 ? m.left().node() : m.right().node());
    1001             :       }
    1002       54810 :       break;
    1003             :     }
    1004             :     case IrOpcode::kInt32MulWithOverflow: {
    1005             :       DCHECK(index == 0 || index == 1);
    1006       27708 :       Int32BinopMatcher m(node);
    1007       27708 :       if (m.IsFoldable()) {
    1008             :         int32_t val;
    1009             :         bool ovf = base::bits::SignedMulOverflow32(m.left().Value(),
    1010       20334 :                                                    m.right().Value(), &val);
    1011       20334 :         return ReplaceInt32(index == 0 ? val : ovf);
    1012             :       }
    1013        7374 :       if (m.right().Is(0)) {
    1014             :         return Replace(m.right().node());
    1015             :       }
    1016        7298 :       if (m.right().Is(1)) {
    1017        1692 :         return index == 0 ? Replace(m.left().node()) : ReplaceInt32(0);
    1018             :       }
    1019        5606 :       break;
    1020             :     }
    1021             :     default:
    1022             :       break;
    1023             :   }
    1024             :   return NoChange();
    1025             : }
    1026             : 
    1027             : 
    1028       90018 : Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
    1029             :   DCHECK((node->opcode() == IrOpcode::kWord32Shl) ||
    1030             :          (node->opcode() == IrOpcode::kWord32Shr) ||
    1031             :          (node->opcode() == IrOpcode::kWord32Sar));
    1032       90018 :   if (machine()->Word32ShiftIsSafe()) {
    1033             :     // Remove the explicit 'and' with 0x1f if the shift provided by the machine
    1034             :     // instruction matches that required by JavaScript.
    1035       89577 :     Int32BinopMatcher m(node);
    1036       89577 :     if (m.right().IsWord32And()) {
    1037        2806 :       Int32BinopMatcher mright(m.right().node());
    1038        2806 :       if (mright.right().Is(0x1f)) {
    1039        1329 :         node->ReplaceInput(1, mright.left().node());
    1040        1329 :         return Changed(node);
    1041             :       }
    1042             :     }
    1043             :   }
    1044             :   return NoChange();
    1045             : }
    1046             : 
    1047             : 
    1048       56214 : Reduction MachineOperatorReducer::ReduceWord32Shl(Node* node) {
    1049             :   DCHECK_EQ(IrOpcode::kWord32Shl, node->opcode());
    1050       56214 :   Int32BinopMatcher m(node);
    1051       56214 :   if (m.right().Is(0)) return Replace(m.left().node());  // x << 0 => x
    1052       55357 :   if (m.IsFoldable()) {                                  // K << K => K
    1053       15249 :     return ReplaceInt32(m.left().Value() << m.right().Value());
    1054             :   }
    1055       40108 :   if (m.right().IsInRange(1, 31)) {
    1056             :     // (x >>> K) << K => x & ~(2^K - 1)
    1057             :     // (x >> K) << K => x & ~(2^K - 1)
    1058       35790 :     if (m.left().IsWord32Sar() || m.left().IsWord32Shr()) {
    1059       12768 :       Int32BinopMatcher mleft(m.left().node());
    1060       12768 :       if (mleft.right().Is(m.right().Value())) {
    1061       11738 :         node->ReplaceInput(0, mleft.left().node());
    1062             :         node->ReplaceInput(1,
    1063       23476 :                            Uint32Constant(~((1U << m.right().Value()) - 1U)));
    1064       11738 :         NodeProperties::ChangeOp(node, machine()->Word32And());
    1065       11738 :         Reduction reduction = ReduceWord32And(node);
    1066       11738 :         return reduction.Changed() ? reduction : Changed(node);
    1067             :       }
    1068             :     }
    1069             :   }
    1070       28370 :   return ReduceWord32Shifts(node);
    1071             : }
    1072             : 
    1073      337054 : Reduction MachineOperatorReducer::ReduceWord64Shl(Node* node) {
    1074             :   DCHECK_EQ(IrOpcode::kWord64Shl, node->opcode());
    1075      337054 :   Int64BinopMatcher m(node);
    1076      337055 :   if (m.right().Is(0)) return Replace(m.left().node());  // x << 0 => x
    1077      336502 :   if (m.IsFoldable()) {                                  // K << K => K
    1078      204955 :     return ReplaceInt64(m.left().Value() << m.right().Value());
    1079             :   }
    1080             :   return NoChange();
    1081             : }
    1082             : 
    1083       45260 : Reduction MachineOperatorReducer::ReduceWord32Shr(Node* node) {
    1084       45260 :   Uint32BinopMatcher m(node);
    1085       45261 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >>> 0 => x
    1086       40114 :   if (m.IsFoldable()) {                                  // K >>> K => K
    1087       12765 :     return ReplaceInt32(m.left().Value() >> m.right().Value());
    1088             :   }
    1089       27349 :   if (m.left().IsWord32And() && m.right().HasValue()) {
    1090          63 :     Uint32BinopMatcher mleft(m.left().node());
    1091          63 :     if (mleft.right().HasValue()) {
    1092          60 :       uint32_t shift = m.right().Value() & 0x1f;
    1093          60 :       uint32_t mask = mleft.right().Value();
    1094          60 :       if ((mask >> shift) == 0) {
    1095             :         // (m >>> s) == 0 implies ((x & m) >>> s) == 0
    1096          31 :         return ReplaceInt32(0);
    1097             :       }
    1098             :     }
    1099             :   }
    1100       27318 :   return ReduceWord32Shifts(node);
    1101             : }
    1102             : 
    1103       34789 : Reduction MachineOperatorReducer::ReduceWord64Shr(Node* node) {
    1104             :   DCHECK_EQ(IrOpcode::kWord64Shr, node->opcode());
    1105       34789 :   Uint64BinopMatcher m(node);
    1106       34789 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >>> 0 => x
    1107       34236 :   if (m.IsFoldable()) {                                  // K >> K => K
    1108       33964 :     return ReplaceInt64(m.left().Value() >> m.right().Value());
    1109             :   }
    1110             :   return NoChange();
    1111             : }
    1112             : 
    1113       48378 : Reduction MachineOperatorReducer::ReduceWord32Sar(Node* node) {
    1114       48378 :   Int32BinopMatcher m(node);
    1115       48378 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >> 0 => x
    1116       47427 :   if (m.IsFoldable()) {                                  // K >> K => K
    1117       13035 :     return ReplaceInt32(m.left().Value() >> m.right().Value());
    1118             :   }
    1119       34392 :   if (m.left().IsWord32Shl()) {
    1120        1578 :     Int32BinopMatcher mleft(m.left().node());
    1121        1578 :     if (mleft.left().IsComparison()) {
    1122         116 :       if (m.right().Is(31) && mleft.right().Is(31)) {
    1123             :         // Comparison << 31 >> 31 => 0 - Comparison
    1124          58 :         node->ReplaceInput(0, Int32Constant(0));
    1125          58 :         node->ReplaceInput(1, mleft.left().node());
    1126          58 :         NodeProperties::ChangeOp(node, machine()->Int32Sub());
    1127          58 :         Reduction const reduction = ReduceInt32Sub(node);
    1128          58 :         return reduction.Changed() ? reduction : Changed(node);
    1129             :       }
    1130        1520 :     } else if (mleft.left().IsLoad()) {
    1131             :       LoadRepresentation const rep =
    1132           4 :           LoadRepresentationOf(mleft.left().node()->op());
    1133          10 :       if (m.right().Is(24) && mleft.right().Is(24) &&
    1134             :           rep == MachineType::Int8()) {
    1135             :         // Load[kMachInt8] << 24 >> 24 => Load[kMachInt8]
    1136             :         return Replace(mleft.left().node());
    1137             :       }
    1138           3 :       if (m.right().Is(16) && mleft.right().Is(16) &&
    1139             :           rep == MachineType::Int16()) {
    1140             :         // Load[kMachInt16] << 16 >> 16 => Load[kMachInt8]
    1141             :         return Replace(mleft.left().node());
    1142             :       }
    1143             :     }
    1144             :   }
    1145       34330 :   return ReduceWord32Shifts(node);
    1146             : }
    1147             : 
    1148      215313 : Reduction MachineOperatorReducer::ReduceWord64Sar(Node* node) {
    1149      215313 :   Int64BinopMatcher m(node);
    1150      215313 :   if (m.right().Is(0)) return Replace(m.left().node());  // x >> 0 => x
    1151      214760 :   if (m.IsFoldable()) {
    1152       33972 :     return ReplaceInt64(m.left().Value() >> m.right().Value());
    1153             :   }
    1154             :   return NoChange();
    1155             : }
    1156             : 
    1157      547823 : Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
    1158             :   DCHECK_EQ(IrOpcode::kWord32And, node->opcode());
    1159      547823 :   Int32BinopMatcher m(node);
    1160      547823 :   if (m.right().Is(0)) return Replace(m.right().node());  // x & 0  => 0
    1161      545636 :   if (m.right().Is(-1)) return Replace(m.left().node());  // x & -1 => x
    1162      546240 :   if (m.left().IsComparison() && m.right().Is(1)) {       // CMP & 1 => CMP
    1163             :     return Replace(m.left().node());
    1164             :   }
    1165      544844 :   if (m.IsFoldable()) {                                   // K & K  => K
    1166       27799 :     return ReplaceInt32(m.left().Value() & m.right().Value());
    1167             :   }
    1168      517045 :   if (m.LeftEqualsRight()) return Replace(m.left().node());  // x & x => x
    1169      517021 :   if (m.left().IsWord32And() && m.right().HasValue()) {
    1170       19763 :     Int32BinopMatcher mleft(m.left().node());
    1171       19763 :     if (mleft.right().HasValue()) {  // (x & K) & K => x & K
    1172       19747 :       node->ReplaceInput(0, mleft.left().node());
    1173             :       node->ReplaceInput(
    1174       39494 :           1, Int32Constant(m.right().Value() & mleft.right().Value()));
    1175       19747 :       Reduction const reduction = ReduceWord32And(node);
    1176       19747 :       return reduction.Changed() ? reduction : Changed(node);
    1177             :     }
    1178             :   }
    1179      497274 :   if (m.right().IsNegativePowerOf2()) {
    1180      325503 :     int32_t const mask = m.right().Value();
    1181      325503 :     if (m.left().IsWord32Shl()) {
    1182        2668 :       Uint32BinopMatcher mleft(m.left().node());
    1183        5336 :       if (mleft.right().HasValue() &&
    1184        2668 :           (mleft.right().Value() & 0x1f) >=
    1185        2668 :               base::bits::CountTrailingZeros32(mask)) {
    1186             :         // (x << L) & (-1 << K) => x << L iff L >= K
    1187        2638 :         return Replace(mleft.node());
    1188             :       }
    1189      322835 :     } else if (m.left().IsInt32Add()) {
    1190      123120 :       Int32BinopMatcher mleft(m.left().node());
    1191      219130 :       if (mleft.right().HasValue() &&
    1192       96010 :           (mleft.right().Value() & mask) == mleft.right().Value()) {
    1193             :         // (x + (K << L)) & (-1 << L) => (x & (-1 << L)) + (K << L)
    1194       95841 :         node->ReplaceInput(0, Word32And(mleft.left().node(), m.right().node()));
    1195       95841 :         node->ReplaceInput(1, mleft.right().node());
    1196       95841 :         NodeProperties::ChangeOp(node, machine()->Int32Add());
    1197       95841 :         Reduction const reduction = ReduceInt32Add(node);
    1198       95841 :         return reduction.Changed() ? reduction : Changed(node);
    1199             :       }
    1200       27279 :       if (mleft.left().IsInt32Mul()) {
    1201        2923 :         Int32BinopMatcher mleftleft(mleft.left().node());
    1202        5846 :         if (mleftleft.right().IsMultipleOf(-mask)) {
    1203             :           // (y * (K << L) + x) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
    1204             :           node->ReplaceInput(0,
    1205        2923 :                              Word32And(mleft.right().node(), m.right().node()));
    1206        2923 :           node->ReplaceInput(1, mleftleft.node());
    1207        2923 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1208        2923 :           Reduction const reduction = ReduceInt32Add(node);
    1209        2923 :           return reduction.Changed() ? reduction : Changed(node);
    1210             :         }
    1211             :       }
    1212       24356 :       if (mleft.right().IsInt32Mul()) {
    1213        9724 :         Int32BinopMatcher mleftright(mleft.right().node());
    1214       19448 :         if (mleftright.right().IsMultipleOf(-mask)) {
    1215             :           // (x + y * (K << L)) & (-1 << L) => (x & (-1 << L)) + y * (K << L)
    1216             :           node->ReplaceInput(0,
    1217        9706 :                              Word32And(mleft.left().node(), m.right().node()));
    1218        9706 :           node->ReplaceInput(1, mleftright.node());
    1219        9706 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1220        9706 :           Reduction const reduction = ReduceInt32Add(node);
    1221        9706 :           return reduction.Changed() ? reduction : Changed(node);
    1222             :         }
    1223             :       }
    1224       14650 :       if (mleft.left().IsWord32Shl()) {
    1225          38 :         Int32BinopMatcher mleftleft(mleft.left().node());
    1226         114 :         if (mleftleft.right().Is(base::bits::CountTrailingZeros32(mask))) {
    1227             :           // (y << L + x) & (-1 << L) => (x & (-1 << L)) + y << L
    1228             :           node->ReplaceInput(0,
    1229          31 :                              Word32And(mleft.right().node(), m.right().node()));
    1230          31 :           node->ReplaceInput(1, mleftleft.node());
    1231          31 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1232          31 :           Reduction const reduction = ReduceInt32Add(node);
    1233          31 :           return reduction.Changed() ? reduction : Changed(node);
    1234             :         }
    1235             :       }
    1236       14619 :       if (mleft.right().IsWord32Shl()) {
    1237        9161 :         Int32BinopMatcher mleftright(mleft.right().node());
    1238       27483 :         if (mleftright.right().Is(base::bits::CountTrailingZeros32(mask))) {
    1239             :           // (x + y << L) & (-1 << L) => (x & (-1 << L)) + y << L
    1240             :           node->ReplaceInput(0,
    1241        3276 :                              Word32And(mleft.left().node(), m.right().node()));
    1242        3276 :           node->ReplaceInput(1, mleftright.node());
    1243        3276 :           NodeProperties::ChangeOp(node, machine()->Int32Add());
    1244        3276 :           Reduction const reduction = ReduceInt32Add(node);
    1245        3276 :           return reduction.Changed() ? reduction : Changed(node);
    1246             :         }
    1247             :       }
    1248      199715 :     } else if (m.left().IsInt32Mul()) {
    1249        5949 :       Int32BinopMatcher mleft(m.left().node());
    1250       11898 :       if (mleft.right().IsMultipleOf(-mask)) {
    1251             :         // (x * (K << L)) & (-1 << L) => x * (K << L)
    1252        5893 :         return Replace(mleft.node());
    1253             :       }
    1254             :     }
    1255             :   }
    1256             :   return NoChange();
    1257             : }
    1258             : 
    1259       23982 : Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
    1260             :   DCHECK(IrOpcode::kWord32Or == node->opcode() ||
    1261             :          IrOpcode::kWord32Xor == node->opcode());
    1262       23982 :   Int32BinopMatcher m(node);
    1263             :   Node* shl = nullptr;
    1264             :   Node* shr = nullptr;
    1265             :   // Recognize rotation, we are matching:
    1266             :   //  * x << y | x >>> (32 - y) => x ror (32 - y), i.e  x rol y
    1267             :   //  * x << (32 - y) | x >>> y => x ror y
    1268             :   //  * x << y ^ x >>> (32 - y) => x ror (32 - y), i.e. x rol y
    1269             :   //  * x << (32 - y) ^ x >>> y => x ror y
    1270             :   // as well as their commuted form.
    1271       28171 :   if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
    1272             :     shl = m.left().node();
    1273             :     shr = m.right().node();
    1274       23695 :   } else if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
    1275             :     shl = m.right().node();
    1276             :     shr = m.left().node();
    1277             :   } else {
    1278             :     return NoChange();
    1279             :   }
    1280             : 
    1281         713 :   Int32BinopMatcher mshl(shl);
    1282         713 :   Int32BinopMatcher mshr(shr);
    1283         713 :   if (mshl.left().node() != mshr.left().node()) return NoChange();
    1284             : 
    1285         533 :   if (mshl.right().HasValue() && mshr.right().HasValue()) {
    1286             :     // Case where y is a constant.
    1287         367 :     if (mshl.right().Value() + mshr.right().Value() != 32) return NoChange();
    1288             :   } else {
    1289             :     Node* sub = nullptr;
    1290             :     Node* y = nullptr;
    1291         166 :     if (mshl.right().IsInt32Sub()) {
    1292             :       sub = mshl.right().node();
    1293             :       y = mshr.right().node();
    1294         159 :     } else if (mshr.right().IsInt32Sub()) {
    1295             :       sub = mshr.right().node();
    1296             :       y = mshl.right().node();
    1297             :     } else {
    1298         152 :       return NoChange();
    1299             :     }
    1300             : 
    1301          14 :     Int32BinopMatcher msub(sub);
    1302          28 :     if (!msub.left().Is(32) || msub.right().node() != y) return NoChange();
    1303             :   }
    1304             : 
    1305         381 :   node->ReplaceInput(0, mshl.left().node());
    1306         381 :   node->ReplaceInput(1, mshr.right().node());
    1307         381 :   NodeProperties::ChangeOp(node, machine()->Word32Ror());
    1308             :   return Changed(node);
    1309             : }
    1310             : 
    1311       79844 : Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
    1312             :   DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
    1313       79844 :   Int32BinopMatcher m(node);
    1314       79845 :   if (m.right().Is(0)) return Replace(m.left().node());    // x | 0  => x
    1315       38248 :   if (m.right().Is(-1)) return Replace(m.right().node());  // x | -1 => -1
    1316       34631 :   if (m.IsFoldable()) {                                    // K | K  => K
    1317       20802 :     return ReplaceInt32(m.left().Value() | m.right().Value());
    1318             :   }
    1319       13829 :   if (m.LeftEqualsRight()) return Replace(m.left().node());  // x | x => x
    1320             : 
    1321       13780 :   return TryMatchWord32Ror(node);
    1322             : }
    1323             : 
    1324       32122 : Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
    1325             :   DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
    1326       32122 :   Int32BinopMatcher m(node);
    1327       32122 :   if (m.right().Is(0)) return Replace(m.left().node());  // x ^ 0 => x
    1328       31417 :   if (m.IsFoldable()) {                                  // K ^ K => K
    1329       21180 :     return ReplaceInt32(m.left().Value() ^ m.right().Value());
    1330             :   }
    1331       10237 :   if (m.LeftEqualsRight()) return ReplaceInt32(0);  // x ^ x => 0
    1332       10522 :   if (m.left().IsWord32Xor() && m.right().Is(-1)) {
    1333          90 :     Int32BinopMatcher mleft(m.left().node());
    1334          90 :     if (mleft.right().Is(-1)) {  // (x ^ -1) ^ -1 => x
    1335          16 :       return Replace(mleft.left().node());
    1336             :     }
    1337             :   }
    1338             : 
    1339       10202 :   return TryMatchWord32Ror(node);
    1340             : }
    1341             : 
    1342        4800 : Reduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) {
    1343             :   DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode());
    1344             :   Float64Matcher mlhs(node->InputAt(0));
    1345             :   Uint32Matcher mrhs(node->InputAt(1));
    1346        4800 :   if (mlhs.HasValue() && mrhs.HasValue()) {
    1347             :     return ReplaceFloat64(bit_cast<double>(
    1348        4800 :         (bit_cast<uint64_t>(mlhs.Value()) & V8_UINT64_C(0xFFFFFFFF00000000)) |
    1349             :         mrhs.Value()));
    1350             :   }
    1351             :   return NoChange();
    1352             : }
    1353             : 
    1354             : 
    1355        4800 : Reduction MachineOperatorReducer::ReduceFloat64InsertHighWord32(Node* node) {
    1356             :   DCHECK_EQ(IrOpcode::kFloat64InsertHighWord32, node->opcode());
    1357             :   Float64Matcher mlhs(node->InputAt(0));
    1358             :   Uint32Matcher mrhs(node->InputAt(1));
    1359        4800 :   if (mlhs.HasValue() && mrhs.HasValue()) {
    1360             :     return ReplaceFloat64(bit_cast<double>(
    1361        9600 :         (bit_cast<uint64_t>(mlhs.Value()) & V8_UINT64_C(0xFFFFFFFF)) |
    1362        4800 :         (static_cast<uint64_t>(mrhs.Value()) << 32)));
    1363             :   }
    1364             :   return NoChange();
    1365             : }
    1366             : 
    1367             : 
    1368             : namespace {
    1369             : 
    1370             : bool IsFloat64RepresentableAsFloat32(const Float64Matcher& m) {
    1371      191204 :   if (m.HasValue()) {
    1372       89814 :     double v = m.Value();
    1373       89814 :     float fv = static_cast<float>(v);
    1374       89814 :     return static_cast<double>(fv) == v;
    1375             :   }
    1376             :   return false;
    1377             : }
    1378             : 
    1379             : }  // namespace
    1380             : 
    1381             : 
    1382      193058 : Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
    1383             :   DCHECK((IrOpcode::kFloat64Equal == node->opcode()) ||
    1384             :          (IrOpcode::kFloat64LessThan == node->opcode()) ||
    1385             :          (IrOpcode::kFloat64LessThanOrEqual == node->opcode()));
    1386             :   // As all Float32 values have an exact representation in Float64, comparing
    1387             :   // two Float64 values both converted from Float32 is equivalent to comparing
    1388             :   // the original Float32s, so we can ignore the conversions. We can also reduce
    1389             :   // comparisons of converted Float64 values against constants that can be
    1390             :   // represented exactly as Float32.
    1391      191628 :   Float64BinopMatcher m(node);
    1392      193099 :   if ((m.left().IsChangeFloat32ToFloat64() &&
    1393      190889 :        m.right().IsChangeFloat32ToFloat64()) ||
    1394         732 :       (m.left().IsChangeFloat32ToFloat64() &&
    1395      382100 :        IsFloat64RepresentableAsFloat32(m.right())) ||
    1396       87796 :       (IsFloat64RepresentableAsFloat32(m.left()) &&
    1397             :        m.right().IsChangeFloat32ToFloat64())) {
    1398        1430 :     switch (node->opcode()) {
    1399             :       case IrOpcode::kFloat64Equal:
    1400         308 :         NodeProperties::ChangeOp(node, machine()->Float32Equal());
    1401         308 :         break;
    1402             :       case IrOpcode::kFloat64LessThan:
    1403         815 :         NodeProperties::ChangeOp(node, machine()->Float32LessThan());
    1404         815 :         break;
    1405             :       case IrOpcode::kFloat64LessThanOrEqual:
    1406         307 :         NodeProperties::ChangeOp(node, machine()->Float32LessThanOrEqual());
    1407         307 :         break;
    1408             :       default:
    1409             :         return NoChange();
    1410             :     }
    1411             :     node->ReplaceInput(
    1412        1430 :         0, m.left().HasValue()
    1413         274 :                ? Float32Constant(static_cast<float>(m.left().Value()))
    1414        3134 :                : m.left().InputAt(0));
    1415             :     node->ReplaceInput(
    1416        1430 :         1, m.right().HasValue()
    1417         417 :                ? Float32Constant(static_cast<float>(m.right().Value()))
    1418        3277 :                : m.right().InputAt(0));
    1419             :     return Changed(node);
    1420             :   }
    1421             :   return NoChange();
    1422             : }
    1423             : 
    1424       18064 : Reduction MachineOperatorReducer::ReduceFloat64RoundDown(Node* node) {
    1425             :   DCHECK_EQ(IrOpcode::kFloat64RoundDown, node->opcode());
    1426             :   Float64Matcher m(node->InputAt(0));
    1427       18064 :   if (m.HasValue()) {
    1428             :     return ReplaceFloat64(Floor(m.Value()));
    1429             :   }
    1430             :   return NoChange();
    1431             : }
    1432             : 
    1433     1016262 : CommonOperatorBuilder* MachineOperatorReducer::common() const {
    1434     1016262 :   return jsgraph()->common();
    1435             : }
    1436             : 
    1437             : 
    1438      549672 : MachineOperatorBuilder* MachineOperatorReducer::machine() const {
    1439      549672 :   return jsgraph()->machine();
    1440             : }
    1441             : 
    1442             : 
    1443     1168049 : Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); }
    1444             : 
    1445             : }  // namespace compiler
    1446             : }  // namespace internal
    1447             : }  // namespace v8

Generated by: LCOV version 1.10