Home | History | Annotate | Download | only in compiler
      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-properties.h"
     19 #include "src/compiler/operation-typer.h"
     20 #include "src/compiler/operator-properties.h"
     21 #include "src/compiler/representation-change.h"
     22 #include "src/compiler/simplified-operator.h"
     23 #include "src/compiler/type-cache.h"
     24 #include "src/conversions-inl.h"
     25 #include "src/objects.h"
     26 
     27 namespace v8 {
     28 namespace internal {
     29 namespace compiler {
     30 
     31 // Macro for outputting trace information from representation inference.
     32 #define TRACE(...)                                      \
     33   do {                                                  \
     34     if (FLAG_trace_representation) PrintF(__VA_ARGS__); \
     35   } while (false)
     36 
     37 // Representation selection and lowering of {Simplified} operators to machine
     38 // operators are interwined. We use a fixpoint calculation to compute both the
     39 // output representation and the best possible lowering for {Simplified} nodes.
     40 // Representation change insertion ensures that all values are in the correct
     41 // machine representation after this phase, as dictated by the machine
     42 // operators themselves.
     43 enum Phase {
     44   // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information
     45   //     backwards from uses to definitions, around cycles in phis, according
     46   //     to local rules for each operator.
     47   //     During this phase, the usage information for a node determines the best
     48   //     possible lowering for each operator so far, and that in turn determines
     49   //     the output representation.
     50   //     Therefore, to be correct, this phase must iterate to a fixpoint before
     51   //     the next phase can begin.
     52   PROPAGATE,
     53 
     54   // 2.) RETYPE: Propagate types from type feedback forwards.
     55   RETYPE,
     56 
     57   // 3.) LOWER: perform lowering for all {Simplified} nodes by replacing some
     58   //     operators for some nodes, expanding some nodes to multiple nodes, or
     59   //     removing some (redundant) nodes.
     60   //     During this phase, use the {RepresentationChanger} to insert
     61   //     representation changes between uses that demand a particular
     62   //     representation and nodes that produce a different representation.
     63   LOWER
     64 };
     65 
     66 namespace {
     67 
     68 MachineRepresentation MachineRepresentationFromArrayType(
     69     ExternalArrayType array_type) {
     70   switch (array_type) {
     71     case kExternalUint8Array:
     72     case kExternalUint8ClampedArray:
     73     case kExternalInt8Array:
     74       return MachineRepresentation::kWord8;
     75     case kExternalUint16Array:
     76     case kExternalInt16Array:
     77       return MachineRepresentation::kWord16;
     78     case kExternalUint32Array:
     79     case kExternalInt32Array:
     80       return MachineRepresentation::kWord32;
     81     case kExternalFloat32Array:
     82       return MachineRepresentation::kFloat32;
     83     case kExternalFloat64Array:
     84       return MachineRepresentation::kFloat64;
     85   }
     86   UNREACHABLE();
     87   return MachineRepresentation::kNone;
     88 }
     89 
     90 UseInfo CheckedUseInfoAsWord32FromHint(
     91     NumberOperationHint hint, CheckForMinusZeroMode minus_zero_mode =
     92                                   CheckForMinusZeroMode::kCheckForMinusZero) {
     93   switch (hint) {
     94     case NumberOperationHint::kSignedSmall:
     95       return UseInfo::CheckedSignedSmallAsWord32(minus_zero_mode);
     96     case NumberOperationHint::kSigned32:
     97       return UseInfo::CheckedSigned32AsWord32(minus_zero_mode);
     98     case NumberOperationHint::kNumber:
     99       return UseInfo::CheckedNumberAsWord32();
    100     case NumberOperationHint::kNumberOrOddball:
    101       return UseInfo::CheckedNumberOrOddballAsWord32();
    102   }
    103   UNREACHABLE();
    104   return UseInfo::None();
    105 }
    106 
    107 UseInfo CheckedUseInfoAsFloat64FromHint(NumberOperationHint hint) {
    108   switch (hint) {
    109     case NumberOperationHint::kSignedSmall:
    110     case NumberOperationHint::kSigned32:
    111       // Not used currently.
    112       UNREACHABLE();
    113       break;
    114     case NumberOperationHint::kNumber:
    115       return UseInfo::CheckedNumberAsFloat64();
    116     case NumberOperationHint::kNumberOrOddball:
    117       return UseInfo::CheckedNumberOrOddballAsFloat64();
    118   }
    119   UNREACHABLE();
    120   return UseInfo::None();
    121 }
    122 
    123 UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) {
    124   switch (rep) {
    125     case MachineRepresentation::kTaggedSigned:
    126     case MachineRepresentation::kTaggedPointer:
    127     case MachineRepresentation::kTagged:
    128       return UseInfo::AnyTagged();
    129     case MachineRepresentation::kFloat64:
    130       return UseInfo::TruncatingFloat64();
    131     case MachineRepresentation::kFloat32:
    132       return UseInfo::Float32();
    133     case MachineRepresentation::kWord64:
    134       return UseInfo::TruncatingWord64();
    135     case MachineRepresentation::kWord8:
    136     case MachineRepresentation::kWord16:
    137     case MachineRepresentation::kWord32:
    138       return UseInfo::TruncatingWord32();
    139     case MachineRepresentation::kBit:
    140       return UseInfo::Bool();
    141     case MachineRepresentation::kSimd128:
    142     case MachineRepresentation::kSimd1x4:
    143     case MachineRepresentation::kSimd1x8:
    144     case MachineRepresentation::kSimd1x16:
    145     case MachineRepresentation::kNone:
    146       break;
    147   }
    148   UNREACHABLE();
    149   return UseInfo::None();
    150 }
    151 
    152 
    153 UseInfo UseInfoForBasePointer(const FieldAccess& access) {
    154   return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
    155 }
    156 
    157 
    158 UseInfo UseInfoForBasePointer(const ElementAccess& access) {
    159   return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
    160 }
    161 
    162 void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) {
    163   for (Edge edge : node->use_edges()) {
    164     if (NodeProperties::IsControlEdge(edge)) {
    165       edge.UpdateTo(control);
    166     } else if (NodeProperties::IsEffectEdge(edge)) {
    167       edge.UpdateTo(effect);
    168     } else {
    169       DCHECK(NodeProperties::IsValueEdge(edge) ||
    170              NodeProperties::IsContextEdge(edge));
    171     }
    172   }
    173 }
    174 
    175 void ChangeToPureOp(Node* node, const Operator* new_op) {
    176   DCHECK(new_op->HasProperty(Operator::kPure));
    177   if (node->op()->EffectInputCount() > 0) {
    178     DCHECK_LT(0, node->op()->ControlInputCount());
    179     // Disconnect the node from effect and control chains.
    180     Node* control = NodeProperties::GetControlInput(node);
    181     Node* effect = NodeProperties::GetEffectInput(node);
    182     ReplaceEffectControlUses(node, effect, control);
    183     node->TrimInputCount(new_op->ValueInputCount());
    184   } else {
    185     DCHECK_EQ(0, node->op()->ControlInputCount());
    186   }
    187   NodeProperties::ChangeOp(node, new_op);
    188 }
    189 
    190 #ifdef DEBUG
    191 // Helpers for monotonicity checking.
    192 class InputUseInfos {
    193  public:
    194   explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
    195 
    196   void SetAndCheckInput(Node* node, int index, UseInfo use_info) {
    197     if (input_use_infos_.empty()) {
    198       input_use_infos_.resize(node->InputCount(), UseInfo::None());
    199     }
    200     // Check that the new use informatin is a super-type of the old
    201     // one.
    202     CHECK(IsUseLessGeneral(input_use_infos_[index], use_info));
    203     input_use_infos_[index] = use_info;
    204   }
    205 
    206  private:
    207   ZoneVector<UseInfo> input_use_infos_;
    208 
    209   static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
    210     return use1.truncation().IsLessGeneralThan(use2.truncation());
    211   }
    212 };
    213 
    214 #endif  // DEBUG
    215 
    216 bool CanOverflowSigned32(const Operator* op, Type* left, Type* right,
    217                          Zone* type_zone) {
    218   // We assume the inputs are checked Signed32 (or known statically
    219   // to be Signed32). Technically, theinputs could also be minus zero, but
    220   // that cannot cause overflow.
    221   left = Type::Intersect(left, Type::Signed32(), type_zone);
    222   right = Type::Intersect(right, Type::Signed32(), type_zone);
    223   if (!left->IsInhabited() || !right->IsInhabited()) return false;
    224   switch (op->opcode()) {
    225     case IrOpcode::kSpeculativeNumberAdd:
    226       return (left->Max() + right->Max() > kMaxInt) ||
    227              (left->Min() + right->Min() < kMinInt);
    228 
    229     case IrOpcode::kSpeculativeNumberSubtract:
    230       return (left->Max() - right->Min() > kMaxInt) ||
    231              (left->Min() - right->Max() < kMinInt);
    232 
    233     default:
    234       UNREACHABLE();
    235   }
    236   return true;
    237 }
    238 
    239 }  // namespace
    240 
    241 class RepresentationSelector {
    242  public:
    243   // Information for each node tracked during the fixpoint.
    244   class NodeInfo final {
    245    public:
    246     // Adds new use to the node. Returns true if something has changed
    247     // and the node has to be requeued.
    248     bool AddUse(UseInfo info) {
    249       Truncation old_truncation = truncation_;
    250       truncation_ = Truncation::Generalize(truncation_, info.truncation());
    251       return truncation_ != old_truncation;
    252     }
    253 
    254     void set_queued() { state_ = kQueued; }
    255     void set_visited() { state_ = kVisited; }
    256     void set_pushed() { state_ = kPushed; }
    257     void reset_state() { state_ = kUnvisited; }
    258     bool visited() const { return state_ == kVisited; }
    259     bool queued() const { return state_ == kQueued; }
    260     bool unvisited() const { return state_ == kUnvisited; }
    261     Truncation truncation() const { return truncation_; }
    262     void set_output(MachineRepresentation output) { representation_ = output; }
    263 
    264     MachineRepresentation representation() const { return representation_; }
    265 
    266     // Helpers for feedback typing.
    267     void set_feedback_type(Type* type) { feedback_type_ = type; }
    268     Type* feedback_type() const { return feedback_type_; }
    269     void set_weakened() { weakened_ = true; }
    270     bool weakened() const { return weakened_; }
    271     void set_restriction_type(Type* type) { restriction_type_ = type; }
    272     Type* restriction_type() const { return restriction_type_; }
    273 
    274    private:
    275     enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued };
    276     State state_ = kUnvisited;
    277     MachineRepresentation representation_ =
    278         MachineRepresentation::kNone;             // Output representation.
    279     Truncation truncation_ = Truncation::None();  // Information about uses.
    280 
    281     Type* restriction_type_ = Type::Any();
    282     Type* feedback_type_ = nullptr;
    283     bool weakened_ = false;
    284   };
    285 
    286   RepresentationSelector(JSGraph* jsgraph, Zone* zone,
    287                          RepresentationChanger* changer,
    288                          SourcePositionTable* source_positions)
    289       : jsgraph_(jsgraph),
    290         zone_(zone),
    291         count_(jsgraph->graph()->NodeCount()),
    292         info_(count_, zone),
    293 #ifdef DEBUG
    294         node_input_use_infos_(count_, InputUseInfos(zone), zone),
    295 #endif
    296         nodes_(zone),
    297         replacements_(zone),
    298         phase_(PROPAGATE),
    299         changer_(changer),
    300         queue_(zone),
    301         typing_stack_(zone),
    302         source_positions_(source_positions),
    303         type_cache_(TypeCache::Get()),
    304         op_typer_(jsgraph->isolate(), graph_zone()) {
    305   }
    306 
    307   // Forward propagation of types from type feedback.
    308   void RunTypePropagationPhase() {
    309     // Run type propagation.
    310     TRACE("--{Type propagation phase}--\n");
    311     phase_ = RETYPE;
    312     ResetNodeInfoState();
    313 
    314     DCHECK(typing_stack_.empty());
    315     typing_stack_.push({graph()->end(), 0});
    316     GetInfo(graph()->end())->set_pushed();
    317     while (!typing_stack_.empty()) {
    318       NodeState& current = typing_stack_.top();
    319 
    320       // If there is an unvisited input, push it and continue.
    321       bool pushed_unvisited = false;
    322       while (current.input_index < current.node->InputCount()) {
    323         Node* input = current.node->InputAt(current.input_index);
    324         NodeInfo* input_info = GetInfo(input);
    325         current.input_index++;
    326         if (input_info->unvisited()) {
    327           input_info->set_pushed();
    328           typing_stack_.push({input, 0});
    329           pushed_unvisited = true;
    330           break;
    331         }
    332       }
    333       if (pushed_unvisited) continue;
    334 
    335       // Process the top of the stack.
    336       Node* node = current.node;
    337       typing_stack_.pop();
    338       NodeInfo* info = GetInfo(node);
    339       info->set_visited();
    340       bool updated = UpdateFeedbackType(node);
    341       TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
    342       VisitNode(node, info->truncation(), nullptr);
    343       TRACE("  ==> output ");
    344       PrintOutputInfo(info);
    345       TRACE("\n");
    346       if (updated) {
    347         for (Node* const user : node->uses()) {
    348           if (GetInfo(user)->visited()) {
    349             GetInfo(user)->set_queued();
    350             queue_.push(user);
    351           }
    352         }
    353       }
    354     }
    355 
    356     // Process the revisit queue.
    357     while (!queue_.empty()) {
    358       Node* node = queue_.front();
    359       queue_.pop();
    360       NodeInfo* info = GetInfo(node);
    361       info->set_visited();
    362       bool updated = UpdateFeedbackType(node);
    363       TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
    364       VisitNode(node, info->truncation(), nullptr);
    365       TRACE("  ==> output ");
    366       PrintOutputInfo(info);
    367       TRACE("\n");
    368       if (updated) {
    369         for (Node* const user : node->uses()) {
    370           if (GetInfo(user)->visited()) {
    371             GetInfo(user)->set_queued();
    372             queue_.push(user);
    373           }
    374         }
    375       }
    376     }
    377   }
    378 
    379   void ResetNodeInfoState() {
    380     // Clean up for the next phase.
    381     for (NodeInfo& info : info_) {
    382       info.reset_state();
    383     }
    384   }
    385 
    386   Type* TypeOf(Node* node) {
    387     Type* type = GetInfo(node)->feedback_type();
    388     return type == nullptr ? NodeProperties::GetType(node) : type;
    389   }
    390 
    391   Type* FeedbackTypeOf(Node* node) {
    392     Type* type = GetInfo(node)->feedback_type();
    393     return type == nullptr ? Type::None() : type;
    394   }
    395 
    396   Type* TypePhi(Node* node) {
    397     int arity = node->op()->ValueInputCount();
    398     Type* type = FeedbackTypeOf(node->InputAt(0));
    399     for (int i = 1; i < arity; ++i) {
    400       type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i)));
    401     }
    402     return type;
    403   }
    404 
    405   Type* TypeSelect(Node* node) {
    406     return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)),
    407                            FeedbackTypeOf(node->InputAt(2)));
    408   }
    409 
    410   bool UpdateFeedbackType(Node* node) {
    411     if (node->op()->ValueOutputCount() == 0) return false;
    412 
    413     NodeInfo* info = GetInfo(node);
    414     Type* type = info->feedback_type();
    415     Type* new_type = type;
    416 
    417     // For any non-phi node just wait until we get all inputs typed. We only
    418     // allow untyped inputs for phi nodes because phis are the only places
    419     // where cycles need to be broken.
    420     if (node->opcode() != IrOpcode::kPhi) {
    421       for (int i = 0; i < node->op()->ValueInputCount(); i++) {
    422         if (GetInfo(node->InputAt(i))->feedback_type() == nullptr) {
    423           return false;
    424         }
    425       }
    426     }
    427 
    428     switch (node->opcode()) {
    429 #define DECLARE_CASE(Name)                                       \
    430   case IrOpcode::k##Name: {                                      \
    431     new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0)),  \
    432                               FeedbackTypeOf(node->InputAt(1))); \
    433     break;                                                       \
    434   }
    435       SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE)
    436 #undef DECLARE_CASE
    437 
    438 #define DECLARE_CASE(Name)                                                \
    439   case IrOpcode::k##Name: {                                               \
    440     new_type =                                                            \
    441         Type::Intersect(op_typer_.Name(FeedbackTypeOf(node->InputAt(0)),  \
    442                                        FeedbackTypeOf(node->InputAt(1))), \
    443                         info->restriction_type(), graph_zone());          \
    444     break;                                                                \
    445   }
    446       SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE)
    447 #undef DECLARE_CASE
    448 
    449 #define DECLARE_CASE(Name)                                       \
    450   case IrOpcode::k##Name: {                                      \
    451     new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0))); \
    452     break;                                                       \
    453   }
    454       SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE)
    455 #undef DECLARE_CASE
    456 
    457       case IrOpcode::kPlainPrimitiveToNumber:
    458         new_type = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
    459         break;
    460 
    461       case IrOpcode::kPhi: {
    462         new_type = TypePhi(node);
    463         if (type != nullptr) {
    464           new_type = Weaken(node, type, new_type);
    465         }
    466         break;
    467       }
    468 
    469       case IrOpcode::kTypeGuard: {
    470         new_type = op_typer_.TypeTypeGuard(node->op(),
    471                                            FeedbackTypeOf(node->InputAt(0)));
    472         break;
    473       }
    474 
    475       case IrOpcode::kSelect: {
    476         new_type = TypeSelect(node);
    477         break;
    478       }
    479 
    480       default:
    481         // Shortcut for operations that we do not handle.
    482         if (type == nullptr) {
    483           GetInfo(node)->set_feedback_type(NodeProperties::GetType(node));
    484           return true;
    485         }
    486         return false;
    487     }
    488     // We need to guarantee that the feedback type is a subtype of the upper
    489     // bound. Naively that should hold, but weakening can actually produce
    490     // a bigger type if we are unlucky with ordering of phi typing. To be
    491     // really sure, just intersect the upper bound with the feedback type.
    492     new_type = Type::Intersect(GetUpperBound(node), new_type, graph_zone());
    493 
    494     if (type != nullptr && new_type->Is(type)) return false;
    495     GetInfo(node)->set_feedback_type(new_type);
    496     if (FLAG_trace_representation) {
    497       PrintNodeFeedbackType(node);
    498     }
    499     return true;
    500   }
    501 
    502   void PrintNodeFeedbackType(Node* n) {
    503     OFStream os(stdout);
    504     os << "#" << n->id() << ":" << *n->op() << "(";
    505     int j = 0;
    506     for (Node* const i : n->inputs()) {
    507       if (j++ > 0) os << ", ";
    508       os << "#" << i->id() << ":" << i->op()->mnemonic();
    509     }
    510     os << ")";
    511     if (NodeProperties::IsTyped(n)) {
    512       os << "  [Static type: ";
    513       Type* static_type = NodeProperties::GetType(n);
    514       static_type->PrintTo(os);
    515       Type* feedback_type = GetInfo(n)->feedback_type();
    516       if (feedback_type != nullptr && feedback_type != static_type) {
    517         os << ", Feedback type: ";
    518         feedback_type->PrintTo(os);
    519       }
    520       os << "]";
    521     }
    522     os << std::endl;
    523   }
    524 
    525   Type* Weaken(Node* node, Type* previous_type, Type* current_type) {
    526     // If the types have nothing to do with integers, return the types.
    527     Type* const integer = type_cache_.kInteger;
    528     if (!previous_type->Maybe(integer)) {
    529       return current_type;
    530     }
    531     DCHECK(current_type->Maybe(integer));
    532 
    533     Type* current_integer =
    534         Type::Intersect(current_type, integer, graph_zone());
    535     Type* previous_integer =
    536         Type::Intersect(previous_type, integer, graph_zone());
    537 
    538     // Once we start weakening a node, we should always weaken.
    539     if (!GetInfo(node)->weakened()) {
    540       // Only weaken if there is range involved; we should converge quickly
    541       // for all other types (the exception is a union of many constants,
    542       // but we currently do not increase the number of constants in unions).
    543       Type* previous = previous_integer->GetRange();
    544       Type* current = current_integer->GetRange();
    545       if (current == nullptr || previous == nullptr) {
    546         return current_type;
    547       }
    548       // Range is involved => we are weakening.
    549       GetInfo(node)->set_weakened();
    550     }
    551 
    552     return Type::Union(current_type,
    553                        op_typer_.WeakenRange(previous_integer, current_integer),
    554                        graph_zone());
    555   }
    556 
    557   // Backward propagation of truncations.
    558   void RunTruncationPropagationPhase() {
    559     // Run propagation phase to a fixpoint.
    560     TRACE("--{Propagation phase}--\n");
    561     phase_ = PROPAGATE;
    562     EnqueueInitial(jsgraph_->graph()->end());
    563     // Process nodes from the queue until it is empty.
    564     while (!queue_.empty()) {
    565       Node* node = queue_.front();
    566       NodeInfo* info = GetInfo(node);
    567       queue_.pop();
    568       info->set_visited();
    569       TRACE(" visit #%d: %s (trunc: %s)\n", node->id(), node->op()->mnemonic(),
    570             info->truncation().description());
    571       VisitNode(node, info->truncation(), nullptr);
    572     }
    573   }
    574 
    575   void Run(SimplifiedLowering* lowering) {
    576     RunTruncationPropagationPhase();
    577 
    578     RunTypePropagationPhase();
    579 
    580     // Run lowering and change insertion phase.
    581     TRACE("--{Simplified lowering phase}--\n");
    582     phase_ = LOWER;
    583     // Process nodes from the collected {nodes_} vector.
    584     for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
    585       Node* node = *i;
    586       NodeInfo* info = GetInfo(node);
    587       TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
    588       // Reuse {VisitNode()} so the representation rules are in one place.
    589       SourcePositionTable::Scope scope(
    590           source_positions_, source_positions_->GetSourcePosition(node));
    591       VisitNode(node, info->truncation(), lowering);
    592     }
    593 
    594     // Perform the final replacements.
    595     for (NodeVector::iterator i = replacements_.begin();
    596          i != replacements_.end(); ++i) {
    597       Node* node = *i;
    598       Node* replacement = *(++i);
    599       node->ReplaceUses(replacement);
    600       node->Kill();
    601       // We also need to replace the node in the rest of the vector.
    602       for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
    603         ++j;
    604         if (*j == node) *j = replacement;
    605       }
    606     }
    607   }
    608 
    609   void EnqueueInitial(Node* node) {
    610     NodeInfo* info = GetInfo(node);
    611     info->set_queued();
    612     nodes_.push_back(node);
    613     queue_.push(node);
    614   }
    615 
    616   // Enqueue {use_node}'s {index} input if the {use} contains new information
    617   // for that input node. Add the input to {nodes_} if this is the first time
    618   // it's been visited.
    619   void EnqueueInput(Node* use_node, int index,
    620                     UseInfo use_info = UseInfo::None()) {
    621     Node* node = use_node->InputAt(index);
    622     if (phase_ != PROPAGATE) return;
    623     NodeInfo* info = GetInfo(node);
    624 #ifdef DEBUG
    625     // Check monotonicity of input requirements.
    626     node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
    627                                                            use_info);
    628 #endif  // DEBUG
    629     if (info->unvisited()) {
    630       // First visit of this node.
    631       info->set_queued();
    632       nodes_.push_back(node);
    633       queue_.push(node);
    634       TRACE("  initial #%i: ", node->id());
    635       info->AddUse(use_info);
    636       PrintTruncation(info->truncation());
    637       return;
    638     }
    639     TRACE("   queue #%i?: ", node->id());
    640     PrintTruncation(info->truncation());
    641     if (info->AddUse(use_info)) {
    642       // New usage information for the node is available.
    643       if (!info->queued()) {
    644         queue_.push(node);
    645         info->set_queued();
    646         TRACE("   added: ");
    647       } else {
    648         TRACE(" inqueue: ");
    649       }
    650       PrintTruncation(info->truncation());
    651     }
    652   }
    653 
    654   bool lower() const { return phase_ == LOWER; }
    655   bool retype() const { return phase_ == RETYPE; }
    656   bool propagate() const { return phase_ == PROPAGATE; }
    657 
    658   void SetOutput(Node* node, MachineRepresentation representation,
    659                  Type* restriction_type = Type::Any()) {
    660     NodeInfo* const info = GetInfo(node);
    661     switch (phase_) {
    662       case PROPAGATE:
    663         info->set_restriction_type(restriction_type);
    664         break;
    665       case RETYPE:
    666         DCHECK(info->restriction_type()->Is(restriction_type));
    667         DCHECK(restriction_type->Is(info->restriction_type()));
    668         info->set_output(representation);
    669         break;
    670       case LOWER:
    671         DCHECK_EQ(info->representation(), representation);
    672         DCHECK(info->restriction_type()->Is(restriction_type));
    673         DCHECK(restriction_type->Is(info->restriction_type()));
    674         break;
    675     }
    676   }
    677 
    678   Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
    679 
    680   bool InputCannotBe(Node* node, Type* type) {
    681     DCHECK_EQ(1, node->op()->ValueInputCount());
    682     return !GetUpperBound(node->InputAt(0))->Maybe(type);
    683   }
    684 
    685   bool InputIs(Node* node, Type* type) {
    686     DCHECK_EQ(1, node->op()->ValueInputCount());
    687     return GetUpperBound(node->InputAt(0))->Is(type);
    688   }
    689 
    690   bool BothInputsAreSigned32(Node* node) {
    691     return BothInputsAre(node, Type::Signed32());
    692   }
    693 
    694   bool BothInputsAreUnsigned32(Node* node) {
    695     return BothInputsAre(node, Type::Unsigned32());
    696   }
    697 
    698   bool BothInputsAre(Node* node, Type* type) {
    699     DCHECK_EQ(2, node->op()->ValueInputCount());
    700     return GetUpperBound(node->InputAt(0))->Is(type) &&
    701            GetUpperBound(node->InputAt(1))->Is(type);
    702   }
    703 
    704   bool IsNodeRepresentationTagged(Node* node) {
    705     MachineRepresentation representation = GetInfo(node)->representation();
    706     return IsAnyTagged(representation);
    707   }
    708 
    709   bool OneInputCannotBe(Node* node, Type* type) {
    710     DCHECK_EQ(2, node->op()->ValueInputCount());
    711     return !GetUpperBound(node->InputAt(0))->Maybe(type) ||
    712            !GetUpperBound(node->InputAt(1))->Maybe(type);
    713   }
    714 
    715   void ConvertInput(Node* node, int index, UseInfo use) {
    716     Node* input = node->InputAt(index);
    717     // In the change phase, insert a change before the use if necessary.
    718     if (use.representation() == MachineRepresentation::kNone)
    719       return;  // No input requirement on the use.
    720     DCHECK_NOT_NULL(input);
    721     NodeInfo* input_info = GetInfo(input);
    722     MachineRepresentation input_rep = input_info->representation();
    723     if (input_rep != use.representation() ||
    724         use.type_check() != TypeCheckKind::kNone) {
    725       // Output representation doesn't match usage.
    726       TRACE("  change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
    727             index, input->id(), input->op()->mnemonic());
    728       TRACE(" from ");
    729       PrintOutputInfo(input_info);
    730       TRACE(" to ");
    731       PrintUseInfo(use);
    732       TRACE("\n");
    733       Node* n = changer_->GetRepresentationFor(
    734           input, input_info->representation(), TypeOf(input), node, use);
    735       node->ReplaceInput(index, n);
    736     }
    737   }
    738 
    739   void ProcessInput(Node* node, int index, UseInfo use) {
    740     switch (phase_) {
    741       case PROPAGATE:
    742         EnqueueInput(node, index, use);
    743         break;
    744       case RETYPE:
    745         break;
    746       case LOWER:
    747         ConvertInput(node, index, use);
    748         break;
    749     }
    750   }
    751 
    752   void ProcessRemainingInputs(Node* node, int index) {
    753     DCHECK_GE(index, NodeProperties::PastValueIndex(node));
    754     DCHECK_GE(index, NodeProperties::PastContextIndex(node));
    755     for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
    756          i < NodeProperties::PastEffectIndex(node); ++i) {
    757       EnqueueInput(node, i);  // Effect inputs: just visit
    758     }
    759     for (int i = std::max(index, NodeProperties::FirstControlIndex(node));
    760          i < NodeProperties::PastControlIndex(node); ++i) {
    761       EnqueueInput(node, i);  // Control inputs: just visit
    762     }
    763   }
    764 
    765   // The default, most general visitation case. For {node}, process all value,
    766   // context, frame state, effect, and control inputs, assuming that value
    767   // inputs should have {kRepTagged} representation and can observe all output
    768   // values {kTypeAny}.
    769   void VisitInputs(Node* node) {
    770     int tagged_count = node->op()->ValueInputCount() +
    771                        OperatorProperties::GetContextInputCount(node->op()) +
    772                        OperatorProperties::GetFrameStateInputCount(node->op());
    773     // Visit value, context and frame state inputs as tagged.
    774     for (int i = 0; i < tagged_count; i++) {
    775       ProcessInput(node, i, UseInfo::AnyTagged());
    776     }
    777     // Only enqueue other inputs (effects, control).
    778     for (int i = tagged_count; i < node->InputCount(); i++) {
    779       EnqueueInput(node, i);
    780     }
    781   }
    782 
    783   void VisitReturn(Node* node) {
    784     int tagged_limit = node->op()->ValueInputCount() +
    785                        OperatorProperties::GetContextInputCount(node->op()) +
    786                        OperatorProperties::GetFrameStateInputCount(node->op());
    787     // Visit integer slot count to pop
    788     ProcessInput(node, 0, UseInfo::TruncatingWord32());
    789 
    790     // Visit value, context and frame state inputs as tagged.
    791     for (int i = 1; i < tagged_limit; i++) {
    792       ProcessInput(node, i, UseInfo::AnyTagged());
    793     }
    794     // Only enqueue other inputs (effects, control).
    795     for (int i = tagged_limit; i < node->InputCount(); i++) {
    796       EnqueueInput(node, i);
    797     }
    798   }
    799 
    800   // Helper for an unused node.
    801   void VisitUnused(Node* node) {
    802     int value_count = node->op()->ValueInputCount() +
    803                       OperatorProperties::GetContextInputCount(node->op()) +
    804                       OperatorProperties::GetFrameStateInputCount(node->op());
    805     for (int i = 0; i < value_count; i++) {
    806       ProcessInput(node, i, UseInfo::None());
    807     }
    808     ProcessRemainingInputs(node, value_count);
    809     if (lower()) Kill(node);
    810   }
    811 
    812   // Helper for binops of the R x L -> O variety.
    813   void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
    814                   MachineRepresentation output,
    815                   Type* restriction_type = Type::Any()) {
    816     DCHECK_EQ(2, node->op()->ValueInputCount());
    817     ProcessInput(node, 0, left_use);
    818     ProcessInput(node, 1, right_use);
    819     for (int i = 2; i < node->InputCount(); i++) {
    820       EnqueueInput(node, i);
    821     }
    822     SetOutput(node, output, restriction_type);
    823   }
    824 
    825   // Helper for binops of the I x I -> O variety.
    826   void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output,
    827                   Type* restriction_type = Type::Any()) {
    828     VisitBinop(node, input_use, input_use, output, restriction_type);
    829   }
    830 
    831   void VisitSpeculativeInt32Binop(Node* node) {
    832     DCHECK_EQ(2, node->op()->ValueInputCount());
    833     if (BothInputsAre(node, Type::NumberOrOddball())) {
    834       return VisitBinop(node, UseInfo::TruncatingWord32(),
    835                         MachineRepresentation::kWord32);
    836     }
    837     NumberOperationHint hint = NumberOperationHintOf(node->op());
    838     return VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
    839                       MachineRepresentation::kWord32);
    840   }
    841 
    842   // Helper for unops of the I -> O variety.
    843   void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) {
    844     DCHECK_EQ(1, node->op()->ValueInputCount());
    845     ProcessInput(node, 0, input_use);
    846     ProcessRemainingInputs(node, 1);
    847     SetOutput(node, output);
    848   }
    849 
    850   // Helper for leaf nodes.
    851   void VisitLeaf(Node* node, MachineRepresentation output) {
    852     DCHECK_EQ(0, node->InputCount());
    853     SetOutput(node, output);
    854   }
    855 
    856   // Helpers for specific types of binops.
    857   void VisitFloat64Binop(Node* node) {
    858     VisitBinop(node, UseInfo::TruncatingFloat64(),
    859                MachineRepresentation::kFloat64);
    860   }
    861   void VisitWord32TruncatingBinop(Node* node) {
    862     VisitBinop(node, UseInfo::TruncatingWord32(),
    863                MachineRepresentation::kWord32);
    864   }
    865 
    866   // Infer representation for phi-like nodes.
    867   // The {node} parameter is only used to decide on the int64 representation.
    868   // Once the type system supports an external pointer type, the {node}
    869   // parameter can be removed.
    870   MachineRepresentation GetOutputInfoForPhi(Node* node, Type* type,
    871                                             Truncation use) {
    872     // Compute the representation.
    873     if (type->Is(Type::None())) {
    874       return MachineRepresentation::kNone;
    875     } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
    876       return MachineRepresentation::kWord32;
    877     } else if (type->Is(Type::NumberOrOddball()) && use.IsUsedAsWord32()) {
    878       return MachineRepresentation::kWord32;
    879     } else if (type->Is(Type::Boolean())) {
    880       return MachineRepresentation::kBit;
    881     } else if (type->Is(Type::NumberOrOddball()) && use.IsUsedAsFloat64()) {
    882       return MachineRepresentation::kFloat64;
    883     } else if (type->Is(
    884                    Type::Union(Type::SignedSmall(), Type::NaN(), zone()))) {
    885       // TODO(turbofan): For Phis that return either NaN or some Smi, it's
    886       // beneficial to not go all the way to double, unless the uses are
    887       // double uses. For tagging that just means some potentially expensive
    888       // allocation code; we might want to do the same for -0 as well?
    889       return MachineRepresentation::kTagged;
    890     } else if (type->Is(Type::Number())) {
    891       return MachineRepresentation::kFloat64;
    892     } else if (type->Is(Type::ExternalPointer())) {
    893       return MachineType::PointerRepresentation();
    894     }
    895     return MachineRepresentation::kTagged;
    896   }
    897 
    898   // Helper for handling selects.
    899   void VisitSelect(Node* node, Truncation truncation,
    900                    SimplifiedLowering* lowering) {
    901     DCHECK(TypeOf(node->InputAt(0))->Is(Type::Boolean()));
    902     ProcessInput(node, 0, UseInfo::Bool());
    903 
    904     MachineRepresentation output =
    905         GetOutputInfoForPhi(node, TypeOf(node), truncation);
    906     SetOutput(node, output);
    907 
    908     if (lower()) {
    909       // Update the select operator.
    910       SelectParameters p = SelectParametersOf(node->op());
    911       if (output != p.representation()) {
    912         NodeProperties::ChangeOp(node,
    913                                  lowering->common()->Select(output, p.hint()));
    914       }
    915     }
    916     // Convert inputs to the output representation of this phi, pass the
    917     // truncation truncation along.
    918     UseInfo input_use(output, truncation);
    919     ProcessInput(node, 1, input_use);
    920     ProcessInput(node, 2, input_use);
    921   }
    922 
    923   // Helper for handling phis.
    924   void VisitPhi(Node* node, Truncation truncation,
    925                 SimplifiedLowering* lowering) {
    926     MachineRepresentation output =
    927         GetOutputInfoForPhi(node, TypeOf(node), truncation);
    928     // Only set the output representation if not running with type
    929     // feedback. (Feedback typing will set the representation.)
    930     SetOutput(node, output);
    931 
    932     int values = node->op()->ValueInputCount();
    933     if (lower()) {
    934       // Update the phi operator.
    935       if (output != PhiRepresentationOf(node->op())) {
    936         NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values));
    937       }
    938     }
    939 
    940     // Convert inputs to the output representation of this phi, pass the
    941     // truncation along.
    942     UseInfo input_use(output, truncation);
    943     for (int i = 0; i < node->InputCount(); i++) {
    944       ProcessInput(node, i, i < values ? input_use : UseInfo::None());
    945     }
    946   }
    947 
    948   void VisitObjectIs(Node* node, Type* type, SimplifiedLowering* lowering) {
    949     Type* const input_type = TypeOf(node->InputAt(0));
    950     if (input_type->Is(type)) {
    951       VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
    952       if (lower()) {
    953         DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
    954       }
    955     } else {
    956       VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
    957       if (lower() && !input_type->Maybe(type)) {
    958         DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
    959       }
    960     }
    961   }
    962 
    963   void VisitCall(Node* node, SimplifiedLowering* lowering) {
    964     const CallDescriptor* desc = CallDescriptorOf(node->op());
    965     int params = static_cast<int>(desc->ParameterCount());
    966     int value_input_count = node->op()->ValueInputCount();
    967     // Propagate representation information from call descriptor.
    968     for (int i = 0; i < value_input_count; i++) {
    969       if (i == 0) {
    970         // The target of the call.
    971         ProcessInput(node, i, UseInfo::Any());
    972       } else if ((i - 1) < params) {
    973         ProcessInput(node, i, TruncatingUseInfoFromRepresentation(
    974                                   desc->GetInputType(i).representation()));
    975       } else {
    976         ProcessInput(node, i, UseInfo::AnyTagged());
    977       }
    978     }
    979     ProcessRemainingInputs(node, value_input_count);
    980 
    981     if (desc->ReturnCount() > 0) {
    982       SetOutput(node, desc->GetReturnType(0).representation());
    983     } else {
    984       SetOutput(node, MachineRepresentation::kTagged);
    985     }
    986   }
    987 
    988   static MachineSemantic DeoptValueSemanticOf(Type* type) {
    989     // We only need signedness to do deopt correctly.
    990     if (type->Is(Type::Signed32())) {
    991       return MachineSemantic::kInt32;
    992     } else if (type->Is(Type::Unsigned32())) {
    993       return MachineSemantic::kUint32;
    994     } else {
    995       return MachineSemantic::kAny;
    996     }
    997   }
    998 
    999   static MachineType DeoptMachineTypeOf(MachineRepresentation rep, Type* type) {
   1000     if (!type->IsInhabited()) {
   1001       return MachineType::None();
   1002     }
   1003     // TODO(turbofan): Special treatment for ExternalPointer here,
   1004     // to avoid incompatible truncations. We really need a story
   1005     // for the JSFunction::entry field.
   1006     if (type->Is(Type::ExternalPointer())) {
   1007       return MachineType::Pointer();
   1008     }
   1009     // Do not distinguish between various Tagged variations.
   1010     if (IsAnyTagged(rep)) {
   1011       return MachineType::AnyTagged();
   1012     }
   1013     MachineType machine_type(rep, DeoptValueSemanticOf(type));
   1014     DCHECK(machine_type.representation() != MachineRepresentation::kWord32 ||
   1015            machine_type.semantic() == MachineSemantic::kInt32 ||
   1016            machine_type.semantic() == MachineSemantic::kUint32);
   1017     DCHECK(machine_type.representation() != MachineRepresentation::kBit ||
   1018            type->Is(Type::Boolean()));
   1019     return machine_type;
   1020   }
   1021 
   1022   void VisitStateValues(Node* node) {
   1023     if (propagate()) {
   1024       for (int i = 0; i < node->InputCount(); i++) {
   1025         EnqueueInput(node, i, UseInfo::Any());
   1026       }
   1027     } else if (lower()) {
   1028       Zone* zone = jsgraph_->zone();
   1029       ZoneVector<MachineType>* types =
   1030           new (zone->New(sizeof(ZoneVector<MachineType>)))
   1031               ZoneVector<MachineType>(node->InputCount(), zone);
   1032       for (int i = 0; i < node->InputCount(); i++) {
   1033         Node* input = node->InputAt(i);
   1034         (*types)[i] =
   1035             DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input));
   1036       }
   1037       SparseInputMask mask = SparseInputMaskOf(node->op());
   1038       NodeProperties::ChangeOp(
   1039           node, jsgraph_->common()->TypedStateValues(types, mask));
   1040     }
   1041     SetOutput(node, MachineRepresentation::kTagged);
   1042   }
   1043 
   1044   void VisitObjectState(Node* node) {
   1045     if (propagate()) {
   1046       for (int i = 0; i < node->InputCount(); i++) {
   1047         Node* input = node->InputAt(i);
   1048         Type* input_type = TypeOf(input);
   1049         // TODO(turbofan): Special treatment for ExternalPointer here,
   1050         // to avoid incompatible truncations. We really need a story
   1051         // for the JSFunction::entry field.
   1052         UseInfo use_info = UseInfo::None();
   1053         if (input_type->IsInhabited()) {
   1054           if (input_type->Is(Type::ExternalPointer())) {
   1055             use_info = UseInfo::PointerInt();
   1056           } else {
   1057             use_info = UseInfo::Any();
   1058           }
   1059         }
   1060         EnqueueInput(node, i, use_info);
   1061       }
   1062     } else if (lower()) {
   1063       Zone* zone = jsgraph_->zone();
   1064       ZoneVector<MachineType>* types =
   1065           new (zone->New(sizeof(ZoneVector<MachineType>)))
   1066               ZoneVector<MachineType>(node->InputCount(), zone);
   1067       for (int i = 0; i < node->InputCount(); i++) {
   1068         Node* input = node->InputAt(i);
   1069         (*types)[i] =
   1070             DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input));
   1071       }
   1072       NodeProperties::ChangeOp(node,
   1073                                jsgraph_->common()->TypedObjectState(types));
   1074     }
   1075     SetOutput(node, MachineRepresentation::kTagged);
   1076   }
   1077 
   1078   const Operator* Int32Op(Node* node) {
   1079     return changer_->Int32OperatorFor(node->opcode());
   1080   }
   1081 
   1082   const Operator* Int32OverflowOp(Node* node) {
   1083     return changer_->Int32OverflowOperatorFor(node->opcode());
   1084   }
   1085 
   1086   const Operator* Uint32Op(Node* node) {
   1087     return changer_->Uint32OperatorFor(node->opcode());
   1088   }
   1089 
   1090   const Operator* Uint32OverflowOp(Node* node) {
   1091     return changer_->Uint32OverflowOperatorFor(node->opcode());
   1092   }
   1093 
   1094   const Operator* Float64Op(Node* node) {
   1095     return changer_->Float64OperatorFor(node->opcode());
   1096   }
   1097 
   1098   WriteBarrierKind WriteBarrierKindFor(
   1099       BaseTaggedness base_taggedness,
   1100       MachineRepresentation field_representation, Type* field_type,
   1101       MachineRepresentation value_representation, Node* value) {
   1102     if (base_taggedness == kTaggedBase &&
   1103         CanBeTaggedPointer(field_representation)) {
   1104       Type* value_type = NodeProperties::GetType(value);
   1105       if (field_representation == MachineRepresentation::kTaggedSigned ||
   1106           value_representation == MachineRepresentation::kTaggedSigned) {
   1107         // Write barriers are only for stores of heap objects.
   1108         return kNoWriteBarrier;
   1109       }
   1110       if (field_type->Is(Type::BooleanOrNullOrUndefined()) ||
   1111           value_type->Is(Type::BooleanOrNullOrUndefined())) {
   1112         // Write barriers are not necessary when storing true, false, null or
   1113         // undefined, because these special oddballs are always in the root set.
   1114         return kNoWriteBarrier;
   1115       }
   1116       if (value_type->IsHeapConstant()) {
   1117         Heap::RootListIndex root_index;
   1118         Heap* heap = jsgraph_->isolate()->heap();
   1119         if (heap->IsRootHandle(value_type->AsHeapConstant()->Value(),
   1120                                &root_index)) {
   1121           if (heap->RootIsImmortalImmovable(root_index)) {
   1122             // Write barriers are unnecessary for immortal immovable roots.
   1123             return kNoWriteBarrier;
   1124           }
   1125         }
   1126       }
   1127       if (field_representation == MachineRepresentation::kTaggedPointer ||
   1128           value_representation == MachineRepresentation::kTaggedPointer) {
   1129         // Write barriers for heap objects are cheaper.
   1130         return kPointerWriteBarrier;
   1131       }
   1132       NumberMatcher m(value);
   1133       if (m.HasValue()) {
   1134         if (IsSmiDouble(m.Value())) {
   1135           // Storing a smi doesn't need a write barrier.
   1136           return kNoWriteBarrier;
   1137         }
   1138         // The NumberConstant will be represented as HeapNumber.
   1139         return kPointerWriteBarrier;
   1140       }
   1141       return kFullWriteBarrier;
   1142     }
   1143     return kNoWriteBarrier;
   1144   }
   1145 
   1146   WriteBarrierKind WriteBarrierKindFor(
   1147       BaseTaggedness base_taggedness,
   1148       MachineRepresentation field_representation, int field_offset,
   1149       Type* field_type, MachineRepresentation value_representation,
   1150       Node* value) {
   1151     if (base_taggedness == kTaggedBase &&
   1152         field_offset == HeapObject::kMapOffset) {
   1153       return kMapWriteBarrier;
   1154     }
   1155     return WriteBarrierKindFor(base_taggedness, field_representation,
   1156                                field_type, value_representation, value);
   1157   }
   1158 
   1159   Graph* graph() const { return jsgraph_->graph(); }
   1160   CommonOperatorBuilder* common() const { return jsgraph_->common(); }
   1161   SimplifiedOperatorBuilder* simplified() const {
   1162     return jsgraph_->simplified();
   1163   }
   1164 
   1165   void LowerToCheckedInt32Mul(Node* node, Truncation truncation,
   1166                               Type* input0_type, Type* input1_type) {
   1167     // If one of the inputs is positive and/or truncation is being applied,
   1168     // there is no need to return -0.
   1169     CheckForMinusZeroMode mz_mode =
   1170         truncation.IsUsedAsWord32() ||
   1171                 (input0_type->Is(Type::OrderedNumber()) &&
   1172                  input0_type->Min() > 0) ||
   1173                 (input1_type->Is(Type::OrderedNumber()) &&
   1174                  input1_type->Min() > 0)
   1175             ? CheckForMinusZeroMode::kDontCheckForMinusZero
   1176             : CheckForMinusZeroMode::kCheckForMinusZero;
   1177 
   1178     NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode));
   1179   }
   1180 
   1181   void ChangeToInt32OverflowOp(Node* node) {
   1182     NodeProperties::ChangeOp(node, Int32OverflowOp(node));
   1183   }
   1184 
   1185   void ChangeToUint32OverflowOp(Node* node) {
   1186     NodeProperties::ChangeOp(node, Uint32OverflowOp(node));
   1187   }
   1188 
   1189   void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
   1190                                   SimplifiedLowering* lowering) {
   1191     // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we can
   1192     // only eliminate an unused speculative number operation if we know that
   1193     // the inputs are PlainPrimitive, which excludes everything that's might
   1194     // have side effects or throws during a ToNumber conversion. We are only
   1195     // allowed to perform a number addition if neither input is a String, even
   1196     // if the value is never used, so we further limit to NumberOrOddball in
   1197     // order to explicitly exclude String inputs.
   1198     if (BothInputsAre(node, Type::NumberOrOddball())) {
   1199       if (truncation.IsUnused()) return VisitUnused(node);
   1200     }
   1201 
   1202     if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) &&
   1203         (GetUpperBound(node)->Is(Type::Signed32()) ||
   1204          GetUpperBound(node)->Is(Type::Unsigned32()) ||
   1205          truncation.IsUsedAsWord32())) {
   1206       // => Int32Add/Sub
   1207       VisitWord32TruncatingBinop(node);
   1208       if (lower()) ChangeToPureOp(node, Int32Op(node));
   1209       return;
   1210     }
   1211 
   1212     // Try to use type feedback.
   1213     NumberOperationHint hint = NumberOperationHintOf(node->op());
   1214 
   1215     if (hint == NumberOperationHint::kSignedSmall ||
   1216         hint == NumberOperationHint::kSigned32) {
   1217       Type* left_feedback_type = TypeOf(node->InputAt(0));
   1218       Type* right_feedback_type = TypeOf(node->InputAt(1));
   1219       // Handle the case when no int32 checks on inputs are necessary (but
   1220       // an overflow check is needed on the output).
   1221       // TODO(jarin) We should not look at the upper bound because the typer
   1222       // could have already baked in some feedback into the upper bound.
   1223       if (BothInputsAre(node, Type::Signed32()) ||
   1224           (BothInputsAre(node, Type::Signed32OrMinusZero()) &&
   1225            GetUpperBound(node)->Is(type_cache_.kSafeInteger))) {
   1226         VisitBinop(node, UseInfo::TruncatingWord32(),
   1227                    MachineRepresentation::kWord32, Type::Signed32());
   1228       } else {
   1229         UseInfo left_use = CheckedUseInfoAsWord32FromHint(hint);
   1230         // For CheckedInt32Add and CheckedInt32Sub, we don't need to do
   1231         // a minus zero check for the right hand side, since we already
   1232         // know that the left hand side is a proper Signed32 value,
   1233         // potentially guarded by a check.
   1234         UseInfo right_use = CheckedUseInfoAsWord32FromHint(
   1235             hint, CheckForMinusZeroMode::kDontCheckForMinusZero);
   1236         VisitBinop(node, left_use, right_use, MachineRepresentation::kWord32,
   1237                    Type::Signed32());
   1238       }
   1239       if (lower()) {
   1240         if (CanOverflowSigned32(node->op(), left_feedback_type,
   1241                                 right_feedback_type, graph_zone())) {
   1242           ChangeToInt32OverflowOp(node);
   1243         } else {
   1244           ChangeToPureOp(node, Int32Op(node));
   1245         }
   1246       }
   1247       return;
   1248     }
   1249 
   1250     // default case => Float64Add/Sub
   1251     VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
   1252                MachineRepresentation::kFloat64, Type::Number());
   1253     if (lower()) {
   1254       ChangeToPureOp(node, Float64Op(node));
   1255     }
   1256     return;
   1257   }
   1258 
   1259   void VisitSpeculativeNumberModulus(Node* node, Truncation truncation,
   1260                                      SimplifiedLowering* lowering) {
   1261     // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
   1262     // can only eliminate an unused speculative number operation if we know
   1263     // that the inputs are PlainPrimitive, which excludes everything that's
   1264     // might have side effects or throws during a ToNumber conversion.
   1265     if (BothInputsAre(node, Type::PlainPrimitive())) {
   1266       if (truncation.IsUnused()) return VisitUnused(node);
   1267     }
   1268     if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) &&
   1269         (truncation.IsUsedAsWord32() ||
   1270          NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
   1271       // => unsigned Uint32Mod
   1272       VisitWord32TruncatingBinop(node);
   1273       if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
   1274       return;
   1275     }
   1276     if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) &&
   1277         (truncation.IsUsedAsWord32() ||
   1278          NodeProperties::GetType(node)->Is(Type::Signed32()))) {
   1279       // => signed Int32Mod
   1280       VisitWord32TruncatingBinop(node);
   1281       if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
   1282       return;
   1283     }
   1284 
   1285     // Try to use type feedback.
   1286     NumberOperationHint hint = NumberOperationHintOf(node->op());
   1287 
   1288     // Handle the case when no uint32 checks on inputs are necessary
   1289     // (but an overflow check is needed on the output).
   1290     if (BothInputsAreUnsigned32(node)) {
   1291       if (hint == NumberOperationHint::kSignedSmall ||
   1292           hint == NumberOperationHint::kSigned32) {
   1293         VisitBinop(node, UseInfo::TruncatingWord32(),
   1294                    MachineRepresentation::kWord32, Type::Unsigned32());
   1295         if (lower()) ChangeToUint32OverflowOp(node);
   1296         return;
   1297       }
   1298     }
   1299 
   1300     // Handle the case when no int32 checks on inputs are necessary
   1301     // (but an overflow check is needed on the output).
   1302     if (BothInputsAre(node, Type::Signed32())) {
   1303       // If both the inputs the feedback are int32, use the overflow op.
   1304       if (hint == NumberOperationHint::kSignedSmall ||
   1305           hint == NumberOperationHint::kSigned32) {
   1306         VisitBinop(node, UseInfo::TruncatingWord32(),
   1307                    MachineRepresentation::kWord32, Type::Signed32());
   1308         if (lower()) ChangeToInt32OverflowOp(node);
   1309         return;
   1310       }
   1311     }
   1312 
   1313     if (hint == NumberOperationHint::kSignedSmall ||
   1314         hint == NumberOperationHint::kSigned32) {
   1315       // If the result is truncated, we only need to check the inputs.
   1316       if (truncation.IsUsedAsWord32()) {
   1317         VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   1318                    MachineRepresentation::kWord32);
   1319         if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
   1320       } else if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN())) {
   1321         VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   1322                    MachineRepresentation::kWord32, Type::Unsigned32());
   1323         if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
   1324       } else {
   1325         VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   1326                    MachineRepresentation::kWord32, Type::Signed32());
   1327         if (lower()) ChangeToInt32OverflowOp(node);
   1328       }
   1329       return;
   1330     }
   1331 
   1332     if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
   1333         TypeOf(node->InputAt(1))->Is(Type::Unsigned32()) &&
   1334         (truncation.IsUsedAsWord32() ||
   1335          NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
   1336       // We can only promise Float64 truncation here, as the decision is
   1337       // based on the feedback types of the inputs.
   1338       VisitBinop(node,
   1339                  UseInfo(MachineRepresentation::kWord32, Truncation::Float64()),
   1340                  MachineRepresentation::kWord32, Type::Number());
   1341       if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
   1342       return;
   1343     }
   1344     if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
   1345         TypeOf(node->InputAt(1))->Is(Type::Signed32()) &&
   1346         (truncation.IsUsedAsWord32() ||
   1347          NodeProperties::GetType(node)->Is(Type::Signed32()))) {
   1348       // We can only promise Float64 truncation here, as the decision is
   1349       // based on the feedback types of the inputs.
   1350       VisitBinop(node,
   1351                  UseInfo(MachineRepresentation::kWord32, Truncation::Float64()),
   1352                  MachineRepresentation::kWord32, Type::Number());
   1353       if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
   1354       return;
   1355     }
   1356     // default case => Float64Mod
   1357     VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
   1358                MachineRepresentation::kFloat64, Type::Number());
   1359     if (lower()) ChangeToPureOp(node, Float64Op(node));
   1360     return;
   1361   }
   1362 
   1363   void VisitOsrGuard(Node* node) {
   1364     VisitInputs(node);
   1365 
   1366     // Insert a dynamic check for the OSR value type if necessary.
   1367     switch (OsrGuardTypeOf(node->op())) {
   1368       case OsrGuardType::kUninitialized:
   1369         // At this point, we should always have a type for the OsrValue.
   1370         UNREACHABLE();
   1371         break;
   1372       case OsrGuardType::kSignedSmall:
   1373         if (lower()) {
   1374           NodeProperties::ChangeOp(node,
   1375                                    simplified()->CheckedTaggedToTaggedSigned());
   1376         }
   1377         return SetOutput(node, MachineRepresentation::kTaggedSigned);
   1378       case OsrGuardType::kAny:  // Nothing to check.
   1379         if (lower()) {
   1380           DeferReplacement(node, node->InputAt(0));
   1381         }
   1382         return SetOutput(node, MachineRepresentation::kTagged);
   1383     }
   1384     UNREACHABLE();
   1385   }
   1386 
   1387   // Dispatching routine for visiting the node {node} with the usage {use}.
   1388   // Depending on the operator, propagate new usage info to the inputs.
   1389   void VisitNode(Node* node, Truncation truncation,
   1390                  SimplifiedLowering* lowering) {
   1391     // Unconditionally eliminate unused pure nodes (only relevant if there's
   1392     // a pure operation in between two effectful ones, where the last one
   1393     // is unused).
   1394     // Note: We must not do this for constants, as they are cached and we
   1395     // would thus kill the cached {node} during lowering (i.e. replace all
   1396     // uses with Dead), but at that point some node lowering might have
   1397     // already taken the constant {node} from the cache (while it was in
   1398     // a sane state still) and we would afterwards replace that use with
   1399     // Dead as well.
   1400     if (node->op()->ValueInputCount() > 0 &&
   1401         node->op()->HasProperty(Operator::kPure)) {
   1402       if (truncation.IsUnused()) return VisitUnused(node);
   1403     }
   1404     switch (node->opcode()) {
   1405       //------------------------------------------------------------------
   1406       // Common operators.
   1407       //------------------------------------------------------------------
   1408       case IrOpcode::kStart:
   1409         // We use Start as a terminator for the frame state chain, so even
   1410         // tho Start doesn't really produce a value, we have to say Tagged
   1411         // here, otherwise the input conversion will fail.
   1412         return VisitLeaf(node, MachineRepresentation::kTagged);
   1413       case IrOpcode::kParameter:
   1414         // TODO(titzer): use representation from linkage.
   1415         return VisitUnop(node, UseInfo::None(), MachineRepresentation::kTagged);
   1416       case IrOpcode::kInt32Constant:
   1417         return VisitLeaf(node, MachineRepresentation::kWord32);
   1418       case IrOpcode::kInt64Constant:
   1419         return VisitLeaf(node, MachineRepresentation::kWord64);
   1420       case IrOpcode::kExternalConstant:
   1421         return VisitLeaf(node, MachineType::PointerRepresentation());
   1422       case IrOpcode::kNumberConstant:
   1423         return VisitLeaf(node, MachineRepresentation::kTagged);
   1424       case IrOpcode::kHeapConstant:
   1425         return VisitLeaf(node, MachineRepresentation::kTaggedPointer);
   1426       case IrOpcode::kPointerConstant: {
   1427         VisitLeaf(node, MachineType::PointerRepresentation());
   1428         if (lower()) {
   1429           intptr_t const value = OpParameter<intptr_t>(node);
   1430           DeferReplacement(node, lowering->jsgraph()->IntPtrConstant(value));
   1431         }
   1432         return;
   1433       }
   1434 
   1435       case IrOpcode::kBranch: {
   1436         DCHECK(TypeOf(node->InputAt(0))->Is(Type::Boolean()));
   1437         ProcessInput(node, 0, UseInfo::Bool());
   1438         EnqueueInput(node, NodeProperties::FirstControlIndex(node));
   1439         return;
   1440       }
   1441       case IrOpcode::kSwitch:
   1442         ProcessInput(node, 0, UseInfo::TruncatingWord32());
   1443         EnqueueInput(node, NodeProperties::FirstControlIndex(node));
   1444         return;
   1445       case IrOpcode::kSelect:
   1446         return VisitSelect(node, truncation, lowering);
   1447       case IrOpcode::kPhi:
   1448         return VisitPhi(node, truncation, lowering);
   1449       case IrOpcode::kCall:
   1450         return VisitCall(node, lowering);
   1451 
   1452       //------------------------------------------------------------------
   1453       // JavaScript operators.
   1454       //------------------------------------------------------------------
   1455       case IrOpcode::kJSToBoolean: {
   1456         if (truncation.IsUsedAsBool()) {
   1457           ProcessInput(node, 0, UseInfo::Bool());
   1458           ProcessInput(node, 1, UseInfo::None());
   1459           SetOutput(node, MachineRepresentation::kBit);
   1460           if (lower()) DeferReplacement(node, node->InputAt(0));
   1461         } else {
   1462           VisitInputs(node);
   1463           SetOutput(node, MachineRepresentation::kTaggedPointer);
   1464         }
   1465         return;
   1466       }
   1467       case IrOpcode::kJSToNumber: {
   1468         VisitInputs(node);
   1469         // TODO(bmeurer): Optimize somewhat based on input type?
   1470         if (truncation.IsUsedAsWord32()) {
   1471           SetOutput(node, MachineRepresentation::kWord32);
   1472           if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this);
   1473         } else if (truncation.IsUsedAsFloat64()) {
   1474           SetOutput(node, MachineRepresentation::kFloat64);
   1475           if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this);
   1476         } else {
   1477           SetOutput(node, MachineRepresentation::kTagged);
   1478         }
   1479         return;
   1480       }
   1481 
   1482       //------------------------------------------------------------------
   1483       // Simplified operators.
   1484       //------------------------------------------------------------------
   1485       case IrOpcode::kBooleanNot: {
   1486         if (lower()) {
   1487           NodeInfo* input_info = GetInfo(node->InputAt(0));
   1488           if (input_info->representation() == MachineRepresentation::kBit) {
   1489             // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
   1490             node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
   1491             NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
   1492           } else {
   1493             DCHECK(CanBeTaggedPointer(input_info->representation()));
   1494             // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
   1495             node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
   1496             NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
   1497           }
   1498         } else {
   1499           // No input representation requirement; adapt during lowering.
   1500           ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
   1501           SetOutput(node, MachineRepresentation::kBit);
   1502         }
   1503         return;
   1504       }
   1505       case IrOpcode::kNumberEqual: {
   1506         Type* const lhs_type = TypeOf(node->InputAt(0));
   1507         Type* const rhs_type = TypeOf(node->InputAt(1));
   1508         // Number comparisons reduce to integer comparisons for integer inputs.
   1509         if ((lhs_type->Is(Type::Unsigned32()) &&
   1510              rhs_type->Is(Type::Unsigned32())) ||
   1511             (lhs_type->Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
   1512              rhs_type->Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
   1513              OneInputCannotBe(node, type_cache_.kZeroish))) {
   1514           // => unsigned Int32Cmp
   1515           VisitBinop(node, UseInfo::TruncatingWord32(),
   1516                      MachineRepresentation::kBit);
   1517           if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
   1518           return;
   1519         }
   1520         if ((lhs_type->Is(Type::Signed32()) &&
   1521              rhs_type->Is(Type::Signed32())) ||
   1522             (lhs_type->Is(Type::Signed32OrMinusZeroOrNaN()) &&
   1523              rhs_type->Is(Type::Signed32OrMinusZeroOrNaN()) &&
   1524              OneInputCannotBe(node, type_cache_.kZeroish))) {
   1525           // => signed Int32Cmp
   1526           VisitBinop(node, UseInfo::TruncatingWord32(),
   1527                      MachineRepresentation::kBit);
   1528           if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
   1529           return;
   1530         }
   1531         // => Float64Cmp
   1532         VisitBinop(node, UseInfo::TruncatingFloat64(),
   1533                    MachineRepresentation::kBit);
   1534         if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
   1535         return;
   1536       }
   1537       case IrOpcode::kNumberLessThan:
   1538       case IrOpcode::kNumberLessThanOrEqual: {
   1539         // Number comparisons reduce to integer comparisons for integer inputs.
   1540         if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
   1541             TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
   1542           // => unsigned Int32Cmp
   1543           VisitBinop(node, UseInfo::TruncatingWord32(),
   1544                      MachineRepresentation::kBit);
   1545           if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
   1546         } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
   1547                    TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
   1548           // => signed Int32Cmp
   1549           VisitBinop(node, UseInfo::TruncatingWord32(),
   1550                      MachineRepresentation::kBit);
   1551           if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
   1552         } else {
   1553           // => Float64Cmp
   1554           VisitBinop(node, UseInfo::TruncatingFloat64(),
   1555                      MachineRepresentation::kBit);
   1556           if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
   1557         }
   1558         return;
   1559       }
   1560 
   1561       case IrOpcode::kSpeculativeNumberAdd:
   1562       case IrOpcode::kSpeculativeNumberSubtract:
   1563         return VisitSpeculativeAdditiveOp(node, truncation, lowering);
   1564 
   1565       case IrOpcode::kSpeculativeNumberLessThan:
   1566       case IrOpcode::kSpeculativeNumberLessThanOrEqual:
   1567       case IrOpcode::kSpeculativeNumberEqual: {
   1568         // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
   1569         // can only eliminate an unused speculative number operation if we know
   1570         // that the inputs are PlainPrimitive, which excludes everything that's
   1571         // might have side effects or throws during a ToNumber conversion.
   1572         if (BothInputsAre(node, Type::PlainPrimitive())) {
   1573           if (truncation.IsUnused()) return VisitUnused(node);
   1574         }
   1575         // Number comparisons reduce to integer comparisons for integer inputs.
   1576         if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
   1577             TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
   1578           // => unsigned Int32Cmp
   1579           VisitBinop(node, UseInfo::TruncatingWord32(),
   1580                      MachineRepresentation::kBit);
   1581           if (lower()) ChangeToPureOp(node, Uint32Op(node));
   1582           return;
   1583         } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
   1584                    TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
   1585           // => signed Int32Cmp
   1586           VisitBinop(node, UseInfo::TruncatingWord32(),
   1587                      MachineRepresentation::kBit);
   1588           if (lower()) ChangeToPureOp(node, Int32Op(node));
   1589           return;
   1590         }
   1591         // Try to use type feedback.
   1592         NumberOperationHint hint = NumberOperationHintOf(node->op());
   1593         switch (hint) {
   1594           case NumberOperationHint::kSignedSmall:
   1595           case NumberOperationHint::kSigned32: {
   1596             if (propagate()) {
   1597               VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   1598                          MachineRepresentation::kBit);
   1599             } else if (retype()) {
   1600               SetOutput(node, MachineRepresentation::kBit, Type::Any());
   1601             } else {
   1602               DCHECK(lower());
   1603               Node* lhs = node->InputAt(0);
   1604               Node* rhs = node->InputAt(1);
   1605               if (IsNodeRepresentationTagged(lhs) &&
   1606                   IsNodeRepresentationTagged(rhs)) {
   1607                 VisitBinop(node, UseInfo::CheckedSignedSmallAsTaggedSigned(),
   1608                            MachineRepresentation::kBit);
   1609                 ChangeToPureOp(
   1610                     node, changer_->TaggedSignedOperatorFor(node->opcode()));
   1611 
   1612               } else {
   1613                 VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   1614                            MachineRepresentation::kBit);
   1615                 ChangeToPureOp(node, Int32Op(node));
   1616               }
   1617             }
   1618             return;
   1619           }
   1620           case NumberOperationHint::kNumberOrOddball:
   1621             // Abstract and strict equality don't perform ToNumber conversions
   1622             // on Oddballs, so make sure we don't accidentially sneak in a
   1623             // hint with Oddball feedback here.
   1624             DCHECK_NE(IrOpcode::kSpeculativeNumberEqual, node->opcode());
   1625           // Fallthrough
   1626           case NumberOperationHint::kNumber:
   1627             VisitBinop(node, CheckedUseInfoAsFloat64FromHint(hint),
   1628                        MachineRepresentation::kBit);
   1629             if (lower()) ChangeToPureOp(node, Float64Op(node));
   1630             return;
   1631         }
   1632         UNREACHABLE();
   1633         return;
   1634       }
   1635 
   1636       case IrOpcode::kNumberAdd:
   1637       case IrOpcode::kNumberSubtract: {
   1638         if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) &&
   1639             (GetUpperBound(node)->Is(Type::Signed32()) ||
   1640              GetUpperBound(node)->Is(Type::Unsigned32()) ||
   1641              truncation.IsUsedAsWord32())) {
   1642           // => Int32Add/Sub
   1643           VisitWord32TruncatingBinop(node);
   1644           if (lower()) ChangeToPureOp(node, Int32Op(node));
   1645         } else {
   1646           // => Float64Add/Sub
   1647           VisitFloat64Binop(node);
   1648           if (lower()) ChangeToPureOp(node, Float64Op(node));
   1649         }
   1650         return;
   1651       }
   1652       case IrOpcode::kSpeculativeNumberMultiply: {
   1653         // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
   1654         // can only eliminate an unused speculative number operation if we know
   1655         // that the inputs are PlainPrimitive, which excludes everything that's
   1656         // might have side effects or throws during a ToNumber conversion.
   1657         if (BothInputsAre(node, Type::PlainPrimitive())) {
   1658           if (truncation.IsUnused()) return VisitUnused(node);
   1659         }
   1660         if (BothInputsAre(node, Type::Integral32()) &&
   1661             (NodeProperties::GetType(node)->Is(Type::Signed32()) ||
   1662              NodeProperties::GetType(node)->Is(Type::Unsigned32()) ||
   1663              (truncation.IsUsedAsWord32() &&
   1664               NodeProperties::GetType(node)->Is(
   1665                   type_cache_.kSafeIntegerOrMinusZero)))) {
   1666           // Multiply reduces to Int32Mul if the inputs are integers, and
   1667           // (a) the output is either known to be Signed32, or
   1668           // (b) the output is known to be Unsigned32, or
   1669           // (c) the uses are truncating and the result is in the safe
   1670           //     integer range.
   1671           VisitWord32TruncatingBinop(node);
   1672           if (lower()) ChangeToPureOp(node, Int32Op(node));
   1673           return;
   1674         }
   1675         // Try to use type feedback.
   1676         NumberOperationHint hint = NumberOperationHintOf(node->op());
   1677         Type* input0_type = TypeOf(node->InputAt(0));
   1678         Type* input1_type = TypeOf(node->InputAt(1));
   1679 
   1680         // Handle the case when no int32 checks on inputs are necessary
   1681         // (but an overflow check is needed on the output).
   1682         if (BothInputsAre(node, Type::Signed32())) {
   1683           // If both the inputs the feedback are int32, use the overflow op.
   1684           if (hint == NumberOperationHint::kSignedSmall ||
   1685               hint == NumberOperationHint::kSigned32) {
   1686             VisitBinop(node, UseInfo::TruncatingWord32(),
   1687                        MachineRepresentation::kWord32, Type::Signed32());
   1688             if (lower()) {
   1689               LowerToCheckedInt32Mul(node, truncation, input0_type,
   1690                                      input1_type);
   1691             }
   1692             return;
   1693           }
   1694         }
   1695 
   1696         if (hint == NumberOperationHint::kSignedSmall ||
   1697             hint == NumberOperationHint::kSigned32) {
   1698           VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   1699                      MachineRepresentation::kWord32, Type::Signed32());
   1700           if (lower()) {
   1701             LowerToCheckedInt32Mul(node, truncation, input0_type, input1_type);
   1702           }
   1703           return;
   1704         }
   1705 
   1706         // Checked float64 x float64 => float64
   1707         VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
   1708                    MachineRepresentation::kFloat64, Type::Number());
   1709         if (lower()) ChangeToPureOp(node, Float64Op(node));
   1710         return;
   1711       }
   1712       case IrOpcode::kNumberMultiply: {
   1713         if (BothInputsAre(node, Type::Integral32()) &&
   1714             (NodeProperties::GetType(node)->Is(Type::Signed32()) ||
   1715              NodeProperties::GetType(node)->Is(Type::Unsigned32()) ||
   1716              (truncation.IsUsedAsWord32() &&
   1717               NodeProperties::GetType(node)->Is(
   1718                   type_cache_.kSafeIntegerOrMinusZero)))) {
   1719           // Multiply reduces to Int32Mul if the inputs are integers, and
   1720           // (a) the output is either known to be Signed32, or
   1721           // (b) the output is known to be Unsigned32, or
   1722           // (c) the uses are truncating and the result is in the safe
   1723           //     integer range.
   1724           VisitWord32TruncatingBinop(node);
   1725           if (lower()) ChangeToPureOp(node, Int32Op(node));
   1726           return;
   1727         }
   1728         // Number x Number => Float64Mul
   1729         VisitFloat64Binop(node);
   1730         if (lower()) ChangeToPureOp(node, Float64Op(node));
   1731         return;
   1732       }
   1733       case IrOpcode::kSpeculativeNumberDivide: {
   1734         // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
   1735         // can only eliminate an unused speculative number operation if we know
   1736         // that the inputs are PlainPrimitive, which excludes everything that's
   1737         // might have side effects or throws during a ToNumber conversion.
   1738         if (BothInputsAre(node, Type::PlainPrimitive())) {
   1739           if (truncation.IsUnused()) return VisitUnused(node);
   1740         }
   1741         if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) {
   1742           // => unsigned Uint32Div
   1743           VisitWord32TruncatingBinop(node);
   1744           if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
   1745           return;
   1746         }
   1747         if (BothInputsAreSigned32(node)) {
   1748           if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
   1749             // => signed Int32Div
   1750             VisitWord32TruncatingBinop(node);
   1751             if (lower()) DeferReplacement(node, lowering->Int32Div(node));
   1752             return;
   1753           }
   1754           if (truncation.IsUsedAsWord32()) {
   1755             // => signed Int32Div
   1756             VisitWord32TruncatingBinop(node);
   1757             if (lower()) DeferReplacement(node, lowering->Int32Div(node));
   1758             return;
   1759           }
   1760         }
   1761 
   1762         // Try to use type feedback.
   1763         NumberOperationHint hint = NumberOperationHintOf(node->op());
   1764 
   1765         // Handle the case when no uint32 checks on inputs are necessary
   1766         // (but an overflow check is needed on the output).
   1767         if (BothInputsAreUnsigned32(node)) {
   1768           if (hint == NumberOperationHint::kSignedSmall ||
   1769               hint == NumberOperationHint::kSigned32) {
   1770             VisitBinop(node, UseInfo::TruncatingWord32(),
   1771                        MachineRepresentation::kWord32, Type::Unsigned32());
   1772             if (lower()) ChangeToUint32OverflowOp(node);
   1773             return;
   1774           }
   1775         }
   1776 
   1777         // Handle the case when no int32 checks on inputs are necessary
   1778         // (but an overflow check is needed on the output).
   1779         if (BothInputsAreSigned32(node)) {
   1780           // If both the inputs the feedback are int32, use the overflow op.
   1781           if (hint == NumberOperationHint::kSignedSmall ||
   1782               hint == NumberOperationHint::kSigned32) {
   1783             VisitBinop(node, UseInfo::TruncatingWord32(),
   1784                        MachineRepresentation::kWord32, Type::Signed32());
   1785             if (lower()) ChangeToInt32OverflowOp(node);
   1786             return;
   1787           }
   1788         }
   1789 
   1790         if (hint == NumberOperationHint::kSignedSmall ||
   1791             hint == NumberOperationHint::kSigned32) {
   1792           // If the result is truncated, we only need to check the inputs.
   1793           if (truncation.IsUsedAsWord32()) {
   1794             VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   1795                        MachineRepresentation::kWord32);
   1796             if (lower()) DeferReplacement(node, lowering->Int32Div(node));
   1797           } else {
   1798             VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   1799                        MachineRepresentation::kWord32, Type::Signed32());
   1800             if (lower()) ChangeToInt32OverflowOp(node);
   1801           }
   1802           return;
   1803         }
   1804 
   1805         // default case => Float64Div
   1806         VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
   1807                    MachineRepresentation::kFloat64, Type::Number());
   1808         if (lower()) ChangeToPureOp(node, Float64Op(node));
   1809         return;
   1810       }
   1811       case IrOpcode::kNumberDivide: {
   1812         if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) {
   1813           // => unsigned Uint32Div
   1814           VisitWord32TruncatingBinop(node);
   1815           if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
   1816           return;
   1817         }
   1818         if (BothInputsAreSigned32(node)) {
   1819           if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
   1820             // => signed Int32Div
   1821             VisitWord32TruncatingBinop(node);
   1822             if (lower()) DeferReplacement(node, lowering->Int32Div(node));
   1823             return;
   1824           }
   1825           if (truncation.IsUsedAsWord32()) {
   1826             // => signed Int32Div
   1827             VisitWord32TruncatingBinop(node);
   1828             if (lower()) DeferReplacement(node, lowering->Int32Div(node));
   1829             return;
   1830           }
   1831         }
   1832         // Number x Number => Float64Div
   1833         VisitFloat64Binop(node);
   1834         if (lower()) ChangeToPureOp(node, Float64Op(node));
   1835         return;
   1836       }
   1837       case IrOpcode::kSpeculativeNumberModulus:
   1838         return VisitSpeculativeNumberModulus(node, truncation, lowering);
   1839       case IrOpcode::kNumberModulus: {
   1840         if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) &&
   1841             (truncation.IsUsedAsWord32() ||
   1842              NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
   1843           // => unsigned Uint32Mod
   1844           VisitWord32TruncatingBinop(node);
   1845           if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
   1846           return;
   1847         }
   1848         if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) &&
   1849             (truncation.IsUsedAsWord32() ||
   1850              NodeProperties::GetType(node)->Is(Type::Signed32()))) {
   1851           // => signed Int32Mod
   1852           VisitWord32TruncatingBinop(node);
   1853           if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
   1854           return;
   1855         }
   1856         if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
   1857             TypeOf(node->InputAt(1))->Is(Type::Unsigned32()) &&
   1858             (truncation.IsUsedAsWord32() ||
   1859              NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
   1860           // We can only promise Float64 truncation here, as the decision is
   1861           // based on the feedback types of the inputs.
   1862           VisitBinop(node, UseInfo(MachineRepresentation::kWord32,
   1863                                    Truncation::Float64()),
   1864                      MachineRepresentation::kWord32);
   1865           if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
   1866           return;
   1867         }
   1868         if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
   1869             TypeOf(node->InputAt(1))->Is(Type::Signed32()) &&
   1870             (truncation.IsUsedAsWord32() ||
   1871              NodeProperties::GetType(node)->Is(Type::Signed32()))) {
   1872           // We can only promise Float64 truncation here, as the decision is
   1873           // based on the feedback types of the inputs.
   1874           VisitBinop(node, UseInfo(MachineRepresentation::kWord32,
   1875                                    Truncation::Float64()),
   1876                      MachineRepresentation::kWord32);
   1877           if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
   1878           return;
   1879         }
   1880         // default case => Float64Mod
   1881         VisitFloat64Binop(node);
   1882         if (lower()) ChangeToPureOp(node, Float64Op(node));
   1883         return;
   1884       }
   1885       case IrOpcode::kNumberBitwiseOr:
   1886       case IrOpcode::kNumberBitwiseXor:
   1887       case IrOpcode::kNumberBitwiseAnd: {
   1888         VisitWord32TruncatingBinop(node);
   1889         if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
   1890         return;
   1891       }
   1892       case IrOpcode::kSpeculativeNumberBitwiseOr:
   1893       case IrOpcode::kSpeculativeNumberBitwiseXor:
   1894       case IrOpcode::kSpeculativeNumberBitwiseAnd:
   1895         VisitSpeculativeInt32Binop(node);
   1896         if (lower()) {
   1897           ChangeToPureOp(node, Int32Op(node));
   1898         }
   1899         return;
   1900       case IrOpcode::kNumberShiftLeft: {
   1901         Type* rhs_type = GetUpperBound(node->InputAt(1));
   1902         VisitBinop(node, UseInfo::TruncatingWord32(),
   1903                    UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
   1904         if (lower()) {
   1905           lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
   1906         }
   1907         return;
   1908       }
   1909       case IrOpcode::kSpeculativeNumberShiftLeft: {
   1910         // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
   1911         // can only eliminate an unused speculative number operation if we know
   1912         // that the inputs are PlainPrimitive, which excludes everything that's
   1913         // might have side effects or throws during a ToNumber conversion.
   1914         if (BothInputsAre(node, Type::PlainPrimitive())) {
   1915           if (truncation.IsUnused()) return VisitUnused(node);
   1916         }
   1917         if (BothInputsAre(node, Type::NumberOrOddball())) {
   1918           Type* rhs_type = GetUpperBound(node->InputAt(1));
   1919           VisitBinop(node, UseInfo::TruncatingWord32(),
   1920                      UseInfo::TruncatingWord32(),
   1921                      MachineRepresentation::kWord32);
   1922           if (lower()) {
   1923             lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
   1924           }
   1925           return;
   1926         }
   1927         NumberOperationHint hint = NumberOperationHintOf(node->op());
   1928         Type* rhs_type = GetUpperBound(node->InputAt(1));
   1929         VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   1930                    MachineRepresentation::kWord32, Type::Signed32());
   1931         if (lower()) {
   1932           lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
   1933         }
   1934         return;
   1935       }
   1936       case IrOpcode::kNumberShiftRight: {
   1937         Type* rhs_type = GetUpperBound(node->InputAt(1));
   1938         VisitBinop(node, UseInfo::TruncatingWord32(),
   1939                    UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
   1940         if (lower()) {
   1941           lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
   1942         }
   1943         return;
   1944       }
   1945       case IrOpcode::kSpeculativeNumberShiftRight: {
   1946         // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
   1947         // can only eliminate an unused speculative number operation if we know
   1948         // that the inputs are PlainPrimitive, which excludes everything that's
   1949         // might have side effects or throws during a ToNumber conversion.
   1950         if (BothInputsAre(node, Type::PlainPrimitive())) {
   1951           if (truncation.IsUnused()) return VisitUnused(node);
   1952         }
   1953         if (BothInputsAre(node, Type::NumberOrOddball())) {
   1954           Type* rhs_type = GetUpperBound(node->InputAt(1));
   1955           VisitBinop(node, UseInfo::TruncatingWord32(),
   1956                      UseInfo::TruncatingWord32(),
   1957                      MachineRepresentation::kWord32);
   1958           if (lower()) {
   1959             lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
   1960           }
   1961           return;
   1962         }
   1963         NumberOperationHint hint = NumberOperationHintOf(node->op());
   1964         Type* rhs_type = GetUpperBound(node->InputAt(1));
   1965         VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   1966                    MachineRepresentation::kWord32, Type::Signed32());
   1967         if (lower()) {
   1968           lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
   1969         }
   1970         return;
   1971       }
   1972       case IrOpcode::kNumberShiftRightLogical: {
   1973         Type* rhs_type = GetUpperBound(node->InputAt(1));
   1974         VisitBinop(node, UseInfo::TruncatingWord32(),
   1975                    UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
   1976         if (lower()) {
   1977           lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
   1978         }
   1979         return;
   1980       }
   1981       case IrOpcode::kSpeculativeNumberShiftRightLogical: {
   1982         // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
   1983         // can only eliminate an unused speculative number operation if we know
   1984         // that the inputs are PlainPrimitive, which excludes everything that's
   1985         // might have side effects or throws during a ToNumber conversion.
   1986         if (BothInputsAre(node, Type::PlainPrimitive())) {
   1987           if (truncation.IsUnused()) return VisitUnused(node);
   1988         }
   1989         NumberOperationHint hint = NumberOperationHintOf(node->op());
   1990         Type* rhs_type = GetUpperBound(node->InputAt(1));
   1991         if (rhs_type->Is(type_cache_.kZeroish) &&
   1992             (hint == NumberOperationHint::kSignedSmall ||
   1993              hint == NumberOperationHint::kSigned32) &&
   1994             !truncation.IsUsedAsWord32()) {
   1995           // The SignedSmall or Signed32 feedback means that the results that we
   1996           // have seen so far were of type Unsigned31.  We speculate that this
   1997           // will continue to hold.  Moreover, since the RHS is 0, the result
   1998           // will just be the (converted) LHS.
   1999           VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   2000                      MachineRepresentation::kWord32, Type::Unsigned31());
   2001           if (lower()) {
   2002             node->RemoveInput(1);
   2003             NodeProperties::ChangeOp(node,
   2004                                      simplified()->CheckedUint32ToInt32());
   2005           }
   2006           return;
   2007         }
   2008         if (BothInputsAre(node, Type::NumberOrOddball())) {
   2009           VisitBinop(node, UseInfo::TruncatingWord32(),
   2010                      UseInfo::TruncatingWord32(),
   2011                      MachineRepresentation::kWord32);
   2012           if (lower()) {
   2013             lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
   2014           }
   2015           return;
   2016         }
   2017         VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
   2018                    MachineRepresentation::kWord32, Type::Unsigned32());
   2019         if (lower()) {
   2020           lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
   2021         }
   2022         return;
   2023       }
   2024       case IrOpcode::kNumberAbs: {
   2025         if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32())) {
   2026           VisitUnop(node, UseInfo::TruncatingWord32(),
   2027                     MachineRepresentation::kWord32);
   2028           if (lower()) DeferReplacement(node, node->InputAt(0));
   2029         } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32())) {
   2030           VisitUnop(node, UseInfo::TruncatingWord32(),
   2031                     MachineRepresentation::kWord32);
   2032           if (lower()) DeferReplacement(node, lowering->Int32Abs(node));
   2033         } else if (TypeOf(node->InputAt(0))
   2034                        ->Is(type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) {
   2035           VisitUnop(node, UseInfo::TruncatingFloat64(),
   2036                     MachineRepresentation::kFloat64);
   2037           if (lower()) DeferReplacement(node, node->InputAt(0));
   2038         } else {
   2039           VisitUnop(node, UseInfo::TruncatingFloat64(),
   2040                     MachineRepresentation::kFloat64);
   2041           if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
   2042         }
   2043         return;
   2044       }
   2045       case IrOpcode::kNumberClz32: {
   2046         VisitUnop(node, UseInfo::TruncatingWord32(),
   2047                   MachineRepresentation::kWord32);
   2048         if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
   2049         return;
   2050       }
   2051       case IrOpcode::kNumberImul: {
   2052         VisitBinop(node, UseInfo::TruncatingWord32(),
   2053                    UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
   2054         if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
   2055         return;
   2056       }
   2057       case IrOpcode::kNumberFround: {
   2058         VisitUnop(node, UseInfo::TruncatingFloat64(),
   2059                   MachineRepresentation::kFloat32);
   2060         if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
   2061         return;
   2062       }
   2063       case IrOpcode::kNumberMax: {
   2064         // TODO(turbofan): We should consider feedback types here as well.
   2065         if (BothInputsAreUnsigned32(node)) {
   2066           VisitWord32TruncatingBinop(node);
   2067           if (lower()) {
   2068             lowering->DoMax(node, lowering->machine()->Uint32LessThan(),
   2069                             MachineRepresentation::kWord32);
   2070           }
   2071         } else if (BothInputsAreSigned32(node)) {
   2072           VisitWord32TruncatingBinop(node);
   2073           if (lower()) {
   2074             lowering->DoMax(node, lowering->machine()->Int32LessThan(),
   2075                             MachineRepresentation::kWord32);
   2076           }
   2077         } else if (BothInputsAre(node, Type::PlainNumber())) {
   2078           VisitFloat64Binop(node);
   2079           if (lower()) {
   2080             lowering->DoMax(node, lowering->machine()->Float64LessThan(),
   2081                             MachineRepresentation::kFloat64);
   2082           }
   2083         } else {
   2084           VisitFloat64Binop(node);
   2085           if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
   2086         }
   2087         return;
   2088       }
   2089       case IrOpcode::kNumberMin: {
   2090         // TODO(turbofan): We should consider feedback types here as well.
   2091         if (BothInputsAreUnsigned32(node)) {
   2092           VisitWord32TruncatingBinop(node);
   2093           if (lower()) {
   2094             lowering->DoMin(node, lowering->machine()->Uint32LessThan(),
   2095                             MachineRepresentation::kWord32);
   2096           }
   2097         } else if (BothInputsAreSigned32(node)) {
   2098           VisitWord32TruncatingBinop(node);
   2099           if (lower()) {
   2100             lowering->DoMin(node, lowering->machine()->Int32LessThan(),
   2101                             MachineRepresentation::kWord32);
   2102           }
   2103         } else if (BothInputsAre(node, Type::PlainNumber())) {
   2104           VisitFloat64Binop(node);
   2105           if (lower()) {
   2106             lowering->DoMin(node, lowering->machine()->Float64LessThan(),
   2107                             MachineRepresentation::kFloat64);
   2108           }
   2109         } else {
   2110           VisitFloat64Binop(node);
   2111           if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
   2112         }
   2113         return;
   2114       }
   2115       case IrOpcode::kNumberAtan2:
   2116       case IrOpcode::kNumberPow: {
   2117         VisitBinop(node, UseInfo::TruncatingFloat64(),
   2118                    MachineRepresentation::kFloat64);
   2119         if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
   2120         return;
   2121       }
   2122       case IrOpcode::kNumberAcos:
   2123       case IrOpcode::kNumberAcosh:
   2124       case IrOpcode::kNumberAsin:
   2125       case IrOpcode::kNumberAsinh:
   2126       case IrOpcode::kNumberAtan:
   2127       case IrOpcode::kNumberAtanh:
   2128       case IrOpcode::kNumberCeil:
   2129       case IrOpcode::kNumberCos:
   2130       case IrOpcode::kNumberCosh:
   2131       case IrOpcode::kNumberExp:
   2132       case IrOpcode::kNumberExpm1:
   2133       case IrOpcode::kNumberFloor:
   2134       case IrOpcode::kNumberLog:
   2135       case IrOpcode::kNumberLog1p:
   2136       case IrOpcode::kNumberLog2:
   2137       case IrOpcode::kNumberLog10:
   2138       case IrOpcode::kNumberCbrt:
   2139       case IrOpcode::kNumberSin:
   2140       case IrOpcode::kNumberSinh:
   2141       case IrOpcode::kNumberTan:
   2142       case IrOpcode::kNumberTanh:
   2143       case IrOpcode::kNumberTrunc: {
   2144         VisitUnop(node, UseInfo::TruncatingFloat64(),
   2145                   MachineRepresentation::kFloat64);
   2146         if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
   2147         return;
   2148       }
   2149       case IrOpcode::kNumberRound: {
   2150         VisitUnop(node, UseInfo::TruncatingFloat64(),
   2151                   MachineRepresentation::kFloat64);
   2152         if (lower()) DeferReplacement(node, lowering->Float64Round(node));
   2153         return;
   2154       }
   2155       case IrOpcode::kNumberSign: {
   2156         if (InputIs(node, Type::Signed32())) {
   2157           VisitUnop(node, UseInfo::TruncatingWord32(),
   2158                     MachineRepresentation::kWord32);
   2159           if (lower()) DeferReplacement(node, lowering->Int32Sign(node));
   2160         } else {
   2161           VisitUnop(node, UseInfo::TruncatingFloat64(),
   2162                     MachineRepresentation::kFloat64);
   2163           if (lower()) DeferReplacement(node, lowering->Float64Sign(node));
   2164         }
   2165         return;
   2166       }
   2167       case IrOpcode::kNumberSqrt: {
   2168         VisitUnop(node, UseInfo::TruncatingFloat64(),
   2169                   MachineRepresentation::kFloat64);
   2170         if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
   2171         return;
   2172       }
   2173       case IrOpcode::kNumberToBoolean: {
   2174         Type* const input_type = TypeOf(node->InputAt(0));
   2175         if (input_type->Is(Type::Integral32())) {
   2176           VisitUnop(node, UseInfo::TruncatingWord32(),
   2177                     MachineRepresentation::kBit);
   2178           if (lower()) lowering->DoIntegral32ToBit(node);
   2179         } else if (input_type->Is(Type::OrderedNumber())) {
   2180           VisitUnop(node, UseInfo::TruncatingFloat64(),
   2181                     MachineRepresentation::kBit);
   2182           if (lower()) lowering->DoOrderedNumberToBit(node);
   2183         } else {
   2184           VisitUnop(node, UseInfo::TruncatingFloat64(),
   2185                     MachineRepresentation::kBit);
   2186           if (lower()) lowering->DoNumberToBit(node);
   2187         }
   2188         return;
   2189       }
   2190       case IrOpcode::kNumberToInt32: {
   2191         // Just change representation if necessary.
   2192         VisitUnop(node, UseInfo::TruncatingWord32(),
   2193                   MachineRepresentation::kWord32);
   2194         if (lower()) DeferReplacement(node, node->InputAt(0));
   2195         return;
   2196       }
   2197       case IrOpcode::kNumberToUint32: {
   2198         // Just change representation if necessary.
   2199         VisitUnop(node, UseInfo::TruncatingWord32(),
   2200                   MachineRepresentation::kWord32);
   2201         if (lower()) DeferReplacement(node, node->InputAt(0));
   2202         return;
   2203       }
   2204       case IrOpcode::kNumberToUint8Clamped: {
   2205         Type* const input_type = TypeOf(node->InputAt(0));
   2206         if (input_type->Is(type_cache_.kUint8OrMinusZeroOrNaN)) {
   2207           VisitUnop(node, UseInfo::TruncatingWord32(),
   2208                     MachineRepresentation::kWord32);
   2209           if (lower()) DeferReplacement(node, node->InputAt(0));
   2210         } else if (input_type->Is(Type::Unsigned32OrMinusZeroOrNaN())) {
   2211           VisitUnop(node, UseInfo::TruncatingWord32(),
   2212                     MachineRepresentation::kWord32);
   2213           if (lower()) lowering->DoUnsigned32ToUint8Clamped(node);
   2214         } else if (input_type->Is(Type::Signed32OrMinusZeroOrNaN())) {
   2215           VisitUnop(node, UseInfo::TruncatingWord32(),
   2216                     MachineRepresentation::kWord32);
   2217           if (lower()) lowering->DoSigned32ToUint8Clamped(node);
   2218         } else if (input_type->Is(type_cache_.kIntegerOrMinusZeroOrNaN)) {
   2219           VisitUnop(node, UseInfo::TruncatingFloat64(),
   2220                     MachineRepresentation::kFloat64);
   2221           if (lower()) lowering->DoIntegerToUint8Clamped(node);
   2222         } else {
   2223           VisitUnop(node, UseInfo::TruncatingFloat64(),
   2224                     MachineRepresentation::kFloat64);
   2225           if (lower()) lowering->DoNumberToUint8Clamped(node);
   2226         }
   2227         return;
   2228       }
   2229       case IrOpcode::kReferenceEqual: {
   2230         VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
   2231         if (lower()) {
   2232           NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
   2233         }
   2234         return;
   2235       }
   2236       case IrOpcode::kStringEqual:
   2237       case IrOpcode::kStringLessThan:
   2238       case IrOpcode::kStringLessThanOrEqual: {
   2239         return VisitBinop(node, UseInfo::AnyTagged(),
   2240                           MachineRepresentation::kTaggedPointer);
   2241       }
   2242       case IrOpcode::kStringCharAt: {
   2243         VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
   2244                    MachineRepresentation::kTaggedPointer);
   2245         return;
   2246       }
   2247       case IrOpcode::kStringCharCodeAt: {
   2248         // TODO(turbofan): Allow builtins to return untagged values.
   2249         VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
   2250                    MachineRepresentation::kTaggedSigned);
   2251         return;
   2252       }
   2253       case IrOpcode::kStringFromCharCode: {
   2254         VisitUnop(node, UseInfo::TruncatingWord32(),
   2255                   MachineRepresentation::kTaggedPointer);
   2256         return;
   2257       }
   2258       case IrOpcode::kStringFromCodePoint: {
   2259         VisitUnop(node, UseInfo::TruncatingWord32(),
   2260                   MachineRepresentation::kTaggedPointer);
   2261         return;
   2262       }
   2263       case IrOpcode::kStringIndexOf: {
   2264         ProcessInput(node, 0, UseInfo::AnyTagged());
   2265         ProcessInput(node, 1, UseInfo::AnyTagged());
   2266         ProcessInput(node, 2, UseInfo::TaggedSigned());
   2267         SetOutput(node, MachineRepresentation::kTaggedSigned);
   2268         return;
   2269       }
   2270 
   2271       case IrOpcode::kCheckBounds: {
   2272         Type* index_type = TypeOf(node->InputAt(0));
   2273         Type* length_type = TypeOf(node->InputAt(1));
   2274         if (index_type->Is(Type::Unsigned32())) {
   2275           VisitBinop(node, UseInfo::TruncatingWord32(),
   2276                      MachineRepresentation::kWord32);
   2277           if (lower() && index_type->Max() < length_type->Min()) {
   2278             // The bounds check is redundant if we already know that
   2279             // the index is within the bounds of [0.0, length[.
   2280             DeferReplacement(node, node->InputAt(0));
   2281           }
   2282         } else {
   2283           VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
   2284                      UseInfo::TruncatingWord32(),
   2285                      MachineRepresentation::kWord32);
   2286         }
   2287         return;
   2288       }
   2289       case IrOpcode::kCheckHeapObject: {
   2290         if (InputCannotBe(node, Type::SignedSmall())) {
   2291           VisitUnop(node, UseInfo::AnyTagged(),
   2292                     MachineRepresentation::kTaggedPointer);
   2293         } else {
   2294           VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
   2295                     MachineRepresentation::kTaggedPointer);
   2296         }
   2297         if (lower()) DeferReplacement(node, node->InputAt(0));
   2298         return;
   2299       }
   2300       case IrOpcode::kCheckIf: {
   2301         ProcessInput(node, 0, UseInfo::Bool());
   2302         ProcessRemainingInputs(node, 1);
   2303         SetOutput(node, MachineRepresentation::kNone);
   2304         return;
   2305       }
   2306       case IrOpcode::kCheckInternalizedString: {
   2307         if (InputIs(node, Type::InternalizedString())) {
   2308           VisitUnop(node, UseInfo::AnyTagged(),
   2309                     MachineRepresentation::kTaggedPointer);
   2310           if (lower()) DeferReplacement(node, node->InputAt(0));
   2311         } else {
   2312           VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
   2313                     MachineRepresentation::kTaggedPointer);
   2314         }
   2315         return;
   2316       }
   2317       case IrOpcode::kCheckNumber: {
   2318         if (InputIs(node, Type::Number())) {
   2319           if (truncation.IsUsedAsWord32()) {
   2320             VisitUnop(node, UseInfo::TruncatingWord32(),
   2321                       MachineRepresentation::kWord32);
   2322           } else {
   2323             // TODO(jarin,bmeurer): We need to go to Tagged here, because
   2324             // otherwise we cannot distinguish the hole NaN (which might need to
   2325             // be treated as undefined). We should have a dedicated Type for
   2326             // that at some point, and maybe even a dedicated truncation.
   2327             VisitUnop(node, UseInfo::AnyTagged(),
   2328                       MachineRepresentation::kTagged);
   2329           }
   2330           if (lower()) DeferReplacement(node, node->InputAt(0));
   2331         } else {
   2332           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
   2333         }
   2334         return;
   2335       }
   2336       case IrOpcode::kCheckReceiver: {
   2337         if (InputIs(node, Type::Receiver())) {
   2338           VisitUnop(node, UseInfo::AnyTagged(),
   2339                     MachineRepresentation::kTaggedPointer);
   2340           if (lower()) DeferReplacement(node, node->InputAt(0));
   2341         } else {
   2342           VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
   2343                     MachineRepresentation::kTaggedPointer);
   2344         }
   2345         return;
   2346       }
   2347       case IrOpcode::kCheckSmi: {
   2348         if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) {
   2349           VisitUnop(node, UseInfo::CheckedSignedSmallAsWord32(),
   2350                     MachineRepresentation::kWord32);
   2351         } else {
   2352           VisitUnop(node, UseInfo::CheckedSignedSmallAsTaggedSigned(),
   2353                     MachineRepresentation::kTaggedSigned);
   2354         }
   2355         if (lower()) DeferReplacement(node, node->InputAt(0));
   2356         return;
   2357       }
   2358       case IrOpcode::kCheckString: {
   2359         if (InputIs(node, Type::String())) {
   2360           VisitUnop(node, UseInfo::AnyTagged(),
   2361                     MachineRepresentation::kTaggedPointer);
   2362           if (lower()) DeferReplacement(node, node->InputAt(0));
   2363         } else {
   2364           VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
   2365                     MachineRepresentation::kTaggedPointer);
   2366         }
   2367         return;
   2368       }
   2369 
   2370       case IrOpcode::kAllocate: {
   2371         ProcessInput(node, 0, UseInfo::TruncatingWord32());
   2372         ProcessRemainingInputs(node, 1);
   2373         SetOutput(node, MachineRepresentation::kTaggedPointer);
   2374         return;
   2375       }
   2376       case IrOpcode::kLoadField: {
   2377         if (truncation.IsUnused()) return VisitUnused(node);
   2378         FieldAccess access = FieldAccessOf(node->op());
   2379         MachineRepresentation const representation =
   2380             access.machine_type.representation();
   2381         VisitUnop(node, UseInfoForBasePointer(access), representation);
   2382         return;
   2383       }
   2384       case IrOpcode::kStoreField: {
   2385         FieldAccess access = FieldAccessOf(node->op());
   2386         NodeInfo* input_info = GetInfo(node->InputAt(1));
   2387         WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
   2388             access.base_is_tagged, access.machine_type.representation(),
   2389             access.offset, access.type, input_info->representation(),
   2390             node->InputAt(1));
   2391         ProcessInput(node, 0, UseInfoForBasePointer(access));
   2392         ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
   2393                                   access.machine_type.representation()));
   2394         ProcessRemainingInputs(node, 2);
   2395         SetOutput(node, MachineRepresentation::kNone);
   2396         if (lower()) {
   2397           if (write_barrier_kind < access.write_barrier_kind) {
   2398             access.write_barrier_kind = write_barrier_kind;
   2399             NodeProperties::ChangeOp(
   2400                 node, jsgraph_->simplified()->StoreField(access));
   2401           }
   2402         }
   2403         return;
   2404       }
   2405       case IrOpcode::kLoadBuffer: {
   2406         if (truncation.IsUnused()) return VisitUnused(node);
   2407         BufferAccess access = BufferAccessOf(node->op());
   2408         ProcessInput(node, 0, UseInfo::PointerInt());        // buffer
   2409         ProcessInput(node, 1, UseInfo::TruncatingWord32());  // offset
   2410         ProcessInput(node, 2, UseInfo::TruncatingWord32());  // length
   2411         ProcessRemainingInputs(node, 3);
   2412 
   2413         MachineRepresentation output;
   2414         if (truncation.IdentifiesUndefinedAndNaNAndZero()) {
   2415           if (truncation.IdentifiesNaNAndZero()) {
   2416             // If undefined is truncated to a non-NaN number, we can use
   2417             // the load's representation.
   2418             output = access.machine_type().representation();
   2419           } else {
   2420             // If undefined is truncated to a number, but the use can
   2421             // observe NaN, we need to output at least the float32
   2422             // representation.
   2423             if (access.machine_type().representation() ==
   2424                 MachineRepresentation::kFloat32) {
   2425               output = access.machine_type().representation();
   2426             } else {
   2427               output = MachineRepresentation::kFloat64;
   2428             }
   2429           }
   2430         } else {
   2431           // If undefined is not truncated away, we need to have the tagged
   2432           // representation.
   2433           output = MachineRepresentation::kTagged;
   2434         }
   2435         SetOutput(node, output);
   2436         if (lower()) lowering->DoLoadBuffer(node, output, changer_);
   2437         return;
   2438       }
   2439       case IrOpcode::kStoreBuffer: {
   2440         BufferAccess access = BufferAccessOf(node->op());
   2441         ProcessInput(node, 0, UseInfo::PointerInt());        // buffer
   2442         ProcessInput(node, 1, UseInfo::TruncatingWord32());  // offset
   2443         ProcessInput(node, 2, UseInfo::TruncatingWord32());  // length
   2444         ProcessInput(node, 3,
   2445                      TruncatingUseInfoFromRepresentation(
   2446                          access.machine_type().representation()));  // value
   2447         ProcessRemainingInputs(node, 4);
   2448         SetOutput(node, MachineRepresentation::kNone);
   2449         if (lower()) lowering->DoStoreBuffer(node);
   2450         return;
   2451       }
   2452       case IrOpcode::kLoadElement: {
   2453         if (truncation.IsUnused()) return VisitUnused(node);
   2454         ElementAccess access = ElementAccessOf(node->op());
   2455         VisitBinop(node, UseInfoForBasePointer(access),
   2456                    UseInfo::TruncatingWord32(),
   2457                    access.machine_type.representation());
   2458         return;
   2459       }
   2460       case IrOpcode::kStoreElement: {
   2461         ElementAccess access = ElementAccessOf(node->op());
   2462         NodeInfo* input_info = GetInfo(node->InputAt(2));
   2463         WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
   2464             access.base_is_tagged, access.machine_type.representation(),
   2465             access.type, input_info->representation(), node->InputAt(2));
   2466         ProcessInput(node, 0, UseInfoForBasePointer(access));  // base
   2467         ProcessInput(node, 1, UseInfo::TruncatingWord32());    // index
   2468         ProcessInput(node, 2,
   2469                      TruncatingUseInfoFromRepresentation(
   2470                          access.machine_type.representation()));  // value
   2471         ProcessRemainingInputs(node, 3);
   2472         SetOutput(node, MachineRepresentation::kNone);
   2473         if (lower()) {
   2474           if (write_barrier_kind < access.write_barrier_kind) {
   2475             access.write_barrier_kind = write_barrier_kind;
   2476             NodeProperties::ChangeOp(
   2477                 node, jsgraph_->simplified()->StoreElement(access));
   2478           }
   2479         }
   2480         return;
   2481       }
   2482       case IrOpcode::kLoadTypedElement: {
   2483         MachineRepresentation const rep =
   2484             MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
   2485         ProcessInput(node, 0, UseInfo::AnyTagged());         // buffer
   2486         ProcessInput(node, 1, UseInfo::AnyTagged());         // base pointer
   2487         ProcessInput(node, 2, UseInfo::PointerInt());        // external pointer
   2488         ProcessInput(node, 3, UseInfo::TruncatingWord32());  // index
   2489         ProcessRemainingInputs(node, 4);
   2490         SetOutput(node, rep);
   2491         return;
   2492       }
   2493       case IrOpcode::kStoreTypedElement: {
   2494         MachineRepresentation const rep =
   2495             MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
   2496         ProcessInput(node, 0, UseInfo::AnyTagged());         // buffer
   2497         ProcessInput(node, 1, UseInfo::AnyTagged());         // base pointer
   2498         ProcessInput(node, 2, UseInfo::PointerInt());        // external pointer
   2499         ProcessInput(node, 3, UseInfo::TruncatingWord32());  // index
   2500         ProcessInput(node, 4,
   2501                      TruncatingUseInfoFromRepresentation(rep));  // value
   2502         ProcessRemainingInputs(node, 5);
   2503         SetOutput(node, MachineRepresentation::kNone);
   2504         return;
   2505       }
   2506       case IrOpcode::kPlainPrimitiveToNumber: {
   2507         if (InputIs(node, Type::Boolean())) {
   2508           VisitUnop(node, UseInfo::Bool(), MachineRepresentation::kWord32);
   2509           if (lower()) DeferReplacement(node, node->InputAt(0));
   2510         } else if (InputIs(node, Type::String())) {
   2511           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
   2512           if (lower()) lowering->DoStringToNumber(node);
   2513         } else if (truncation.IsUsedAsWord32()) {
   2514           if (InputIs(node, Type::NumberOrOddball())) {
   2515             VisitUnop(node, UseInfo::TruncatingWord32(),
   2516                       MachineRepresentation::kWord32);
   2517             if (lower()) DeferReplacement(node, node->InputAt(0));
   2518           } else {
   2519             VisitUnop(node, UseInfo::AnyTagged(),
   2520                       MachineRepresentation::kWord32);
   2521             if (lower()) {
   2522               NodeProperties::ChangeOp(node,
   2523                                        simplified()->PlainPrimitiveToWord32());
   2524             }
   2525           }
   2526         } else if (truncation.IsUsedAsFloat64()) {
   2527           if (InputIs(node, Type::NumberOrOddball())) {
   2528             VisitUnop(node, UseInfo::TruncatingFloat64(),
   2529                       MachineRepresentation::kFloat64);
   2530             if (lower()) DeferReplacement(node, node->InputAt(0));
   2531           } else {
   2532             VisitUnop(node, UseInfo::AnyTagged(),
   2533                       MachineRepresentation::kFloat64);
   2534             if (lower()) {
   2535               NodeProperties::ChangeOp(node,
   2536                                        simplified()->PlainPrimitiveToFloat64());
   2537             }
   2538           }
   2539         } else {
   2540           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
   2541         }
   2542         return;
   2543       }
   2544       case IrOpcode::kObjectIsDetectableCallable: {
   2545         VisitObjectIs(node, Type::DetectableCallable(), lowering);
   2546         return;
   2547       }
   2548       case IrOpcode::kObjectIsNonCallable: {
   2549         VisitObjectIs(node, Type::NonCallable(), lowering);
   2550         return;
   2551       }
   2552       case IrOpcode::kObjectIsNumber: {
   2553         VisitObjectIs(node, Type::Number(), lowering);
   2554         return;
   2555       }
   2556       case IrOpcode::kObjectIsReceiver: {
   2557         VisitObjectIs(node, Type::Receiver(), lowering);
   2558         return;
   2559       }
   2560       case IrOpcode::kObjectIsSmi: {
   2561         // TODO(turbofan): Optimize based on input representation.
   2562         VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
   2563         return;
   2564       }
   2565       case IrOpcode::kObjectIsString: {
   2566         VisitObjectIs(node, Type::String(), lowering);
   2567         return;
   2568       }
   2569       case IrOpcode::kObjectIsUndetectable: {
   2570         VisitObjectIs(node, Type::Undetectable(), lowering);
   2571         return;
   2572       }
   2573       case IrOpcode::kNewRestParameterElements:
   2574       case IrOpcode::kNewUnmappedArgumentsElements: {
   2575         ProcessRemainingInputs(node, 0);
   2576         SetOutput(node, MachineRepresentation::kTaggedPointer);
   2577         return;
   2578       }
   2579       case IrOpcode::kArrayBufferWasNeutered: {
   2580         VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
   2581         return;
   2582       }
   2583       case IrOpcode::kCheckFloat64Hole: {
   2584         CheckFloat64HoleMode mode = CheckFloat64HoleModeOf(node->op());
   2585         ProcessInput(node, 0, UseInfo::TruncatingFloat64());
   2586         ProcessRemainingInputs(node, 1);
   2587         SetOutput(node, MachineRepresentation::kFloat64);
   2588         if (truncation.IsUsedAsFloat64() &&
   2589             mode == CheckFloat64HoleMode::kAllowReturnHole) {
   2590           if (lower()) DeferReplacement(node, node->InputAt(0));
   2591         }
   2592         return;
   2593       }
   2594       case IrOpcode::kCheckTaggedHole: {
   2595         VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
   2596         return;
   2597       }
   2598       case IrOpcode::kConvertTaggedHoleToUndefined: {
   2599         if (InputIs(node, Type::NumberOrOddball()) &&
   2600             truncation.IsUsedAsWord32()) {
   2601           // Propagate the Word32 truncation.
   2602           VisitUnop(node, UseInfo::TruncatingWord32(),
   2603                     MachineRepresentation::kWord32);
   2604           if (lower()) DeferReplacement(node, node->InputAt(0));
   2605         } else if (InputIs(node, Type::NumberOrOddball()) &&
   2606                    truncation.IsUsedAsFloat64()) {
   2607           // Propagate the Float64 truncation.
   2608           VisitUnop(node, UseInfo::TruncatingFloat64(),
   2609                     MachineRepresentation::kFloat64);
   2610           if (lower()) DeferReplacement(node, node->InputAt(0));
   2611         } else if (InputIs(node, Type::NonInternal())) {
   2612           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
   2613           if (lower()) DeferReplacement(node, node->InputAt(0));
   2614         } else {
   2615           // TODO(turbofan): Add a (Tagged) truncation that identifies hole
   2616           // and undefined, i.e. for a[i] === obj cases.
   2617           VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
   2618         }
   2619         return;
   2620       }
   2621       case IrOpcode::kCheckMaps:
   2622       case IrOpcode::kTransitionElementsKind: {
   2623         VisitInputs(node);
   2624         return SetOutput(node, MachineRepresentation::kNone);
   2625       }
   2626       case IrOpcode::kEnsureWritableFastElements:
   2627         return VisitBinop(node, UseInfo::AnyTagged(),
   2628                           MachineRepresentation::kTaggedPointer);
   2629       case IrOpcode::kMaybeGrowFastElements: {
   2630         ProcessInput(node, 0, UseInfo::AnyTagged());         // object
   2631         ProcessInput(node, 1, UseInfo::AnyTagged());         // elements
   2632         ProcessInput(node, 2, UseInfo::TruncatingWord32());  // index
   2633         ProcessInput(node, 3, UseInfo::TruncatingWord32());  // length
   2634         ProcessRemainingInputs(node, 4);
   2635         SetOutput(node, MachineRepresentation::kTaggedPointer);
   2636         return;
   2637       }
   2638 
   2639       case IrOpcode::kNumberSilenceNaN:
   2640         VisitUnop(node, UseInfo::TruncatingFloat64(),
   2641                   MachineRepresentation::kFloat64);
   2642         if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
   2643         return;
   2644       case IrOpcode::kStateValues:
   2645         return VisitStateValues(node);
   2646       case IrOpcode::kObjectState:
   2647         return VisitObjectState(node);
   2648       case IrOpcode::kTypeGuard: {
   2649         // We just get rid of the sigma here. In principle, it should be
   2650         // possible to refine the truncation and representation based on
   2651         // the sigma's type.
   2652         MachineRepresentation output =
   2653             GetOutputInfoForPhi(node, TypeOf(node->InputAt(0)), truncation);
   2654         VisitUnop(node, UseInfo(output, truncation), output);
   2655         if (lower()) DeferReplacement(node, node->InputAt(0));
   2656         return;
   2657       }
   2658 
   2659       case IrOpcode::kOsrGuard:
   2660         return VisitOsrGuard(node);
   2661 
   2662       case IrOpcode::kFinishRegion:
   2663         VisitInputs(node);
   2664         // Assume the output is tagged pointer.
   2665         return SetOutput(node, MachineRepresentation::kTaggedPointer);
   2666 
   2667       case IrOpcode::kReturn:
   2668         VisitReturn(node);
   2669         // Assume the output is tagged.
   2670         return SetOutput(node, MachineRepresentation::kTagged);
   2671 
   2672       // Operators with all inputs tagged and no or tagged output have uniform
   2673       // handling.
   2674       case IrOpcode::kEnd:
   2675       case IrOpcode::kIfSuccess:
   2676       case IrOpcode::kIfException:
   2677       case IrOpcode::kIfTrue:
   2678       case IrOpcode::kIfFalse:
   2679       case IrOpcode::kDeoptimize:
   2680       case IrOpcode::kEffectPhi:
   2681       case IrOpcode::kTerminate:
   2682       case IrOpcode::kFrameState:
   2683       case IrOpcode::kCheckpoint:
   2684       case IrOpcode::kLoop:
   2685       case IrOpcode::kMerge:
   2686       case IrOpcode::kThrow:
   2687       case IrOpcode::kBeginRegion:
   2688       case IrOpcode::kProjection:
   2689       case IrOpcode::kOsrValue:
   2690       case IrOpcode::kArgumentsObjectState:
   2691 // All JavaScript operators except JSToNumber have uniform handling.
   2692 #define OPCODE_CASE(name) case IrOpcode::k##name:
   2693         JS_SIMPLE_BINOP_LIST(OPCODE_CASE)
   2694         JS_OTHER_UNOP_LIST(OPCODE_CASE)
   2695         JS_OBJECT_OP_LIST(OPCODE_CASE)
   2696         JS_CONTEXT_OP_LIST(OPCODE_CASE)
   2697         JS_OTHER_OP_LIST(OPCODE_CASE)
   2698 #undef OPCODE_CASE
   2699       case IrOpcode::kJSToInteger:
   2700       case IrOpcode::kJSToLength:
   2701       case IrOpcode::kJSToName:
   2702       case IrOpcode::kJSToObject:
   2703       case IrOpcode::kJSToString:
   2704         VisitInputs(node);
   2705         // Assume the output is tagged.
   2706         return SetOutput(node, MachineRepresentation::kTagged);
   2707 
   2708       default:
   2709         V8_Fatal(
   2710             __FILE__, __LINE__,
   2711             "Representation inference: unsupported opcode %i (%s), node #%i\n.",
   2712             node->opcode(), node->op()->mnemonic(), node->id());
   2713         break;
   2714     }
   2715     UNREACHABLE();
   2716   }
   2717 
   2718   void DeferReplacement(Node* node, Node* replacement) {
   2719     TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(),
   2720           node->op()->mnemonic(), replacement->id(),
   2721           replacement->op()->mnemonic());
   2722 
   2723     // Disconnect the node from effect and control chains, if necessary.
   2724     if (node->op()->EffectInputCount() > 0) {
   2725       DCHECK_LT(0, node->op()->ControlInputCount());
   2726       // Disconnect the node from effect and control chains.
   2727       Node* control = NodeProperties::GetControlInput(node);
   2728       Node* effect = NodeProperties::GetEffectInput(node);
   2729       ReplaceEffectControlUses(node, effect, control);
   2730     }
   2731 
   2732     replacements_.push_back(node);
   2733     replacements_.push_back(replacement);
   2734 
   2735     node->NullAllInputs();  // Node is now dead.
   2736   }
   2737 
   2738   void Kill(Node* node) {
   2739     TRACE("killing #%d:%s\n", node->id(), node->op()->mnemonic());
   2740 
   2741     if (node->op()->EffectInputCount() == 1) {
   2742       DCHECK_LT(0, node->op()->ControlInputCount());
   2743       // Disconnect the node from effect and control chains.
   2744       Node* control = NodeProperties::GetControlInput(node);
   2745       Node* effect = NodeProperties::GetEffectInput(node);
   2746       ReplaceEffectControlUses(node, effect, control);
   2747     } else {
   2748       DCHECK_EQ(0, node->op()->EffectInputCount());
   2749       DCHECK_EQ(0, node->op()->ControlOutputCount());
   2750       DCHECK_EQ(0, node->op()->EffectOutputCount());
   2751     }
   2752 
   2753     node->ReplaceUses(jsgraph_->Dead());
   2754 
   2755     node->NullAllInputs();  // The {node} is now dead.
   2756   }
   2757 
   2758   void PrintOutputInfo(NodeInfo* info) {
   2759     if (FLAG_trace_representation) {
   2760       OFStream os(stdout);
   2761       os << info->representation();
   2762     }
   2763   }
   2764 
   2765   void PrintRepresentation(MachineRepresentation rep) {
   2766     if (FLAG_trace_representation) {
   2767       OFStream os(stdout);
   2768       os << rep;
   2769     }
   2770   }
   2771 
   2772   void PrintTruncation(Truncation truncation) {
   2773     if (FLAG_trace_representation) {
   2774       OFStream os(stdout);
   2775       os << truncation.description() << std::endl;
   2776     }
   2777   }
   2778 
   2779   void PrintUseInfo(UseInfo info) {
   2780     if (FLAG_trace_representation) {
   2781       OFStream os(stdout);
   2782       os << info.representation() << ":" << info.truncation().description();
   2783     }
   2784   }
   2785 
   2786  private:
   2787   JSGraph* jsgraph_;
   2788   Zone* zone_;                      // Temporary zone.
   2789   size_t const count_;              // number of nodes in the graph
   2790   ZoneVector<NodeInfo> info_;       // node id -> usage information
   2791 #ifdef DEBUG
   2792   ZoneVector<InputUseInfos> node_input_use_infos_;  // Debug information about
   2793                                                     // requirements on inputs.
   2794 #endif                                              // DEBUG
   2795   NodeVector nodes_;                // collected nodes
   2796   NodeVector replacements_;         // replacements to be done after lowering
   2797   Phase phase_;                     // current phase of algorithm
   2798   RepresentationChanger* changer_;  // for inserting representation changes
   2799   ZoneQueue<Node*> queue_;          // queue for traversing the graph
   2800 
   2801   struct NodeState {
   2802     Node* node;
   2803     int input_index;
   2804   };
   2805   ZoneStack<NodeState> typing_stack_;  // stack for graph typing.
   2806   // TODO(danno): RepresentationSelector shouldn't know anything about the
   2807   // source positions table, but must for now since there currently is no other
   2808   // way to pass down source position information to nodes created during
   2809   // lowering. Once this phase becomes a vanilla reducer, it should get source
   2810   // position information via the SourcePositionWrapper like all other reducers.
   2811   SourcePositionTable* source_positions_;
   2812   TypeCache const& type_cache_;
   2813   OperationTyper op_typer_;  // helper for the feedback typer
   2814 
   2815   NodeInfo* GetInfo(Node* node) {
   2816     DCHECK(node->id() < count_);
   2817     return &info_[node->id()];
   2818   }
   2819   Zone* zone() { return zone_; }
   2820   Zone* graph_zone() { return jsgraph_->zone(); }
   2821 };
   2822 
   2823 SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
   2824                                        SourcePositionTable* source_positions)
   2825     : jsgraph_(jsgraph),
   2826       zone_(zone),
   2827       type_cache_(TypeCache::Get()),
   2828       source_positions_(source_positions) {}
   2829 
   2830 void SimplifiedLowering::LowerAllNodes() {
   2831   RepresentationChanger changer(jsgraph(), jsgraph()->isolate());
   2832   RepresentationSelector selector(jsgraph(), zone_, &changer,
   2833                                   source_positions_);
   2834   selector.Run(this);
   2835 }
   2836 
   2837 void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
   2838     Node* node, RepresentationSelector* selector) {
   2839   DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
   2840   Node* value = node->InputAt(0);
   2841   Node* context = node->InputAt(1);
   2842   Node* frame_state = node->InputAt(2);
   2843   Node* effect = node->InputAt(3);
   2844   Node* control = node->InputAt(4);
   2845   Node* throwing;
   2846 
   2847   Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
   2848   Node* branch0 =
   2849       graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
   2850 
   2851   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
   2852   Node* etrue0 = effect;
   2853   Node* vtrue0;
   2854   {
   2855     vtrue0 = graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
   2856     vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
   2857   }
   2858 
   2859   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
   2860   Node* efalse0 = effect;
   2861   Node* vfalse0;
   2862   {
   2863     throwing = vfalse0 = efalse0 =
   2864         graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
   2865                          frame_state, efalse0, if_false0);
   2866     if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
   2867 
   2868     Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
   2869     Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
   2870 
   2871     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
   2872     Node* etrue1 = efalse0;
   2873     Node* vtrue1;
   2874     {
   2875       vtrue1 =
   2876           graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
   2877       vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
   2878     }
   2879 
   2880     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
   2881     Node* efalse1 = efalse0;
   2882     Node* vfalse1;
   2883     {
   2884       vfalse1 = efalse1 = graph()->NewNode(
   2885           simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
   2886           efalse1, if_false1);
   2887     }
   2888 
   2889     if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
   2890     efalse0 =
   2891         graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
   2892     vfalse0 =
   2893         graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
   2894                          vtrue1, vfalse1, if_false0);
   2895   }
   2896 
   2897   control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
   2898   effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
   2899   value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
   2900                            vtrue0, vfalse0, control);
   2901 
   2902   // Replace effect and control uses appropriately.
   2903   for (Edge edge : node->use_edges()) {
   2904     if (NodeProperties::IsControlEdge(edge)) {
   2905       if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
   2906         edge.from()->ReplaceUses(control);
   2907         edge.from()->Kill();
   2908       } else if (edge.from()->opcode() == IrOpcode::kIfException) {
   2909         edge.UpdateTo(throwing);
   2910       } else {
   2911         UNREACHABLE();
   2912       }
   2913     } else if (NodeProperties::IsEffectEdge(edge)) {
   2914       edge.UpdateTo(effect);
   2915     }
   2916   }
   2917 
   2918   selector->DeferReplacement(node, value);
   2919 }
   2920 
   2921 void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
   2922     Node* node, RepresentationSelector* selector) {
   2923   DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
   2924   Node* value = node->InputAt(0);
   2925   Node* context = node->InputAt(1);
   2926   Node* frame_state = node->InputAt(2);
   2927   Node* effect = node->InputAt(3);
   2928   Node* control = node->InputAt(4);
   2929   Node* throwing;
   2930 
   2931   Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
   2932   Node* branch0 =
   2933       graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
   2934 
   2935   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
   2936   Node* etrue0 = effect;
   2937   Node* vtrue0 =
   2938       graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
   2939 
   2940   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
   2941   Node* efalse0 = effect;
   2942   Node* vfalse0;
   2943   {
   2944     throwing = vfalse0 = efalse0 =
   2945         graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
   2946                          frame_state, efalse0, if_false0);
   2947     if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
   2948 
   2949     Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
   2950     Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
   2951 
   2952     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
   2953     Node* etrue1 = efalse0;
   2954     Node* vtrue1 =
   2955         graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
   2956 
   2957     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
   2958     Node* efalse1 = efalse0;
   2959     Node* vfalse1;
   2960     {
   2961       vfalse1 = efalse1 = graph()->NewNode(
   2962           simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
   2963           efalse1, if_false1);
   2964       vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
   2965     }
   2966 
   2967     if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
   2968     efalse0 =
   2969         graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
   2970     vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
   2971                                vtrue1, vfalse1, if_false0);
   2972   }
   2973 
   2974   control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
   2975   effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
   2976   value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
   2977                            vtrue0, vfalse0, control);
   2978 
   2979   // Replace effect and control uses appropriately.
   2980   for (Edge edge : node->use_edges()) {
   2981     if (NodeProperties::IsControlEdge(edge)) {
   2982       if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
   2983         edge.from()->ReplaceUses(control);
   2984         edge.from()->Kill();
   2985       } else if (edge.from()->opcode() == IrOpcode::kIfException) {
   2986         edge.UpdateTo(throwing);
   2987       } else {
   2988         UNREACHABLE();
   2989       }
   2990     } else if (NodeProperties::IsEffectEdge(edge)) {
   2991       edge.UpdateTo(effect);
   2992     }
   2993   }
   2994 
   2995   selector->DeferReplacement(node, value);
   2996 }
   2997 
   2998 void SimplifiedLowering::DoLoadBuffer(Node* node,
   2999                                       MachineRepresentation output_rep,
   3000                                       RepresentationChanger* changer) {
   3001   DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode());
   3002   DCHECK_NE(MachineRepresentation::kNone, output_rep);
   3003   MachineType const access_type = BufferAccessOf(node->op()).machine_type();
   3004   if (output_rep != access_type.representation()) {
   3005     Node* const buffer = node->InputAt(0);
   3006     Node* const offset = node->InputAt(1);
   3007     Node* const length = node->InputAt(2);
   3008     Node* const effect = node->InputAt(3);
   3009     Node* const control = node->InputAt(4);
   3010     Node* const index =
   3011         machine()->Is64()
   3012             ? graph()->NewNode(machine()->ChangeUint32ToUint64(), offset)
   3013             : offset;
   3014 
   3015     Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length);
   3016     Node* branch =
   3017         graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
   3018 
   3019     Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
   3020     Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
   3021                                    effect, if_true);
   3022     Type* element_type =
   3023         Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone());
   3024     Node* vtrue = changer->GetRepresentationFor(
   3025         etrue, access_type.representation(), element_type, node,
   3026         UseInfo(output_rep, Truncation::None()));
   3027 
   3028     Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
   3029     Node* efalse = effect;
   3030     Node* vfalse;
   3031     if (output_rep == MachineRepresentation::kTagged) {
   3032       vfalse = jsgraph()->UndefinedConstant();
   3033     } else if (output_rep == MachineRepresentation::kFloat64) {
   3034       vfalse =
   3035           jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
   3036     } else if (output_rep == MachineRepresentation::kFloat32) {
   3037       vfalse =
   3038           jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN());
   3039     } else {
   3040       vfalse = jsgraph()->Int32Constant(0);
   3041     }
   3042 
   3043     Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
   3044     Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
   3045 
   3046     // Replace effect uses of {node} with the {ephi}.
   3047     NodeProperties::ReplaceUses(node, node, ephi);
   3048 
   3049     // Turn the {node} into a Phi.
   3050     node->ReplaceInput(0, vtrue);
   3051     node->ReplaceInput(1, vfalse);
   3052     node->ReplaceInput(2, merge);
   3053     node->TrimInputCount(3);
   3054     NodeProperties::ChangeOp(node, common()->Phi(output_rep, 2));
   3055   } else {
   3056     NodeProperties::ChangeOp(node, machine()->CheckedLoad(access_type));
   3057   }
   3058 }
   3059 
   3060 
   3061 void SimplifiedLowering::DoStoreBuffer(Node* node) {
   3062   DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode());
   3063   MachineRepresentation const rep =
   3064       BufferAccessOf(node->op()).machine_type().representation();
   3065   NodeProperties::ChangeOp(node, machine()->CheckedStore(rep));
   3066 }
   3067 
   3068 Node* SimplifiedLowering::Float64Round(Node* const node) {
   3069   Node* const one = jsgraph()->Float64Constant(1.0);
   3070   Node* const one_half = jsgraph()->Float64Constant(0.5);
   3071   Node* const input = node->InputAt(0);
   3072 
   3073   // Round up towards Infinity, and adjust if the difference exceeds 0.5.
   3074   Node* result = graph()->NewNode(machine()->Float64RoundUp().placeholder(),
   3075                                   node->InputAt(0));
   3076   return graph()->NewNode(
   3077       common()->Select(MachineRepresentation::kFloat64),
   3078       graph()->NewNode(
   3079           machine()->Float64LessThanOrEqual(),
   3080           graph()->NewNode(machine()->Float64Sub(), result, one_half), input),
   3081       result, graph()->NewNode(machine()->Float64Sub(), result, one));
   3082 }
   3083 
   3084 Node* SimplifiedLowering::Float64Sign(Node* const node) {
   3085   Node* const minus_one = jsgraph()->Float64Constant(-1.0);
   3086   Node* const zero = jsgraph()->Float64Constant(0.0);
   3087   Node* const one = jsgraph()->Float64Constant(1.0);
   3088 
   3089   Node* const input = node->InputAt(0);
   3090 
   3091   return graph()->NewNode(
   3092       common()->Select(MachineRepresentation::kFloat64),
   3093       graph()->NewNode(machine()->Float64LessThan(), input, zero), minus_one,
   3094       graph()->NewNode(
   3095           common()->Select(MachineRepresentation::kFloat64),
   3096           graph()->NewNode(machine()->Float64LessThan(), zero, input), one,
   3097           input));
   3098 }
   3099 
   3100 Node* SimplifiedLowering::Int32Abs(Node* const node) {
   3101   Node* const input = node->InputAt(0);
   3102 
   3103   // Generate case for absolute integer value.
   3104   //
   3105   //    let sign = input >> 31 in
   3106   //    (input ^ sign) - sign
   3107 
   3108   Node* sign = graph()->NewNode(machine()->Word32Sar(), input,
   3109                                 jsgraph()->Int32Constant(31));
   3110   return graph()->NewNode(machine()->Int32Sub(),
   3111                           graph()->NewNode(machine()->Word32Xor(), input, sign),
   3112                           sign);
   3113 }
   3114 
   3115 Node* SimplifiedLowering::Int32Div(Node* const node) {
   3116   Int32BinopMatcher m(node);
   3117   Node* const zero = jsgraph()->Int32Constant(0);
   3118   Node* const minus_one = jsgraph()->Int32Constant(-1);
   3119   Node* const lhs = m.left().node();
   3120   Node* const rhs = m.right().node();
   3121 
   3122   if (m.right().Is(-1)) {
   3123     return graph()->NewNode(machine()->Int32Sub(), zero, lhs);
   3124   } else if (m.right().Is(0)) {
   3125     return rhs;
   3126   } else if (machine()->Int32DivIsSafe() || m.right().HasValue()) {
   3127     return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
   3128   }
   3129 
   3130   // General case for signed integer division.
   3131   //
   3132   //    if 0 < rhs then
   3133   //      lhs / rhs
   3134   //    else
   3135   //      if rhs < -1 then
   3136   //        lhs / rhs
   3137   //      else if rhs == 0 then
   3138   //        0
   3139   //      else
   3140   //        0 - lhs
   3141   //
   3142   // Note: We do not use the Diamond helper class here, because it really hurts
   3143   // readability with nested diamonds.
   3144   const Operator* const merge_op = common()->Merge(2);
   3145   const Operator* const phi_op =
   3146       common()->Phi(MachineRepresentation::kWord32, 2);
   3147 
   3148   Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
   3149   Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
   3150                                    graph()->start());
   3151 
   3152   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
   3153   Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0);
   3154 
   3155   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
   3156   Node* false0;
   3157   {
   3158     Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
   3159     Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
   3160 
   3161     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
   3162     Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1);
   3163 
   3164     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
   3165     Node* false1;
   3166     {
   3167       Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
   3168       Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
   3169 
   3170       Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
   3171       Node* true2 = zero;
   3172 
   3173       Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
   3174       Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
   3175 
   3176       if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
   3177       false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
   3178     }
   3179 
   3180     if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
   3181     false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
   3182   }
   3183 
   3184   Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
   3185   return graph()->NewNode(phi_op, true0, false0, merge0);
   3186 }
   3187 
   3188 
   3189 Node* SimplifiedLowering::Int32Mod(Node* const node) {
   3190   Int32BinopMatcher m(node);
   3191   Node* const zero = jsgraph()->Int32Constant(0);
   3192   Node* const minus_one = jsgraph()->Int32Constant(-1);
   3193   Node* const lhs = m.left().node();
   3194   Node* const rhs = m.right().node();
   3195 
   3196   if (m.right().Is(-1) || m.right().Is(0)) {
   3197     return zero;
   3198   } else if (m.right().HasValue()) {
   3199     return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
   3200   }
   3201 
   3202   // General case for signed integer modulus, with optimization for (unknown)
   3203   // power of 2 right hand side.
   3204   //
   3205   //   if 0 < rhs then
   3206   //     msk = rhs - 1
   3207   //     if rhs & msk != 0 then
   3208   //       lhs % rhs
   3209   //     else
   3210   //       if lhs < 0 then
   3211   //         -(-lhs & msk)
   3212   //       else
   3213   //         lhs & msk
   3214   //   else
   3215   //     if rhs < -1 then
   3216   //       lhs % rhs
   3217   //     else
   3218   //       zero
   3219   //
   3220   // Note: We do not use the Diamond helper class here, because it really hurts
   3221   // readability with nested diamonds.
   3222   const Operator* const merge_op = common()->Merge(2);
   3223   const Operator* const phi_op =
   3224       common()->Phi(MachineRepresentation::kWord32, 2);
   3225 
   3226   Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
   3227   Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
   3228                                    graph()->start());
   3229 
   3230   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
   3231   Node* true0;
   3232   {
   3233     Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
   3234 
   3235     Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
   3236     Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
   3237 
   3238     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
   3239     Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
   3240 
   3241     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
   3242     Node* false1;
   3243     {
   3244       Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
   3245       Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
   3246                                        check2, if_false1);
   3247 
   3248       Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
   3249       Node* true2 = graph()->NewNode(
   3250           machine()->Int32Sub(), zero,
   3251           graph()->NewNode(machine()->Word32And(),
   3252                            graph()->NewNode(machine()->Int32Sub(), zero, lhs),
   3253                            msk));
   3254 
   3255       Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
   3256       Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
   3257 
   3258       if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
   3259       false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
   3260     }
   3261 
   3262     if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
   3263     true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
   3264   }
   3265 
   3266   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
   3267   Node* false0;
   3268   {
   3269     Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
   3270     Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
   3271                                      check1, if_false0);
   3272 
   3273     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
   3274     Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
   3275 
   3276     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
   3277     Node* false1 = zero;
   3278 
   3279     if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
   3280     false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
   3281   }
   3282 
   3283   Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
   3284   return graph()->NewNode(phi_op, true0, false0, merge0);
   3285 }
   3286 
   3287 Node* SimplifiedLowering::Int32Sign(Node* const node) {
   3288   Node* const minus_one = jsgraph()->Int32Constant(-1);
   3289   Node* const zero = jsgraph()->Int32Constant(0);
   3290   Node* const one = jsgraph()->Int32Constant(1);
   3291 
   3292   Node* const input = node->InputAt(0);
   3293 
   3294   return graph()->NewNode(
   3295       common()->Select(MachineRepresentation::kWord32),
   3296       graph()->NewNode(machine()->Int32LessThan(), input, zero), minus_one,
   3297       graph()->NewNode(
   3298           common()->Select(MachineRepresentation::kWord32),
   3299           graph()->NewNode(machine()->Int32LessThan(), zero, input), one,
   3300           zero));
   3301 }
   3302 
   3303 Node* SimplifiedLowering::Uint32Div(Node* const node) {
   3304   Uint32BinopMatcher m(node);
   3305   Node* const zero = jsgraph()->Uint32Constant(0);
   3306   Node* const lhs = m.left().node();
   3307   Node* const rhs = m.right().node();
   3308 
   3309   if (m.right().Is(0)) {
   3310     return zero;
   3311   } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) {
   3312     return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
   3313   }
   3314 
   3315   Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
   3316   Diamond d(graph(), common(), check, BranchHint::kFalse);
   3317   Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
   3318   return d.Phi(MachineRepresentation::kWord32, zero, div);
   3319 }
   3320 
   3321 
   3322 Node* SimplifiedLowering::Uint32Mod(Node* const node) {
   3323   Uint32BinopMatcher m(node);
   3324   Node* const minus_one = jsgraph()->Int32Constant(-1);
   3325   Node* const zero = jsgraph()->Uint32Constant(0);
   3326   Node* const lhs = m.left().node();
   3327   Node* const rhs = m.right().node();
   3328 
   3329   if (m.right().Is(0)) {
   3330     return zero;
   3331   } else if (m.right().HasValue()) {
   3332     return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
   3333   }
   3334 
   3335   // General case for unsigned integer modulus, with optimization for (unknown)
   3336   // power of 2 right hand side.
   3337   //
   3338   //   if rhs then
   3339   //     msk = rhs - 1
   3340   //     if rhs & msk != 0 then
   3341   //       lhs % rhs
   3342   //     else
   3343   //       lhs & msk
   3344   //   else
   3345   //     zero
   3346   //
   3347   // Note: We do not use the Diamond helper class here, because it really hurts
   3348   // readability with nested diamonds.
   3349   const Operator* const merge_op = common()->Merge(2);
   3350   const Operator* const phi_op =
   3351       common()->Phi(MachineRepresentation::kWord32, 2);
   3352 
   3353   Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), rhs,
   3354                                    graph()->start());
   3355 
   3356   Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
   3357   Node* true0;
   3358   {
   3359     Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
   3360 
   3361     Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
   3362     Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
   3363 
   3364     Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
   3365     Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1);
   3366 
   3367     Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
   3368     Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk);
   3369 
   3370     if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
   3371     true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
   3372   }
   3373 
   3374   Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
   3375   Node* false0 = zero;
   3376 
   3377   Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
   3378   return graph()->NewNode(phi_op, true0, false0, merge0);
   3379 }
   3380 
   3381 void SimplifiedLowering::DoMax(Node* node, Operator const* op,
   3382                                MachineRepresentation rep) {
   3383   Node* const lhs = node->InputAt(0);
   3384   Node* const rhs = node->InputAt(1);
   3385 
   3386   node->ReplaceInput(0, graph()->NewNode(op, lhs, rhs));
   3387   DCHECK_EQ(rhs, node->InputAt(1));
   3388   node->AppendInput(graph()->zone(), lhs);
   3389   NodeProperties::ChangeOp(node, common()->Select(rep));
   3390 }
   3391 
   3392 void SimplifiedLowering::DoMin(Node* node, Operator const* op,
   3393                                MachineRepresentation rep) {
   3394   Node* const lhs = node->InputAt(0);
   3395   Node* const rhs = node->InputAt(1);
   3396 
   3397   node->InsertInput(graph()->zone(), 0, graph()->NewNode(op, lhs, rhs));
   3398   DCHECK_EQ(lhs, node->InputAt(1));
   3399   DCHECK_EQ(rhs, node->InputAt(2));
   3400   NodeProperties::ChangeOp(node, common()->Select(rep));
   3401 }
   3402 
   3403 void SimplifiedLowering::DoShift(Node* node, Operator const* op,
   3404                                  Type* rhs_type) {
   3405   if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) {
   3406     Node* const rhs = NodeProperties::GetValueInput(node, 1);
   3407     node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs,
   3408                                            jsgraph()->Int32Constant(0x1f)));
   3409   }
   3410   ChangeToPureOp(node, op);
   3411 }
   3412 
   3413 void SimplifiedLowering::DoStringToNumber(Node* node) {
   3414   Operator::Properties properties = Operator::kEliminatable;
   3415   Callable callable = CodeFactory::StringToNumber(isolate());
   3416   CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
   3417   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
   3418       isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
   3419   node->InsertInput(graph()->zone(), 0,
   3420                     jsgraph()->HeapConstant(callable.code()));
   3421   node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant());
   3422   node->AppendInput(graph()->zone(), graph()->start());
   3423   NodeProperties::ChangeOp(node, common()->Call(desc));
   3424 }
   3425 
   3426 void SimplifiedLowering::DoIntegral32ToBit(Node* node) {
   3427   Node* const input = node->InputAt(0);
   3428   Node* const zero = jsgraph()->Int32Constant(0);
   3429   Operator const* const op = machine()->Word32Equal();
   3430 
   3431   node->ReplaceInput(0, graph()->NewNode(op, input, zero));
   3432   node->AppendInput(graph()->zone(), zero);
   3433   NodeProperties::ChangeOp(node, op);
   3434 }
   3435 
   3436 void SimplifiedLowering::DoOrderedNumberToBit(Node* node) {
   3437   Node* const input = node->InputAt(0);
   3438 
   3439   node->ReplaceInput(0, graph()->NewNode(machine()->Float64Equal(), input,
   3440                                          jsgraph()->Float64Constant(0.0)));
   3441   node->AppendInput(graph()->zone(), jsgraph()->Int32Constant(0));
   3442   NodeProperties::ChangeOp(node, machine()->Word32Equal());
   3443 }
   3444 
   3445 void SimplifiedLowering::DoNumberToBit(Node* node) {
   3446   Node* const input = node->InputAt(0);
   3447 
   3448   node->ReplaceInput(0, jsgraph()->Float64Constant(0.0));
   3449   node->AppendInput(graph()->zone(),
   3450                     graph()->NewNode(machine()->Float64Abs(), input));
   3451   NodeProperties::ChangeOp(node, machine()->Float64LessThan());
   3452 }
   3453 
   3454 void SimplifiedLowering::DoIntegerToUint8Clamped(Node* node) {
   3455   Node* const input = node->InputAt(0);
   3456   Node* const min = jsgraph()->Float64Constant(0.0);
   3457   Node* const max = jsgraph()->Float64Constant(255.0);
   3458 
   3459   node->ReplaceInput(
   3460       0, graph()->NewNode(machine()->Float64LessThan(), min, input));
   3461   node->AppendInput(
   3462       graph()->zone(),
   3463       graph()->NewNode(
   3464           common()->Select(MachineRepresentation::kFloat64),
   3465           graph()->NewNode(machine()->Float64LessThan(), input, max), input,
   3466           max));
   3467   node->AppendInput(graph()->zone(), min);
   3468   NodeProperties::ChangeOp(node,
   3469                            common()->Select(MachineRepresentation::kFloat64));
   3470 }
   3471 
   3472 void SimplifiedLowering::DoNumberToUint8Clamped(Node* node) {
   3473   Node* const input = node->InputAt(0);
   3474   Node* const min = jsgraph()->Float64Constant(0.0);
   3475   Node* const max = jsgraph()->Float64Constant(255.0);
   3476 
   3477   node->ReplaceInput(
   3478       0, graph()->NewNode(
   3479              common()->Select(MachineRepresentation::kFloat64),
   3480              graph()->NewNode(machine()->Float64LessThan(), min, input),
   3481              graph()->NewNode(
   3482                  common()->Select(MachineRepresentation::kFloat64),
   3483                  graph()->NewNode(machine()->Float64LessThan(), input, max),
   3484                  input, max),
   3485              min));
   3486   NodeProperties::ChangeOp(node,
   3487                            machine()->Float64RoundTiesEven().placeholder());
   3488 }
   3489 
   3490 void SimplifiedLowering::DoSigned32ToUint8Clamped(Node* node) {
   3491   Node* const input = node->InputAt(0);
   3492   Node* const min = jsgraph()->Int32Constant(0);
   3493   Node* const max = jsgraph()->Int32Constant(255);
   3494 
   3495   node->ReplaceInput(
   3496       0, graph()->NewNode(machine()->Int32LessThanOrEqual(), input, max));
   3497   node->AppendInput(
   3498       graph()->zone(),
   3499       graph()->NewNode(common()->Select(MachineRepresentation::kWord32),
   3500                        graph()->NewNode(machine()->Int32LessThan(), input, min),
   3501                        min, input));
   3502   node->AppendInput(graph()->zone(), max);
   3503   NodeProperties::ChangeOp(node,
   3504                            common()->Select(MachineRepresentation::kWord32));
   3505 }
   3506 
   3507 void SimplifiedLowering::DoUnsigned32ToUint8Clamped(Node* node) {
   3508   Node* const input = node->InputAt(0);
   3509   Node* const max = jsgraph()->Uint32Constant(255u);
   3510 
   3511   node->ReplaceInput(
   3512       0, graph()->NewNode(machine()->Uint32LessThanOrEqual(), input, max));
   3513   node->AppendInput(graph()->zone(), input);
   3514   node->AppendInput(graph()->zone(), max);
   3515   NodeProperties::ChangeOp(node,
   3516                            common()->Select(MachineRepresentation::kWord32));
   3517 }
   3518 
   3519 Node* SimplifiedLowering::ToNumberCode() {
   3520   if (!to_number_code_.is_set()) {
   3521     Callable callable = CodeFactory::ToNumber(isolate());
   3522     to_number_code_.set(jsgraph()->HeapConstant(callable.code()));
   3523   }
   3524   return to_number_code_.get();
   3525 }
   3526 
   3527 Operator const* SimplifiedLowering::ToNumberOperator() {
   3528   if (!to_number_operator_.is_set()) {
   3529     Callable callable = CodeFactory::ToNumber(isolate());
   3530     CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
   3531     CallDescriptor* desc = Linkage::GetStubCallDescriptor(
   3532         isolate(), graph()->zone(), callable.descriptor(), 0, flags,
   3533         Operator::kNoProperties);
   3534     to_number_operator_.set(common()->Call(desc));
   3535   }
   3536   return to_number_operator_.get();
   3537 }
   3538 
   3539 }  // namespace compiler
   3540 }  // namespace internal
   3541 }  // namespace v8
   3542