LCOV - code coverage report
Current view: top level - src/compiler - simplified-lowering.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1581 1674 94.4 %
Date: 2019-02-19 Functions: 92 96 95.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/simplified-lowering.h"
       6             : 
       7             : #include <limits>
       8             : 
       9             : #include "src/address-map.h"
      10             : #include "src/base/bits.h"
      11             : #include "src/code-factory.h"
      12             : #include "src/compiler/access-builder.h"
      13             : #include "src/compiler/common-operator.h"
      14             : #include "src/compiler/compiler-source-position-table.h"
      15             : #include "src/compiler/diamond.h"
      16             : #include "src/compiler/linkage.h"
      17             : #include "src/compiler/node-matchers.h"
      18             : #include "src/compiler/node-origin-table.h"
      19             : #include "src/compiler/node-properties.h"
      20             : #include "src/compiler/operation-typer.h"
      21             : #include "src/compiler/operator-properties.h"
      22             : #include "src/compiler/representation-change.h"
      23             : #include "src/compiler/simplified-operator.h"
      24             : #include "src/compiler/type-cache.h"
      25             : #include "src/conversions-inl.h"
      26             : #include "src/objects.h"
      27             : 
      28             : namespace v8 {
      29             : namespace internal {
      30             : namespace compiler {
      31             : 
      32             : // Macro for outputting trace information from representation inference.
      33             : #define TRACE(...)                                      \
      34             :   do {                                                  \
      35             :     if (FLAG_trace_representation) PrintF(__VA_ARGS__); \
      36             :   } while (false)
      37             : 
      38             : // Representation selection and lowering of {Simplified} operators to machine
      39             : // operators are interwined. We use a fixpoint calculation to compute both the
      40             : // output representation and the best possible lowering for {Simplified} nodes.
      41             : // Representation change insertion ensures that all values are in the correct
      42             : // machine representation after this phase, as dictated by the machine
      43             : // operators themselves.
      44             : enum Phase {
      45             :   // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information
      46             :   //     backwards from uses to definitions, around cycles in phis, according
      47             :   //     to local rules for each operator.
      48             :   //     During this phase, the usage information for a node determines the best
      49             :   //     possible lowering for each operator so far, and that in turn determines
      50             :   //     the output representation.
      51             :   //     Therefore, to be correct, this phase must iterate to a fixpoint before
      52             :   //     the next phase can begin.
      53             :   PROPAGATE,
      54             : 
      55             :   // 2.) RETYPE: Propagate types from type feedback forwards.
      56             :   RETYPE,
      57             : 
      58             :   // 3.) LOWER: perform lowering for all {Simplified} nodes by replacing some
      59             :   //     operators for some nodes, expanding some nodes to multiple nodes, or
      60             :   //     removing some (redundant) nodes.
      61             :   //     During this phase, use the {RepresentationChanger} to insert
      62             :   //     representation changes between uses that demand a particular
      63             :   //     representation and nodes that produce a different representation.
      64             :   LOWER
      65             : };
      66             : 
      67             : namespace {
      68             : 
      69       33000 : MachineRepresentation MachineRepresentationFromArrayType(
      70             :     ExternalArrayType array_type) {
      71       33000 :   switch (array_type) {
      72             :     case kExternalUint8Array:
      73             :     case kExternalUint8ClampedArray:
      74             :     case kExternalInt8Array:
      75             :       return MachineRepresentation::kWord8;
      76             :     case kExternalUint16Array:
      77             :     case kExternalInt16Array:
      78        5289 :       return MachineRepresentation::kWord16;
      79             :     case kExternalUint32Array:
      80             :     case kExternalInt32Array:
      81        6510 :       return MachineRepresentation::kWord32;
      82             :     case kExternalFloat32Array:
      83        7441 :       return MachineRepresentation::kFloat32;
      84             :     case kExternalFloat64Array:
      85        3066 :       return MachineRepresentation::kFloat64;
      86             :     case kExternalBigInt64Array:
      87             :     case kExternalBigUint64Array:
      88           0 :       UNIMPLEMENTED();
      89             :   }
      90           0 :   UNREACHABLE();
      91             : }
      92             : 
      93     1089175 : UseInfo CheckedUseInfoAsWord32FromHint(
      94             :     NumberOperationHint hint, const VectorSlotPair& feedback = VectorSlotPair(),
      95             :     IdentifyZeros identify_zeros = kDistinguishZeros) {
      96     1089175 :   switch (hint) {
      97             :     case NumberOperationHint::kSignedSmall:
      98             :     case NumberOperationHint::kSignedSmallInputs:
      99             :       return UseInfo::CheckedSignedSmallAsWord32(identify_zeros, feedback);
     100             :     case NumberOperationHint::kSigned32:
     101             :       return UseInfo::CheckedSigned32AsWord32(identify_zeros, feedback);
     102             :     case NumberOperationHint::kNumber:
     103             :       return UseInfo::CheckedNumberAsWord32(feedback);
     104             :     case NumberOperationHint::kNumberOrOddball:
     105             :       return UseInfo::CheckedNumberOrOddballAsWord32(feedback);
     106             :   }
     107           0 :   UNREACHABLE();
     108             : }
     109             : 
     110      163191 : UseInfo CheckedUseInfoAsFloat64FromHint(
     111             :     NumberOperationHint hint, const VectorSlotPair& feedback,
     112             :     IdentifyZeros identify_zeros = kDistinguishZeros) {
     113      163191 :   switch (hint) {
     114             :     case NumberOperationHint::kSignedSmall:
     115             :     case NumberOperationHint::kSignedSmallInputs:
     116             :     case NumberOperationHint::kSigned32:
     117             :       // Not used currently.
     118           0 :       UNREACHABLE();
     119             :       break;
     120             :     case NumberOperationHint::kNumber:
     121             :       return UseInfo::CheckedNumberAsFloat64(identify_zeros, feedback);
     122             :     case NumberOperationHint::kNumberOrOddball:
     123             :       return UseInfo::CheckedNumberOrOddballAsFloat64(identify_zeros, feedback);
     124             :   }
     125           0 :   UNREACHABLE();
     126             : }
     127             : 
     128     8123200 : UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) {
     129     8123200 :   switch (rep) {
     130             :     case MachineRepresentation::kTaggedSigned:
     131             :       return UseInfo::TaggedSigned();
     132             :     case MachineRepresentation::kTaggedPointer:
     133             :     case MachineRepresentation::kTagged:
     134             :       return UseInfo::AnyTagged();
     135             :     case MachineRepresentation::kFloat64:
     136             :       return UseInfo::TruncatingFloat64();
     137             :     case MachineRepresentation::kFloat32:
     138             :       return UseInfo::Float32();
     139             :     case MachineRepresentation::kWord8:
     140             :     case MachineRepresentation::kWord16:
     141             :     case MachineRepresentation::kWord32:
     142             :       return UseInfo::TruncatingWord32();
     143             :     case MachineRepresentation::kWord64:
     144             :       return UseInfo::Word64();
     145             :     case MachineRepresentation::kBit:
     146             :       return UseInfo::Bool();
     147             :     case MachineRepresentation::kSimd128:
     148             :     case MachineRepresentation::kNone:
     149             :       break;
     150             :   }
     151           0 :   UNREACHABLE();
     152             : }
     153             : 
     154     9910168 : UseInfo UseInfoForBasePointer(const FieldAccess& access) {
     155    19820335 :   return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::Word();
     156             : }
     157             : 
     158      181128 : UseInfo UseInfoForBasePointer(const ElementAccess& access) {
     159      362256 :   return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::Word();
     160             : }
     161             : 
     162      352197 : void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) {
     163     2039740 :   for (Edge edge : node->use_edges()) {
     164      843786 :     if (NodeProperties::IsControlEdge(edge)) {
     165           0 :       edge.UpdateTo(control);
     166      843782 :     } else if (NodeProperties::IsEffectEdge(edge)) {
     167      428605 :       edge.UpdateTo(effect);
     168             :     } else {
     169             :       DCHECK(NodeProperties::IsValueEdge(edge) ||
     170             :              NodeProperties::IsContextEdge(edge));
     171             :     }
     172             :   }
     173      352168 : }
     174             : 
     175      310861 : bool CanOverflowSigned32(const Operator* op, Type left, Type right,
     176             :                          Zone* type_zone) {
     177             :   // We assume the inputs are checked Signed32 (or known statically
     178             :   // to be Signed32). Technically, the inputs could also be minus zero, but
     179             :   // that cannot cause overflow.
     180      155445 :   left = Type::Intersect(left, Type::Signed32(), type_zone);
     181      155443 :   right = Type::Intersect(right, Type::Signed32(), type_zone);
     182      310868 :   if (left.IsNone() || right.IsNone()) return false;
     183      155416 :   switch (op->opcode()) {
     184             :     case IrOpcode::kSpeculativeSafeIntegerAdd:
     185      151744 :       return (left.Max() + right.Max() > kMaxInt) ||
     186      151745 :              (left.Min() + right.Min() < kMinInt);
     187             : 
     188             :     case IrOpcode::kSpeculativeSafeIntegerSubtract:
     189       16398 :       return (left.Max() - right.Min() > kMaxInt) ||
     190       16398 :              (left.Min() - right.Max() < kMinInt);
     191             : 
     192             :     default:
     193           0 :       UNREACHABLE();
     194             :   }
     195             :   return true;
     196             : }
     197             : 
     198        8623 : bool IsSomePositiveOrderedNumber(Type type) {
     199       14345 :   return type.Is(Type::OrderedNumber()) && !type.IsNone() && type.Min() > 0;
     200             : }
     201             : 
     202             : }  // namespace
     203             : 
     204             : #ifdef DEBUG
     205             : // Helpers for monotonicity checking.
     206             : class InputUseInfos {
     207             :  public:
     208             :   explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
     209             : 
     210             :   void SetAndCheckInput(Node* node, int index, UseInfo use_info) {
     211             :     if (input_use_infos_.empty()) {
     212             :       input_use_infos_.resize(node->InputCount(), UseInfo::None());
     213             :     }
     214             :     // Check that the new use informatin is a super-type of the old
     215             :     // one.
     216             :     DCHECK(IsUseLessGeneral(input_use_infos_[index], use_info));
     217             :     input_use_infos_[index] = use_info;
     218             :   }
     219             : 
     220             :  private:
     221             :   ZoneVector<UseInfo> input_use_infos_;
     222             : 
     223             :   static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
     224             :     return use1.truncation().IsLessGeneralThan(use2.truncation());
     225             :   }
     226             : };
     227             : 
     228             : #endif  // DEBUG
     229             : 
     230             : class RepresentationSelector {
     231             :  public:
     232             :   // Information for each node tracked during the fixpoint.
     233      456705 :   class NodeInfo final {
     234             :    public:
     235             :     // Adds new use to the node. Returns true if something has changed
     236             :     // and the node has to be requeued.
     237   104281031 :     bool AddUse(UseInfo info) {
     238   104281031 :       Truncation old_truncation = truncation_;
     239   104281031 :       truncation_ = Truncation::Generalize(truncation_, info.truncation());
     240   104280583 :       return truncation_ != old_truncation;
     241             :     }
     242             : 
     243    37143227 :     void set_queued() { state_ = kQueued; }
     244    68453067 :     void set_visited() { state_ = kVisited; }
     245    31311100 :     void set_pushed() { state_ = kPushed; }
     246    44144549 :     void reset_state() { state_ = kUnvisited; }
     247             :     bool visited() const { return state_ == kVisited; }
     248             :     bool queued() const { return state_ == kQueued; }
     249             :     bool unvisited() const { return state_ == kUnvisited; }
     250             :     Truncation truncation() const { return truncation_; }
     251    35468735 :     void set_output(MachineRepresentation output) { representation_ = output; }
     252             : 
     253             :     MachineRepresentation representation() const { return representation_; }
     254             : 
     255             :     // Helpers for feedback typing.
     256    22032273 :     void set_feedback_type(Type type) { feedback_type_ = type; }
     257             :     Type feedback_type() const { return feedback_type_; }
     258       92239 :     void set_weakened() { weakened_ = true; }
     259             :     bool weakened() const { return weakened_; }
     260    31426899 :     void set_restriction_type(Type type) { restriction_type_ = type; }
     261             :     Type restriction_type() const { return restriction_type_; }
     262             : 
     263             :    private:
     264             :     enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued };
     265             :     State state_ = kUnvisited;
     266             :     MachineRepresentation representation_ =
     267             :         MachineRepresentation::kNone;             // Output representation.
     268             :     Truncation truncation_ = Truncation::None();  // Information about uses.
     269             : 
     270             :     Type restriction_type_ = Type::Any();
     271             :     Type feedback_type_;
     272             :     bool weakened_ = false;
     273             :   };
     274             : 
     275      456705 :   RepresentationSelector(JSGraph* jsgraph, JSHeapBroker* broker, Zone* zone,
     276             :                          RepresentationChanger* changer,
     277             :                          SourcePositionTable* source_positions,
     278      456710 :                          NodeOriginTable* node_origins)
     279             :       : jsgraph_(jsgraph),
     280             :         zone_(zone),
     281      456705 :         count_(jsgraph->graph()->NodeCount()),
     282             :         info_(count_, zone),
     283             : #ifdef DEBUG
     284             :         node_input_use_infos_(count_, InputUseInfos(zone), zone),
     285             : #endif
     286             :         nodes_(zone),
     287             :         replacements_(zone),
     288             :         phase_(PROPAGATE),
     289             :         changer_(changer),
     290             :         queue_(zone),
     291             :         typing_stack_(zone),
     292             :         source_positions_(source_positions),
     293             :         node_origins_(node_origins),
     294      456710 :         type_cache_(TypeCache::Get()),
     295     2283540 :         op_typer_(broker, graph_zone()) {
     296      456710 :   }
     297             : 
     298             :   // Forward propagation of types from type feedback.
     299     1370119 :   void RunTypePropagationPhase() {
     300             :     // Run type propagation.
     301      456704 :     TRACE("--{Type propagation phase}--\n");
     302      456710 :     phase_ = RETYPE;
     303             :     ResetNodeInfoState();
     304             : 
     305             :     DCHECK(typing_stack_.empty());
     306      913415 :     typing_stack_.push({graph()->end(), 0});
     307      456705 :     GetInfo(graph()->end())->set_pushed();
     308    62620469 :     while (!typing_stack_.empty()) {
     309             :       NodeState& current = typing_stack_.top();
     310             : 
     311             :       // If there is an unvisited input, push it and continue.
     312             :       bool pushed_unvisited = false;
     313   327154857 :       while (current.input_index < current.node->InputCount()) {
     314             :         Node* input = current.node->InputAt(current.input_index);
     315   101186176 :         NodeInfo* input_info = GetInfo(input);
     316   101186176 :         current.input_index++;
     317   101186176 :         if (input_info->unvisited()) {
     318             :           input_info->set_pushed();
     319    61708820 :           typing_stack_.push({input, 0});
     320             :           pushed_unvisited = true;
     321    30854425 :           break;
     322             :         }
     323             :       }
     324    62163795 :       if (pushed_unvisited) continue;
     325             : 
     326             :       // Process the top of the stack.
     327    31310296 :       Node* node = current.node;
     328             :       typing_stack_.pop();
     329             :       NodeInfo* info = GetInfo(node);
     330             :       info->set_visited();
     331    31310296 :       bool updated = UpdateFeedbackType(node);
     332    31310254 :       TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
     333    31310254 :       VisitNode(node, info->truncation(), nullptr);
     334    31310227 :       TRACE("  ==> output ");
     335    31310227 :       PrintOutputInfo(info);
     336    31310223 :       TRACE("\n");
     337    31310358 :       if (updated) {
     338   209934903 :         for (Node* const user : node->uses()) {
     339    84400096 :           if (GetInfo(user)->visited()) {
     340             :             GetInfo(user)->set_queued();
     341             :             queue_.push(user);
     342             :           }
     343             :         }
     344             :       }
     345             :     }
     346             : 
     347             :     // Process the revisit queue.
     348     5325095 :     while (!queue_.empty()) {
     349     4868392 :       Node* node = queue_.front();
     350             :       queue_.pop();
     351             :       NodeInfo* info = GetInfo(node);
     352             :       info->set_visited();
     353     4868389 :       bool updated = UpdateFeedbackType(node);
     354     4868371 :       TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
     355     4868371 :       VisitNode(node, info->truncation(), nullptr);
     356     4868392 :       TRACE("  ==> output ");
     357     4868392 :       PrintOutputInfo(info);
     358     4868389 :       TRACE("\n");
     359     4868394 :       if (updated) {
     360    14258957 :         for (Node* const user : node->uses()) {
     361     5664498 :           if (GetInfo(user)->visited()) {
     362             :             GetInfo(user)->set_queued();
     363             :             queue_.push(user);
     364             :           }
     365             :         }
     366             :       }
     367             :     }
     368      456703 :   }
     369             : 
     370             :   void ResetNodeInfoState() {
     371             :     // Clean up for the next phase.
     372    44601259 :     for (NodeInfo& info : info_) {
     373             :       info.reset_state();
     374             :     }
     375             :   }
     376             : 
     377             :   Type TypeOf(Node* node) {
     378             :     Type type = GetInfo(node)->feedback_type();
     379    46081268 :     return type.IsInvalid() ? NodeProperties::GetType(node) : type;
     380             :   }
     381             : 
     382             :   Type FeedbackTypeOf(Node* node) {
     383             :     Type type = GetInfo(node)->feedback_type();
     384    39202918 :     return type.IsInvalid() ? Type::None() : type;
     385             :   }
     386             : 
     387      802095 :   Type TypePhi(Node* node) {
     388      802095 :     int arity = node->op()->ValueInputCount();
     389             :     Type type = FeedbackTypeOf(node->InputAt(0));
     390     1971083 :     for (int i = 1; i < arity; ++i) {
     391     1168996 :       type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i)));
     392             :     }
     393      802087 :     return type;
     394             :   }
     395             : 
     396       12428 :   Type TypeSelect(Node* node) {
     397             :     return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)),
     398       12428 :                            FeedbackTypeOf(node->InputAt(2)));
     399             :   }
     400             : 
     401    38543672 :   bool UpdateFeedbackType(Node* node) {
     402    36178021 :     if (node->op()->ValueOutputCount() == 0) return false;
     403             : 
     404             :     NodeInfo* info = GetInfo(node);
     405             :     Type type = info->feedback_type();
     406    25652744 :     Type new_type = type;
     407             : 
     408             :     // For any non-phi node just wait until we get all inputs typed. We only
     409             :     // allow untyped inputs for phi nodes because phis are the only places
     410             :     // where cycles need to be broken.
     411    25652744 :     if (node->opcode() != IrOpcode::kPhi) {
     412   145920399 :       for (int i = 0; i < node->op()->ValueInputCount(); i++) {
     413    61353854 :         if (GetInfo(node->InputAt(i))->feedback_type().IsInvalid()) {
     414             :           return false;
     415             :         }
     416             :       }
     417             :     }
     418             : 
     419             :     // We preload these values here to avoid increasing the binary size too
     420             :     // much, which happens if we inline the calls into the macros below.
     421             :     Type input0_type;
     422    44937768 :     if (node->InputCount() > 0) input0_type = FeedbackTypeOf(node->InputAt(0));
     423             :     Type input1_type;
     424    41901646 :     if (node->InputCount() > 1) input1_type = FeedbackTypeOf(node->InputAt(1));
     425             : 
     426    24833769 :     switch (node->opcode()) {
     427             : #define DECLARE_CASE(Name)                               \
     428             :   case IrOpcode::k##Name: {                              \
     429             :     new_type = op_typer_.Name(input0_type, input1_type); \
     430             :     break;                                               \
     431             :   }
     432      478240 :       SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE)
     433          10 :       DECLARE_CASE(SameValue)
     434             : #undef DECLARE_CASE
     435             : 
     436             : #define DECLARE_CASE(Name)                                               \
     437             :   case IrOpcode::k##Name: {                                              \
     438             :     new_type = Type::Intersect(op_typer_.Name(input0_type, input1_type), \
     439             :                                info->restriction_type(), graph_zone());  \
     440             :     break;                                                               \
     441             :   }
     442      353540 :       SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE)
     443             : #undef DECLARE_CASE
     444             : 
     445             : #define DECLARE_CASE(Name)                  \
     446             :   case IrOpcode::k##Name: {                 \
     447             :     new_type = op_typer_.Name(input0_type); \
     448             :     break;                                  \
     449             :   }
     450         282 :       SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE)
     451             : #undef DECLARE_CASE
     452             : 
     453             : #define DECLARE_CASE(Name)                                              \
     454             :   case IrOpcode::k##Name: {                                             \
     455             :     new_type = Type::Intersect(op_typer_.Name(input0_type),             \
     456             :                                info->restriction_type(), graph_zone()); \
     457             :     break;                                                              \
     458             :   }
     459       39477 :       SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_CASE)
     460             : #undef DECLARE_CASE
     461             : 
     462             :       case IrOpcode::kConvertReceiver:
     463         876 :         new_type = op_typer_.ConvertReceiver(input0_type);
     464         876 :         break;
     465             : 
     466             :       case IrOpcode::kPlainPrimitiveToNumber:
     467        1051 :         new_type = op_typer_.ToNumber(input0_type);
     468        1051 :         break;
     469             : 
     470             :       case IrOpcode::kCheckBounds:
     471             :         new_type =
     472             :             Type::Intersect(op_typer_.CheckBounds(input0_type, input1_type),
     473       64030 :                             info->restriction_type(), graph_zone());
     474       64030 :         break;
     475             : 
     476             :       case IrOpcode::kCheckFloat64Hole:
     477             :         new_type = Type::Intersect(op_typer_.CheckFloat64Hole(input0_type),
     478         584 :                                    info->restriction_type(), graph_zone());
     479         584 :         break;
     480             : 
     481             :       case IrOpcode::kCheckNumber:
     482             :         new_type = Type::Intersect(op_typer_.CheckNumber(input0_type),
     483         524 :                                    info->restriction_type(), graph_zone());
     484         524 :         break;
     485             : 
     486             :       case IrOpcode::kPhi: {
     487      802094 :         new_type = TypePhi(node);
     488      802086 :         if (!type.IsInvalid()) {
     489      479607 :           new_type = Weaken(node, type, new_type);
     490             :         }
     491             :         break;
     492             :       }
     493             : 
     494             :       case IrOpcode::kConvertTaggedHoleToUndefined:
     495             :         new_type = op_typer_.ConvertTaggedHoleToUndefined(
     496        2121 :             FeedbackTypeOf(node->InputAt(0)));
     497        2121 :         break;
     498             : 
     499             :       case IrOpcode::kTypeGuard: {
     500             :         new_type = op_typer_.TypeTypeGuard(node->op(),
     501       32974 :                                            FeedbackTypeOf(node->InputAt(0)));
     502       32974 :         break;
     503             :       }
     504             : 
     505             :       case IrOpcode::kSelect: {
     506       12428 :         new_type = TypeSelect(node);
     507       12428 :         break;
     508             :       }
     509             : 
     510             :       default:
     511             :         // Shortcut for operations that we do not handle.
     512    22926246 :         if (type.IsInvalid()) {
     513             :           GetInfo(node)->set_feedback_type(NodeProperties::GetType(node));
     514    20341798 :           return true;
     515             :         }
     516             :         return false;
     517             :     }
     518             :     // We need to guarantee that the feedback type is a subtype of the upper
     519             :     // bound. Naively that should hold, but weakening can actually produce
     520             :     // a bigger type if we are unlucky with ordering of phi typing. To be
     521             :     // really sure, just intersect the upper bound with the feedback type.
     522     1907496 :     new_type = Type::Intersect(GetUpperBound(node), new_type, graph_zone());
     523             : 
     524     2864587 :     if (!type.IsInvalid() && new_type.Is(type)) return false;
     525             :     GetInfo(node)->set_feedback_type(new_type);
     526     1690475 :     if (FLAG_trace_representation) {
     527           0 :       PrintNodeFeedbackType(node);
     528             :     }
     529             :     return true;
     530             :   }
     531             : 
     532           0 :   void PrintNodeFeedbackType(Node* n) {
     533           0 :     StdoutStream os;
     534           0 :     os << "#" << n->id() << ":" << *n->op() << "(";
     535             :     int j = 0;
     536           0 :     for (Node* const i : n->inputs()) {
     537           0 :       if (j++ > 0) os << ", ";
     538           0 :       os << "#" << i->id() << ":" << i->op()->mnemonic();
     539             :     }
     540           0 :     os << ")";
     541           0 :     if (NodeProperties::IsTyped(n)) {
     542             :       Type static_type = NodeProperties::GetType(n);
     543           0 :       os << "  [Static type: " << static_type;
     544             :       Type feedback_type = GetInfo(n)->feedback_type();
     545           0 :       if (!feedback_type.IsInvalid() && feedback_type != static_type) {
     546           0 :         os << ", Feedback type: " << feedback_type;
     547             :       }
     548           0 :       os << "]";
     549             :     }
     550           0 :     os << std::endl;
     551           0 :   }
     552             : 
     553     1822009 :   Type Weaken(Node* node, Type previous_type, Type current_type) {
     554             :     // If the types have nothing to do with integers, return the types.
     555      479607 :     Type const integer = type_cache_->kInteger;
     556      479607 :     if (!previous_type.Maybe(integer)) {
     557       30679 :       return current_type;
     558             :     }
     559             :     DCHECK(current_type.Maybe(integer));
     560             : 
     561      448928 :     Type current_integer = Type::Intersect(current_type, integer, graph_zone());
     562             :     DCHECK(!current_integer.IsNone());
     563             :     Type previous_integer =
     564      448926 :         Type::Intersect(previous_type, integer, graph_zone());
     565             :     DCHECK(!previous_integer.IsNone());
     566             : 
     567             :     // Once we start weakening a node, we should always weaken.
     568      448928 :     if (!GetInfo(node)->weakened()) {
     569             :       // Only weaken if there is range involved; we should converge quickly
     570             :       // for all other types (the exception is a union of many constants,
     571             :       // but we currently do not increase the number of constants in unions).
     572       96619 :       Type previous = previous_integer.GetRange();
     573       96619 :       Type current = current_integer.GetRange();
     574      188950 :       if (current.IsInvalid() || previous.IsInvalid()) {
     575        4378 :         return current_type;
     576             :       }
     577             :       // Range is involved => we are weakening.
     578             :       GetInfo(node)->set_weakened();
     579             :     }
     580             : 
     581             :     return Type::Union(current_type,
     582             :                        op_typer_.WeakenRange(previous_integer, current_integer),
     583      444548 :                        graph_zone());
     584             :   }
     585             : 
     586             :   // Backward propagation of truncations.
     587      456709 :   void RunTruncationPropagationPhase() {
     588             :     // Run propagation phase to a fixpoint.
     589      456709 :     TRACE("--{Propagation phase}--\n");
     590      456709 :     phase_ = PROPAGATE;
     591      456709 :     EnqueueInitial(jsgraph_->graph()->end());
     592             :     // Process nodes from the queue until it is empty.
     593    33187802 :     while (!queue_.empty()) {
     594    32274382 :       Node* node = queue_.front();
     595             :       NodeInfo* info = GetInfo(node);
     596             :       queue_.pop();
     597             :       info->set_visited();
     598    32274382 :       TRACE(" visit #%d: %s (trunc: %s)\n", node->id(), node->op()->mnemonic(),
     599             :             info->truncation().description());
     600    32274382 :       VisitNode(node, info->truncation(), nullptr);
     601             :     }
     602      456710 :   }
     603             : 
     604      456709 :   void Run(SimplifiedLowering* lowering) {
     605      456709 :     RunTruncationPropagationPhase();
     606             : 
     607      456710 :     RunTypePropagationPhase();
     608             : 
     609             :     // Run lowering and change insertion phase.
     610      456703 :     TRACE("--{Simplified lowering phase}--\n");
     611      456718 :     phase_ = LOWER;
     612             :     // Process nodes from the collected {nodes_} vector.
     613    32223556 :     for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
     614    31310128 :       Node* node = *i;
     615             :       NodeInfo* info = GetInfo(node);
     616    31310128 :       TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
     617             :       // Reuse {VisitNode()} so the representation rules are in one place.
     618             :       SourcePositionTable::Scope scope(
     619    31310128 :           source_positions_, source_positions_->GetSourcePosition(node));
     620             :       NodeOriginTable::Scope origin_scope(node_origins_, "simplified lowering",
     621    31310076 :                                           node);
     622    31310076 :       VisitNode(node, info->truncation(), lowering);
     623             :     }
     624             : 
     625             :     // Perform the final replacements.
     626     2245323 :     for (NodeVector::iterator i = replacements_.begin();
     627             :          i != replacements_.end(); ++i) {
     628     1331907 :       Node* node = *i;
     629     1331907 :       Node* replacement = *(++i);
     630     1331907 :       node->ReplaceUses(replacement);
     631     1331900 :       node->Kill();
     632             :       // We also need to replace the node in the rest of the vector.
     633   407513531 :       for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
     634             :         ++j;
     635   404849725 :         if (*j == node) *j = replacement;
     636             :       }
     637             :     }
     638      456706 :   }
     639             : 
     640      456709 :   void EnqueueInitial(Node* node) {
     641      456709 :     NodeInfo* info = GetInfo(node);
     642             :     info->set_queued();
     643      456709 :     nodes_.push_back(node);
     644             :     queue_.push(node);
     645      456710 :   }
     646             : 
     647             :   // Enqueue {use_node}'s {index} input if the {use} contains new information
     648             :   // for that input node. Add the input to {nodes_} if this is the first time
     649             :   // it's been visited.
     650   164670575 :   void EnqueueInput(Node* use_node, int index,
     651             :                     UseInfo use_info = UseInfo::None()) {
     652   164670575 :     Node* node = use_node->InputAt(index);
     653   255911121 :     if (phase_ != PROPAGATE) return;
     654   106641087 :     NodeInfo* info = GetInfo(node);
     655             : #ifdef DEBUG
     656             :     // Check monotonicity of input requirements.
     657             :     node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
     658             :                                                            use_info);
     659             : #endif  // DEBUG
     660   104283615 :     if (info->unvisited()) {
     661             :       // First visit of this node.
     662             :       info->set_queued();
     663    30853786 :       nodes_.push_back(node);
     664             :       queue_.push(node);
     665    30853741 :       TRACE("  initial #%i: ", node->id());
     666    30853741 :       info->AddUse(use_info);
     667    30853636 :       PrintTruncation(info->truncation());
     668    30853586 :       return;
     669             :     }
     670    73429829 :     TRACE("   queue #%i?: ", node->id());
     671    73429829 :     PrintTruncation(info->truncation());
     672    73429690 :     if (info->AddUse(use_info)) {
     673             :       // New usage information for the node is available.
     674     2357472 :       if (!info->queued()) {
     675             :         queue_.push(node);
     676             :         info->set_queued();
     677      964238 :         TRACE("   added: ");
     678             :       } else {
     679     1393233 :         TRACE(" inqueue: ");
     680             :       }
     681     2357471 :       PrintTruncation(info->truncation());
     682             :     }
     683             :   }
     684             : 
     685             :   bool lower() const { return phase_ == LOWER; }
     686             :   bool retype() const { return phase_ == RETYPE; }
     687             :   bool propagate() const { return phase_ == PROPAGATE; }
     688             : 
     689             :   void SetOutput(Node* node, MachineRepresentation representation,
     690             :                  Type restriction_type = Type::Any()) {
     691             :     NodeInfo* const info = GetInfo(node);
     692    97582449 :     switch (phase_) {
     693             :       case PROPAGATE:
     694             :         info->set_restriction_type(restriction_type);
     695             :         break;
     696             :       case RETYPE:
     697             :         DCHECK(info->restriction_type().Is(restriction_type));
     698             :         DCHECK(restriction_type.Is(info->restriction_type()));
     699             :         info->set_output(representation);
     700             :         break;
     701             :       case LOWER:
     702             :         DCHECK_EQ(info->representation(), representation);
     703             :         DCHECK(info->restriction_type().Is(restriction_type));
     704             :         DCHECK(restriction_type.Is(info->restriction_type()));
     705             :         break;
     706             :     }
     707             :   }
     708             : 
     709             :   Type GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
     710             : 
     711       94277 :   bool InputCannotBe(Node* node, Type type) {
     712             :     DCHECK_EQ(1, node->op()->ValueInputCount());
     713       94277 :     return !GetUpperBound(node->InputAt(0)).Maybe(type);
     714             :   }
     715             : 
     716       56342 :   bool InputIs(Node* node, Type type) {
     717             :     DCHECK_EQ(1, node->op()->ValueInputCount());
     718      112684 :     return GetUpperBound(node->InputAt(0)).Is(type);
     719             :   }
     720             : 
     721             :   bool BothInputsAreSigned32(Node* node) {
     722       93633 :     return BothInputsAre(node, Type::Signed32());
     723             :   }
     724             : 
     725             :   bool BothInputsAreUnsigned32(Node* node) {
     726      100194 :     return BothInputsAre(node, Type::Unsigned32());
     727             :   }
     728             : 
     729     1037104 :   bool BothInputsAre(Node* node, Type type) {
     730             :     DCHECK_EQ(2, node->op()->ValueInputCount());
     731     3427986 :     return GetUpperBound(node->InputAt(0)).Is(type) &&
     732     2390882 :            GetUpperBound(node->InputAt(1)).Is(type);
     733             :   }
     734             : 
     735             :   bool IsNodeRepresentationTagged(Node* node) {
     736       32626 :     MachineRepresentation representation = GetInfo(node)->representation();
     737             :     return IsAnyTagged(representation);
     738             :   }
     739             : 
     740          72 :   bool OneInputCannotBe(Node* node, Type type) {
     741             :     DCHECK_EQ(2, node->op()->ValueInputCount());
     742         216 :     return !GetUpperBound(node->InputAt(0)).Maybe(type) ||
     743         216 :            !GetUpperBound(node->InputAt(1)).Maybe(type);
     744             :   }
     745             : 
     746      773030 :   void ChangeToPureOp(Node* node, const Operator* new_op) {
     747             :     DCHECK(new_op->HasProperty(Operator::kPure));
     748      692944 :     if (node->op()->EffectInputCount() > 0) {
     749             :       DCHECK_LT(0, node->op()->ControlInputCount());
     750      213132 :       Node* control = NodeProperties::GetControlInput(node);
     751      213129 :       Node* effect = NodeProperties::GetEffectInput(node);
     752      213126 :       if (TypeOf(node).IsNone()) {
     753             :         // If the node is unreachable, insert an Unreachable node and mark the
     754             :         // value dead.
     755             :         // TODO(jarin,tebbi) Find a way to unify/merge this insertion with
     756             :         // InsertUnreachableIfNecessary.
     757             :         Node* unreachable = effect = graph()->NewNode(
     758         608 :             jsgraph_->common()->Unreachable(), effect, control);
     759         608 :         new_op = jsgraph_->common()->DeadValue(GetInfo(node)->representation());
     760         304 :         node->ReplaceInput(0, unreachable);
     761             :       }
     762             :       // Rewire the effect and control chains.
     763      213126 :       node->TrimInputCount(new_op->ValueInputCount());
     764      213128 :       ReplaceEffectControlUses(node, effect, control);
     765             :     } else {
     766             :       DCHECK_EQ(0, node->op()->ControlInputCount());
     767             :     }
     768      346466 :     NodeProperties::ChangeOp(node, new_op);
     769      346457 :   }
     770             : 
     771             :   // Converts input {index} of {node} according to given UseInfo {use},
     772             :   // assuming the type of the input is {input_type}. If {input_type} is null,
     773             :   // it takes the input from the input node {TypeOf(node->InputAt(index))}.
     774    73260896 :   void ConvertInput(Node* node, int index, UseInfo use,
     775             :                     Type input_type = Type::Invalid()) {
     776           0 :     Node* input = node->InputAt(index);
     777             :     // In the change phase, insert a change before the use if necessary.
     778    56325695 :     if (use.representation() == MachineRepresentation::kNone)
     779    56325570 :       return;  // No input requirement on the use.
     780             :     DCHECK_NOT_NULL(input);
     781    70824406 :     NodeInfo* input_info = GetInfo(input);
     782             :     MachineRepresentation input_rep = input_info->representation();
     783    90951008 :     if (input_rep != use.representation() ||
     784    37061783 :         use.type_check() != TypeCheckKind::kNone) {
     785             :       // Output representation doesn't match usage.
     786    16935236 :       TRACE("  change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
     787             :             index, input->id(), input->op()->mnemonic());
     788    16935221 :       TRACE(" from ");
     789    16935221 :       PrintOutputInfo(input_info);
     790    16935201 :       TRACE(" to ");
     791    16935201 :       PrintUseInfo(use);
     792    16935175 :       TRACE("\n");
     793    16935181 :       if (input_type.IsInvalid()) {
     794             :         input_type = TypeOf(input);
     795             :       }
     796             :       Node* n = changer_->GetRepresentationFor(
     797    16935181 :           input, input_info->representation(), input_type, node, use);
     798    16935141 :       node->ReplaceInput(index, n);
     799             :     }
     800             :   }
     801             : 
     802   181088147 :   void ProcessInput(Node* node, int index, UseInfo use) {
     803   181088147 :     switch (phase_) {
     804             :       case PROPAGATE:
     805    58191265 :         EnqueueInput(node, index, use);
     806    58190157 :         break;
     807             :       case RETYPE:
     808             :         break;
     809             :       case LOWER:
     810    56304193 :         ConvertInput(node, index, use);
     811    56303896 :         break;
     812             :     }
     813   181086742 :   }
     814             : 
     815    18228222 :   void ProcessRemainingInputs(Node* node, int index) {
     816             :     DCHECK_GE(index, NodeProperties::PastValueIndex(node));
     817             :     DCHECK_GE(index, NodeProperties::PastContextIndex(node));
     818    78076230 :     for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
     819    29924008 :          i < NodeProperties::PastEffectIndex(node); ++i) {
     820    11695790 :       EnqueueInput(node, i);  // Effect inputs: just visit
     821             :     }
     822    78204485 :     for (int i = std::max(index, NodeProperties::FirstControlIndex(node));
     823    29988134 :          i < NodeProperties::PastControlIndex(node); ++i) {
     824    11759922 :       EnqueueInput(node, i);  // Control inputs: just visit
     825             :     }
     826    18228215 :   }
     827             : 
     828             :   // The default, most general visitation case. For {node}, process all value,
     829             :   // context, frame state, effect, and control inputs, assuming that value
     830             :   // inputs should have {kRepTagged} representation and can observe all output
     831             :   // values {kTypeAny}.
     832    61824064 :   void VisitInputs(Node* node) {
     833    61824064 :     int tagged_count = node->op()->ValueInputCount() +
     834             :                        OperatorProperties::GetContextInputCount(node->op()) +
     835    30911784 :                        OperatorProperties::GetFrameStateInputCount(node->op());
     836             :     // Visit value, context and frame state inputs as tagged.
     837    76495324 :     for (int i = 0; i < tagged_count; i++) {
     838    45583505 :       ProcessInput(node, i, UseInfo::AnyTagged());
     839             :     }
     840             :     // Only enqueue other inputs (effects, control).
     841   147802640 :     for (int i = tagged_count; i < node->InputCount(); i++) {
     842    58445401 :       EnqueueInput(node, i);
     843             :     }
     844    30911721 :   }
     845             : 
     846     3298724 :   void VisitReturn(Node* node) {
     847     3298724 :     int tagged_limit = node->op()->ValueInputCount() +
     848             :                        OperatorProperties::GetContextInputCount(node->op()) +
     849     1649364 :                        OperatorProperties::GetFrameStateInputCount(node->op());
     850             :     // Visit integer slot count to pop
     851     1649362 :     ProcessInput(node, 0, UseInfo::TruncatingWord32());
     852             : 
     853             :     // Visit value, context and frame state inputs as tagged.
     854     3298715 :     for (int i = 1; i < tagged_limit; i++) {
     855     1649358 :       ProcessInput(node, i, UseInfo::AnyTagged());
     856             :     }
     857             :     // Only enqueue other inputs (effects, control).
     858     8246794 :     for (int i = tagged_limit; i < node->InputCount(); i++) {
     859     3298717 :       EnqueueInput(node, i);
     860             :     }
     861     1649360 :   }
     862             : 
     863             :   // Helper for an unused node.
     864      988352 :   void VisitUnused(Node* node) {
     865      658901 :     int value_count = node->op()->ValueInputCount() +
     866             :                       OperatorProperties::GetContextInputCount(node->op()) +
     867      329450 :                       OperatorProperties::GetFrameStateInputCount(node->op());
     868      849209 :     for (int i = 0; i < value_count; i++) {
     869      519761 :       ProcessInput(node, i, UseInfo::None());
     870             :     }
     871      329450 :     ProcessRemainingInputs(node, value_count);
     872      329451 :     if (lower()) Kill(node);
     873      329451 :   }
     874             : 
     875             :   // Helper for no-op node.
     876          58 :   void VisitNoop(Node* node, Truncation truncation) {
     877          72 :     if (truncation.IsUnused()) return VisitUnused(node);
     878             :     MachineRepresentation representation =
     879          22 :         GetOutputInfoForPhi(node, TypeOf(node), truncation);
     880          44 :     VisitUnop(node, UseInfo(representation, truncation), representation);
     881          33 :     if (lower()) DeferReplacement(node, node->InputAt(0));
     882             :   }
     883             : 
     884             :   // Helper for binops of the R x L -> O variety.
     885     3558427 :   void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
     886             :                   MachineRepresentation output,
     887             :                   Type restriction_type = Type::Any()) {
     888             :     DCHECK_EQ(2, node->op()->ValueInputCount());
     889     3558427 :     ProcessInput(node, 0, left_use);
     890     3558060 :     ProcessInput(node, 1, right_use);
     891    13850496 :     for (int i = 2; i < node->InputCount(); i++) {
     892     3367357 :       EnqueueInput(node, i);
     893             :     }
     894             :     SetOutput(node, output, restriction_type);
     895     3557834 :   }
     896             : 
     897             :   // Helper for binops of the I x I -> O variety.
     898             :   void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output,
     899             :                   Type restriction_type = Type::Any()) {
     900     2883681 :     VisitBinop(node, input_use, input_use, output, restriction_type);
     901             :   }
     902             : 
     903      100493 :   void VisitSpeculativeInt32Binop(Node* node) {
     904             :     DCHECK_EQ(2, node->op()->ValueInputCount());
     905       83560 :     if (BothInputsAre(node, Type::NumberOrOddball())) {
     906             :       return VisitBinop(node, UseInfo::TruncatingWord32(),
     907             :                         MachineRepresentation::kWord32);
     908             :     }
     909       16933 :     NumberOperationHint hint = NumberOperationHintOf(node->op());
     910             :     return VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
     911       33866 :                       MachineRepresentation::kWord32);
     912             :   }
     913             : 
     914             :   // Helper for unops of the I -> O variety.
     915    10668515 :   void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output,
     916             :                  Type restriction_type = Type::Any()) {
     917             :     DCHECK_EQ(1, node->op()->ValueInputCount());
     918    10668515 :     ProcessInput(node, 0, input_use);
     919    10668520 :     ProcessRemainingInputs(node, 1);
     920             :     SetOutput(node, output, restriction_type);
     921    10668512 :   }
     922             : 
     923             :   // Helper for leaf nodes.
     924             :   void VisitLeaf(Node* node, MachineRepresentation output) {
     925             :     DCHECK_EQ(0, node->InputCount());
     926             :     SetOutput(node, output);
     927             :   }
     928             : 
     929             :   // Helpers for specific types of binops.
     930      642738 :   void VisitFloat64Binop(Node* node) {
     931             :     VisitBinop(node, UseInfo::TruncatingFloat64(),
     932             :                MachineRepresentation::kFloat64);
     933      642752 :   }
     934        3499 :   void VisitInt64Binop(Node* node) {
     935             :     VisitBinop(node, UseInfo::Word64(), MachineRepresentation::kWord64);
     936        3499 :   }
     937      504810 :   void VisitWord32TruncatingBinop(Node* node) {
     938             :     VisitBinop(node, UseInfo::TruncatingWord32(),
     939             :                MachineRepresentation::kWord32);
     940      504805 :   }
     941             : 
     942             :   // Infer representation for phi-like nodes.
     943             :   // The {node} parameter is only used to decide on the int64 representation.
     944             :   // Once the type system supports an external pointer type, the {node}
     945             :   // parameter can be removed.
     946     1657272 :   MachineRepresentation GetOutputInfoForPhi(Node* node, Type type,
     947     1144874 :                                             Truncation use) {
     948             :     // Compute the representation.
     949     1657238 :     if (type.Is(Type::None())) {
     950             :       return MachineRepresentation::kNone;
     951     2958099 :     } else if (type.Is(Type::Signed32()) || type.Is(Type::Unsigned32())) {
     952             :       return MachineRepresentation::kWord32;
     953     2135215 :     } else if (type.Is(Type::NumberOrOddball()) && use.IsUsedAsWord32()) {
     954             :       return MachineRepresentation::kWord32;
     955     1303382 :     } else if (type.Is(Type::Boolean())) {
     956             :       return MachineRepresentation::kBit;
     957     1950434 :     } else if (type.Is(Type::NumberOrOddball()) && use.IsUsedAsFloat64()) {
     958             :       return MachineRepresentation::kFloat64;
     959     2289785 :     } else if (type.Is(Type::Union(Type::SignedSmall(), Type::NaN(), zone()))) {
     960             :       // TODO(turbofan): For Phis that return either NaN or some Smi, it's
     961             :       // beneficial to not go all the way to double, unless the uses are
     962             :       // double uses. For tagging that just means some potentially expensive
     963             :       // allocation code; we might want to do the same for -0 as well?
     964             :       return MachineRepresentation::kTagged;
     965     1144777 :     } else if (type.Is(Type::Number())) {
     966             :       return MachineRepresentation::kFloat64;
     967      493710 :     } else if (type.Is(Type::ExternalPointer())) {
     968             :       return MachineType::PointerRepresentation();
     969             :     }
     970      493710 :     return MachineRepresentation::kTagged;
     971             :   }
     972             : 
     973             :   // Helper for handling selects.
     974       50626 :   void VisitSelect(Node* node, Truncation truncation,
     975       38198 :                    SimplifiedLowering* lowering) {
     976             :     DCHECK(TypeOf(node->InputAt(0)).Is(Type::Boolean()));
     977       38198 :     ProcessInput(node, 0, UseInfo::Bool());
     978             : 
     979             :     MachineRepresentation output =
     980       38198 :         GetOutputInfoForPhi(node, TypeOf(node), truncation);
     981             :     SetOutput(node, output);
     982             : 
     983       38198 :     if (lower()) {
     984             :       // Update the select operator.
     985       12428 :       SelectParameters p = SelectParametersOf(node->op());
     986       12428 :       if (output != p.representation()) {
     987             :         NodeProperties::ChangeOp(node,
     988        7190 :                                  lowering->common()->Select(output, p.hint()));
     989             :       }
     990             :     }
     991             :     // Convert inputs to the output representation of this phi, pass the
     992             :     // truncation truncation along.
     993       76396 :     UseInfo input_use(output, truncation);
     994       38198 :     ProcessInput(node, 1, input_use);
     995       38198 :     ProcessInput(node, 2, input_use);
     996       38198 :   }
     997             : 
     998             :   // Helper for handling phis.
     999     3060503 :   void VisitPhi(Node* node, Truncation truncation,
    1000     1530223 :                 SimplifiedLowering* lowering) {
    1001             :     MachineRepresentation output =
    1002     1530280 :         GetOutputInfoForPhi(node, TypeOf(node), truncation);
    1003             :     // Only set the output representation if not running with type
    1004             :     // feedback. (Feedback typing will set the representation.)
    1005             :     SetOutput(node, output);
    1006             : 
    1007     1530223 :     int values = node->op()->ValueInputCount();
    1008     1530223 :     if (lower()) {
    1009             :       // Update the phi operator.
    1010      322498 :       if (output != PhiRepresentationOf(node->op())) {
    1011      179767 :         NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values));
    1012             :       }
    1013             :     }
    1014             : 
    1015             :     // Convert inputs to the output representation of this phi, pass the
    1016             :     // truncation along.
    1017     3060434 :     UseInfo input_use(output, truncation);
    1018    14237226 :     for (int i = 0; i < node->InputCount(); i++) {
    1019    11176960 :       ProcessInput(node, i, i < values ? input_use : UseInfo::None());
    1020             :     }
    1021     1530293 :   }
    1022             : 
    1023      322662 :   void VisitObjectIs(Node* node, Type type, SimplifiedLowering* lowering) {
    1024      160403 :     Type const input_type = TypeOf(node->InputAt(0));
    1025      160403 :     if (input_type.Is(type)) {
    1026        4029 :       VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
    1027        4029 :       if (lower()) {
    1028        1375 :         DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
    1029             :       }
    1030             :     } else {
    1031      156374 :       VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
    1032      156374 :       if (lower() && !input_type.Maybe(type)) {
    1033         481 :         DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
    1034             :       }
    1035             :     }
    1036      160403 :   }
    1037             : 
    1038       30622 :   void VisitCheck(Node* node, Type type, SimplifiedLowering* lowering) {
    1039       30404 :     if (InputIs(node, type)) {
    1040             :       VisitUnop(node, UseInfo::AnyTagged(),
    1041         218 :                 MachineRepresentation::kTaggedPointer);
    1042         279 :       if (lower()) DeferReplacement(node, node->InputAt(0));
    1043             :     } else {
    1044             :       VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
    1045       30186 :                 MachineRepresentation::kTaggedPointer);
    1046             :     }
    1047       30404 :   }
    1048             : 
    1049      669668 :   void VisitCall(Node* node, SimplifiedLowering* lowering) {
    1050      669674 :     auto call_descriptor = CallDescriptorOf(node->op());
    1051      334830 :     int params = static_cast<int>(call_descriptor->ParameterCount());
    1052      334830 :     int value_input_count = node->op()->ValueInputCount();
    1053             :     // Propagate representation information from call descriptor.
    1054     2823144 :     for (int i = 0; i < value_input_count; i++) {
    1055     2488308 :       if (i == 0) {
    1056             :         // The target of the call.
    1057      334838 :         ProcessInput(node, i, UseInfo::Any());
    1058     2153478 :       } else if ((i - 1) < params) {
    1059             :         ProcessInput(node, i,
    1060             :                      TruncatingUseInfoFromRepresentation(
    1061     3647128 :                          call_descriptor->GetInputType(i).representation()));
    1062             :       } else {
    1063      329913 :         ProcessInput(node, i, UseInfo::AnyTagged());
    1064             :       }
    1065             :     }
    1066      334836 :     ProcessRemainingInputs(node, value_input_count);
    1067             : 
    1068      334836 :     if (call_descriptor->ReturnCount() > 0) {
    1069             :       SetOutput(node, call_descriptor->GetReturnType(0).representation());
    1070             :     } else {
    1071             :       SetOutput(node, MachineRepresentation::kTagged);
    1072             :     }
    1073      334836 :   }
    1074             : 
    1075       19274 :   void MaskShiftOperand(Node* node, Type rhs_type) {
    1076       29100 :     if (!rhs_type.Is(type_cache_->kZeroToThirtyOne)) {
    1077        4724 :       Node* const rhs = NodeProperties::GetValueInput(node, 1);
    1078             :       node->ReplaceInput(1,
    1079             :                          graph()->NewNode(jsgraph_->machine()->Word32And(), rhs,
    1080        9448 :                                           jsgraph_->Int32Constant(0x1F)));
    1081             :     }
    1082       14550 :   }
    1083             : 
    1084      540850 :   static MachineSemantic DeoptValueSemanticOf(Type type) {
    1085             :     // We only need signedness to do deopt correctly.
    1086      540844 :     if (type.Is(Type::Signed32())) {
    1087             :       return MachineSemantic::kInt32;
    1088      365624 :     } else if (type.Is(Type::Unsigned32())) {
    1089             :       return MachineSemantic::kUint32;
    1090             :     } else {
    1091      362814 :       return MachineSemantic::kAny;
    1092             :     }
    1093             :   }
    1094             : 
    1095    11143108 :   static MachineType DeoptMachineTypeOf(MachineRepresentation rep, Type type) {
    1096    11143108 :     if (type.IsNone()) {
    1097             :       return MachineType::None();
    1098             :     }
    1099             :     // Do not distinguish between various Tagged variations.
    1100    11143108 :     if (IsAnyTagged(rep)) {
    1101             :       return MachineType::AnyTagged();
    1102             :     }
    1103             :     // Word64 representation is only valid for safe integer values.
    1104      541590 :     if (rep == MachineRepresentation::kWord64) {
    1105             :       DCHECK(type.Is(TypeCache::Get()->kSafeInteger));
    1106         739 :       return MachineType(rep, MachineSemantic::kInt64);
    1107             :     }
    1108      540851 :     MachineType machine_type(rep, DeoptValueSemanticOf(type));
    1109             :     DCHECK(machine_type.representation() != MachineRepresentation::kWord32 ||
    1110             :            machine_type.semantic() == MachineSemantic::kInt32 ||
    1111             :            machine_type.semantic() == MachineSemantic::kUint32);
    1112             :     DCHECK(machine_type.representation() != MachineRepresentation::kBit ||
    1113             :            type.Is(Type::Boolean()));
    1114      540843 :     return machine_type;
    1115             :   }
    1116             : 
    1117    13702651 :   void VisitStateValues(Node* node) {
    1118    10663581 :     if (propagate()) {
    1119    23387510 :       for (int i = 0; i < node->InputCount(); i++) {
    1120    10174243 :         EnqueueInput(node, i, UseInfo::Any());
    1121             :       }
    1122     7624559 :     } else if (lower()) {
    1123     6078140 :       Zone* zone = jsgraph_->zone();
    1124             :       ZoneVector<MachineType>* types =
    1125             :           new (zone->New(sizeof(ZoneVector<MachineType>)))
    1126     3039071 :               ZoneVector<MachineType>(node->InputCount(), zone);
    1127    26426666 :       for (int i = 0; i < node->InputCount(); i++) {
    1128             :         Node* input = node->InputAt(i);
    1129    10174263 :         (*types)[i] =
    1130    10174263 :             DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input));
    1131             :       }
    1132     3039070 :       SparseInputMask mask = SparseInputMaskOf(node->op());
    1133             :       NodeProperties::ChangeOp(
    1134     6078138 :           node, jsgraph_->common()->TypedStateValues(types, mask));
    1135             :     }
    1136             :     SetOutput(node, MachineRepresentation::kTagged);
    1137    10663578 :   }
    1138             : 
    1139    36005818 :   void VisitFrameState(Node* node) {
    1140             :     DCHECK_EQ(5, node->op()->ValueInputCount());
    1141             :     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
    1142             : 
    1143    18002910 :     ProcessInput(node, 0, UseInfo::AnyTagged());  // Parameters.
    1144    18002922 :     ProcessInput(node, 1, UseInfo::AnyTagged());  // Registers.
    1145             : 
    1146             :     // Accumulator is a special flower - we need to remember its type in
    1147             :     // a singleton typed-state-values node (as if it was a singleton
    1148             :     // state-values node).
    1149    18002925 :     if (propagate()) {
    1150     5729105 :       EnqueueInput(node, 2, UseInfo::Any());
    1151    12273825 :     } else if (lower()) {
    1152     7394153 :       Zone* zone = jsgraph_->zone();
    1153             :       Node* accumulator = node->InputAt(2);
    1154     5729113 :       if (accumulator == jsgraph_->OptimizedOutConstant()) {
    1155     4896586 :         node->ReplaceInput(2, jsgraph_->SingleDeadTypedStateValues());
    1156             :       } else {
    1157             :         ZoneVector<MachineType>* types =
    1158             :             new (zone->New(sizeof(ZoneVector<MachineType>)))
    1159      832521 :                 ZoneVector<MachineType>(1, zone);
    1160      832521 :         (*types)[0] = DeoptMachineTypeOf(GetInfo(accumulator)->representation(),
    1161      832521 :                                          TypeOf(accumulator));
    1162             : 
    1163             :         node->ReplaceInput(
    1164             :             2, jsgraph_->graph()->NewNode(jsgraph_->common()->TypedStateValues(
    1165             :                                               types, SparseInputMask::Dense()),
    1166     2497558 :                                           accumulator));
    1167             :       }
    1168             :     }
    1169             : 
    1170    18002945 :     ProcessInput(node, 3, UseInfo::AnyTagged());  // Context.
    1171    18002938 :     ProcessInput(node, 4, UseInfo::AnyTagged());  // Closure.
    1172    18002932 :     ProcessInput(node, 5, UseInfo::AnyTagged());  // Outer frame state.
    1173    18002914 :     return SetOutput(node, MachineRepresentation::kTagged);
    1174             :   }
    1175             : 
    1176       95252 :   void VisitObjectState(Node* node) {
    1177       72212 :     if (propagate()) {
    1178      295674 :       for (int i = 0; i < node->InputCount(); i++) {
    1179      136317 :         EnqueueInput(node, i, UseInfo::Any());
    1180             :       }
    1181       49172 :     } else if (lower()) {
    1182       46080 :       Zone* zone = jsgraph_->zone();
    1183             :       ZoneVector<MachineType>* types =
    1184             :           new (zone->New(sizeof(ZoneVector<MachineType>)))
    1185       23040 :               ZoneVector<MachineType>(node->InputCount(), zone);
    1186      318714 :       for (int i = 0; i < node->InputCount(); i++) {
    1187             :         Node* input = node->InputAt(i);
    1188      136317 :         (*types)[i] =
    1189      136317 :             DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input));
    1190             :       }
    1191             :       NodeProperties::ChangeOp(node, jsgraph_->common()->TypedObjectState(
    1192       46080 :                                          ObjectIdOf(node->op()), types));
    1193             :     }
    1194             :     SetOutput(node, MachineRepresentation::kTagged);
    1195       72212 :   }
    1196             : 
    1197      218552 :   const Operator* Int32Op(Node* node) {
    1198      218552 :     return changer_->Int32OperatorFor(node->opcode());
    1199             :   }
    1200             : 
    1201      151274 :   const Operator* Int32OverflowOp(Node* node) {
    1202      151274 :     return changer_->Int32OverflowOperatorFor(node->opcode());
    1203             :   }
    1204             : 
    1205         927 :   const Operator* Int64Op(Node* node) {
    1206         927 :     return changer_->Int64OperatorFor(node->opcode());
    1207             :   }
    1208             : 
    1209       36224 :   const Operator* Uint32Op(Node* node) {
    1210       36224 :     return changer_->Uint32OperatorFor(node->opcode());
    1211             :   }
    1212             : 
    1213         105 :   const Operator* Uint32OverflowOp(Node* node) {
    1214         105 :     return changer_->Uint32OverflowOperatorFor(node->opcode());
    1215             :   }
    1216             : 
    1217      132171 :   const Operator* Float64Op(Node* node) {
    1218      172140 :     return changer_->Float64OperatorFor(node->opcode());
    1219             :   }
    1220             : 
    1221     6284276 :   WriteBarrierKind WriteBarrierKindFor(
    1222             :       BaseTaggedness base_taggedness,
    1223             :       MachineRepresentation field_representation, Type field_type,
    1224             :       MachineRepresentation value_representation, Node* value) {
    1225    12568552 :     if (base_taggedness == kTaggedBase &&
    1226             :         CanBeTaggedPointer(field_representation)) {
    1227     5540686 :       Type value_type = NodeProperties::GetType(value);
    1228    11081372 :       if (field_representation == MachineRepresentation::kTaggedSigned ||
    1229     5540686 :           value_representation == MachineRepresentation::kTaggedSigned) {
    1230             :         // Write barriers are only for stores of heap objects.
    1231             :         return kNoWriteBarrier;
    1232             :       }
    1233    11081372 :       if (field_type.Is(Type::BooleanOrNullOrUndefined()) ||
    1234             :           value_type.Is(Type::BooleanOrNullOrUndefined())) {
    1235             :         // Write barriers are not necessary when storing true, false, null or
    1236             :         // undefined, because these special oddballs are always in the root set.
    1237             :         return kNoWriteBarrier;
    1238             :       }
    1239     5160983 :       if (value_type.IsHeapConstant()) {
    1240             :         RootIndex root_index;
    1241     1825767 :         const RootsTable& roots_table = jsgraph_->isolate()->roots_table();
    1242     1825767 :         if (roots_table.IsRootHandle(value_type.AsHeapConstant()->Value(),
    1243     1825767 :                                      &root_index)) {
    1244     1027858 :           if (RootsTable::IsImmortalImmovable(root_index)) {
    1245             :             // Write barriers are unnecessary for immortal immovable roots.
    1246             :             return kNoWriteBarrier;
    1247             :           }
    1248             :         }
    1249             :       }
    1250     8266250 :       if (field_representation == MachineRepresentation::kTaggedPointer ||
    1251     4133125 :           value_representation == MachineRepresentation::kTaggedPointer) {
    1252             :         // Write barriers for heap objects are cheaper.
    1253             :         return kPointerWriteBarrier;
    1254             :       }
    1255             :       NumberMatcher m(value);
    1256     3194170 :       if (m.HasValue()) {
    1257        1568 :         if (IsSmiDouble(m.Value())) {
    1258             :           // Storing a smi doesn't need a write barrier.
    1259             :           return kNoWriteBarrier;
    1260             :         }
    1261             :         // The NumberConstant will be represented as HeapNumber.
    1262        1568 :         return kPointerWriteBarrier;
    1263             :       }
    1264             :       return kFullWriteBarrier;
    1265             :     }
    1266             :     return kNoWriteBarrier;
    1267             :   }
    1268             : 
    1269     6170892 :   WriteBarrierKind WriteBarrierKindFor(
    1270             :       BaseTaggedness base_taggedness,
    1271             :       MachineRepresentation field_representation, int field_offset,
    1272             :       Type field_type, MachineRepresentation value_representation,
    1273             :       Node* value) {
    1274             :     WriteBarrierKind write_barrier_kind =
    1275             :         WriteBarrierKindFor(base_taggedness, field_representation, field_type,
    1276     6170892 :                             value_representation, value);
    1277     6170892 :     if (write_barrier_kind != kNoWriteBarrier) {
    1278     8179354 :       if (base_taggedness == kTaggedBase &&
    1279     4089677 :           field_offset == HeapObject::kMapOffset) {
    1280             :         write_barrier_kind = kMapWriteBarrier;
    1281             :       }
    1282             :     }
    1283     6170892 :     return write_barrier_kind;
    1284             :   }
    1285             : 
    1286      919478 :   Graph* graph() const { return jsgraph_->graph(); }
    1287        1035 :   CommonOperatorBuilder* common() const { return jsgraph_->common(); }
    1288             :   SimplifiedOperatorBuilder* simplified() const {
    1289       61108 :     return jsgraph_->simplified();
    1290             :   }
    1291             : 
    1292        5990 :   void LowerToCheckedInt32Mul(Node* node, Truncation truncation,
    1293        5990 :                               Type input0_type, Type input1_type) {
    1294             :     // If one of the inputs is positive and/or truncation is being applied,
    1295             :     // there is no need to return -0.
    1296             :     CheckForMinusZeroMode mz_mode =
    1297        4332 :         truncation.IdentifiesZeroAndMinusZero() ||
    1298        8623 :                 IsSomePositiveOrderedNumber(input0_type) ||
    1299        4291 :                 IsSomePositiveOrderedNumber(input1_type)
    1300             :             ? CheckForMinusZeroMode::kDontCheckForMinusZero
    1301        5990 :             : CheckForMinusZeroMode::kCheckForMinusZero;
    1302             : 
    1303        5990 :     NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode));
    1304        5990 :   }
    1305             : 
    1306      151274 :   void ChangeToInt32OverflowOp(Node* node) {
    1307      151271 :     NodeProperties::ChangeOp(node, Int32OverflowOp(node));
    1308      151270 :   }
    1309             : 
    1310         105 :   void ChangeToUint32OverflowOp(Node* node) {
    1311         105 :     NodeProperties::ChangeOp(node, Uint32OverflowOp(node));
    1312         105 :   }
    1313             : 
    1314     2451319 :   void VisitSpeculativeIntegerAdditiveOp(Node* node, Truncation truncation,
    1315     1009234 :                                          SimplifiedLowering* lowering) {
    1316      801317 :     Type left_upper = GetUpperBound(node->InputAt(0));
    1317      801317 :     Type right_upper = GetUpperBound(node->InputAt(1));
    1318             : 
    1319     1954703 :     if (left_upper.Is(type_cache_->kAdditiveSafeIntegerOrMinusZero) &&
    1320      352137 :         right_upper.Is(type_cache_->kAdditiveSafeIntegerOrMinusZero)) {
    1321             :       // Only eliminate the node if its typing rule can be satisfied, namely
    1322             :       // that a safe integer is produced.
    1323      346072 :       if (truncation.IsUnused()) return VisitUnused(node);
    1324             : 
    1325             :       // If we know how to interpret the result or if the users only care
    1326             :       // about the low 32-bits, we can truncate to Word32 do a wrapping
    1327             :       // addition.
    1328      723464 :       if (GetUpperBound(node).Is(Type::Signed32()) ||
    1329      395227 :           GetUpperBound(node).Is(Type::Unsigned32()) ||
    1330             :           truncation.IsUsedAsWord32()) {
    1331             :         // => Int32Add/Sub
    1332      264552 :         VisitWord32TruncatingBinop(node);
    1333      328845 :         if (lower()) ChangeToPureOp(node, Int32Op(node));
    1334             :         return;
    1335             :       }
    1336             :     }
    1337             : 
    1338             :     // Try to use type feedback.
    1339      518581 :     NumberOperationHint hint = NumberOperationHintOf(node->op());
    1340             :     DCHECK(hint == NumberOperationHint::kSignedSmall ||
    1341             :            hint == NumberOperationHint::kSigned32);
    1342             : 
    1343      518749 :     Type left_feedback_type = TypeOf(node->InputAt(0));
    1344      518749 :     Type right_feedback_type = TypeOf(node->InputAt(1));
    1345             :     // Handle the case when no int32 checks on inputs are necessary (but
    1346             :     // an overflow check is needed on the output). Note that we do not
    1347             :     // have to do any check if at most one side can be minus zero. For
    1348             :     // subtraction we need to handle the case of -0 - 0 properly, since
    1349             :     // that can produce -0.
    1350             :     Type left_constraint_type =
    1351             :         node->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd
    1352             :             ? Type::Signed32OrMinusZero()
    1353      518749 :             : Type::Signed32();
    1354      586456 :     if (left_upper.Is(left_constraint_type) &&
    1355      580289 :         right_upper.Is(Type::Signed32OrMinusZero()) &&
    1356          21 :         (left_upper.Is(Type::Signed32()) || right_upper.Is(Type::Signed32()))) {
    1357             :       VisitBinop(node, UseInfo::TruncatingWord32(),
    1358             :                  MachineRepresentation::kWord32, Type::Signed32());
    1359             :     } else {
    1360             :       // If the output's truncation is identify-zeros, we can pass it
    1361             :       // along. Moreover, if the operation is addition and we know the
    1362             :       // right-hand side is not minus zero, we do not have to distinguish
    1363             :       // between 0 and -0.
    1364      457226 :       IdentifyZeros left_identify_zeros = truncation.identify_zeros();
    1365      899641 :       if (node->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd &&
    1366      442426 :           !right_feedback_type.Maybe(Type::MinusZero())) {
    1367             :         left_identify_zeros = kIdentifyZeros;
    1368             :       }
    1369             :       UseInfo left_use = CheckedUseInfoAsWord32FromHint(hint, VectorSlotPair(),
    1370      457215 :                                                         left_identify_zeros);
    1371             :       // For CheckedInt32Add and CheckedInt32Sub, we don't need to do
    1372             :       // a minus zero check for the right hand side, since we already
    1373             :       // know that the left hand side is a proper Signed32 value,
    1374             :       // potentially guarded by a check.
    1375             :       UseInfo right_use = CheckedUseInfoAsWord32FromHint(hint, VectorSlotPair(),
    1376      457323 :                                                          kIdentifyZeros);
    1377             :       VisitBinop(node, left_use, right_use, MachineRepresentation::kWord32,
    1378      457280 :                  Type::Signed32());
    1379             :     }
    1380      518819 :     if (lower()) {
    1381      311464 :       if (truncation.IsUsedAsWord32() ||
    1382             :           !CanOverflowSigned32(node->op(), left_feedback_type,
    1383      155446 :                                right_feedback_type, graph_zone())) {
    1384        6123 :         ChangeToPureOp(node, Int32Op(node));
    1385             : 
    1386             :       } else {
    1387      149895 :         ChangeToInt32OverflowOp(node);
    1388             :       }
    1389             :     }
    1390             :     return;
    1391             :   }
    1392             : 
    1393        3906 :   void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
    1394        5022 :                                   SimplifiedLowering* lowering) {
    1395       11718 :     if (BothInputsAre(node, type_cache_->kAdditiveSafeIntegerOrMinusZero) &&
    1396        3906 :         (GetUpperBound(node).Is(Type::Signed32()) ||
    1397           0 :          GetUpperBound(node).Is(Type::Unsigned32()) ||
    1398           0 :          truncation.IsUsedAsWord32())) {
    1399             :       // => Int32Add/Sub
    1400           0 :       VisitWord32TruncatingBinop(node);
    1401           0 :       if (lower()) ChangeToPureOp(node, Int32Op(node));
    1402             :       return;
    1403             :     }
    1404             : 
    1405             :     // default case => Float64Add/Sub
    1406             :     VisitBinop(node,
    1407             :                UseInfo::CheckedNumberOrOddballAsFloat64(kDistinguishZeros,
    1408             :                                                         VectorSlotPair()),
    1409        7812 :                MachineRepresentation::kFloat64, Type::Number());
    1410        3906 :     if (lower()) {
    1411        1116 :       ChangeToPureOp(node, Float64Op(node));
    1412             :     }
    1413             :     return;
    1414             :   }
    1415             : 
    1416       18294 :   void VisitSpeculativeNumberModulus(Node* node, Truncation truncation,
    1417       12753 :                                      SimplifiedLowering* lowering) {
    1418       38233 :     if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) &&
    1419         165 :         (truncation.IsUsedAsWord32() ||
    1420       12872 :          NodeProperties::GetType(node).Is(Type::Unsigned32()))) {
    1421             :       // => unsigned Uint32Mod
    1422         640 :       VisitWord32TruncatingBinop(node);
    1423         640 :       if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
    1424             :       return;
    1425             :     }
    1426       41856 :     if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) &&
    1427        1253 :         (truncation.IsUsedAsWord32() ||
    1428       14408 :          NodeProperties::GetType(node).Is(Type::Signed32()))) {
    1429             :       // => signed Int32Mod
    1430        6150 :       VisitWord32TruncatingBinop(node);
    1431        6150 :       if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
    1432             :       return;
    1433             :     }
    1434             : 
    1435             :     // Try to use type feedback.
    1436        5752 :     NumberOperationHint hint = NumberOperationHintOf(node->op());
    1437             : 
    1438             :     // Handle the case when no uint32 checks on inputs are necessary
    1439             :     // (but an overflow check is needed on the output).
    1440        5752 :     if (BothInputsAreUnsigned32(node)) {
    1441         264 :       if (hint == NumberOperationHint::kSignedSmall ||
    1442         132 :           hint == NumberOperationHint::kSigned32) {
    1443             :         VisitBinop(node, UseInfo::TruncatingWord32(),
    1444             :                    MachineRepresentation::kWord32, Type::Unsigned32());
    1445         132 :         if (lower()) ChangeToUint32OverflowOp(node);
    1446             :         return;
    1447             :       }
    1448             :     }
    1449             : 
    1450             :     // Handle the case when no int32 checks on inputs are necessary
    1451             :     // (but an overflow check is needed on the output).
    1452        5620 :     if (BothInputsAre(node, Type::Signed32())) {
    1453             :       // If both the inputs the feedback are int32, use the overflow op.
    1454        2242 :       if (hint == NumberOperationHint::kSignedSmall ||
    1455        1121 :           hint == NumberOperationHint::kSigned32) {
    1456             :         VisitBinop(node, UseInfo::TruncatingWord32(),
    1457             :                    MachineRepresentation::kWord32, Type::Signed32());
    1458        1121 :         if (lower()) ChangeToInt32OverflowOp(node);
    1459             :         return;
    1460             :       }
    1461             :     }
    1462             : 
    1463        8998 :     if (hint == NumberOperationHint::kSignedSmall ||
    1464        4499 :         hint == NumberOperationHint::kSigned32) {
    1465             :       // If the result is truncated, we only need to check the inputs.
    1466             :       // For the left hand side we just propagate the identify zeros
    1467             :       // mode of the {truncation}; and for modulus the sign of the
    1468             :       // right hand side doesn't matter anyways, so in particular there's
    1469             :       // no observable difference between a 0 and a -0 then.
    1470             :       UseInfo const lhs_use = CheckedUseInfoAsWord32FromHint(
    1471        3694 :           hint, VectorSlotPair(), truncation.identify_zeros());
    1472             :       UseInfo const rhs_use = CheckedUseInfoAsWord32FromHint(
    1473        3694 :           hint, VectorSlotPair(), kIdentifyZeros);
    1474        3694 :       if (truncation.IsUsedAsWord32()) {
    1475         230 :         VisitBinop(node, lhs_use, rhs_use, MachineRepresentation::kWord32);
    1476         230 :         if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
    1477        3464 :       } else if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN())) {
    1478             :         VisitBinop(node, lhs_use, rhs_use, MachineRepresentation::kWord32,
    1479           0 :                    Type::Unsigned32());
    1480           0 :         if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
    1481             :       } else {
    1482             :         VisitBinop(node, lhs_use, rhs_use, MachineRepresentation::kWord32,
    1483        3464 :                    Type::Signed32());
    1484        3464 :         if (lower()) ChangeToInt32OverflowOp(node);
    1485             :       }
    1486             :       return;
    1487             :     }
    1488             : 
    1489        1662 :     if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) &&
    1490        1662 :         TypeOf(node->InputAt(1)).Is(Type::Unsigned32()) &&
    1491           0 :         (truncation.IsUsedAsWord32() ||
    1492         805 :          NodeProperties::GetType(node).Is(Type::Unsigned32()))) {
    1493             :       VisitBinop(node, UseInfo::TruncatingWord32(),
    1494             :                  MachineRepresentation::kWord32, Type::Number());
    1495           0 :       if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
    1496             :       return;
    1497             :     }
    1498        1729 :     if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) &&
    1499        1729 :         TypeOf(node->InputAt(1)).Is(Type::Signed32()) &&
    1500           0 :         (truncation.IsUsedAsWord32() ||
    1501         805 :          NodeProperties::GetType(node).Is(Type::Signed32()))) {
    1502             :       VisitBinop(node, UseInfo::TruncatingWord32(),
    1503             :                  MachineRepresentation::kWord32, Type::Number());
    1504           0 :       if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
    1505             :       return;
    1506             :     }
    1507             : 
    1508             :     // default case => Float64Mod
    1509             :     // For the left hand side we just propagate the identify zeros
    1510             :     // mode of the {truncation}; and for modulus the sign of the
    1511             :     // right hand side doesn't matter anyways, so in particular there's
    1512             :     // no observable difference between a 0 and a -0 then.
    1513             :     UseInfo const lhs_use = UseInfo::CheckedNumberOrOddballAsFloat64(
    1514        1610 :         truncation.identify_zeros(), VectorSlotPair());
    1515             :     UseInfo const rhs_use = UseInfo::CheckedNumberOrOddballAsFloat64(
    1516        1610 :         kIdentifyZeros, VectorSlotPair());
    1517             :     VisitBinop(node, lhs_use, rhs_use, MachineRepresentation::kFloat64,
    1518         805 :                Type::Number());
    1519        1016 :     if (lower()) ChangeToPureOp(node, Float64Op(node));
    1520             :     return;
    1521             :   }
    1522             : 
    1523    31311776 :   void InsertUnreachableIfNecessary(Node* node) {
    1524             :     DCHECK(lower());
    1525             :     // If the node is effectful and it produces an impossible value, then we
    1526             :     // insert Unreachable node after it.
    1527    83910805 :     if (node->op()->ValueOutputCount() > 0 &&
    1528    26972528 :         node->op()->EffectOutputCount() > 0 &&
    1529    36990170 :         node->opcode() != IrOpcode::kUnreachable && TypeOf(node).IsNone()) {
    1530             :       Node* control =
    1531        1035 :           (node->op()->ControlOutputCount() == 0)
    1532             :               ? NodeProperties::GetControlInput(node, 0)
    1533        1035 :               : NodeProperties::FindSuccessfulControlProjection(node);
    1534             : 
    1535             :       Node* unreachable =
    1536        1035 :           graph()->NewNode(common()->Unreachable(), node, control);
    1537             : 
    1538             :       // Insert unreachable node and replace all the effect uses of the {node}
    1539             :       // with the new unreachable node.
    1540        7670 :       for (Edge edge : node->use_edges()) {
    1541        2800 :         if (!NodeProperties::IsEffectEdge(edge)) continue;
    1542             :         // Make sure to not overwrite the unreachable node's input. That would
    1543             :         // create a cycle.
    1544        4154 :         if (edge.from() == unreachable) continue;
    1545             :         // Avoid messing up the exceptional path.
    1546        2084 :         if (edge.from()->opcode() == IrOpcode::kIfException) {
    1547             :           DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
    1548             :           DCHECK_EQ(NodeProperties::GetControlInput(edge.from()), node);
    1549             :           continue;
    1550             :         }
    1551             : 
    1552        1035 :         edge.UpdateTo(unreachable);
    1553             :       }
    1554             :     }
    1555    31309706 :   }
    1556             : 
    1557      427483 :   void VisitCheckBounds(Node* node, SimplifiedLowering* lowering) {
    1558      186587 :     CheckParameters const& p = CheckParametersOf(node->op());
    1559      186587 :     Type const index_type = TypeOf(node->InputAt(0));
    1560      186587 :     Type const length_type = TypeOf(node->InputAt(1));
    1561      186587 :     if (length_type.Is(Type::Unsigned31())) {
    1562      186045 :       if (index_type.Is(Type::Integral32OrMinusZero())) {
    1563             :         // Map -0 to 0, and the values in the [-2^31,-1] range to the
    1564             :         // [2^31,2^32-1] range, which will be considered out-of-bounds
    1565             :         // as well, because the {length_type} is limited to Unsigned31.
    1566             :         VisitBinop(node, UseInfo::TruncatingWord32(),
    1567             :                    MachineRepresentation::kWord32);
    1568      170853 :         if (lower()) {
    1569             :           CheckBoundsParameters::Mode mode =
    1570             :               CheckBoundsParameters::kDeoptOnOutOfBounds;
    1571      102552 :           if (lowering->poisoning_level_ ==
    1572      102552 :                   PoisoningMitigationLevel::kDontPoison &&
    1573      102552 :               (index_type.IsNone() || length_type.IsNone() ||
    1574       99195 :                (index_type.Min() >= 0.0 &&
    1575       47919 :                 index_type.Max() < length_type.Min()))) {
    1576             :             // The bounds check is redundant if we already know that
    1577             :             // the index is within the bounds of [0.0, length[.
    1578             :             mode = CheckBoundsParameters::kAbortOnOutOfBounds;
    1579             :           }
    1580             :           NodeProperties::ChangeOp(
    1581      102552 :               node, simplified()->CheckedUint32Bounds(p.feedback(), mode));
    1582             :         }
    1583             :       } else {
    1584             :         VisitBinop(
    1585             :             node,
    1586             :             UseInfo::CheckedSigned32AsWord32(kIdentifyZeros, p.feedback()),
    1587       15192 :             UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
    1588       15192 :         if (lower()) {
    1589             :           NodeProperties::ChangeOp(
    1590             :               node,
    1591             :               simplified()->CheckedUint32Bounds(
    1592        5714 :                   p.feedback(), CheckBoundsParameters::kDeoptOnOutOfBounds));
    1593             :         }
    1594             :       }
    1595             :     } else {
    1596             :       DCHECK(length_type.Is(type_cache_->kPositiveSafeInteger));
    1597             :       VisitBinop(node,
    1598             :                  UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, p.feedback()),
    1599         542 :                  UseInfo::Word64(), MachineRepresentation::kWord64);
    1600         542 :       if (lower()) {
    1601             :         NodeProperties::ChangeOp(
    1602         352 :             node, simplified()->CheckedUint64Bounds(p.feedback()));
    1603             :       }
    1604             :     }
    1605      186587 :   }
    1606             : 
    1607             :   // Dispatching routine for visiting the node {node} with the usage {use}.
    1608             :   // Depending on the operator, propagate new usage info to the inputs.
    1609   199757360 :   void VisitNode(Node* node, Truncation truncation,
    1610   114262661 :                  SimplifiedLowering* lowering) {
    1611             :     // Unconditionally eliminate unused pure nodes (only relevant if there's
    1612             :     // a pure operation in between two effectful ones, where the last one
    1613             :     // is unused).
    1614             :     // Note: We must not do this for constants, as they are cached and we
    1615             :     // would thus kill the cached {node} during lowering (i.e. replace all
    1616             :     // uses with Dead), but at that point some node lowering might have
    1617             :     // already taken the constant {node} from the cache (while it was in
    1618             :     // a sane state still) and we would afterwards replace that use with
    1619             :     // Dead as well.
    1620   260949294 :     if (node->op()->ValueInputCount() > 0 &&
    1621   137728267 :         node->op()->HasProperty(Operator::kPure) && truncation.IsUnused()) {
    1622      108453 :       return VisitUnused(node);
    1623             :     }
    1624             : 
    1625    99648365 :     if (lower()) InsertUnreachableIfNecessary(node);
    1626             : 
    1627    99655923 :     switch (node->opcode()) {
    1628             :       //------------------------------------------------------------------
    1629             :       // Common operators.
    1630             :       //------------------------------------------------------------------
    1631             :       case IrOpcode::kStart:
    1632             :         // We use Start as a terminator for the frame state chain, so even
    1633             :         // tho Start doesn't really produce a value, we have to say Tagged
    1634             :         // here, otherwise the input conversion will fail.
    1635             :         return VisitLeaf(node, MachineRepresentation::kTagged);
    1636             :       case IrOpcode::kParameter:
    1637             :         // TODO(titzer): use representation from linkage.
    1638     5945901 :         return VisitUnop(node, UseInfo::None(), MachineRepresentation::kTagged);
    1639             :       case IrOpcode::kInt32Constant:
    1640             :         return VisitLeaf(node, MachineRepresentation::kWord32);
    1641             :       case IrOpcode::kInt64Constant:
    1642             :         return VisitLeaf(node, MachineRepresentation::kWord64);
    1643             :       case IrOpcode::kExternalConstant:
    1644             :         return VisitLeaf(node, MachineType::PointerRepresentation());
    1645             :       case IrOpcode::kNumberConstant: {
    1646     3781007 :         double const value = OpParameter<double>(node->op());
    1647             :         int value_as_int;
    1648     3781007 :         if (DoubleToSmiInteger(value, &value_as_int)) {
    1649             :           VisitLeaf(node, MachineRepresentation::kTaggedSigned);
    1650     3615414 :           if (lower()) {
    1651     1160980 :             intptr_t smi = bit_cast<intptr_t>(Smi::FromInt(value_as_int));
    1652     1160980 :             DeferReplacement(node, lowering->jsgraph()->IntPtrConstant(smi));
    1653             :           }
    1654             :           return;
    1655             :         }
    1656             :         VisitLeaf(node, MachineRepresentation::kTagged);
    1657             :         return;
    1658             :       }
    1659             :       case IrOpcode::kHeapConstant:
    1660             :       case IrOpcode::kDelayedStringConstant:
    1661             :         return VisitLeaf(node, MachineRepresentation::kTaggedPointer);
    1662             :       case IrOpcode::kPointerConstant: {
    1663             :         VisitLeaf(node, MachineType::PointerRepresentation());
    1664         621 :         if (lower()) {
    1665         207 :           intptr_t const value = OpParameter<intptr_t>(node->op());
    1666         207 :           DeferReplacement(node, lowering->jsgraph()->IntPtrConstant(value));
    1667             :         }
    1668             :         return;
    1669             :       }
    1670             : 
    1671             :       case IrOpcode::kBranch: {
    1672             :         DCHECK(TypeOf(node->InputAt(0)).Is(Type::Boolean()));
    1673     1826331 :         ProcessInput(node, 0, UseInfo::Bool());
    1674     1826304 :         EnqueueInput(node, NodeProperties::FirstControlIndex(node));
    1675     1826301 :         return;
    1676             :       }
    1677             :       case IrOpcode::kSwitch:
    1678       21941 :         ProcessInput(node, 0, UseInfo::TruncatingWord32());
    1679       21941 :         EnqueueInput(node, NodeProperties::FirstControlIndex(node));
    1680       21941 :         return;
    1681             :       case IrOpcode::kSelect:
    1682       38198 :         return VisitSelect(node, truncation, lowering);
    1683             :       case IrOpcode::kPhi:
    1684     1530300 :         return VisitPhi(node, truncation, lowering);
    1685             :       case IrOpcode::kCall:
    1686      334837 :         return VisitCall(node, lowering);
    1687             : 
    1688             :       //------------------------------------------------------------------
    1689             :       // JavaScript operators.
    1690             :       //------------------------------------------------------------------
    1691             :       case IrOpcode::kToBoolean: {
    1692      151150 :         if (truncation.IsUsedAsBool()) {
    1693      150541 :           ProcessInput(node, 0, UseInfo::Bool());
    1694             :           SetOutput(node, MachineRepresentation::kBit);
    1695      198254 :           if (lower()) DeferReplacement(node, node->InputAt(0));
    1696             :         } else {
    1697         609 :           VisitInputs(node);
    1698             :           SetOutput(node, MachineRepresentation::kTaggedPointer);
    1699             :         }
    1700             :         return;
    1701             :       }
    1702             :       case IrOpcode::kJSToNumber:
    1703             :       case IrOpcode::kJSToNumberConvertBigInt:
    1704             :       case IrOpcode::kJSToNumeric: {
    1705       33400 :         VisitInputs(node);
    1706             :         // TODO(bmeurer): Optimize somewhat based on input type?
    1707       33400 :         if (truncation.IsUsedAsWord32()) {
    1708             :           SetOutput(node, MachineRepresentation::kWord32);
    1709         335 :           if (lower())
    1710          75 :             lowering->DoJSToNumberOrNumericTruncatesToWord32(node, this);
    1711       33065 :         } else if (truncation.IsUsedAsFloat64()) {
    1712             :           SetOutput(node, MachineRepresentation::kFloat64);
    1713        4986 :           if (lower())
    1714        1413 :             lowering->DoJSToNumberOrNumericTruncatesToFloat64(node, this);
    1715             :         } else {
    1716             :           SetOutput(node, MachineRepresentation::kTagged);
    1717             :         }
    1718             :         return;
    1719             :       }
    1720             : 
    1721             :       //------------------------------------------------------------------
    1722             :       // Simplified operators.
    1723             :       //------------------------------------------------------------------
    1724             :       case IrOpcode::kBooleanNot: {
    1725        9473 :         if (lower()) {
    1726        3053 :           NodeInfo* input_info = GetInfo(node->InputAt(0));
    1727        3053 :           if (input_info->representation() == MachineRepresentation::kBit) {
    1728             :             // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
    1729     1319668 :             node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
    1730        2026 :             NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
    1731        1027 :           } else if (CanBeTaggedPointer(input_info->representation())) {
    1732             :             // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
    1733        2054 :             node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
    1734        1027 :             NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
    1735             :           } else {
    1736             :             DCHECK(TypeOf(node->InputAt(0)).IsNone());
    1737           0 :             DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
    1738             :           }
    1739             :         } else {
    1740             :           // No input representation requirement; adapt during lowering.
    1741        6420 :           ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
    1742             :           SetOutput(node, MachineRepresentation::kBit);
    1743             :         }
    1744             :         return;
    1745             :       }
    1746             :       case IrOpcode::kNumberEqual: {
    1747      158693 :         Type const lhs_type = TypeOf(node->InputAt(0));
    1748      158693 :         Type const rhs_type = TypeOf(node->InputAt(1));
    1749             :         // Regular number comparisons in JavaScript generally identify zeros,
    1750             :         // so we always pass kIdentifyZeros for the inputs, and in addition
    1751             :         // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs.
    1752             :         // For equality we also handle the case that one side is non-zero, in
    1753             :         // which case we allow to truncate NaN to 0 on the other side.
    1754      216082 :         if ((lhs_type.Is(Type::Unsigned32OrMinusZero()) &&
    1755      260107 :              rhs_type.Is(Type::Unsigned32OrMinusZero())) ||
    1756         146 :             (lhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
    1757          36 :              rhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
    1758          36 :              OneInputCannotBe(node, type_cache_->kZeroish))) {
    1759             :           // => unsigned Int32Cmp
    1760             :           VisitBinop(node, UseInfo::TruncatingWord32(),
    1761             :                      MachineRepresentation::kBit);
    1762       70912 :           if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
    1763             :           return;
    1764             :         }
    1765      122368 :         if ((lhs_type.Is(Type::Signed32OrMinusZero()) &&
    1766      181903 :              rhs_type.Is(Type::Signed32OrMinusZero())) ||
    1767          65 :             (lhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) &&
    1768          36 :              rhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) &&
    1769          36 :              OneInputCannotBe(node, type_cache_->kZeroish))) {
    1770             :           // => signed Int32Cmp
    1771             :           VisitBinop(node, UseInfo::TruncatingWord32(),
    1772             :                      MachineRepresentation::kBit);
    1773       27542 :           if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
    1774             :           return;
    1775             :         }
    1776             :         // => Float64Cmp
    1777             :         VisitBinop(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
    1778             :                    MachineRepresentation::kBit);
    1779       89019 :         if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
    1780             :         return;
    1781             :       }
    1782             :       case IrOpcode::kNumberLessThan:
    1783             :       case IrOpcode::kNumberLessThanOrEqual: {
    1784      160992 :         Type const lhs_type = TypeOf(node->InputAt(0));
    1785      160992 :         Type const rhs_type = TypeOf(node->InputAt(1));
    1786             :         // Regular number comparisons in JavaScript generally identify zeros,
    1787             :         // so we always pass kIdentifyZeros for the inputs, and in addition
    1788             :         // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs.
    1789      260761 :         if (lhs_type.Is(Type::Unsigned32OrMinusZero()) &&
    1790             :             rhs_type.Is(Type::Unsigned32OrMinusZero())) {
    1791             :           // => unsigned Int32Cmp
    1792             :           VisitBinop(node, UseInfo::TruncatingWord32(),
    1793             :                      MachineRepresentation::kBit);
    1794      111062 :           if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
    1795       85408 :         } else if (lhs_type.Is(Type::Signed32OrMinusZero()) &&
    1796             :                    rhs_type.Is(Type::Signed32OrMinusZero())) {
    1797             :           // => signed Int32Cmp
    1798             :           VisitBinop(node, UseInfo::TruncatingWord32(),
    1799             :                      MachineRepresentation::kBit);
    1800       14171 :           if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
    1801             :         } else {
    1802             :           // => Float64Cmp
    1803             :           VisitBinop(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
    1804             :                      MachineRepresentation::kBit);
    1805       62463 :           if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
    1806             :         }
    1807             :         return;
    1808             :       }
    1809             : 
    1810             :       case IrOpcode::kSpeculativeSafeIntegerAdd:
    1811             :       case IrOpcode::kSpeculativeSafeIntegerSubtract:
    1812      801309 :         return VisitSpeculativeIntegerAdditiveOp(node, truncation, lowering);
    1813             : 
    1814             :       case IrOpcode::kSpeculativeNumberAdd:
    1815             :       case IrOpcode::kSpeculativeNumberSubtract:
    1816        3906 :         return VisitSpeculativeAdditiveOp(node, truncation, lowering);
    1817             : 
    1818             :       case IrOpcode::kSpeculativeNumberLessThan:
    1819             :       case IrOpcode::kSpeculativeNumberLessThanOrEqual:
    1820             :       case IrOpcode::kSpeculativeNumberEqual: {
    1821      393628 :         Type const lhs_type = TypeOf(node->InputAt(0));
    1822      393628 :         Type const rhs_type = TypeOf(node->InputAt(1));
    1823             :         // Regular number comparisons in JavaScript generally identify zeros,
    1824             :         // so we always pass kIdentifyZeros for the inputs, and in addition
    1825             :         // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs.
    1826      666835 :         if (lhs_type.Is(Type::Unsigned32OrMinusZero()) &&
    1827             :             rhs_type.Is(Type::Unsigned32OrMinusZero())) {
    1828             :           // => unsigned Int32Cmp
    1829             :           VisitBinop(node, UseInfo::TruncatingWord32(),
    1830             :                      MachineRepresentation::kBit);
    1831        6846 :           if (lower()) ChangeToPureOp(node, Uint32Op(node));
    1832             :           return;
    1833      671091 :         } else if (lhs_type.Is(Type::Signed32OrMinusZero()) &&
    1834             :                    rhs_type.Is(Type::Signed32OrMinusZero())) {
    1835             :           // => signed Int32Cmp
    1836             :           VisitBinop(node, UseInfo::TruncatingWord32(),
    1837             :                      MachineRepresentation::kBit);
    1838      248154 :           if (lower()) ChangeToPureOp(node, Int32Op(node));
    1839             :           return;
    1840             :         }
    1841             :         // Try to use type feedback.
    1842      202596 :         NumberOperationHint hint = NumberOperationHintOf(node->op());
    1843      202596 :         switch (hint) {
    1844             :           case NumberOperationHint::kSigned32:
    1845             :           case NumberOperationHint::kSignedSmall:
    1846      162668 :             if (propagate()) {
    1847             :               VisitBinop(node,
    1848             :                          CheckedUseInfoAsWord32FromHint(hint, VectorSlotPair(),
    1849             :                                                         kIdentifyZeros),
    1850      235371 :                          MachineRepresentation::kBit);
    1851       44981 :             } else if (retype()) {
    1852             :               SetOutput(node, MachineRepresentation::kBit, Type::Any());
    1853             :             } else {
    1854             :               DCHECK(lower());
    1855             :               Node* lhs = node->InputAt(0);
    1856             :               Node* rhs = node->InputAt(1);
    1857       32626 :               if (IsNodeRepresentationTagged(lhs) &&
    1858             :                   IsNodeRepresentationTagged(rhs)) {
    1859             :                 VisitBinop(node,
    1860             :                            UseInfo::CheckedSignedSmallAsTaggedSigned(
    1861             :                                VectorSlotPair(), kIdentifyZeros),
    1862       29436 :                            MachineRepresentation::kBit);
    1863             :                 ChangeToPureOp(
    1864       14718 :                     node, changer_->TaggedSignedOperatorFor(node->opcode()));
    1865             : 
    1866             :               } else {
    1867             :                 VisitBinop(node,
    1868             :                            CheckedUseInfoAsWord32FromHint(
    1869             :                                hint, VectorSlotPair(), kIdentifyZeros),
    1870        5384 :                            MachineRepresentation::kBit);
    1871        2692 :                 ChangeToPureOp(node, Int32Op(node));
    1872             :               }
    1873             :             }
    1874             :             return;
    1875             :           case NumberOperationHint::kSignedSmallInputs:
    1876             :             // This doesn't make sense for compare operations.
    1877           0 :             UNREACHABLE();
    1878             :           case NumberOperationHint::kNumberOrOddball:
    1879             :             // Abstract and strict equality don't perform ToNumber conversions
    1880             :             // on Oddballs, so make sure we don't accidentially sneak in a
    1881             :             // hint with Oddball feedback here.
    1882             :             DCHECK_NE(IrOpcode::kSpeculativeNumberEqual, node->opcode());
    1883             :             V8_FALLTHROUGH;
    1884             :           case NumberOperationHint::kNumber:
    1885             :             VisitBinop(node,
    1886             :                        CheckedUseInfoAsFloat64FromHint(hint, VectorSlotPair(),
    1887             :                                                        kIdentifyZeros),
    1888       79856 :                        MachineRepresentation::kBit);
    1889       49373 :             if (lower()) ChangeToPureOp(node, Float64Op(node));
    1890             :             return;
    1891             :         }
    1892           0 :         UNREACHABLE();
    1893             :         return;
    1894             :       }
    1895             : 
    1896             :       case IrOpcode::kNumberAdd:
    1897             :       case IrOpcode::kNumberSubtract: {
    1898      774132 :         if (TypeOf(node->InputAt(0))
    1899     2854690 :                 .Is(type_cache_->kAdditiveSafeIntegerOrMinusZero) &&
    1900             :             TypeOf(node->InputAt(1))
    1901     2516236 :                 .Is(type_cache_->kAdditiveSafeIntegerOrMinusZero) &&
    1902     1489977 :             (TypeOf(node).Is(Type::Signed32()) ||
    1903      545974 :              TypeOf(node).Is(Type::Unsigned32()) ||
    1904             :              truncation.IsUsedAsWord32())) {
    1905             :           // => Int32Add/Sub
    1906      171831 :           VisitWord32TruncatingBinop(node);
    1907      210432 :           if (lower()) ChangeToPureOp(node, Int32Op(node));
    1908     2406145 :         } else if (jsgraph_->machine()->Is64() &&
    1909      605338 :                    BothInputsAre(node, type_cache_->kSafeInteger) &&
    1910      608368 :                    GetUpperBound(node).Is(type_cache_->kSafeInteger)) {
    1911             :           // => Int64Add/Sub
    1912        3012 :           VisitInt64Binop(node);
    1913        3939 :           if (lower()) ChangeToPureOp(node, Int64Op(node));
    1914             :         } else {
    1915             :           // => Float64Add/Sub
    1916      599282 :           VisitFloat64Binop(node);
    1917      674621 :           if (lower()) ChangeToPureOp(node, Float64Op(node));
    1918             :         }
    1919             :         return;
    1920             :       }
    1921             :       case IrOpcode::kSpeculativeNumberMultiply: {
    1922      123444 :         if (BothInputsAre(node, Type::Integral32()) &&
    1923       53487 :             (NodeProperties::GetType(node).Is(Type::Signed32()) ||
    1924       47594 :              NodeProperties::GetType(node).Is(Type::Unsigned32()) ||
    1925         351 :              (truncation.IsUsedAsWord32() &&
    1926             :               NodeProperties::GetType(node).Is(
    1927       41499 :                   type_cache_->kSafeIntegerOrMinusZero)))) {
    1928             :           // Multiply reduces to Int32Mul if the inputs are integers, and
    1929             :           // (a) the output is either known to be Signed32, or
    1930             :           // (b) the output is known to be Unsigned32, or
    1931             :           // (c) the uses are truncating and the result is in the safe
    1932             :           //     integer range.
    1933        1602 :           VisitWord32TruncatingBinop(node);
    1934        2021 :           if (lower()) ChangeToPureOp(node, Int32Op(node));
    1935             :           return;
    1936             :         }
    1937             :         // Try to use type feedback.
    1938       39546 :         NumberOperationHint hint = NumberOperationHintOf(node->op());
    1939       39546 :         Type input0_type = TypeOf(node->InputAt(0));
    1940       39546 :         Type input1_type = TypeOf(node->InputAt(1));
    1941             : 
    1942             :         // Handle the case when no int32 checks on inputs are necessary
    1943             :         // (but an overflow check is needed on the output).
    1944       39546 :         if (BothInputsAre(node, Type::Signed32())) {
    1945             :           // If both inputs and feedback are int32, use the overflow op.
    1946        5912 :           if (hint == NumberOperationHint::kSignedSmall ||
    1947        2956 :               hint == NumberOperationHint::kSigned32) {
    1948             :             VisitBinop(node, UseInfo::TruncatingWord32(),
    1949             :                        MachineRepresentation::kWord32, Type::Signed32());
    1950        2956 :             if (lower()) {
    1951             :               LowerToCheckedInt32Mul(node, truncation, input0_type,
    1952         947 :                                      input1_type);
    1953             :             }
    1954             :             return;
    1955             :           }
    1956             :         }
    1957             : 
    1958       73180 :         if (hint == NumberOperationHint::kSignedSmall ||
    1959       36590 :             hint == NumberOperationHint::kSigned32) {
    1960             :           VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
    1961       33536 :                      MachineRepresentation::kWord32, Type::Signed32());
    1962       16768 :           if (lower()) {
    1963        5043 :             LowerToCheckedInt32Mul(node, truncation, input0_type, input1_type);
    1964             :           }
    1965             :           return;
    1966             :         }
    1967             : 
    1968             :         // Checked float64 x float64 => float64
    1969             :         VisitBinop(node,
    1970             :                    UseInfo::CheckedNumberOrOddballAsFloat64(kDistinguishZeros,
    1971             :                                                             VectorSlotPair()),
    1972       39644 :                    MachineRepresentation::kFloat64, Type::Number());
    1973       25433 :         if (lower()) ChangeToPureOp(node, Float64Op(node));
    1974             :         return;
    1975             :       }
    1976             :       case IrOpcode::kNumberMultiply: {
    1977       65382 :         if (TypeOf(node->InputAt(0)).Is(Type::Integral32()) &&
    1978       71179 :             TypeOf(node->InputAt(1)).Is(Type::Integral32()) &&
    1979       38130 :             (TypeOf(node).Is(Type::Signed32()) ||
    1980       36419 :              TypeOf(node).Is(Type::Unsigned32()) ||
    1981         955 :              (truncation.IsUsedAsWord32() &&
    1982       30136 :               TypeOf(node).Is(type_cache_->kSafeIntegerOrMinusZero)))) {
    1983             :           // Multiply reduces to Int32Mul if the inputs are integers, and
    1984             :           // (a) the output is either known to be Signed32, or
    1985             :           // (b) the output is known to be Unsigned32, or
    1986             :           // (c) the uses are truncating and the result is in the safe
    1987             :           //     integer range.
    1988        2262 :           VisitWord32TruncatingBinop(node);
    1989        2727 :           if (lower()) ChangeToPureOp(node, Int32Op(node));
    1990             :           return;
    1991             :         }
    1992             :         // Number x Number => Float64Mul
    1993       25964 :         VisitFloat64Binop(node);
    1994       33217 :         if (lower()) ChangeToPureOp(node, Float64Op(node));
    1995             :         return;
    1996             :       }
    1997             :       case IrOpcode::kSpeculativeNumberDivide: {
    1998       57182 :         if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) {
    1999             :           // => unsigned Uint32Div
    2000         556 :           VisitWord32TruncatingBinop(node);
    2001         556 :           if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
    2002             :           return;
    2003             :         }
    2004       49964 :         if (BothInputsAreSigned32(node)) {
    2005       28342 :           if (NodeProperties::GetType(node).Is(Type::Signed32())) {
    2006             :             // => signed Int32Div
    2007           0 :             VisitWord32TruncatingBinop(node);
    2008           0 :             if (lower()) DeferReplacement(node, lowering->Int32Div(node));
    2009             :             return;
    2010             :           }
    2011       14171 :           if (truncation.IsUsedAsWord32()) {
    2012             :             // => signed Int32Div
    2013        6042 :             VisitWord32TruncatingBinop(node);
    2014        6042 :             if (lower()) DeferReplacement(node, lowering->Int32Div(node));
    2015             :             return;
    2016             :           }
    2017             :         }
    2018             : 
    2019             :         // Try to use type feedback.
    2020       43922 :         NumberOperationHint hint = NumberOperationHintOf(node->op());
    2021             : 
    2022             :         // Handle the case when no uint32 checks on inputs are necessary
    2023             :         // (but an overflow check is needed on the output).
    2024       43922 :         if (BothInputsAreUnsigned32(node)) {
    2025       12212 :           if (hint == NumberOperationHint::kSignedSmall ||
    2026        6106 :               hint == NumberOperationHint::kSigned32) {
    2027             :             VisitBinop(node, UseInfo::TruncatingWord32(),
    2028             :                        MachineRepresentation::kWord32, Type::Unsigned32());
    2029         253 :             if (lower()) ChangeToUint32OverflowOp(node);
    2030             :             return;
    2031             :           }
    2032             :         }
    2033             : 
    2034             :         // Handle the case when no int32 checks on inputs are necessary
    2035             :         // (but an overflow check is needed on the output).
    2036       43669 :         if (BothInputsAreSigned32(node)) {
    2037             :           // If both the inputs the feedback are int32, use the overflow op.
    2038       15776 :           if (hint == NumberOperationHint::kSignedSmall ||
    2039        7888 :               hint == NumberOperationHint::kSigned32) {
    2040             :             VisitBinop(node, UseInfo::TruncatingWord32(),
    2041             :                        MachineRepresentation::kWord32, Type::Signed32());
    2042          12 :             if (lower()) ChangeToInt32OverflowOp(node);
    2043             :             return;
    2044             :           }
    2045             :         }
    2046             : 
    2047       87314 :         if (hint == NumberOperationHint::kSigned32 ||
    2048       86403 :             hint == NumberOperationHint::kSignedSmall ||
    2049             :             hint == NumberOperationHint::kSignedSmallInputs) {
    2050             :           // If the result is truncated, we only need to check the inputs.
    2051       37167 :           if (truncation.IsUsedAsWord32()) {
    2052             :             VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
    2053        4734 :                        MachineRepresentation::kWord32);
    2054        2367 :             if (lower()) DeferReplacement(node, lowering->Int32Div(node));
    2055             :             return;
    2056       34800 :           } else if (hint != NumberOperationHint::kSignedSmallInputs) {
    2057             :             VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
    2058        1628 :                        MachineRepresentation::kWord32, Type::Signed32());
    2059         814 :             if (lower()) ChangeToInt32OverflowOp(node);
    2060             :             return;
    2061             :           }
    2062             :         }
    2063             : 
    2064             :         // default case => Float64Div
    2065             :         VisitBinop(node,
    2066             :                    UseInfo::CheckedNumberOrOddballAsFloat64(kDistinguishZeros,
    2067             :                                                             VectorSlotPair()),
    2068       80952 :                    MachineRepresentation::kFloat64, Type::Number());
    2069       52204 :         if (lower()) ChangeToPureOp(node, Float64Op(node));
    2070             :         return;
    2071             :       }
    2072             :       case IrOpcode::kNumberDivide: {
    2073       45886 :         if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) &&
    2074       46887 :             TypeOf(node->InputAt(1)).Is(Type::Unsigned32()) &&
    2075         784 :             (truncation.IsUsedAsWord32() ||
    2076       18803 :              TypeOf(node).Is(Type::Unsigned32()))) {
    2077             :           // => unsigned Uint32Div
    2078         217 :           VisitWord32TruncatingBinop(node);
    2079         217 :           if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
    2080             :           return;
    2081             :         }
    2082       46671 :         if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) &&
    2083       49026 :             TypeOf(node->InputAt(1)).Is(Type::Signed32()) &&
    2084        2042 :             (truncation.IsUsedAsWord32() ||
    2085       19844 :              TypeOf(node).Is(Type::Signed32()))) {
    2086             :           // => signed Int32Div
    2087         313 :           VisitWord32TruncatingBinop(node);
    2088         313 :           if (lower()) DeferReplacement(node, lowering->Int32Div(node));
    2089             :           return;
    2090             :         }
    2091             :         // Number x Number => Float64Div
    2092       17489 :         VisitFloat64Binop(node);
    2093       22028 :         if (lower()) ChangeToPureOp(node, Float64Op(node));
    2094             :         return;
    2095             :       }
    2096             :       case IrOpcode::kSpeculativeNumberModulus:
    2097       12542 :         return VisitSpeculativeNumberModulus(node, truncation, lowering);
    2098             :       case IrOpcode::kNumberModulus: {
    2099        7225 :         Type const lhs_type = TypeOf(node->InputAt(0));
    2100        7225 :         Type const rhs_type = TypeOf(node->InputAt(1));
    2101       15320 :         if ((lhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
    2102        7688 :              rhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN())) &&
    2103         237 :             (truncation.IsUsedAsWord32() ||
    2104        7699 :              TypeOf(node).Is(Type::Unsigned32()))) {
    2105             :           // => unsigned Uint32Mod
    2106         402 :           VisitWord32TruncatingBinop(node);
    2107         402 :           if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
    2108             :           return;
    2109             :         }
    2110       15404 :         if ((lhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) &&
    2111        8071 :              rhs_type.Is(Type::Signed32OrMinusZeroOrNaN())) &&
    2112        9352 :             (truncation.IsUsedAsWord32() || TypeOf(node).Is(Type::Signed32()) ||
    2113          79 :              (truncation.IdentifiesZeroAndMinusZero() &&
    2114        6902 :               TypeOf(node).Is(Type::Signed32OrMinusZero())))) {
    2115             :           // => signed Int32Mod
    2116         483 :           VisitWord32TruncatingBinop(node);
    2117         483 :           if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
    2118             :           return;
    2119             :         }
    2120             :         // => Float64Mod
    2121             :         // For the left hand side we just propagate the identify zeros
    2122             :         // mode of the {truncation}; and for modulus the sign of the
    2123             :         // right hand side doesn't matter anyways, so in particular there's
    2124             :         // no observable difference between a 0 and a -0 then.
    2125             :         UseInfo const lhs_use =
    2126             :             UseInfo::TruncatingFloat64(truncation.identify_zeros());
    2127             :         UseInfo const rhs_use = UseInfo::TruncatingFloat64(kIdentifyZeros);
    2128        6340 :         VisitBinop(node, lhs_use, rhs_use, MachineRepresentation::kFloat64);
    2129        7950 :         if (lower()) ChangeToPureOp(node, Float64Op(node));
    2130             :         return;
    2131             :       }
    2132             :       case IrOpcode::kNumberBitwiseOr:
    2133             :       case IrOpcode::kNumberBitwiseXor:
    2134             :       case IrOpcode::kNumberBitwiseAnd: {
    2135       33613 :         VisitWord32TruncatingBinop(node);
    2136       44207 :         if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
    2137             :         return;
    2138             :       }
    2139             :       case IrOpcode::kSpeculativeNumberBitwiseOr:
    2140             :       case IrOpcode::kSpeculativeNumberBitwiseXor:
    2141             :       case IrOpcode::kSpeculativeNumberBitwiseAnd:
    2142       83559 :         VisitSpeculativeInt32Binop(node);
    2143       83559 :         if (lower()) {
    2144       22842 :           ChangeToPureOp(node, Int32Op(node));
    2145             :         }
    2146             :         return;
    2147             :       case IrOpcode::kNumberShiftLeft: {
    2148        5476 :         Type rhs_type = GetUpperBound(node->InputAt(1));
    2149             :         VisitBinop(node, UseInfo::TruncatingWord32(),
    2150        5476 :                    UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
    2151        5476 :         if (lower()) {
    2152        1621 :           MaskShiftOperand(node, rhs_type);
    2153        1621 :           ChangeToPureOp(node, lowering->machine()->Word32Shl());
    2154             :         }
    2155             :         return;
    2156             :       }
    2157             :       case IrOpcode::kSpeculativeNumberShiftLeft: {
    2158        8122 :         if (BothInputsAre(node, Type::NumberOrOddball())) {
    2159        7326 :           Type rhs_type = GetUpperBound(node->InputAt(1));
    2160             :           VisitBinop(node, UseInfo::TruncatingWord32(),
    2161             :                      UseInfo::TruncatingWord32(),
    2162        7326 :                      MachineRepresentation::kWord32);
    2163        7326 :           if (lower()) {
    2164        1837 :             MaskShiftOperand(node, rhs_type);
    2165        1837 :             ChangeToPureOp(node, lowering->machine()->Word32Shl());
    2166             :           }
    2167             :           return;
    2168             :         }
    2169         796 :         NumberOperationHint hint = NumberOperationHintOf(node->op());
    2170         796 :         Type rhs_type = GetUpperBound(node->InputAt(1));
    2171             :         VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
    2172        1592 :                    MachineRepresentation::kWord32, Type::Signed32());
    2173         796 :         if (lower()) {
    2174         251 :           MaskShiftOperand(node, rhs_type);
    2175         251 :           ChangeToPureOp(node, lowering->machine()->Word32Shl());
    2176             :         }
    2177             :         return;
    2178             :       }
    2179             :       case IrOpcode::kNumberShiftRight: {
    2180        4874 :         Type rhs_type = GetUpperBound(node->InputAt(1));
    2181             :         VisitBinop(node, UseInfo::TruncatingWord32(),
    2182        4874 :                    UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
    2183        4874 :         if (lower()) {
    2184        1440 :           MaskShiftOperand(node, rhs_type);
    2185        1440 :           ChangeToPureOp(node, lowering->machine()->Word32Sar());
    2186             :         }
    2187             :         return;
    2188             :       }
    2189             :       case IrOpcode::kSpeculativeNumberShiftRight: {
    2190       22472 :         if (BothInputsAre(node, Type::NumberOrOddball())) {
    2191       21203 :           Type rhs_type = GetUpperBound(node->InputAt(1));
    2192             :           VisitBinop(node, UseInfo::TruncatingWord32(),
    2193             :                      UseInfo::TruncatingWord32(),
    2194       21203 :                      MachineRepresentation::kWord32);
    2195       21203 :           if (lower()) {
    2196        5098 :             MaskShiftOperand(node, rhs_type);
    2197        5098 :             ChangeToPureOp(node, lowering->machine()->Word32Sar());
    2198             :           }
    2199             :           return;
    2200             :         }
    2201        1269 :         NumberOperationHint hint = NumberOperationHintOf(node->op());
    2202        1269 :         Type rhs_type = GetUpperBound(node->InputAt(1));
    2203             :         VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
    2204        2538 :                    MachineRepresentation::kWord32, Type::Signed32());
    2205        1269 :         if (lower()) {
    2206         389 :           MaskShiftOperand(node, rhs_type);
    2207         389 :           ChangeToPureOp(node, lowering->machine()->Word32Sar());
    2208             :         }
    2209             :         return;
    2210             :       }
    2211             :       case IrOpcode::kNumberShiftRightLogical: {
    2212        5286 :         Type rhs_type = GetUpperBound(node->InputAt(1));
    2213             :         VisitBinop(node, UseInfo::TruncatingWord32(),
    2214        5286 :                    UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
    2215        5286 :         if (lower()) {
    2216        1570 :           MaskShiftOperand(node, rhs_type);
    2217        1570 :           ChangeToPureOp(node, lowering->machine()->Word32Shr());
    2218             :         }
    2219             :         return;
    2220             :       }
    2221             :       case IrOpcode::kSpeculativeNumberShiftRightLogical: {
    2222        9018 :         NumberOperationHint hint = NumberOperationHintOf(node->op());
    2223        9018 :         Type rhs_type = GetUpperBound(node->InputAt(1));
    2224       21240 :         if (rhs_type.Is(type_cache_->kZeroish) &&
    2225        6408 :             (hint == NumberOperationHint::kSignedSmall ||
    2226       12876 :              hint == NumberOperationHint::kSigned32) &&
    2227             :             !truncation.IsUsedAsWord32()) {
    2228             :           // The SignedSmall or Signed32 feedback means that the results that we
    2229             :           // have seen so far were of type Unsigned31.  We speculate that this
    2230             :           // will continue to hold.  Moreover, since the RHS is 0, the result
    2231             :           // will just be the (converted) LHS.
    2232             :           VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
    2233         632 :                      MachineRepresentation::kWord32, Type::Unsigned31());
    2234         316 :           if (lower()) {
    2235          89 :             node->RemoveInput(1);
    2236             :             NodeProperties::ChangeOp(
    2237         178 :                 node, simplified()->CheckedUint32ToInt32(VectorSlotPair()));
    2238             :           }
    2239             :           return;
    2240             :         }
    2241        8702 :         if (BothInputsAre(node, Type::NumberOrOddball())) {
    2242             :           VisitBinop(node, UseInfo::TruncatingWord32(),
    2243             :                      UseInfo::TruncatingWord32(),
    2244        7210 :                      MachineRepresentation::kWord32);
    2245        7209 :           if (lower()) {
    2246        1902 :             MaskShiftOperand(node, rhs_type);
    2247        1902 :             ChangeToPureOp(node, lowering->machine()->Word32Shr());
    2248             :           }
    2249             :           return;
    2250             :         }
    2251             :         VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
    2252        2984 :                    MachineRepresentation::kWord32, Type::Unsigned32());
    2253        1492 :         if (lower()) {
    2254         442 :           MaskShiftOperand(node, rhs_type);
    2255         442 :           ChangeToPureOp(node, lowering->machine()->Word32Shr());
    2256             :         }
    2257             :         return;
    2258             :       }
    2259             :       case IrOpcode::kNumberAbs: {
    2260             :         // NumberAbs maps both 0 and -0 to 0, so we can generally
    2261             :         // pass the kIdentifyZeros truncation to its input, and
    2262             :         // choose to ignore minus zero in all cases.
    2263         864 :         Type const input_type = TypeOf(node->InputAt(0));
    2264         864 :         if (input_type.Is(Type::Unsigned32OrMinusZero())) {
    2265             :           VisitUnop(node, UseInfo::TruncatingWord32(),
    2266          35 :                     MachineRepresentation::kWord32);
    2267          49 :           if (lower()) DeferReplacement(node, node->InputAt(0));
    2268         829 :         } else if (input_type.Is(Type::Signed32OrMinusZero())) {
    2269             :           VisitUnop(node, UseInfo::TruncatingWord32(),
    2270         196 :                     MachineRepresentation::kWord32);
    2271         196 :           if (lower()) DeferReplacement(node, lowering->Int32Abs(node));
    2272        1266 :         } else if (input_type.Is(type_cache_->kPositiveIntegerOrNaN)) {
    2273             :           VisitUnop(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
    2274          14 :                     MachineRepresentation::kFloat64);
    2275          21 :           if (lower()) DeferReplacement(node, node->InputAt(0));
    2276             :         } else {
    2277             :           VisitUnop(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
    2278         619 :                     MachineRepresentation::kFloat64);
    2279         803 :           if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
    2280             :         }
    2281             :         return;
    2282             :       }
    2283             :       case IrOpcode::kNumberClz32: {
    2284             :         VisitUnop(node, UseInfo::TruncatingWord32(),
    2285         102 :                   MachineRepresentation::kWord32);
    2286         136 :         if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
    2287             :         return;
    2288             :       }
    2289             :       case IrOpcode::kNumberImul: {
    2290             :         VisitBinop(node, UseInfo::TruncatingWord32(),
    2291        2601 :                    UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
    2292        3468 :         if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
    2293             :         return;
    2294             :       }
    2295             :       case IrOpcode::kNumberFround: {
    2296             :         VisitUnop(node, UseInfo::TruncatingFloat64(),
    2297        3875 :                   MachineRepresentation::kFloat32);
    2298        5158 :         if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
    2299             :         return;
    2300             :       }
    2301             :       case IrOpcode::kNumberMax: {
    2302             :         // It is safe to use the feedback types for left and right hand side
    2303             :         // here, since we can only narrow those types and thus we can only
    2304             :         // promise a more specific truncation.
    2305             :         // For NumberMax we generally propagate whether the truncation
    2306             :         // identifies zeros to the inputs, and we choose to ignore minus
    2307             :         // zero in those cases.
    2308        7434 :         Type const lhs_type = TypeOf(node->InputAt(0));
    2309        7434 :         Type const rhs_type = TypeOf(node->InputAt(1));
    2310       11372 :         if ((lhs_type.Is(Type::Unsigned32()) &&
    2311       11470 :              rhs_type.Is(Type::Unsigned32())) ||
    2312         591 :             (lhs_type.Is(Type::Unsigned32OrMinusZero()) &&
    2313          81 :              rhs_type.Is(Type::Unsigned32OrMinusZero()) &&
    2314             :              truncation.IdentifiesZeroAndMinusZero())) {
    2315        3398 :           VisitWord32TruncatingBinop(node);
    2316        3398 :           if (lower()) {
    2317             :             lowering->DoMax(node, lowering->machine()->Uint32LessThan(),
    2318        1081 :                             MachineRepresentation::kWord32);
    2319             :           }
    2320        7750 :         } else if ((lhs_type.Is(Type::Signed32()) &&
    2321        4863 :                     rhs_type.Is(Type::Signed32())) ||
    2322         556 :                    (lhs_type.Is(Type::Signed32OrMinusZero()) &&
    2323          81 :                     rhs_type.Is(Type::Signed32OrMinusZero()) &&
    2324             :                     truncation.IdentifiesZeroAndMinusZero())) {
    2325        3209 :           VisitWord32TruncatingBinop(node);
    2326        3209 :           if (lower()) {
    2327             :             lowering->DoMax(node, lowering->machine()->Int32LessThan(),
    2328        1045 :                             MachineRepresentation::kWord32);
    2329             :           }
    2330        2481 :         } else if (jsgraph_->machine()->Is64() &&
    2331        1402 :                    lhs_type.Is(type_cache_->kSafeInteger) &&
    2332         575 :                    rhs_type.Is(type_cache_->kSafeInteger)) {
    2333         452 :           VisitInt64Binop(node);
    2334         452 :           if (lower()) {
    2335             :             lowering->DoMax(node, lowering->machine()->Int64LessThan(),
    2336         146 :                             MachineRepresentation::kWord64);
    2337             :           }
    2338             :         } else {
    2339             :           VisitBinop(node,
    2340             :                      UseInfo::TruncatingFloat64(truncation.identify_zeros()),
    2341             :                      MachineRepresentation::kFloat64);
    2342         375 :           if (lower()) {
    2343             :             // If the right hand side is not NaN, and the left hand side
    2344             :             // is not NaN (or -0 if the difference between the zeros is
    2345             :             // observed), we can do a simple floating point comparison here.
    2346         118 :             if (lhs_type.Is(truncation.IdentifiesZeroAndMinusZero()
    2347             :                                 ? Type::OrderedNumber()
    2348         308 :                                 : Type::PlainNumber()) &&
    2349             :                 rhs_type.Is(Type::OrderedNumber())) {
    2350             :               lowering->DoMax(node, lowering->machine()->Float64LessThan(),
    2351          48 :                               MachineRepresentation::kFloat64);
    2352             :             } else {
    2353          70 :               NodeProperties::ChangeOp(node, Float64Op(node));
    2354             :             }
    2355             :           }
    2356             :         }
    2357             :         return;
    2358             :       }
    2359             :       case IrOpcode::kNumberMin: {
    2360             :         // It is safe to use the feedback types for left and right hand side
    2361             :         // here, since we can only narrow those types and thus we can only
    2362             :         // promise a more specific truncation.
    2363             :         // For NumberMin we generally propagate whether the truncation
    2364             :         // identifies zeros to the inputs, and we choose to ignore minus
    2365             :         // zero in those cases.
    2366       10167 :         Type const lhs_type = TypeOf(node->InputAt(0));
    2367       10167 :         Type const rhs_type = TypeOf(node->InputAt(1));
    2368       19728 :         if ((lhs_type.Is(Type::Unsigned32()) &&
    2369       11051 :              rhs_type.Is(Type::Unsigned32())) ||
    2370         329 :             (lhs_type.Is(Type::Unsigned32OrMinusZero()) &&
    2371          81 :              rhs_type.Is(Type::Unsigned32OrMinusZero()) &&
    2372             :              truncation.IdentifiesZeroAndMinusZero())) {
    2373        9283 :           VisitWord32TruncatingBinop(node);
    2374        9283 :           if (lower()) {
    2375             :             lowering->DoMin(node, lowering->machine()->Uint32LessThan(),
    2376        2978 :                             MachineRepresentation::kWord32);
    2377             :           }
    2378        1304 :         } else if ((lhs_type.Is(Type::Signed32()) &&
    2379        1509 :                     rhs_type.Is(Type::Signed32())) ||
    2380         212 :                    (lhs_type.Is(Type::Signed32OrMinusZero()) &&
    2381          81 :                     rhs_type.Is(Type::Signed32OrMinusZero()) &&
    2382             :                     truncation.IdentifiesZeroAndMinusZero())) {
    2383         259 :           VisitWord32TruncatingBinop(node);
    2384         259 :           if (lower()) {
    2385             :             lowering->DoMin(node, lowering->machine()->Int32LessThan(),
    2386          76 :                             MachineRepresentation::kWord32);
    2387             :           }
    2388        1875 :         } else if (jsgraph_->machine()->Is64() &&
    2389         807 :                    lhs_type.Is(type_cache_->kSafeInteger) &&
    2390         182 :                    rhs_type.Is(type_cache_->kSafeInteger)) {
    2391          35 :           VisitInt64Binop(node);
    2392          35 :           if (lower()) {
    2393             :             lowering->DoMin(node, lowering->machine()->Int64LessThan(),
    2394          14 :                             MachineRepresentation::kWord64);
    2395             :           }
    2396             :         } else {
    2397             :           VisitBinop(node,
    2398             :                      UseInfo::TruncatingFloat64(truncation.identify_zeros()),
    2399             :                      MachineRepresentation::kFloat64);
    2400         590 :           if (lower()) {
    2401             :             // If the left hand side is not NaN, and the right hand side
    2402             :             // is not NaN (or -0 if the difference between the zeros is
    2403             :             // observed), we can do a simple floating point comparison here.
    2404         275 :             if (lhs_type.Is(Type::OrderedNumber()) &&
    2405             :                 rhs_type.Is(truncation.IdentifiesZeroAndMinusZero()
    2406             :                                 ? Type::OrderedNumber()
    2407          83 :                                 : Type::PlainNumber())) {
    2408             :               lowering->DoMin(node,
    2409             :                               lowering->machine()->Float64LessThanOrEqual(),
    2410          45 :                               MachineRepresentation::kFloat64);
    2411             :             } else {
    2412         147 :               NodeProperties::ChangeOp(node, Float64Op(node));
    2413             :             }
    2414             :           }
    2415             :         }
    2416             :         return;
    2417             :       }
    2418             :       case IrOpcode::kNumberAtan2:
    2419             :       case IrOpcode::kNumberPow: {
    2420             :         VisitBinop(node, UseInfo::TruncatingFloat64(),
    2421             :                    MachineRepresentation::kFloat64);
    2422        3708 :         if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
    2423             :         return;
    2424             :       }
    2425             :       case IrOpcode::kNumberCeil:
    2426             :       case IrOpcode::kNumberFloor:
    2427             :       case IrOpcode::kNumberRound:
    2428             :       case IrOpcode::kNumberTrunc: {
    2429             :         // For NumberCeil, NumberFloor, NumberRound and NumberTrunc we propagate
    2430             :         // the zero identification part of the truncation, and we turn them into
    2431             :         // no-ops if we figure out (late) that their input is already an
    2432             :         // integer, NaN or -0.
    2433      130034 :         Type const input_type = TypeOf(node->InputAt(0));
    2434             :         VisitUnop(node, UseInfo::TruncatingFloat64(truncation.identify_zeros()),
    2435      130034 :                   MachineRepresentation::kFloat64);
    2436      130034 :         if (lower()) {
    2437       85520 :           if (input_type.Is(type_cache_->kIntegerOrMinusZeroOrNaN)) {
    2438        1242 :             DeferReplacement(node, node->InputAt(0));
    2439       41518 :           } else if (node->opcode() == IrOpcode::kNumberRound) {
    2440        1549 :             DeferReplacement(node, lowering->Float64Round(node));
    2441             :           } else {
    2442       39969 :             NodeProperties::ChangeOp(node, Float64Op(node));
    2443             :           }
    2444             :         }
    2445             :         return;
    2446             :       }
    2447             :       case IrOpcode::kNumberAcos:
    2448             :       case IrOpcode::kNumberAcosh:
    2449             :       case IrOpcode::kNumberAsin:
    2450             :       case IrOpcode::kNumberAsinh:
    2451             :       case IrOpcode::kNumberAtan:
    2452             :       case IrOpcode::kNumberAtanh:
    2453             :       case IrOpcode::kNumberCos:
    2454             :       case IrOpcode::kNumberCosh:
    2455             :       case IrOpcode::kNumberExp:
    2456             :       case IrOpcode::kNumberExpm1:
    2457             :       case IrOpcode::kNumberLog:
    2458             :       case IrOpcode::kNumberLog1p:
    2459             :       case IrOpcode::kNumberLog2:
    2460             :       case IrOpcode::kNumberLog10:
    2461             :       case IrOpcode::kNumberCbrt:
    2462             :       case IrOpcode::kNumberSin:
    2463             :       case IrOpcode::kNumberSinh:
    2464             :       case IrOpcode::kNumberTan:
    2465             :       case IrOpcode::kNumberTanh: {
    2466             :         VisitUnop(node, UseInfo::TruncatingFloat64(),
    2467         942 :                   MachineRepresentation::kFloat64);
    2468        1249 :         if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
    2469             :         return;
    2470             :       }
    2471             :       case IrOpcode::kNumberSign: {
    2472         105 :         if (InputIs(node, Type::Signed32())) {
    2473             :           VisitUnop(node, UseInfo::TruncatingWord32(),
    2474          21 :                     MachineRepresentation::kWord32);
    2475          21 :           if (lower()) DeferReplacement(node, lowering->Int32Sign(node));
    2476             :         } else {
    2477             :           VisitUnop(node, UseInfo::TruncatingFloat64(),
    2478          84 :                     MachineRepresentation::kFloat64);
    2479          84 :           if (lower()) DeferReplacement(node, lowering->Float64Sign(node));
    2480             :         }
    2481             :         return;
    2482             :       }
    2483             :       case IrOpcode::kNumberSilenceNaN: {
    2484        2247 :         Type const input_type = TypeOf(node->InputAt(0));
    2485        2247 :         if (input_type.Is(Type::OrderedNumber())) {
    2486             :           // No need to silence anything if the input cannot be NaN.
    2487             :           VisitUnop(node, UseInfo::TruncatingFloat64(),
    2488          14 :                     MachineRepresentation::kFloat64);
    2489          21 :           if (lower()) DeferReplacement(node, node->InputAt(0));
    2490             :         } else {
    2491             :           VisitUnop(node, UseInfo::TruncatingFloat64(),
    2492        2233 :                     MachineRepresentation::kFloat64);
    2493        2956 :           if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
    2494             :         }
    2495             :         return;
    2496             :       }
    2497             :       case IrOpcode::kNumberSqrt: {
    2498             :         VisitUnop(node, UseInfo::TruncatingFloat64(),
    2499         156 :                   MachineRepresentation::kFloat64);
    2500         207 :         if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
    2501             :         return;
    2502             :       }
    2503             :       case IrOpcode::kNumberToBoolean: {
    2504             :         // For NumberToBoolean we don't care whether the input is 0 or
    2505             :         // -0, since both of them are mapped to false anyways, so we
    2506             :         // can generally pass kIdentifyZeros truncation.
    2507         555 :         Type const input_type = TypeOf(node->InputAt(0));
    2508         555 :         if (input_type.Is(Type::Integral32OrMinusZeroOrNaN())) {
    2509             :           // 0, -0 and NaN all map to false, so we can safely truncate
    2510             :           // all of them to zero here.
    2511             :           VisitUnop(node, UseInfo::TruncatingWord32(),
    2512         303 :                     MachineRepresentation::kBit);
    2513         303 :           if (lower()) lowering->DoIntegral32ToBit(node);
    2514         252 :         } else if (input_type.Is(Type::OrderedNumber())) {
    2515             :           VisitUnop(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
    2516          77 :                     MachineRepresentation::kBit);
    2517          77 :           if (lower()) lowering->DoOrderedNumberToBit(node);
    2518             :         } else {
    2519             :           VisitUnop(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
    2520         175 :                     MachineRepresentation::kBit);
    2521         175 :           if (lower()) lowering->DoNumberToBit(node);
    2522             :         }
    2523             :         return;
    2524             :       }
    2525             :       case IrOpcode::kNumberToInt32: {
    2526             :         // Just change representation if necessary.
    2527             :         VisitUnop(node, UseInfo::TruncatingWord32(),
    2528       16811 :                   MachineRepresentation::kWord32);
    2529       22158 :         if (lower()) DeferReplacement(node, node->InputAt(0));
    2530             :         return;
    2531             :       }
    2532             :       case IrOpcode::kNumberToString: {
    2533             :         VisitUnop(node, UseInfo::AnyTagged(),
    2534       11304 :                   MachineRepresentation::kTaggedPointer);
    2535       11304 :         return;
    2536             :       }
    2537             :       case IrOpcode::kNumberToUint32: {
    2538             :         // Just change representation if necessary.
    2539             :         VisitUnop(node, UseInfo::TruncatingWord32(),
    2540       18132 :                   MachineRepresentation::kWord32);
    2541       24043 :         if (lower()) DeferReplacement(node, node->InputAt(0));
    2542             :         return;
    2543             :       }
    2544             :       case IrOpcode::kNumberToUint8Clamped: {
    2545        1437 :         Type const input_type = TypeOf(node->InputAt(0));
    2546        2874 :         if (input_type.Is(type_cache_->kUint8OrMinusZeroOrNaN)) {
    2547             :           VisitUnop(node, UseInfo::TruncatingWord32(),
    2548          45 :                     MachineRepresentation::kWord32);
    2549          60 :           if (lower()) DeferReplacement(node, node->InputAt(0));
    2550        1392 :         } else if (input_type.Is(Type::Unsigned32OrMinusZeroOrNaN())) {
    2551             :           VisitUnop(node, UseInfo::TruncatingWord32(),
    2552         237 :                     MachineRepresentation::kWord32);
    2553         237 :           if (lower()) lowering->DoUnsigned32ToUint8Clamped(node);
    2554        1155 :         } else if (input_type.Is(Type::Signed32OrMinusZeroOrNaN())) {
    2555             :           VisitUnop(node, UseInfo::TruncatingWord32(),
    2556         213 :                     MachineRepresentation::kWord32);
    2557         213 :           if (lower()) lowering->DoSigned32ToUint8Clamped(node);
    2558        1884 :         } else if (input_type.Is(type_cache_->kIntegerOrMinusZeroOrNaN)) {
    2559             :           VisitUnop(node, UseInfo::TruncatingFloat64(),
    2560          63 :                     MachineRepresentation::kFloat64);
    2561          63 :           if (lower()) lowering->DoIntegerToUint8Clamped(node);
    2562             :         } else {
    2563             :           VisitUnop(node, UseInfo::TruncatingFloat64(),
    2564         879 :                     MachineRepresentation::kFloat64);
    2565         879 :           if (lower()) lowering->DoNumberToUint8Clamped(node);
    2566             :         }
    2567             :         return;
    2568             :       }
    2569             :       case IrOpcode::kReferenceEqual: {
    2570             :         VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
    2571      591718 :         if (lower()) {
    2572      195422 :           NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
    2573             :         }
    2574             :         return;
    2575             :       }
    2576             :       case IrOpcode::kSameValue: {
    2577          30 :         if (truncation.IsUnused()) return VisitUnused(node);
    2578             :         VisitBinop(node, UseInfo::AnyTagged(),
    2579             :                    MachineRepresentation::kTaggedPointer);
    2580             :         return;
    2581             :       }
    2582             :       case IrOpcode::kTypeOf: {
    2583             :         return VisitUnop(node, UseInfo::AnyTagged(),
    2584       66852 :                          MachineRepresentation::kTaggedPointer);
    2585             :       }
    2586             :       case IrOpcode::kNewConsString: {
    2587       15314 :         ProcessInput(node, 0, UseInfo::TruncatingWord32());  // length
    2588       15314 :         ProcessInput(node, 1, UseInfo::AnyTagged());         // first
    2589       15314 :         ProcessInput(node, 2, UseInfo::AnyTagged());         // second
    2590             :         SetOutput(node, MachineRepresentation::kTaggedPointer);
    2591             :         return;
    2592             :       }
    2593             :       case IrOpcode::kStringConcat: {
    2594             :         // TODO(turbofan): We currently depend on having this first length input
    2595             :         // to make sure that the overflow check is properly scheduled before the
    2596             :         // actual string concatenation. We should also use the length to pass it
    2597             :         // to the builtin or decide in optimized code how to construct the
    2598             :         // resulting string (i.e. cons string or sequential string).
    2599       66030 :         ProcessInput(node, 0, UseInfo::TaggedSigned());  // length
    2600       66030 :         ProcessInput(node, 1, UseInfo::AnyTagged());     // first
    2601       66030 :         ProcessInput(node, 2, UseInfo::AnyTagged());     // second
    2602             :         SetOutput(node, MachineRepresentation::kTaggedPointer);
    2603             :         return;
    2604             :       }
    2605             :       case IrOpcode::kStringEqual:
    2606             :       case IrOpcode::kStringLessThan:
    2607             :       case IrOpcode::kStringLessThanOrEqual: {
    2608             :         return VisitBinop(node, UseInfo::AnyTagged(),
    2609             :                           MachineRepresentation::kTaggedPointer);
    2610             :       }
    2611             :       case IrOpcode::kStringCharCodeAt: {
    2612             :         return VisitBinop(node, UseInfo::AnyTagged(), UseInfo::Word(),
    2613        8837 :                           MachineRepresentation::kWord32);
    2614             :       }
    2615             :       case IrOpcode::kStringCodePointAt: {
    2616             :         return VisitBinop(node, UseInfo::AnyTagged(), UseInfo::Word(),
    2617         725 :                           MachineRepresentation::kTaggedSigned);
    2618             :       }
    2619             :       case IrOpcode::kStringFromSingleCharCode: {
    2620             :         VisitUnop(node, UseInfo::TruncatingWord32(),
    2621        3474 :                   MachineRepresentation::kTaggedPointer);
    2622        3474 :         return;
    2623             :       }
    2624             :       case IrOpcode::kStringFromSingleCodePoint: {
    2625             :         VisitUnop(node, UseInfo::TruncatingWord32(),
    2626         746 :                   MachineRepresentation::kTaggedPointer);
    2627         746 :         return;
    2628             :       }
    2629             :       case IrOpcode::kStringIndexOf: {
    2630         923 :         ProcessInput(node, 0, UseInfo::AnyTagged());
    2631         923 :         ProcessInput(node, 1, UseInfo::AnyTagged());
    2632         923 :         ProcessInput(node, 2, UseInfo::TaggedSigned());
    2633             :         SetOutput(node, MachineRepresentation::kTaggedSigned);
    2634             :         return;
    2635             :       }
    2636             :       case IrOpcode::kStringLength: {
    2637             :         // TODO(bmeurer): The input representation should be TaggedPointer.
    2638             :         // Fix this once we have a dedicated StringConcat/JSStringAdd
    2639             :         // operator, which marks it's output as TaggedPointer properly.
    2640       75465 :         VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kWord32);
    2641       75465 :         return;
    2642             :       }
    2643             :       case IrOpcode::kStringSubstring: {
    2644        4040 :         ProcessInput(node, 0, UseInfo::AnyTagged());
    2645        4040 :         ProcessInput(node, 1, UseInfo::TruncatingWord32());
    2646        4040 :         ProcessInput(node, 2, UseInfo::TruncatingWord32());
    2647        4040 :         ProcessRemainingInputs(node, 3);
    2648             :         SetOutput(node, MachineRepresentation::kTaggedPointer);
    2649             :         return;
    2650             :       }
    2651             :       case IrOpcode::kStringToLowerCaseIntl:
    2652             :       case IrOpcode::kStringToUpperCaseIntl: {
    2653             :         VisitUnop(node, UseInfo::AnyTagged(),
    2654         370 :                   MachineRepresentation::kTaggedPointer);
    2655         370 :         return;
    2656             :       }
    2657             :       case IrOpcode::kCheckBounds:
    2658      186587 :         return VisitCheckBounds(node, lowering);
    2659             :       case IrOpcode::kPoisonIndex: {
    2660             :         VisitUnop(node, UseInfo::TruncatingWord32(),
    2661        4358 :                   MachineRepresentation::kWord32);
    2662        4358 :         return;
    2663             :       }
    2664             :       case IrOpcode::kCheckHeapObject: {
    2665       94277 :         if (InputCannotBe(node, Type::SignedSmall())) {
    2666             :           VisitUnop(node, UseInfo::AnyTagged(),
    2667           0 :                     MachineRepresentation::kTaggedPointer);
    2668             :         } else {
    2669             :           VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
    2670       94277 :                     MachineRepresentation::kTaggedPointer);
    2671             :         }
    2672      123839 :         if (lower()) DeferReplacement(node, node->InputAt(0));
    2673             :         return;
    2674             :       }
    2675             :       case IrOpcode::kCheckIf: {
    2676       46354 :         ProcessInput(node, 0, UseInfo::Bool());
    2677       46354 :         ProcessRemainingInputs(node, 1);
    2678             :         SetOutput(node, MachineRepresentation::kNone);
    2679             :         return;
    2680             :       }
    2681             :       case IrOpcode::kCheckInternalizedString: {
    2682        5607 :         VisitCheck(node, Type::InternalizedString(), lowering);
    2683        5607 :         return;
    2684             :       }
    2685             :       case IrOpcode::kCheckNumber: {
    2686        1570 :         Type const input_type = TypeOf(node->InputAt(0));
    2687        1570 :         if (input_type.Is(Type::Number())) {
    2688          36 :           VisitNoop(node, truncation);
    2689             :         } else {
    2690        1534 :           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
    2691             :         }
    2692             :         return;
    2693             :       }
    2694             :       case IrOpcode::kCheckReceiver: {
    2695        3210 :         VisitCheck(node, Type::Receiver(), lowering);
    2696        3210 :         return;
    2697             :       }
    2698             :       case IrOpcode::kCheckReceiverOrNullOrUndefined: {
    2699         230 :         VisitCheck(node, Type::ReceiverOrNullOrUndefined(), lowering);
    2700         230 :         return;
    2701             :       }
    2702             :       case IrOpcode::kCheckSmi: {
    2703      100447 :         const CheckParameters& params = CheckParametersOf(node->op());
    2704      100447 :         if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) {
    2705             :           VisitUnop(node,
    2706             :                     UseInfo::CheckedSignedSmallAsWord32(kDistinguishZeros,
    2707             :                                                         params.feedback()),
    2708       28088 :                     MachineRepresentation::kWord32);
    2709             :         } else {
    2710             :           VisitUnop(
    2711             :               node,
    2712             :               UseInfo::CheckedSignedSmallAsTaggedSigned(params.feedback()),
    2713       72359 :               MachineRepresentation::kTaggedSigned);
    2714             :         }
    2715      130623 :         if (lower()) DeferReplacement(node, node->InputAt(0));
    2716             :         return;
    2717             :       }
    2718             :       case IrOpcode::kCheckString: {
    2719       21256 :         VisitCheck(node, Type::String(), lowering);
    2720       21256 :         return;
    2721             :       }
    2722             :       case IrOpcode::kCheckSymbol: {
    2723         101 :         VisitCheck(node, Type::Symbol(), lowering);
    2724         101 :         return;
    2725             :       }
    2726             : 
    2727             :       case IrOpcode::kAllocate: {
    2728      337728 :         ProcessInput(node, 0, UseInfo::Word());
    2729      337728 :         ProcessRemainingInputs(node, 1);
    2730             :         SetOutput(node, MachineRepresentation::kTaggedPointer);
    2731             :         return;
    2732             :       }
    2733             :       case IrOpcode::kLoadMessage: {
    2734       88320 :         if (truncation.IsUnused()) return VisitUnused(node);
    2735       22805 :         VisitUnop(node, UseInfo::Word(), MachineRepresentation::kTagged);
    2736       22805 :         return;
    2737             :       }
    2738             :       case IrOpcode::kStoreMessage: {
    2739       88666 :         ProcessInput(node, 0, UseInfo::Word());
    2740       88666 :         ProcessInput(node, 1, UseInfo::AnyTagged());
    2741       88666 :         ProcessRemainingInputs(node, 2);
    2742             :         SetOutput(node, MachineRepresentation::kNone);
    2743             :         return;
    2744             :       }
    2745             :       case IrOpcode::kLoadFieldByIndex: {
    2746        2093 :         if (truncation.IsUnused()) return VisitUnused(node);
    2747             :         VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
    2748        2059 :                    MachineRepresentation::kTagged);
    2749        2059 :         return;
    2750             :       }
    2751             :       case IrOpcode::kLoadField: {
    2752     3852524 :         if (truncation.IsUnused()) return VisitUnused(node);
    2753     3739276 :         FieldAccess access = FieldAccessOf(node->op());
    2754             :         MachineRepresentation const representation =
    2755     3739276 :             access.machine_type.representation();
    2756     3739276 :         VisitUnop(node, UseInfoForBasePointer(access), representation);
    2757     3739276 :         return;
    2758             :       }
    2759             :       case IrOpcode::kStoreField: {
    2760     6170892 :         FieldAccess access = FieldAccessOf(node->op());
    2761             :         Node* value_node = node->InputAt(1);
    2762     6170892 :         NodeInfo* input_info = GetInfo(value_node);
    2763             :         MachineRepresentation field_representation =
    2764     6170892 :             access.machine_type.representation();
    2765             : 
    2766             :         // Convert to Smi if possible, such that we can avoid a write barrier.
    2767    18512676 :         if (field_representation == MachineRepresentation::kTagged &&
    2768    16075504 :             TypeOf(value_node).Is(Type::SignedSmall())) {
    2769             :           field_representation = MachineRepresentation::kTaggedSigned;
    2770             :         }
    2771             :         WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
    2772             :             access.base_is_tagged, field_representation, access.offset,
    2773     6170892 :             access.type, input_info->representation(), value_node);
    2774             : 
    2775     6170892 :         ProcessInput(node, 0, UseInfoForBasePointer(access));
    2776             :         ProcessInput(node, 1,
    2777     6170892 :                      TruncatingUseInfoFromRepresentation(field_representation));
    2778     6170892 :         ProcessRemainingInputs(node, 2);
    2779             :         SetOutput(node, MachineRepresentation::kNone);
    2780     6170892 :         if (lower()) {
    2781     2053664 :           if (write_barrier_kind < access.write_barrier_kind) {
    2782      689643 :             access.write_barrier_kind = write_barrier_kind;
    2783             :             NodeProperties::ChangeOp(
    2784     1379286 :                 node, jsgraph_->simplified()->StoreField(access));
    2785             :           }
    2786             :         }
    2787             :         return;
    2788             :       }
    2789             :       case IrOpcode::kLoadElement: {
    2790       69992 :         if (truncation.IsUnused()) return VisitUnused(node);
    2791       67744 :         ElementAccess access = ElementAccessOf(node->op());
    2792             :         VisitBinop(node, UseInfoForBasePointer(access), UseInfo::Word(),
    2793      135488 :                    access.machine_type.representation());
    2794       67744 :         return;
    2795             :       }
    2796             :       case IrOpcode::kStoreElement: {
    2797      113384 :         ElementAccess access = ElementAccessOf(node->op());
    2798             :         Node* value_node = node->InputAt(2);
    2799      113384 :         NodeInfo* input_info = GetInfo(value_node);
    2800             :         MachineRepresentation element_representation =
    2801      113384 :             access.machine_type.representation();
    2802             : 
    2803             :         // Convert to Smi if possible, such that we can avoid a write barrier.
    2804      340152 :         if (element_representation == MachineRepresentation::kTagged &&
    2805      266312 :             TypeOf(value_node).Is(Type::SignedSmall())) {
    2806             :           element_representation = MachineRepresentation::kTaggedSigned;
    2807             :         }
    2808             :         WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
    2809             :             access.base_is_tagged, element_representation, access.type,
    2810      113384 :             input_info->representation(), value_node);
    2811      113384 :         ProcessInput(node, 0, UseInfoForBasePointer(access));  // base
    2812      113384 :         ProcessInput(node, 1, UseInfo::Word());                // index
    2813             :         ProcessInput(node, 2,
    2814             :                      TruncatingUseInfoFromRepresentation(
    2815      113384 :                          element_representation));  // value
    2816      113384 :         ProcessRemainingInputs(node, 3);
    2817             :         SetOutput(node, MachineRepresentation::kNone);
    2818      113384 :         if (lower()) {
    2819       36923 :           if (write_barrier_kind < access.write_barrier_kind) {
    2820       22220 :             access.write_barrier_kind = write_barrier_kind;
    2821             :             NodeProperties::ChangeOp(
    2822       44440 :                 node, jsgraph_->simplified()->StoreElement(access));
    2823             :           }
    2824             :         }
    2825             :         return;
    2826             :       }
    2827             :       case IrOpcode::kNumberIsFloat64Hole: {
    2828             :         VisitUnop(node, UseInfo::TruncatingFloat64(),
    2829         230 :                   MachineRepresentation::kBit);
    2830         230 :         return;
    2831             :       }
    2832             :       case IrOpcode::kTransitionAndStoreElement: {
    2833         881 :         Type value_type = TypeOf(node->InputAt(2));
    2834             : 
    2835         881 :         ProcessInput(node, 0, UseInfo::AnyTagged());  // array
    2836         881 :         ProcessInput(node, 1, UseInfo::Word());       // index
    2837             : 
    2838         881 :         if (value_type.Is(Type::SignedSmall())) {
    2839         294 :           ProcessInput(node, 2, UseInfo::TruncatingWord32());  // value
    2840         294 :           if (lower()) {
    2841             :             NodeProperties::ChangeOp(node,
    2842          68 :                                      simplified()->StoreSignedSmallElement());
    2843             :           }
    2844         587 :         } else if (value_type.Is(Type::Number())) {
    2845         127 :           ProcessInput(node, 2, UseInfo::TruncatingFloat64());  // value
    2846         127 :           if (lower()) {
    2847          29 :             Handle<Map> double_map = DoubleMapParameterOf(node->op());
    2848             :             NodeProperties::ChangeOp(
    2849             :                 node,
    2850          29 :                 simplified()->TransitionAndStoreNumberElement(double_map));
    2851             :           }
    2852         460 :         } else if (value_type.Is(Type::NonNumber())) {
    2853          84 :           ProcessInput(node, 2, UseInfo::AnyTagged());  // value
    2854          84 :           if (lower()) {
    2855          18 :             Handle<Map> fast_map = FastMapParameterOf(node->op());
    2856             :             NodeProperties::ChangeOp(
    2857             :                 node, simplified()->TransitionAndStoreNonNumberElement(
    2858          18 :                           fast_map, value_type));
    2859             :           }
    2860             :         } else {
    2861         376 :           ProcessInput(node, 2, UseInfo::AnyTagged());  // value
    2862             :         }
    2863             : 
    2864         881 :         ProcessRemainingInputs(node, 3);
    2865             :         SetOutput(node, MachineRepresentation::kNone);
    2866             :         return;
    2867             :       }
    2868             :       case IrOpcode::kLoadTypedElement: {
    2869             :         MachineRepresentation const rep =
    2870       16893 :             MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
    2871       16893 :         ProcessInput(node, 0, UseInfo::AnyTagged());  // buffer
    2872       16893 :         ProcessInput(node, 1, UseInfo::AnyTagged());  // base pointer
    2873       16893 :         ProcessInput(node, 2, UseInfo::Word());       // external pointer
    2874       16893 :         ProcessInput(node, 3, UseInfo::Word());       // index
    2875       16893 :         ProcessRemainingInputs(node, 4);
    2876             :         SetOutput(node, rep);
    2877             :         return;
    2878             :       }
    2879             :       case IrOpcode::kLoadDataViewElement: {
    2880             :         MachineRepresentation const rep =
    2881         744 :             MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
    2882         744 :         ProcessInput(node, 0, UseInfo::AnyTagged());  // buffer
    2883         744 :         ProcessInput(node, 1, UseInfo::Word());       // external pointer
    2884         744 :         ProcessInput(node, 2, UseInfo::Word());       // byte offset
    2885         744 :         ProcessInput(node, 3, UseInfo::Word());       // index
    2886         744 :         ProcessInput(node, 4, UseInfo::Bool());       // little-endian
    2887         744 :         ProcessRemainingInputs(node, 5);
    2888             :         SetOutput(node, rep);
    2889             :         return;
    2890             :       }
    2891             :       case IrOpcode::kStoreTypedElement: {
    2892             :         MachineRepresentation const rep =
    2893       14823 :             MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
    2894       14823 :         ProcessInput(node, 0, UseInfo::AnyTagged());  // buffer
    2895       14823 :         ProcessInput(node, 1, UseInfo::AnyTagged());  // base pointer
    2896       14823 :         ProcessInput(node, 2, UseInfo::Word());       // external pointer
    2897       14823 :         ProcessInput(node, 3, UseInfo::Word());       // index
    2898             :         ProcessInput(node, 4,
    2899       14823 :                      TruncatingUseInfoFromRepresentation(rep));  // value
    2900       14823 :         ProcessRemainingInputs(node, 5);
    2901             :         SetOutput(node, MachineRepresentation::kNone);
    2902             :         return;
    2903             :       }
    2904             :       case IrOpcode::kStoreDataViewElement: {
    2905             :         MachineRepresentation const rep =
    2906         540 :             MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
    2907         540 :         ProcessInput(node, 0, UseInfo::AnyTagged());         // buffer
    2908         540 :         ProcessInput(node, 1, UseInfo::Word());              // external pointer
    2909         540 :         ProcessInput(node, 2, UseInfo::Word());              // byte offset
    2910         540 :         ProcessInput(node, 3, UseInfo::Word());              // index
    2911             :         ProcessInput(node, 4,
    2912         540 :                      TruncatingUseInfoFromRepresentation(rep));  // value
    2913         540 :         ProcessInput(node, 5, UseInfo::Bool());  // little-endian
    2914         540 :         ProcessRemainingInputs(node, 6);
    2915             :         SetOutput(node, MachineRepresentation::kNone);
    2916             :         return;
    2917             :       }
    2918             :       case IrOpcode::kConvertReceiver: {
    2919        2663 :         Type input_type = TypeOf(node->InputAt(0));
    2920             :         VisitBinop(node, UseInfo::AnyTagged(),
    2921             :                    MachineRepresentation::kTaggedPointer);
    2922        2663 :         if (lower()) {
    2923             :           // Try to optimize the {node} based on the input type.
    2924         869 :           if (input_type.Is(Type::Receiver())) {
    2925           0 :             DeferReplacement(node, node->InputAt(0));
    2926         869 :           } else if (input_type.Is(Type::NullOrUndefined())) {
    2927           0 :             DeferReplacement(node, node->InputAt(1));
    2928         869 :           } else if (!input_type.Maybe(Type::NullOrUndefined())) {
    2929             :             NodeProperties::ChangeOp(
    2930             :                 node, lowering->simplified()->ConvertReceiver(
    2931          83 :                           ConvertReceiverMode::kNotNullOrUndefined));
    2932             :           }
    2933             :         }
    2934             :         return;
    2935             :       }
    2936             :       case IrOpcode::kPlainPrimitiveToNumber: {
    2937        2633 :         if (InputIs(node, Type::Boolean())) {
    2938         193 :           VisitUnop(node, UseInfo::Bool(), MachineRepresentation::kWord32);
    2939         250 :           if (lower()) DeferReplacement(node, node->InputAt(0));
    2940        2440 :         } else if (InputIs(node, Type::String())) {
    2941         998 :           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
    2942         998 :           if (lower()) {
    2943         330 :             NodeProperties::ChangeOp(node, simplified()->StringToNumber());
    2944             :           }
    2945        1442 :         } else if (truncation.IsUsedAsWord32()) {
    2946          57 :           if (InputIs(node, Type::NumberOrOddball())) {
    2947             :             VisitUnop(node, UseInfo::TruncatingWord32(),
    2948          30 :                       MachineRepresentation::kWord32);
    2949          40 :             if (lower()) DeferReplacement(node, node->InputAt(0));
    2950             :           } else {
    2951             :             VisitUnop(node, UseInfo::AnyTagged(),
    2952          27 :                       MachineRepresentation::kWord32);
    2953          27 :             if (lower()) {
    2954             :               NodeProperties::ChangeOp(node,
    2955           9 :                                        simplified()->PlainPrimitiveToWord32());
    2956             :             }
    2957             :           }
    2958        1385 :         } else if (truncation.IsUsedAsFloat64()) {
    2959        1309 :           if (InputIs(node, Type::NumberOrOddball())) {
    2960             :             VisitUnop(node, UseInfo::TruncatingFloat64(),
    2961        1309 :                       MachineRepresentation::kFloat64);
    2962        1647 :             if (lower()) DeferReplacement(node, node->InputAt(0));
    2963             :           } else {
    2964             :             VisitUnop(node, UseInfo::AnyTagged(),
    2965           0 :                       MachineRepresentation::kFloat64);
    2966           0 :             if (lower()) {
    2967             :               NodeProperties::ChangeOp(node,
    2968           0 :                                        simplified()->PlainPrimitiveToFloat64());
    2969             :             }
    2970             :           }
    2971             :         } else {
    2972          76 :           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
    2973             :         }
    2974             :         return;
    2975             :       }
    2976             :       case IrOpcode::kSpeculativeToNumber: {
    2977      129421 :         NumberOperationParameters const& p =
    2978      129421 :             NumberOperationParametersOf(node->op());
    2979      129421 :         switch (p.hint()) {
    2980             :           case NumberOperationHint::kSigned32:
    2981             :           case NumberOperationHint::kSignedSmall:
    2982             :           case NumberOperationHint::kSignedSmallInputs:
    2983             :             VisitUnop(node,
    2984        6158 :                       CheckedUseInfoAsWord32FromHint(p.hint(), p.feedback()),
    2985        6158 :                       MachineRepresentation::kWord32, Type::Signed32());
    2986        6158 :             break;
    2987             :           case NumberOperationHint::kNumber:
    2988             :           case NumberOperationHint::kNumberOrOddball:
    2989             :             VisitUnop(node,
    2990      123263 :                       CheckedUseInfoAsFloat64FromHint(p.hint(), p.feedback()),
    2991      123263 :                       MachineRepresentation::kFloat64);
    2992      123263 :             break;
    2993             :         }
    2994      168498 :         if (lower()) DeferReplacement(node, node->InputAt(0));
    2995             :         return;
    2996             :       }
    2997             :       case IrOpcode::kObjectIsArrayBufferView: {
    2998             :         // TODO(turbofan): Introduce a Type::ArrayBufferView?
    2999          42 :         VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
    3000          42 :         return;
    3001             :       }
    3002             :       case IrOpcode::kObjectIsBigInt: {
    3003          75 :         VisitObjectIs(node, Type::BigInt(), lowering);
    3004          75 :         return;
    3005             :       }
    3006             :       case IrOpcode::kObjectIsCallable: {
    3007         300 :         VisitObjectIs(node, Type::Callable(), lowering);
    3008         300 :         return;
    3009             :       }
    3010             :       case IrOpcode::kObjectIsConstructor: {
    3011             :         // TODO(turbofan): Introduce a Type::Constructor?
    3012         621 :         VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
    3013         621 :         return;
    3014             :       }
    3015             :       case IrOpcode::kObjectIsDetectableCallable: {
    3016       42709 :         VisitObjectIs(node, Type::DetectableCallable(), lowering);
    3017       42709 :         return;
    3018             :       }
    3019             :       case IrOpcode::kObjectIsFiniteNumber: {
    3020         588 :         Type const input_type = GetUpperBound(node->InputAt(0));
    3021        1176 :         if (input_type.Is(type_cache_->kSafeInteger)) {
    3022         210 :           VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
    3023         210 :           if (lower()) {
    3024          70 :             DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
    3025             :           }
    3026         378 :         } else if (!input_type.Maybe(Type::Number())) {
    3027          42 :           VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit);
    3028          42 :           if (lower()) {
    3029          14 :             DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
    3030             :           }
    3031         336 :         } else if (input_type.Is(Type::Number())) {
    3032             :           VisitUnop(node, UseInfo::TruncatingFloat64(),
    3033         315 :                     MachineRepresentation::kBit);
    3034         315 :           if (lower()) {
    3035             :             NodeProperties::ChangeOp(node,
    3036         105 :                                      lowering->simplified()->NumberIsFinite());
    3037             :           }
    3038             :         } else {
    3039          21 :           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
    3040             :         }
    3041             :         return;
    3042             :       }
    3043             :       case IrOpcode::kNumberIsFinite: {
    3044             :         VisitUnop(node, UseInfo::TruncatingFloat64(),
    3045          70 :                   MachineRepresentation::kBit);
    3046          70 :         return;
    3047             :       }
    3048             :       case IrOpcode::kObjectIsSafeInteger: {
    3049          42 :         Type const input_type = GetUpperBound(node->InputAt(0));
    3050          84 :         if (input_type.Is(type_cache_->kSafeInteger)) {
    3051           0 :           VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
    3052           0 :           if (lower()) {
    3053           0 :             DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
    3054             :           }
    3055          42 :         } else if (!input_type.Maybe(Type::Number())) {
    3056           0 :           VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit);
    3057           0 :           if (lower()) {
    3058           0 :             DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
    3059             :           }
    3060          42 :         } else if (input_type.Is(Type::Number())) {
    3061             :           VisitUnop(node, UseInfo::TruncatingFloat64(),
    3062          21 :                     MachineRepresentation::kBit);
    3063          21 :           if (lower()) {
    3064             :             NodeProperties::ChangeOp(
    3065           7 :                 node, lowering->simplified()->NumberIsSafeInteger());
    3066             :           }
    3067             :         } else {
    3068          21 :           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
    3069             :         }
    3070             :         return;
    3071             :       }
    3072             :       case IrOpcode::kNumberIsSafeInteger: {
    3073           0 :         UNREACHABLE();
    3074             :       }
    3075             :       case IrOpcode::kObjectIsInteger: {
    3076         588 :         Type const input_type = GetUpperBound(node->InputAt(0));
    3077        1176 :         if (input_type.Is(type_cache_->kSafeInteger)) {
    3078         210 :           VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
    3079         210 :           if (lower()) {
    3080          70 :             DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
    3081             :           }
    3082         378 :         } else if (!input_type.Maybe(Type::Number())) {
    3083           0 :           VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit);
    3084           0 :           if (lower()) {
    3085           0 :             DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
    3086             :           }
    3087         378 :         } else if (input_type.Is(Type::Number())) {
    3088             :           VisitUnop(node, UseInfo::TruncatingFloat64(),
    3089         357 :                     MachineRepresentation::kBit);
    3090         357 :           if (lower()) {
    3091             :             NodeProperties::ChangeOp(node,
    3092         119 :                                      lowering->simplified()->NumberIsInteger());
    3093             :           }
    3094             :         } else {
    3095          21 :           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
    3096             :         }
    3097             :         return;
    3098             :       }
    3099             :       case IrOpcode::kNumberIsInteger: {
    3100             :         VisitUnop(node, UseInfo::TruncatingFloat64(),
    3101           0 :                   MachineRepresentation::kBit);
    3102           0 :         return;
    3103             :       }
    3104             :       case IrOpcode::kObjectIsMinusZero: {
    3105         336 :         Type const input_type = GetUpperBound(node->InputAt(0));
    3106         336 :         if (input_type.Is(Type::MinusZero())) {
    3107           0 :           VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
    3108           0 :           if (lower()) {
    3109           0 :             DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
    3110             :           }
    3111         336 :         } else if (!input_type.Maybe(Type::MinusZero())) {
    3112           0 :           VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit);
    3113           0 :           if (lower()) {
    3114           0 :             DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
    3115             :           }
    3116         336 :         } else if (input_type.Is(Type::Number())) {
    3117             :           VisitUnop(node, UseInfo::TruncatingFloat64(),
    3118         273 :                     MachineRepresentation::kBit);
    3119         273 :           if (lower()) {
    3120          91 :             NodeProperties::ChangeOp(node, simplified()->NumberIsMinusZero());
    3121             :           }
    3122             :         } else {
    3123          63 :           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
    3124             :         }
    3125             :         return;
    3126             :       }
    3127             :       case IrOpcode::kObjectIsNaN: {
    3128        2613 :         Type const input_type = GetUpperBound(node->InputAt(0));
    3129        2613 :         if (input_type.Is(Type::NaN())) {
    3130           0 :           VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
    3131           0 :           if (lower()) {
    3132           0 :             DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
    3133             :           }
    3134        2613 :         } else if (!input_type.Maybe(Type::NaN())) {
    3135          39 :           VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit);
    3136          39 :           if (lower()) {
    3137          13 :             DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
    3138             :           }
    3139        2574 :         } else if (input_type.Is(Type::Number())) {
    3140             :           VisitUnop(node, UseInfo::TruncatingFloat64(),
    3141         525 :                     MachineRepresentation::kBit);
    3142         525 :           if (lower()) {
    3143         175 :             NodeProperties::ChangeOp(node, simplified()->NumberIsNaN());
    3144             :           }
    3145             :         } else {
    3146        2049 :           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
    3147             :         }
    3148             :         return;
    3149             :       }
    3150             :       case IrOpcode::kNumberIsNaN: {
    3151             :         VisitUnop(node, UseInfo::TruncatingFloat64(),
    3152        8818 :                   MachineRepresentation::kBit);
    3153        8818 :         return;
    3154             :       }
    3155             :       case IrOpcode::kObjectIsNonCallable: {
    3156       18549 :         VisitObjectIs(node, Type::NonCallable(), lowering);
    3157       18549 :         return;
    3158             :       }
    3159             :       case IrOpcode::kObjectIsNumber: {
    3160       23248 :         VisitObjectIs(node, Type::Number(), lowering);
    3161       23248 :         return;
    3162             :       }
    3163             :       case IrOpcode::kObjectIsReceiver: {
    3164       61803 :         VisitObjectIs(node, Type::Receiver(), lowering);
    3165       61803 :         return;
    3166             :       }
    3167             :       case IrOpcode::kObjectIsSmi: {
    3168             :         // TODO(turbofan): Optimize based on input representation.
    3169        3905 :         VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
    3170        3905 :         return;
    3171             :       }
    3172             :       case IrOpcode::kObjectIsString: {
    3173        8969 :         VisitObjectIs(node, Type::String(), lowering);
    3174        8969 :         return;
    3175             :       }
    3176             :       case IrOpcode::kObjectIsSymbol: {
    3177          56 :         VisitObjectIs(node, Type::Symbol(), lowering);
    3178          56 :         return;
    3179             :       }
    3180             :       case IrOpcode::kObjectIsUndetectable: {
    3181        4694 :         VisitObjectIs(node, Type::Undetectable(), lowering);
    3182        4694 :         return;
    3183             :       }
    3184             :       case IrOpcode::kArgumentsFrame: {
    3185             :         SetOutput(node, MachineType::PointerRepresentation());
    3186             :         return;
    3187             :       }
    3188             :       case IrOpcode::kArgumentsLength: {
    3189       50007 :         VisitUnop(node, UseInfo::Word(), MachineRepresentation::kTaggedSigned);
    3190       50007 :         return;
    3191             :       }
    3192             :       case IrOpcode::kNewDoubleElements:
    3193             :       case IrOpcode::kNewSmiOrObjectElements: {
    3194             :         VisitUnop(node, UseInfo::TruncatingWord32(),
    3195        1769 :                   MachineRepresentation::kTaggedPointer);
    3196        1769 :         return;
    3197             :       }
    3198             :       case IrOpcode::kNewArgumentsElements: {
    3199             :         VisitBinop(node, UseInfo::Word(), UseInfo::TaggedSigned(),
    3200       57805 :                    MachineRepresentation::kTaggedPointer);
    3201       57805 :         return;
    3202             :       }
    3203             :       case IrOpcode::kCheckFloat64Hole: {
    3204        1870 :         Type const input_type = TypeOf(node->InputAt(0));
    3205             :         CheckFloat64HoleMode mode =
    3206        1870 :             CheckFloat64HoleParametersOf(node->op()).mode();
    3207        1870 :         if (mode == CheckFloat64HoleMode::kAllowReturnHole) {
    3208             :           // If {mode} is allow-return-hole _and_ the {truncation}
    3209             :           // identifies NaN and undefined, we can just pass along
    3210             :           // the {truncation} and completely wipe the {node}.
    3211        1325 :           if (truncation.IsUnused()) return VisitUnused(node);
    3212        1229 :           if (truncation.IsUsedAsFloat64()) {
    3213             :             VisitUnop(node, UseInfo::TruncatingFloat64(),
    3214         108 :                       MachineRepresentation::kFloat64);
    3215         144 :             if (lower()) DeferReplacement(node, node->InputAt(0));
    3216             :             return;
    3217             :           }
    3218             :         }
    3219             :         VisitUnop(node,
    3220             :                   UseInfo(MachineRepresentation::kFloat64, Truncation::Any()),
    3221        3332 :                   MachineRepresentation::kFloat64, Type::Number());
    3222        2200 :         if (lower() && input_type.Is(Type::Number())) {
    3223          64 :           DeferReplacement(node, node->InputAt(0));
    3224             :         }
    3225             :         return;
    3226             :       }
    3227             :       case IrOpcode::kCheckNotTaggedHole: {
    3228        1226 :         VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
    3229        1226 :         return;
    3230             :       }
    3231             :       case IrOpcode::kConvertTaggedHoleToUndefined: {
    3232       10189 :         if (InputIs(node, Type::NumberOrOddball()) &&
    3233             :             truncation.IsUsedAsWord32()) {
    3234             :           // Propagate the Word32 truncation.
    3235             :           VisitUnop(node, UseInfo::TruncatingWord32(),
    3236        1009 :                     MachineRepresentation::kWord32);
    3237        1259 :           if (lower()) DeferReplacement(node, node->InputAt(0));
    3238        8171 :         } else if (InputIs(node, Type::NumberOrOddball()) &&
    3239             :                    truncation.IsUsedAsFloat64()) {
    3240             :           // Propagate the Float64 truncation.
    3241             :           VisitUnop(node, UseInfo::TruncatingFloat64(),
    3242         143 :                     MachineRepresentation::kFloat64);
    3243         187 :           if (lower()) DeferReplacement(node, node->InputAt(0));
    3244        6033 :         } else if (InputIs(node, Type::NonInternal())) {
    3245         130 :           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
    3246         173 :           if (lower()) DeferReplacement(node, node->InputAt(0));
    3247             :         } else {
    3248             :           // TODO(turbofan): Add a (Tagged) truncation that identifies hole
    3249             :           // and undefined, i.e. for a[i] === obj cases.
    3250        5903 :           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
    3251             :         }
    3252             :         return;
    3253             :       }
    3254             :       case IrOpcode::kCheckEqualsSymbol:
    3255             :       case IrOpcode::kCheckEqualsInternalizedString:
    3256             :         return VisitBinop(node, UseInfo::AnyTagged(),
    3257             :                           MachineRepresentation::kNone);
    3258             :       case IrOpcode::kMapGuard:
    3259             :         // Eliminate MapGuard nodes here.
    3260       21713 :         return VisitUnused(node);
    3261             :       case IrOpcode::kCheckMaps:
    3262             :       case IrOpcode::kTransitionElementsKind: {
    3263      176683 :         VisitInputs(node);
    3264             :         return SetOutput(node, MachineRepresentation::kNone);
    3265             :       }
    3266             :       case IrOpcode::kCompareMaps:
    3267             :         return VisitUnop(node, UseInfo::AnyTagged(),
    3268       23745 :                          MachineRepresentation::kBit);
    3269             :       case IrOpcode::kEnsureWritableFastElements:
    3270             :         return VisitBinop(node, UseInfo::AnyTagged(),
    3271             :                           MachineRepresentation::kTaggedPointer);
    3272             :       case IrOpcode::kMaybeGrowFastElements: {
    3273       11692 :         Type const index_type = TypeOf(node->InputAt(2));
    3274       11692 :         Type const length_type = TypeOf(node->InputAt(3));
    3275       11692 :         ProcessInput(node, 0, UseInfo::AnyTagged());         // object
    3276       11692 :         ProcessInput(node, 1, UseInfo::AnyTagged());         // elements
    3277       11692 :         ProcessInput(node, 2, UseInfo::TruncatingWord32());  // index
    3278       11692 :         ProcessInput(node, 3, UseInfo::TruncatingWord32());  // length
    3279       11692 :         ProcessRemainingInputs(node, 4);
    3280             :         SetOutput(node, MachineRepresentation::kTaggedPointer);
    3281       11692 :         if (lower()) {
    3282             :           // If the index is known to be less than the length (or if
    3283             :           // we're in dead code), we know that we don't need to grow
    3284             :           // the elements, so we can just remove this operation all
    3285             :           // together and replace it with the elements that we have
    3286             :           // on the inputs.
    3287       10767 :           if (index_type.IsNone() || length_type.IsNone() ||
    3288        3589 :               index_type.Max() < length_type.Min()) {
    3289          51 :             DeferReplacement(node, node->InputAt(1));
    3290             :           }
    3291             :         }
    3292             :         return;
    3293             :       }
    3294             : 
    3295             :       case IrOpcode::kDateNow:
    3296          21 :         VisitInputs(node);
    3297             :         return SetOutput(node, MachineRepresentation::kTaggedPointer);
    3298             :       case IrOpcode::kFrameState:
    3299    18002892 :         return VisitFrameState(node);
    3300             :       case IrOpcode::kStateValues:
    3301    10663604 :         return VisitStateValues(node);
    3302             :       case IrOpcode::kObjectState:
    3303       72212 :         return VisitObjectState(node);
    3304             :       case IrOpcode::kObjectId:
    3305             :         return SetOutput(node, MachineRepresentation::kTaggedPointer);
    3306             :       case IrOpcode::kTypeGuard: {
    3307             :         // We just get rid of the sigma here, choosing the best representation
    3308             :         // for the sigma's type.
    3309       88780 :         Type type = TypeOf(node);
    3310             :         MachineRepresentation representation =
    3311       88780 :             GetOutputInfoForPhi(node, type, truncation);
    3312             : 
    3313             :         // Here we pretend that the input has the sigma's type for the
    3314             :         // conversion.
    3315      177563 :         UseInfo use(representation, truncation);
    3316       88781 :         if (propagate()) {
    3317       29734 :           EnqueueInput(node, 0, use);
    3318       59047 :         } else if (lower()) {
    3319       21466 :           ConvertInput(node, 0, use, type);
    3320             :         }
    3321       88784 :         ProcessRemainingInputs(node, 1);
    3322             :         SetOutput(node, representation);
    3323             :         return;
    3324             :       }
    3325             : 
    3326             :       case IrOpcode::kFinishRegion:
    3327      401241 :         VisitInputs(node);
    3328             :         // Assume the output is tagged pointer.
    3329             :         return SetOutput(node, MachineRepresentation::kTaggedPointer);
    3330             : 
    3331             :       case IrOpcode::kReturn:
    3332     1649358 :         VisitReturn(node);
    3333             :         // Assume the output is tagged.
    3334             :         return SetOutput(node, MachineRepresentation::kTagged);
    3335             : 
    3336             :       case IrOpcode::kFindOrderedHashMapEntry: {
    3337         670 :         Type const key_type = TypeOf(node->InputAt(1));
    3338         670 :         if (key_type.Is(Type::Signed32OrMinusZero())) {
    3339             :           VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
    3340          60 :                      MachineType::PointerRepresentation());
    3341          60 :           if (lower()) {
    3342             :             NodeProperties::ChangeOp(
    3343             :                 node,
    3344          15 :                 lowering->simplified()->FindOrderedHashMapEntryForInt32Key());
    3345             :           }
    3346             :         } else {
    3347             :           VisitBinop(node, UseInfo::AnyTagged(),
    3348             :                      MachineRepresentation::kTaggedSigned);
    3349             :         }
    3350             :         return;
    3351             :       }
    3352             : 
    3353             :       // Operators with all inputs tagged and no or tagged output have uniform
    3354             :       // handling.
    3355             :       case IrOpcode::kEnd:
    3356             :       case IrOpcode::kIfSuccess:
    3357             :       case IrOpcode::kIfException:
    3358             :       case IrOpcode::kIfTrue:
    3359             :       case IrOpcode::kIfFalse:
    3360             :       case IrOpcode::kIfValue:
    3361             :       case IrOpcode::kIfDefault:
    3362             :       case IrOpcode::kDeoptimize:
    3363             :       case IrOpcode::kEffectPhi:
    3364             :       case IrOpcode::kTerminate:
    3365             :       case IrOpcode::kCheckpoint:
    3366             :       case IrOpcode::kLoop:
    3367             :       case IrOpcode::kMerge:
    3368             :       case IrOpcode::kThrow:
    3369             :       case IrOpcode::kBeginRegion:
    3370             :       case IrOpcode::kProjection:
    3371             :       case IrOpcode::kOsrValue:
    3372             :       case IrOpcode::kArgumentsElementsState:
    3373             :       case IrOpcode::kArgumentsLengthState:
    3374             :       case IrOpcode::kUnreachable:
    3375             :       case IrOpcode::kRuntimeAbort:
    3376             : // All JavaScript operators except JSToNumber have uniform handling.
    3377             : #define OPCODE_CASE(name) case IrOpcode::k##name:
    3378             :         JS_SIMPLE_BINOP_LIST(OPCODE_CASE)
    3379             :         JS_OBJECT_OP_LIST(OPCODE_CASE)
    3380             :         JS_CONTEXT_OP_LIST(OPCODE_CASE)
    3381             :         JS_OTHER_OP_LIST(OPCODE_CASE)
    3382             : #undef OPCODE_CASE
    3383             :       case IrOpcode::kJSBitwiseNot:
    3384             :       case IrOpcode::kJSDecrement:
    3385             :       case IrOpcode::kJSIncrement:
    3386             :       case IrOpcode::kJSNegate:
    3387             :       case IrOpcode::kJSToLength:
    3388             :       case IrOpcode::kJSToName:
    3389             :       case IrOpcode::kJSToObject:
    3390             :       case IrOpcode::kJSToString:
    3391             :       case IrOpcode::kJSParseInt:
    3392    30300142 :         VisitInputs(node);
    3393             :         // Assume the output is tagged.
    3394             :         return SetOutput(node, MachineRepresentation::kTagged);
    3395             :       case IrOpcode::kDeadValue:
    3396        1403 :         ProcessInput(node, 0, UseInfo::Any());
    3397             :         return SetOutput(node, MachineRepresentation::kNone);
    3398             :       default:
    3399           0 :         FATAL(
    3400             :             "Representation inference: unsupported opcode %i (%s), node #%i\n.",
    3401           0 :             node->opcode(), node->op()->mnemonic(), node->id());
    3402             :         break;
    3403             :     }
    3404             :     UNREACHABLE();
    3405             :   }
    3406             : 
    3407     1331904 :   void DeferReplacement(Node* node, Node* replacement) {
    3408     2769464 :     TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(),
    3409             :           node->op()->mnemonic(), replacement->id(),
    3410             :           replacement->op()->mnemonic());
    3411             : 
    3412             :     // Disconnect the node from effect and control chains, if necessary.
    3413     3995715 :     if (node->op()->EffectInputCount() > 0) {
    3414             :       DCHECK_LT(0, node->op()->ControlInputCount());
    3415             :       // Disconnect the node from effect and control chains.
    3416      105655 :       Node* control = NodeProperties::GetControlInput(node);
    3417      105655 :       Node* effect = NodeProperties::GetEffectInput(node);
    3418      211310 :       ReplaceEffectControlUses(node, effect, control);
    3419             :     }
    3420             : 
    3421     1331905 :     replacements_.push_back(node);
    3422     1331904 :     replacements_.push_back(replacement);
    3423             : 
    3424     1331903 :     node->NullAllInputs();  // Node is now dead.
    3425     1331904 :   }
    3426             : 
    3427      100192 :   void Kill(Node* node) {
    3428       33402 :     TRACE("killing #%d:%s\n", node->id(), node->op()->mnemonic());
    3429             : 
    3430       33402 :     if (node->op()->EffectInputCount() == 1) {
    3431             :       DCHECK_LT(0, node->op()->ControlInputCount());
    3432             :       // Disconnect the node from effect and control chains.
    3433       33388 :       Node* control = NodeProperties::GetControlInput(node);
    3434       33388 :       Node* effect = NodeProperties::GetEffectInput(node);
    3435       33388 :       ReplaceEffectControlUses(node, effect, control);
    3436             :     } else {
    3437             :       DCHECK_EQ(0, node->op()->EffectInputCount());
    3438             :       DCHECK_EQ(0, node->op()->ControlOutputCount());
    3439             :       DCHECK_EQ(0, node->op()->EffectOutputCount());
    3440             :     }
    3441             : 
    3442       33402 :     node->ReplaceUses(jsgraph_->Dead());
    3443             : 
    3444       33402 :     node->NullAllInputs();  // The {node} is now dead.
    3445       33402 :   }
    3446             : 
    3447    53111727 :   void PrintOutputInfo(NodeInfo* info) {
    3448    53111727 :     if (FLAG_trace_representation) {
    3449           0 :       StdoutStream{} << info->representation();
    3450             :     }
    3451    53111727 :   }
    3452             : 
    3453             :   void PrintRepresentation(MachineRepresentation rep) {
    3454             :     if (FLAG_trace_representation) {
    3455             :       StdoutStream{} << rep;
    3456             :     }
    3457             :   }
    3458             : 
    3459   106637536 :   void PrintTruncation(Truncation truncation) {
    3460   106637536 :     if (FLAG_trace_representation) {
    3461           0 :       StdoutStream{} << truncation.description() << std::endl;
    3462             :     }
    3463   106637536 :   }
    3464             : 
    3465    16935189 :   void PrintUseInfo(UseInfo info) {
    3466    16935189 :     if (FLAG_trace_representation) {
    3467           0 :       StdoutStream{} << info.representation() << ":"
    3468           0 :                      << info.truncation().description();
    3469             :     }
    3470    16935189 :   }
    3471             : 
    3472             :  private:
    3473             :   JSGraph* jsgraph_;
    3474             :   Zone* zone_;                      // Temporary zone.
    3475             :   size_t const count_;              // number of nodes in the graph
    3476             :   ZoneVector<NodeInfo> info_;       // node id -> usage information
    3477             : #ifdef DEBUG
    3478             :   ZoneVector<InputUseInfos> node_input_use_infos_;  // Debug information about
    3479             :                                                     // requirements on inputs.
    3480             : #endif                                              // DEBUG
    3481             :   NodeVector nodes_;                // collected nodes
    3482             :   NodeVector replacements_;         // replacements to be done after lowering
    3483             :   Phase phase_;                     // current phase of algorithm
    3484             :   RepresentationChanger* changer_;  // for inserting representation changes
    3485             :   ZoneQueue<Node*> queue_;          // queue for traversing the graph
    3486             : 
    3487             :   struct NodeState {
    3488             :     Node* node;
    3489             :     int input_index;
    3490             :   };
    3491             :   ZoneStack<NodeState> typing_stack_;  // stack for graph typing.
    3492             :   // TODO(danno): RepresentationSelector shouldn't know anything about the
    3493             :   // source positions table, but must for now since there currently is no other
    3494             :   // way to pass down source position information to nodes created during
    3495             :   // lowering. Once this phase becomes a vanilla reducer, it should get source
    3496             :   // position information via the SourcePositionWrapper like all other reducers.
    3497             :   SourcePositionTable* source_positions_;
    3498             :   NodeOriginTable* node_origins_;
    3499             :   TypeCache const* type_cache_;
    3500             :   OperationTyper op_typer_;  // helper for the feedback typer
    3501             : 
    3502   724967519 :   NodeInfo* GetInfo(Node* node) {
    3503             :     DCHECK(node->id() < count_);
    3504   728525353 :     return &info_[node->id()];
    3505             :   }
    3506             :   Zone* zone() { return zone_; }
    3507             :   Zone* graph_zone() { return jsgraph_->zone(); }
    3508             : };
    3509             : 
    3510      456703 : SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, JSHeapBroker* broker,
    3511             :                                        Zone* zone,
    3512             :                                        SourcePositionTable* source_positions,
    3513             :                                        NodeOriginTable* node_origins,
    3514             :                                        PoisoningMitigationLevel poisoning_level)
    3515             :     : jsgraph_(jsgraph),
    3516             :       broker_(broker),
    3517             :       zone_(zone),
    3518      456703 :       type_cache_(TypeCache::Get()),
    3519             :       source_positions_(source_positions),
    3520             :       node_origins_(node_origins),
    3521      913411 :       poisoning_level_(poisoning_level) {}
    3522             : 
    3523      913408 : void SimplifiedLowering::LowerAllNodes() {
    3524      456703 :   RepresentationChanger changer(jsgraph(), jsgraph()->isolate());
    3525             :   RepresentationSelector selector(jsgraph(), broker_, zone_, &changer,
    3526      913410 :                                   source_positions_, node_origins_);
    3527      456710 :   selector.Run(this);
    3528      456709 : }
    3529             : 
    3530        1413 : void SimplifiedLowering::DoJSToNumberOrNumericTruncatesToFloat64(
    3531        2826 :     Node* node, RepresentationSelector* selector) {
    3532             :   DCHECK(node->opcode() == IrOpcode::kJSToNumber ||
    3533             :          node->opcode() == IrOpcode::kJSToNumberConvertBigInt ||
    3534             :          node->opcode() == IrOpcode::kJSToNumeric);
    3535             :   Node* value = node->InputAt(0);
    3536             :   Node* context = node->InputAt(1);
    3537             :   Node* frame_state = node->InputAt(2);
    3538             :   Node* effect = node->InputAt(3);
    3539             :   Node* control = node->InputAt(4);
    3540             : 
    3541        1413 :   Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
    3542             :   Node* branch0 =
    3543        1413 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
    3544             : 
    3545        1413 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    3546             :   Node* etrue0 = effect;
    3547             :   Node* vtrue0;
    3548             :   {
    3549        1413 :     vtrue0 = graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
    3550        1413 :     vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
    3551             :   }
    3552             : 
    3553        1413 :   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    3554             :   Node* efalse0 = effect;
    3555             :   Node* vfalse0;
    3556             :   {
    3557             :     Operator const* op =
    3558             :         node->opcode() == IrOpcode::kJSToNumber
    3559             :             ? (node->opcode() == IrOpcode::kJSToNumberConvertBigInt
    3560             :                    ? ToNumberConvertBigIntOperator()
    3561             :                    : ToNumberOperator())
    3562        1413 :             : ToNumericOperator();
    3563             :     Node* code = node->opcode() == IrOpcode::kJSToNumber
    3564             :                      ? ToNumberCode()
    3565             :                      : (node->opcode() == IrOpcode::kJSToNumberConvertBigInt
    3566             :                             ? ToNumberConvertBigIntCode()
    3567        1413 :                             : ToNumericCode());
    3568             :     vfalse0 = efalse0 = if_false0 = graph()->NewNode(
    3569             :         op, code, value, context, frame_state, efalse0, if_false0);
    3570             : 
    3571             :     // Update potential {IfException} uses of {node} to point to the above
    3572             :     // stub call node instead.
    3573        1413 :     Node* on_exception = nullptr;
    3574        1413 :     if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    3575           0 :       NodeProperties::ReplaceControlInput(on_exception, vfalse0);
    3576           0 :       NodeProperties::ReplaceEffectInput(on_exception, efalse0);
    3577           0 :       if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
    3578             :     }
    3579             : 
    3580        1413 :     Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
    3581        1413 :     Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
    3582             : 
    3583        1413 :     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    3584             :     Node* etrue1 = efalse0;
    3585             :     Node* vtrue1;
    3586             :     {
    3587             :       vtrue1 =
    3588        1413 :           graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
    3589        1413 :       vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
    3590             :     }
    3591             : 
    3592        1413 :     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    3593             :     Node* efalse1 = efalse0;
    3594             :     Node* vfalse1;
    3595             :     {
    3596             :       vfalse1 = efalse1 = graph()->NewNode(
    3597             :           simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
    3598        4239 :           efalse1, if_false1);
    3599             :     }
    3600             : 
    3601        1413 :     if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
    3602             :     efalse0 =
    3603        1413 :         graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
    3604             :     vfalse0 =
    3605             :         graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
    3606        1413 :                          vtrue1, vfalse1, if_false0);
    3607             :   }
    3608             : 
    3609        1413 :   control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
    3610        1413 :   effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
    3611             :   value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
    3612        1413 :                            vtrue0, vfalse0, control);
    3613             : 
    3614             :   // Replace effect and control uses appropriately.
    3615       11306 :   for (Edge edge : node->use_edges()) {
    3616        4240 :     if (NodeProperties::IsControlEdge(edge)) {
    3617        4239 :       if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
    3618           0 :         edge.from()->ReplaceUses(control);
    3619           0 :         edge.from()->Kill();
    3620             :       } else {
    3621             :         DCHECK_NE(IrOpcode::kIfException, edge.from()->opcode());
    3622        1413 :         edge.UpdateTo(control);
    3623             :       }
    3624        2827 :     } else if (NodeProperties::IsEffectEdge(edge)) {
    3625        1414 :       edge.UpdateTo(effect);
    3626             :     }
    3627             :   }
    3628             : 
    3629        1413 :   selector->DeferReplacement(node, value);
    3630        1413 : }
    3631             : 
    3632          75 : void SimplifiedLowering::DoJSToNumberOrNumericTruncatesToWord32(
    3633         150 :     Node* node, RepresentationSelector* selector) {
    3634             :   DCHECK(node->opcode() == IrOpcode::kJSToNumber ||
    3635             :          node->opcode() == IrOpcode::kJSToNumberConvertBigInt ||
    3636             :          node->opcode() == IrOpcode::kJSToNumeric);
    3637             :   Node* value = node->InputAt(0);
    3638             :   Node* context = node->InputAt(1);
    3639             :   Node* frame_state = node->InputAt(2);
    3640             :   Node* effect = node->InputAt(3);
    3641             :   Node* control = node->InputAt(4);
    3642             : 
    3643          75 :   Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
    3644             :   Node* branch0 =
    3645          75 :       graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
    3646             : 
    3647          75 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    3648             :   Node* etrue0 = effect;
    3649             :   Node* vtrue0 =
    3650          75 :       graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
    3651             : 
    3652          75 :   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    3653             :   Node* efalse0 = effect;
    3654             :   Node* vfalse0;
    3655             :   {
    3656             :     Operator const* op =
    3657             :         node->opcode() == IrOpcode::kJSToNumber
    3658             :             ? (node->opcode() == IrOpcode::kJSToNumberConvertBigInt
    3659             :                    ? ToNumberConvertBigIntOperator()
    3660             :                    : ToNumberOperator())
    3661          75 :             : ToNumericOperator();
    3662             :     Node* code = node->opcode() == IrOpcode::kJSToNumber
    3663             :                      ? ToNumberCode()
    3664             :                      : (node->opcode() == IrOpcode::kJSToNumberConvertBigInt
    3665             :                             ? ToNumberConvertBigIntCode()
    3666          75 :                             : ToNumericCode());
    3667             :     vfalse0 = efalse0 = if_false0 = graph()->NewNode(
    3668             :         op, code, value, context, frame_state, efalse0, if_false0);
    3669             : 
    3670             :     // Update potential {IfException} uses of {node} to point to the above
    3671             :     // stub call node instead.
    3672          75 :     Node* on_exception = nullptr;
    3673          75 :     if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
    3674           8 :       NodeProperties::ReplaceControlInput(on_exception, vfalse0);
    3675           8 :       NodeProperties::ReplaceEffectInput(on_exception, efalse0);
    3676           8 :       if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
    3677             :     }
    3678             : 
    3679          75 :     Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
    3680          75 :     Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
    3681             : 
    3682          75 :     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    3683             :     Node* etrue1 = efalse0;
    3684             :     Node* vtrue1 =
    3685          75 :         graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
    3686             : 
    3687          75 :     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    3688             :     Node* efalse1 = efalse0;
    3689             :     Node* vfalse1;
    3690             :     {
    3691             :       vfalse1 = efalse1 = graph()->NewNode(
    3692             :           simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
    3693         225 :           efalse1, if_false1);
    3694          75 :       vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
    3695             :     }
    3696             : 
    3697          75 :     if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
    3698             :     efalse0 =
    3699          75 :         graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
    3700             :     vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
    3701          75 :                                vtrue1, vfalse1, if_false0);
    3702             :   }
    3703             : 
    3704          75 :   control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
    3705          75 :   effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
    3706             :   value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
    3707          75 :                            vtrue0, vfalse0, control);
    3708             : 
    3709             :   // Replace effect and control uses appropriately.
    3710         534 :   for (Edge edge : node->use_edges()) {
    3711         192 :     if (NodeProperties::IsControlEdge(edge)) {
    3712         342 :       if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
    3713           8 :         edge.from()->ReplaceUses(control);
    3714          16 :         edge.from()->Kill();
    3715             :       } else {
    3716             :         DCHECK_NE(IrOpcode::kIfException, edge.from()->opcode());
    3717         106 :         edge.UpdateTo(control);
    3718             :       }
    3719          78 :     } else if (NodeProperties::IsEffectEdge(edge)) {
    3720          75 :       edge.UpdateTo(effect);
    3721             :     }
    3722             :   }
    3723             : 
    3724          75 :   selector->DeferReplacement(node, value);
    3725          75 : }
    3726             : 
    3727        3098 : Node* SimplifiedLowering::Float64Round(Node* const node) {
    3728        1549 :   Node* const one = jsgraph()->Float64Constant(1.0);
    3729        1549 :   Node* const one_half = jsgraph()->Float64Constant(0.5);
    3730             :   Node* const input = node->InputAt(0);
    3731             : 
    3732             :   // Round up towards Infinity, and adjust if the difference exceeds 0.5.
    3733             :   Node* result = graph()->NewNode(machine()->Float64RoundUp().placeholder(),
    3734        3098 :                                   node->InputAt(0));
    3735             :   return graph()->NewNode(
    3736             :       common()->Select(MachineRepresentation::kFloat64),
    3737             :       graph()->NewNode(
    3738             :           machine()->Float64LessThanOrEqual(),
    3739             :           graph()->NewNode(machine()->Float64Sub(), result, one_half), input),
    3740        7745 :       result, graph()->NewNode(machine()->Float64Sub(), result, one));
    3741             : }
    3742             : 
    3743          84 : Node* SimplifiedLowering::Float64Sign(Node* const node) {
    3744          28 :   Node* const minus_one = jsgraph()->Float64Constant(-1.0);
    3745          28 :   Node* const zero = jsgraph()->Float64Constant(0.0);
    3746          28 :   Node* const one = jsgraph()->Float64Constant(1.0);
    3747             : 
    3748             :   Node* const input = node->InputAt(0);
    3749             : 
    3750             :   return graph()->NewNode(
    3751             :       common()->Select(MachineRepresentation::kFloat64),
    3752             :       graph()->NewNode(machine()->Float64LessThan(), input, zero), minus_one,
    3753             :       graph()->NewNode(
    3754             :           common()->Select(MachineRepresentation::kFloat64),
    3755             :           graph()->NewNode(machine()->Float64LessThan(), zero, input), one,
    3756         140 :           input));
    3757             : }
    3758             : 
    3759         154 : Node* SimplifiedLowering::Int32Abs(Node* const node) {
    3760             :   Node* const input = node->InputAt(0);
    3761             : 
    3762             :   // Generate case for absolute integer value.
    3763             :   //
    3764             :   //    let sign = input >> 31 in
    3765             :   //    (input ^ sign) - sign
    3766             : 
    3767             :   Node* sign = graph()->NewNode(machine()->Word32Sar(), input,
    3768         154 :                                 jsgraph()->Int32Constant(31));
    3769             :   return graph()->NewNode(machine()->Int32Sub(),
    3770             :                           graph()->NewNode(machine()->Word32Xor(), input, sign),
    3771         231 :                           sign);
    3772             : }
    3773             : 
    3774        8334 : Node* SimplifiedLowering::Int32Div(Node* const node) {
    3775        2778 :   Int32BinopMatcher m(node);
    3776        2778 :   Node* const zero = jsgraph()->Int32Constant(0);
    3777        2778 :   Node* const minus_one = jsgraph()->Int32Constant(-1);
    3778             :   Node* const lhs = m.left().node();
    3779             :   Node* const rhs = m.right().node();
    3780             : 
    3781        2778 :   if (m.right().Is(-1)) {
    3782          28 :     return graph()->NewNode(machine()->Int32Sub(), zero, lhs);
    3783        2764 :   } else if (m.right().Is(0)) {
    3784             :     return rhs;
    3785        2764 :   } else if (machine()->Int32DivIsSafe() || m.right().HasValue()) {
    3786        4172 :     return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
    3787             :   }
    3788             : 
    3789             :   // General case for signed integer division.
    3790             :   //
    3791             :   //    if 0 < rhs then
    3792             :   //      lhs / rhs
    3793             :   //    else
    3794             :   //      if rhs < -1 then
    3795             :   //        lhs / rhs
    3796             :   //      else if rhs == 0 then
    3797             :   //        0
    3798             :   //      else
    3799             :   //        0 - lhs
    3800             :   //
    3801             :   // Note: We do not use the Diamond helper class here, because it really hurts
    3802             :   // readability with nested diamonds.
    3803         678 :   const Operator* const merge_op = common()->Merge(2);
    3804             :   const Operator* const phi_op =
    3805         678 :       common()->Phi(MachineRepresentation::kWord32, 2);
    3806             : 
    3807         678 :   Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
    3808             :   Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
    3809        1356 :                                    graph()->start());
    3810             : 
    3811         678 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    3812         678 :   Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0);
    3813             : 
    3814         678 :   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    3815             :   Node* false0;
    3816             :   {
    3817         678 :     Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
    3818         678 :     Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
    3819             : 
    3820         678 :     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    3821         678 :     Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1);
    3822             : 
    3823         678 :     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    3824             :     Node* false1;
    3825             :     {
    3826         678 :       Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
    3827         678 :       Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
    3828             : 
    3829         678 :       Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
    3830             :       Node* true2 = zero;
    3831             : 
    3832         678 :       Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
    3833         678 :       Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
    3834             : 
    3835             :       if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
    3836             :       false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
    3837             :     }
    3838             : 
    3839             :     if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
    3840             :     false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
    3841             :   }
    3842             : 
    3843             :   Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
    3844         678 :   return graph()->NewNode(phi_op, true0, false0, merge0);
    3845             : }
    3846             : 
    3847        6723 : Node* SimplifiedLowering::Int32Mod(Node* const node) {
    3848        2241 :   Int32BinopMatcher m(node);
    3849        2241 :   Node* const zero = jsgraph()->Int32Constant(0);
    3850        2241 :   Node* const minus_one = jsgraph()->Int32Constant(-1);
    3851             :   Node* const lhs = m.left().node();
    3852             :   Node* const rhs = m.right().node();
    3853             : 
    3854        4475 :   if (m.right().Is(-1) || m.right().Is(0)) {
    3855             :     return zero;
    3856        2234 :   } else if (m.right().HasValue()) {
    3857        6465 :     return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
    3858             :   }
    3859             : 
    3860             :   // General case for signed integer modulus, with optimization for (unknown)
    3861             :   // power of 2 right hand side.
    3862             :   //
    3863             :   //   if 0 < rhs then
    3864             :   //     msk = rhs - 1
    3865             :   //     if rhs & msk != 0 then
    3866             :   //       lhs % rhs
    3867             :   //     else
    3868             :   //       if lhs < 0 then
    3869             :   //         -(-lhs & msk)
    3870             :   //       else
    3871             :   //         lhs & msk
    3872             :   //   else
    3873             :   //     if rhs < -1 then
    3874             :   //       lhs % rhs
    3875             :   //     else
    3876             :   //       zero
    3877             :   //
    3878             :   // Note: We do not use the Diamond helper class here, because it really hurts
    3879             :   // readability with nested diamonds.
    3880          79 :   const Operator* const merge_op = common()->Merge(2);
    3881             :   const Operator* const phi_op =
    3882          79 :       common()->Phi(MachineRepresentation::kWord32, 2);
    3883             : 
    3884          79 :   Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
    3885             :   Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
    3886         158 :                                    graph()->start());
    3887             : 
    3888          79 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    3889             :   Node* true0;
    3890             :   {
    3891          79 :     Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
    3892             : 
    3893          79 :     Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
    3894          79 :     Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
    3895             : 
    3896          79 :     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    3897          79 :     Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
    3898             : 
    3899          79 :     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    3900             :     Node* false1;
    3901             :     {
    3902          79 :       Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
    3903             :       Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
    3904          79 :                                        check2, if_false1);
    3905             : 
    3906          79 :       Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
    3907             :       Node* true2 = graph()->NewNode(
    3908             :           machine()->Int32Sub(), zero,
    3909             :           graph()->NewNode(machine()->Word32And(),
    3910             :                            graph()->NewNode(machine()->Int32Sub(), zero, lhs),
    3911         237 :                            msk));
    3912             : 
    3913          79 :       Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
    3914          79 :       Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
    3915             : 
    3916             :       if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
    3917             :       false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
    3918             :     }
    3919             : 
    3920             :     if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
    3921             :     true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
    3922             :   }
    3923             : 
    3924          79 :   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    3925             :   Node* false0;
    3926             :   {
    3927          79 :     Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
    3928             :     Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
    3929          79 :                                      check1, if_false0);
    3930             : 
    3931          79 :     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    3932          79 :     Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
    3933             : 
    3934          79 :     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    3935             :     Node* false1 = zero;
    3936             : 
    3937             :     if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
    3938             :     false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
    3939             :   }
    3940             : 
    3941             :   Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
    3942          79 :   return graph()->NewNode(phi_op, true0, false0, merge0);
    3943             : }
    3944             : 
    3945          21 : Node* SimplifiedLowering::Int32Sign(Node* const node) {
    3946           7 :   Node* const minus_one = jsgraph()->Int32Constant(-1);
    3947           7 :   Node* const zero = jsgraph()->Int32Constant(0);
    3948           7 :   Node* const one = jsgraph()->Int32Constant(1);
    3949             : 
    3950             :   Node* const input = node->InputAt(0);
    3951             : 
    3952             :   return graph()->NewNode(
    3953             :       common()->Select(MachineRepresentation::kWord32),
    3954             :       graph()->NewNode(machine()->Int32LessThan(), input, zero), minus_one,
    3955             :       graph()->NewNode(
    3956             :           common()->Select(MachineRepresentation::kWord32),
    3957             :           graph()->NewNode(machine()->Int32LessThan(), zero, input), one,
    3958          35 :           zero));
    3959             : }
    3960             : 
    3961         502 : Node* SimplifiedLowering::Uint32Div(Node* const node) {
    3962         251 :   Uint32BinopMatcher m(node);
    3963         251 :   Node* const zero = jsgraph()->Uint32Constant(0);
    3964             :   Node* const lhs = m.left().node();
    3965             :   Node* const rhs = m.right().node();
    3966             : 
    3967         251 :   if (m.right().Is(0)) {
    3968             :     return zero;
    3969         244 :   } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) {
    3970         394 :     return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
    3971             :   }
    3972             : 
    3973          47 :   Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
    3974          47 :   Diamond d(graph(), common(), check, BranchHint::kFalse);
    3975          94 :   Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
    3976          47 :   return d.Phi(MachineRepresentation::kWord32, zero, div);
    3977             : }
    3978             : 
    3979         720 : Node* SimplifiedLowering::Uint32Mod(Node* const node) {
    3980         240 :   Uint32BinopMatcher m(node);
    3981         240 :   Node* const minus_one = jsgraph()->Int32Constant(-1);
    3982         240 :   Node* const zero = jsgraph()->Uint32Constant(0);
    3983             :   Node* const lhs = m.left().node();
    3984             :   Node* const rhs = m.right().node();
    3985             : 
    3986         240 :   if (m.right().Is(0)) {
    3987             :     return zero;
    3988         240 :   } else if (m.right().HasValue()) {
    3989         615 :     return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
    3990             :   }
    3991             : 
    3992             :   // General case for unsigned integer modulus, with optimization for (unknown)
    3993             :   // power of 2 right hand side.
    3994             :   //
    3995             :   //   if rhs == 0 then
    3996             :   //     zero
    3997             :   //   else
    3998             :   //     msk = rhs - 1
    3999             :   //     if rhs & msk != 0 then
    4000             :   //       lhs % rhs
    4001             :   //     else
    4002             :   //       lhs & msk
    4003             :   //
    4004             :   // Note: We do not use the Diamond helper class here, because it really hurts
    4005             :   // readability with nested diamonds.
    4006          35 :   const Operator* const merge_op = common()->Merge(2);
    4007             :   const Operator* const phi_op =
    4008          35 :       common()->Phi(MachineRepresentation::kWord32, 2);
    4009             : 
    4010          35 :   Node* check0 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
    4011             :   Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse), check0,
    4012          70 :                                    graph()->start());
    4013             : 
    4014          35 :   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
    4015             :   Node* true0 = zero;
    4016             : 
    4017          35 :   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
    4018             :   Node* false0;
    4019             :   {
    4020          35 :     Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
    4021             : 
    4022          35 :     Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
    4023          35 :     Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
    4024             : 
    4025          35 :     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
    4026          35 :     Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1);
    4027             : 
    4028          35 :     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
    4029          35 :     Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk);
    4030             : 
    4031             :     if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
    4032             :     false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
    4033             :   }
    4034             : 
    4035             :   Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
    4036          35 :   return graph()->NewNode(phi_op, true0, false0, merge0);
    4037             : }
    4038             : 
    4039        2320 : void SimplifiedLowering::DoMax(Node* node, Operator const* op,
    4040             :                                MachineRepresentation rep) {
    4041             :   Node* const lhs = node->InputAt(0);
    4042             :   Node* const rhs = node->InputAt(1);
    4043             : 
    4044        2320 :   node->ReplaceInput(0, graph()->NewNode(op, lhs, rhs));
    4045             :   DCHECK_EQ(rhs, node->InputAt(1));
    4046        2320 :   node->AppendInput(graph()->zone(), lhs);
    4047        2320 :   NodeProperties::ChangeOp(node, common()->Select(rep));
    4048        2320 : }
    4049             : 
    4050        3113 : void SimplifiedLowering::DoMin(Node* node, Operator const* op,
    4051             :                                MachineRepresentation rep) {
    4052             :   Node* const lhs = node->InputAt(0);
    4053             :   Node* const rhs = node->InputAt(1);
    4054             : 
    4055        3113 :   node->InsertInput(graph()->zone(), 0, graph()->NewNode(op, lhs, rhs));
    4056             :   DCHECK_EQ(lhs, node->InputAt(1));
    4057             :   DCHECK_EQ(rhs, node->InputAt(2));
    4058        3113 :   NodeProperties::ChangeOp(node, common()->Select(rep));
    4059        3113 : }
    4060             : 
    4061         300 : void SimplifiedLowering::DoIntegral32ToBit(Node* node) {
    4062             :   Node* const input = node->InputAt(0);
    4063         150 :   Node* const zero = jsgraph()->Int32Constant(0);
    4064         150 :   Operator const* const op = machine()->Word32Equal();
    4065             : 
    4066         150 :   node->ReplaceInput(0, graph()->NewNode(op, input, zero));
    4067         150 :   node->AppendInput(graph()->zone(), zero);
    4068         150 :   NodeProperties::ChangeOp(node, op);
    4069         150 : }
    4070             : 
    4071           0 : void SimplifiedLowering::DoOrderedNumberToBit(Node* node) {
    4072             :   Node* const input = node->InputAt(0);
    4073             : 
    4074             :   node->ReplaceInput(0, graph()->NewNode(machine()->Float64Equal(), input,
    4075           0 :                                          jsgraph()->Float64Constant(0.0)));
    4076           0 :   node->AppendInput(graph()->zone(), jsgraph()->Int32Constant(0));
    4077           0 :   NodeProperties::ChangeOp(node, machine()->Word32Equal());
    4078           0 : }
    4079             : 
    4080          64 : void SimplifiedLowering::DoNumberToBit(Node* node) {
    4081             :   Node* const input = node->InputAt(0);
    4082             : 
    4083          32 :   node->ReplaceInput(0, jsgraph()->Float64Constant(0.0));
    4084             :   node->AppendInput(graph()->zone(),
    4085          64 :                     graph()->NewNode(machine()->Float64Abs(), input));
    4086          32 :   NodeProperties::ChangeOp(node, machine()->Float64LessThan());
    4087          32 : }
    4088             : 
    4089          63 : void SimplifiedLowering::DoIntegerToUint8Clamped(Node* node) {
    4090             :   Node* const input = node->InputAt(0);
    4091          21 :   Node* const min = jsgraph()->Float64Constant(0.0);
    4092          21 :   Node* const max = jsgraph()->Float64Constant(255.0);
    4093             : 
    4094             :   node->ReplaceInput(
    4095          42 :       0, graph()->NewNode(machine()->Float64LessThan(), min, input));
    4096             :   node->AppendInput(
    4097             :       graph()->zone(),
    4098             :       graph()->NewNode(
    4099             :           common()->Select(MachineRepresentation::kFloat64),
    4100             :           graph()->NewNode(machine()->Float64LessThan(), input, max), input,
    4101          63 :           max));
    4102          21 :   node->AppendInput(graph()->zone(), min);
    4103             :   NodeProperties::ChangeOp(node,
    4104          21 :                            common()->Select(MachineRepresentation::kFloat64));
    4105          21 : }
    4106             : 
    4107         879 : void SimplifiedLowering::DoNumberToUint8Clamped(Node* node) {
    4108             :   Node* const input = node->InputAt(0);
    4109         293 :   Node* const min = jsgraph()->Float64Constant(0.0);
    4110         293 :   Node* const max = jsgraph()->Float64Constant(255.0);
    4111             : 
    4112             :   node->ReplaceInput(
    4113             :       0, graph()->NewNode(
    4114             :              common()->Select(MachineRepresentation::kFloat64),
    4115             :              graph()->NewNode(machine()->Float64LessThan(), min, input),
    4116             :              graph()->NewNode(
    4117             :                  common()->Select(MachineRepresentation::kFloat64),
    4118             :                  graph()->NewNode(machine()->Float64LessThan(), input, max),
    4119             :                  input, max),
    4120        1465 :              min));
    4121             :   NodeProperties::ChangeOp(node,
    4122         293 :                            machine()->Float64RoundTiesEven().placeholder());
    4123         293 : }
    4124             : 
    4125         189 : void SimplifiedLowering::DoSigned32ToUint8Clamped(Node* node) {
    4126             :   Node* const input = node->InputAt(0);
    4127          63 :   Node* const min = jsgraph()->Int32Constant(0);
    4128          63 :   Node* const max = jsgraph()->Int32Constant(255);
    4129             : 
    4130             :   node->ReplaceInput(
    4131         126 :       0, graph()->NewNode(machine()->Int32LessThanOrEqual(), input, max));
    4132             :   node->AppendInput(
    4133             :       graph()->zone(),
    4134             :       graph()->NewNode(common()->Select(MachineRepresentation::kWord32),
    4135             :                        graph()->NewNode(machine()->Int32LessThan(), input, min),
    4136         189 :                        min, input));
    4137          63 :   node->AppendInput(graph()->zone(), max);
    4138             :   NodeProperties::ChangeOp(node,
    4139          63 :                            common()->Select(MachineRepresentation::kWord32));
    4140          63 : }
    4141             : 
    4142         142 : void SimplifiedLowering::DoUnsigned32ToUint8Clamped(Node* node) {
    4143             :   Node* const input = node->InputAt(0);
    4144          71 :   Node* const max = jsgraph()->Uint32Constant(255u);
    4145             : 
    4146             :   node->ReplaceInput(
    4147         142 :       0, graph()->NewNode(machine()->Uint32LessThanOrEqual(), input, max));
    4148          71 :   node->AppendInput(graph()->zone(), input);
    4149          71 :   node->AppendInput(graph()->zone(), max);
    4150             :   NodeProperties::ChangeOp(node,
    4151          71 :                            common()->Select(MachineRepresentation::kWord32));
    4152          71 : }
    4153             : 
    4154        4272 : Node* SimplifiedLowering::ToNumberCode() {
    4155        1424 :   if (!to_number_code_.is_set()) {
    4156        1424 :     Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumber);
    4157        2848 :     to_number_code_.set(jsgraph()->HeapConstant(callable.code()));
    4158             :   }
    4159        1424 :   return to_number_code_.get();
    4160             : }
    4161             : 
    4162         192 : Node* SimplifiedLowering::ToNumberConvertBigIntCode() {
    4163          64 :   if (!to_number_convert_big_int_code_.is_set()) {
    4164             :     Callable callable =
    4165          64 :         Builtins::CallableFor(isolate(), Builtins::kToNumberConvertBigInt);
    4166             :     to_number_convert_big_int_code_.set(
    4167         128 :         jsgraph()->HeapConstant(callable.code()));
    4168             :   }
    4169          64 :   return to_number_convert_big_int_code_.get();
    4170             : }
    4171             : 
    4172           0 : Node* SimplifiedLowering::ToNumericCode() {
    4173           0 :   if (!to_numeric_code_.is_set()) {
    4174           0 :     Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumeric);
    4175           0 :     to_numeric_code_.set(jsgraph()->HeapConstant(callable.code()));
    4176             :   }
    4177           0 :   return to_numeric_code_.get();
    4178             : }
    4179             : 
    4180        2848 : Operator const* SimplifiedLowering::ToNumberOperator() {
    4181        1424 :   if (!to_number_operator_.is_set()) {
    4182        1424 :     Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumber);
    4183             :     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    4184             :     auto call_descriptor = Linkage::GetStubCallDescriptor(
    4185             :         graph()->zone(), callable.descriptor(),
    4186             :         callable.descriptor().GetStackParameterCount(), flags,
    4187        2848 :         Operator::kNoProperties);
    4188        1424 :     to_number_operator_.set(common()->Call(call_descriptor));
    4189             :   }
    4190        1424 :   return to_number_operator_.get();
    4191             : }
    4192             : 
    4193           0 : Operator const* SimplifiedLowering::ToNumberConvertBigIntOperator() {
    4194           0 :   if (!to_number_convert_big_int_operator_.is_set()) {
    4195             :     Callable callable =
    4196           0 :         Builtins::CallableFor(isolate(), Builtins::kToNumberConvertBigInt);
    4197             :     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    4198             :     auto call_descriptor = Linkage::GetStubCallDescriptor(
    4199             :         graph()->zone(), callable.descriptor(),
    4200             :         callable.descriptor().GetStackParameterCount(), flags,
    4201           0 :         Operator::kNoProperties);
    4202           0 :     to_number_convert_big_int_operator_.set(common()->Call(call_descriptor));
    4203             :   }
    4204           0 :   return to_number_convert_big_int_operator_.get();
    4205             : }
    4206             : 
    4207         128 : Operator const* SimplifiedLowering::ToNumericOperator() {
    4208          64 :   if (!to_numeric_operator_.is_set()) {
    4209          64 :     Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumeric);
    4210             :     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
    4211             :     auto call_descriptor = Linkage::GetStubCallDescriptor(
    4212             :         graph()->zone(), callable.descriptor(),
    4213             :         callable.descriptor().GetStackParameterCount(), flags,
    4214         128 :         Operator::kNoProperties);
    4215          64 :     to_numeric_operator_.set(common()->Call(call_descriptor));
    4216             :   }
    4217          64 :   return to_numeric_operator_.get();
    4218             : }
    4219             : 
    4220             : #undef TRACE
    4221             : 
    4222             : }  // namespace compiler
    4223             : }  // namespace internal
    4224      178779 : }  // namespace v8

Generated by: LCOV version 1.10