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 "include/v8-fast-api-calls.h"
10#include "src/base/bits.h"
11#include "src/base/small-vector.h"
12#include "src/codegen/code-factory.h"
13#include "src/codegen/machine-type.h"
14#include "src/codegen/tick-counter.h"
15#include "src/compiler/access-builder.h"
16#include "src/compiler/common-operator.h"
17#include "src/compiler/compiler-source-position-table.h"
18#include "src/compiler/diamond.h"
19#include "src/compiler/graph-visualizer.h"
20#include "src/compiler/js-heap-broker.h"
21#include "src/compiler/linkage.h"
22#include "src/compiler/node-matchers.h"
23#include "src/compiler/node-observer.h"
24#include "src/compiler/node-origin-table.h"
25#include "src/compiler/operation-typer.h"
26#include "src/compiler/operator-properties.h"
27#include "src/compiler/representation-change.h"
28#include "src/compiler/simplified-lowering-verifier.h"
29#include "src/compiler/simplified-operator.h"
30#include "src/compiler/type-cache.h"
31#include "src/numbers/conversions-inl.h"
32#include "src/objects/objects.h"
33#include "src/utils/address-map.h"
34
35#if V8_ENABLE_WEBASSEMBLY
36#include "src/wasm/value-type.h"
37#endif  // V8_ENABLE_WEBASSEMBLY
38
39namespace v8 {
40namespace internal {
41namespace compiler {
42
43// Macro for outputting trace information from representation inference.
44#define TRACE(...)                                      \
45  do {                                                  \
46    if (FLAG_trace_representation) PrintF(__VA_ARGS__); \
47  } while (false)
48
49const char* kSimplifiedLoweringReducerName = "SimplifiedLowering";
50
51// Representation selection and lowering of {Simplified} operators to machine
52// operators are interwined. We use a fixpoint calculation to compute both the
53// output representation and the best possible lowering for {Simplified} nodes.
54// Representation change insertion ensures that all values are in the correct
55// machine representation after this phase, as dictated by the machine
56// operators themselves.
57enum Phase {
58  // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information
59  //     backwards from uses to definitions, around cycles in phis, according
60  //     to local rules for each operator.
61  //     During this phase, the usage information for a node determines the best
62  //     possible lowering for each operator so far, and that in turn determines
63  //     the output representation.
64  //     Therefore, to be correct, this phase must iterate to a fixpoint before
65  //     the next phase can begin.
66  PROPAGATE,
67
68  // 2.) RETYPE: Propagate types from type feedback forwards.
69  RETYPE,
70
71  // 3.) LOWER: perform lowering for all {Simplified} nodes by replacing some
72  //     operators for some nodes, expanding some nodes to multiple nodes, or
73  //     removing some (redundant) nodes.
74  //     During this phase, use the {RepresentationChanger} to insert
75  //     representation changes between uses that demand a particular
76  //     representation and nodes that produce a different representation.
77  LOWER
78};
79
80namespace {
81
82MachineRepresentation MachineRepresentationFromArrayType(
83    ExternalArrayType array_type) {
84  switch (array_type) {
85    case kExternalUint8Array:
86    case kExternalUint8ClampedArray:
87    case kExternalInt8Array:
88      return MachineRepresentation::kWord8;
89    case kExternalUint16Array:
90    case kExternalInt16Array:
91      return MachineRepresentation::kWord16;
92    case kExternalUint32Array:
93    case kExternalInt32Array:
94      return MachineRepresentation::kWord32;
95    case kExternalFloat32Array:
96      return MachineRepresentation::kFloat32;
97    case kExternalFloat64Array:
98      return MachineRepresentation::kFloat64;
99    case kExternalBigInt64Array:
100    case kExternalBigUint64Array:
101      UNIMPLEMENTED();
102  }
103  UNREACHABLE();
104}
105
106UseInfo CheckedUseInfoAsWord32FromHint(
107    NumberOperationHint hint, IdentifyZeros identify_zeros = kDistinguishZeros,
108    const FeedbackSource& feedback = FeedbackSource()) {
109  switch (hint) {
110    case NumberOperationHint::kSignedSmall:
111    case NumberOperationHint::kSignedSmallInputs:
112      return UseInfo::CheckedSignedSmallAsWord32(identify_zeros, feedback);
113    case NumberOperationHint::kNumber:
114      DCHECK_EQ(identify_zeros, kIdentifyZeros);
115      return UseInfo::CheckedNumberAsWord32(feedback);
116    case NumberOperationHint::kNumberOrBoolean:
117      // Not used currently.
118      UNREACHABLE();
119    case NumberOperationHint::kNumberOrOddball:
120      DCHECK_EQ(identify_zeros, kIdentifyZeros);
121      return UseInfo::CheckedNumberOrOddballAsWord32(feedback);
122  }
123  UNREACHABLE();
124}
125
126UseInfo CheckedUseInfoAsFloat64FromHint(
127    NumberOperationHint hint, const FeedbackSource& feedback,
128    IdentifyZeros identify_zeros = kDistinguishZeros) {
129  switch (hint) {
130    case NumberOperationHint::kSignedSmall:
131    case NumberOperationHint::kSignedSmallInputs:
132      // Not used currently.
133      UNREACHABLE();
134    case NumberOperationHint::kNumber:
135      return UseInfo::CheckedNumberAsFloat64(identify_zeros, feedback);
136    case NumberOperationHint::kNumberOrBoolean:
137      return UseInfo::CheckedNumberOrBooleanAsFloat64(identify_zeros, feedback);
138    case NumberOperationHint::kNumberOrOddball:
139      return UseInfo::CheckedNumberOrOddballAsFloat64(identify_zeros, feedback);
140  }
141  UNREACHABLE();
142}
143
144UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) {
145  switch (rep) {
146    case MachineRepresentation::kTaggedSigned:
147      return UseInfo::TaggedSigned();
148    case MachineRepresentation::kTaggedPointer:
149    case MachineRepresentation::kTagged:
150    case MachineRepresentation::kMapWord:
151      return UseInfo::AnyTagged();
152    case MachineRepresentation::kFloat64:
153      return UseInfo::TruncatingFloat64();
154    case MachineRepresentation::kFloat32:
155      return UseInfo::Float32();
156    case MachineRepresentation::kWord8:
157    case MachineRepresentation::kWord16:
158    case MachineRepresentation::kWord32:
159      return UseInfo::TruncatingWord32();
160    case MachineRepresentation::kWord64:
161      return UseInfo::Word64();
162    case MachineRepresentation::kBit:
163      return UseInfo::Bool();
164    case MachineRepresentation::kCompressedPointer:
165    case MachineRepresentation::kCompressed:
166    case MachineRepresentation::kSandboxedPointer:
167    case MachineRepresentation::kSimd128:
168    case MachineRepresentation::kNone:
169      break;
170  }
171  UNREACHABLE();
172}
173
174UseInfo UseInfoForBasePointer(const FieldAccess& access) {
175  return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::Word();
176}
177
178UseInfo UseInfoForBasePointer(const ElementAccess& access) {
179  return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::Word();
180}
181
182void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) {
183  for (Edge edge : node->use_edges()) {
184    if (NodeProperties::IsControlEdge(edge)) {
185      edge.UpdateTo(control);
186    } else if (NodeProperties::IsEffectEdge(edge)) {
187      edge.UpdateTo(effect);
188    } else {
189      DCHECK(NodeProperties::IsValueEdge(edge) ||
190             NodeProperties::IsContextEdge(edge));
191    }
192  }
193}
194
195bool CanOverflowSigned32(const Operator* op, Type left, Type right,
196                         TypeCache const* type_cache, Zone* type_zone) {
197  // We assume the inputs are checked Signed32 (or known statically to be
198  // Signed32). Technically, the inputs could also be minus zero, which we treat
199  // as 0 for the purpose of this function.
200  if (left.Maybe(Type::MinusZero())) {
201    left = Type::Union(left, type_cache->kSingletonZero, type_zone);
202  }
203  if (right.Maybe(Type::MinusZero())) {
204    right = Type::Union(right, type_cache->kSingletonZero, type_zone);
205  }
206  left = Type::Intersect(left, Type::Signed32(), type_zone);
207  right = Type::Intersect(right, Type::Signed32(), type_zone);
208  if (left.IsNone() || right.IsNone()) return false;
209  switch (op->opcode()) {
210    case IrOpcode::kSpeculativeSafeIntegerAdd:
211      return (left.Max() + right.Max() > kMaxInt) ||
212             (left.Min() + right.Min() < kMinInt);
213
214    case IrOpcode::kSpeculativeSafeIntegerSubtract:
215      return (left.Max() - right.Min() > kMaxInt) ||
216             (left.Min() - right.Max() < kMinInt);
217
218    default:
219      UNREACHABLE();
220  }
221}
222
223bool IsSomePositiveOrderedNumber(Type type) {
224  return type.Is(Type::OrderedNumber()) && (type.IsNone() || type.Min() > 0);
225}
226
227class JSONGraphWriterWithVerifierTypes : public JSONGraphWriter {
228 public:
229  JSONGraphWriterWithVerifierTypes(std::ostream& os, const Graph* graph,
230                                   const SourcePositionTable* positions,
231                                   const NodeOriginTable* origins,
232                                   SimplifiedLoweringVerifier* verifier)
233      : JSONGraphWriter(os, graph, positions, origins), verifier_(verifier) {}
234
235 protected:
236  base::Optional<Type> GetType(Node* node) override {
237    return verifier_->GetType(node);
238  }
239
240 private:
241  SimplifiedLoweringVerifier* verifier_;
242};
243
244}  // namespace
245
246#ifdef DEBUG
247// Helpers for monotonicity checking.
248class InputUseInfos {
249 public:
250  explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
251
252  void SetAndCheckInput(Node* node, int index, UseInfo use_info) {
253    if (input_use_infos_.empty()) {
254      input_use_infos_.resize(node->InputCount(), UseInfo::None());
255    }
256    // Check that the new use informatin is a super-type of the old
257    // one.
258    DCHECK(IsUseLessGeneral(input_use_infos_[index], use_info));
259    input_use_infos_[index] = use_info;
260  }
261
262 private:
263  ZoneVector<UseInfo> input_use_infos_;
264
265  static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
266    return use1.truncation().IsLessGeneralThan(use2.truncation());
267  }
268};
269
270#endif  // DEBUG
271
272class RepresentationSelector {
273  // The purpose of this nested class is to hide method
274  // v8::internal::compiler::NodeProperties::ChangeOp which should not be
275  // directly used by code in RepresentationSelector and SimplifiedLowering.
276  // RepresentationSelector code should call RepresentationSelector::ChangeOp in
277  // place of NodeProperties::ChangeOp, in order to notify the changes to a
278  // registered ObserveNodeManager and support the %ObserveNode intrinsic.
279  class NodeProperties : public compiler::NodeProperties {
280    static void ChangeOp(Node* node, const Operator* new_op) { UNREACHABLE(); }
281  };
282
283 public:
284  // Information for each node tracked during the fixpoint.
285  class NodeInfo final {
286   public:
287    // Adds new use to the node. Returns true if something has changed
288    // and the node has to be requeued.
289    bool AddUse(UseInfo info) {
290      Truncation old_truncation = truncation_;
291      truncation_ = Truncation::Generalize(truncation_, info.truncation());
292      return truncation_ != old_truncation;
293    }
294
295    void set_queued() { state_ = kQueued; }
296    void set_visited() { state_ = kVisited; }
297    void set_pushed() { state_ = kPushed; }
298    void reset_state() { state_ = kUnvisited; }
299    bool visited() const { return state_ == kVisited; }
300    bool queued() const { return state_ == kQueued; }
301    bool pushed() const { return state_ == kPushed; }
302    bool unvisited() const { return state_ == kUnvisited; }
303    Truncation truncation() const { return truncation_; }
304    void set_output(MachineRepresentation output) { representation_ = output; }
305
306    MachineRepresentation representation() const { return representation_; }
307
308    // Helpers for feedback typing.
309    void set_feedback_type(Type type) { feedback_type_ = type; }
310    Type feedback_type() const { return feedback_type_; }
311    void set_weakened() { weakened_ = true; }
312    bool weakened() const { return weakened_; }
313    void set_restriction_type(Type type) { restriction_type_ = type; }
314    Type restriction_type() const { return restriction_type_; }
315
316   private:
317    // Fields are ordered to avoid mixing byte and word size fields to minimize
318    // padding.
319    enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued };
320    State state_ = kUnvisited;
321    MachineRepresentation representation_ =
322        MachineRepresentation::kNone;             // Output representation.
323    Truncation truncation_ = Truncation::None();  // Information about uses.
324    bool weakened_ = false;
325
326    Type restriction_type_ = Type::Any();
327    Type feedback_type_;
328  };
329
330  RepresentationSelector(JSGraph* jsgraph, JSHeapBroker* broker, Zone* zone,
331                         RepresentationChanger* changer,
332                         SourcePositionTable* source_positions,
333                         NodeOriginTable* node_origins,
334                         TickCounter* tick_counter, Linkage* linkage,
335                         ObserveNodeManager* observe_node_manager,
336                         SimplifiedLoweringVerifier* verifier)
337      : jsgraph_(jsgraph),
338        broker_(broker),
339        zone_(zone),
340        might_need_revisit_(zone),
341        count_(jsgraph->graph()->NodeCount()),
342        info_(count_, zone),
343#ifdef DEBUG
344        node_input_use_infos_(count_, InputUseInfos(zone), zone),
345#endif
346        replacements_(zone),
347        changer_(changer),
348        revisit_queue_(zone),
349        traversal_nodes_(zone),
350        source_positions_(source_positions),
351        node_origins_(node_origins),
352        type_cache_(TypeCache::Get()),
353        op_typer_(broker, graph_zone()),
354        tick_counter_(tick_counter),
355        linkage_(linkage),
356        observe_node_manager_(observe_node_manager),
357        verifier_(verifier) {
358  }
359
360  bool verification_enabled() const { return verifier_ != nullptr; }
361
362  void ResetNodeInfoState() {
363    // Clean up for the next phase.
364    for (NodeInfo& info : info_) {
365      info.reset_state();
366    }
367  }
368
369  Type TypeOf(Node* node) {
370    Type type = GetInfo(node)->feedback_type();
371    return type.IsInvalid() ? NodeProperties::GetType(node) : type;
372  }
373
374  Type FeedbackTypeOf(Node* node) {
375    Type type = GetInfo(node)->feedback_type();
376    return type.IsInvalid() ? Type::None() : type;
377  }
378
379  Type TypePhi(Node* node) {
380    int arity = node->op()->ValueInputCount();
381    Type type = FeedbackTypeOf(node->InputAt(0));
382    for (int i = 1; i < arity; ++i) {
383      type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i)));
384    }
385    return type;
386  }
387
388  Type TypeSelect(Node* node) {
389    return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)),
390                           FeedbackTypeOf(node->InputAt(2)));
391  }
392
393  bool UpdateFeedbackType(Node* node) {
394    if (node->op()->ValueOutputCount() == 0) return false;
395
396    // For any non-phi node just wait until we get all inputs typed. We only
397    // allow untyped inputs for phi nodes because phis are the only places
398    // where cycles need to be broken.
399    if (node->opcode() != IrOpcode::kPhi) {
400      for (int i = 0; i < node->op()->ValueInputCount(); i++) {
401        if (GetInfo(node->InputAt(i))->feedback_type().IsInvalid()) {
402          return false;
403        }
404      }
405    }
406
407    NodeInfo* info = GetInfo(node);
408    Type type = info->feedback_type();
409    Type new_type = NodeProperties::GetType(node);
410
411    // We preload these values here to avoid increasing the binary size too
412    // much, which happens if we inline the calls into the macros below.
413    Type input0_type;
414    if (node->InputCount() > 0) input0_type = FeedbackTypeOf(node->InputAt(0));
415    Type input1_type;
416    if (node->InputCount() > 1) input1_type = FeedbackTypeOf(node->InputAt(1));
417
418    switch (node->opcode()) {
419#define DECLARE_CASE(Name)                               \
420  case IrOpcode::k##Name: {                              \
421    new_type = op_typer_.Name(input0_type, input1_type); \
422    break;                                               \
423  }
424      SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE)
425      DECLARE_CASE(SameValue)
426#undef DECLARE_CASE
427
428#define DECLARE_CASE(Name)                                               \
429  case IrOpcode::k##Name: {                                              \
430    new_type = Type::Intersect(op_typer_.Name(input0_type, input1_type), \
431                               info->restriction_type(), graph_zone());  \
432    break;                                                               \
433  }
434      SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE)
435      SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(DECLARE_CASE)
436#undef DECLARE_CASE
437
438#define DECLARE_CASE(Name)                  \
439  case IrOpcode::k##Name: {                 \
440    new_type = op_typer_.Name(input0_type); \
441    break;                                  \
442  }
443      SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE)
444#undef DECLARE_CASE
445
446#define DECLARE_CASE(Name)                                              \
447  case IrOpcode::k##Name: {                                             \
448    new_type = Type::Intersect(op_typer_.Name(input0_type),             \
449                               info->restriction_type(), graph_zone()); \
450    break;                                                              \
451  }
452      SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_CASE)
453#undef DECLARE_CASE
454
455      case IrOpcode::kConvertReceiver:
456        new_type = op_typer_.ConvertReceiver(input0_type);
457        break;
458
459      case IrOpcode::kPlainPrimitiveToNumber:
460        new_type = op_typer_.ToNumber(input0_type);
461        break;
462
463      case IrOpcode::kCheckBounds:
464        new_type =
465            Type::Intersect(op_typer_.CheckBounds(input0_type, input1_type),
466                            info->restriction_type(), graph_zone());
467        break;
468
469      case IrOpcode::kCheckFloat64Hole:
470        new_type = Type::Intersect(op_typer_.CheckFloat64Hole(input0_type),
471                                   info->restriction_type(), graph_zone());
472        break;
473
474      case IrOpcode::kCheckNumber:
475        new_type = Type::Intersect(op_typer_.CheckNumber(input0_type),
476                                   info->restriction_type(), graph_zone());
477        break;
478
479      case IrOpcode::kPhi: {
480        new_type = TypePhi(node);
481        if (!type.IsInvalid()) {
482          new_type = Weaken(node, type, new_type);
483        }
484        break;
485      }
486
487      case IrOpcode::kConvertTaggedHoleToUndefined:
488        new_type = op_typer_.ConvertTaggedHoleToUndefined(
489            FeedbackTypeOf(node->InputAt(0)));
490        break;
491
492      case IrOpcode::kTypeGuard: {
493        new_type = op_typer_.TypeTypeGuard(node->op(),
494                                           FeedbackTypeOf(node->InputAt(0)));
495        break;
496      }
497
498      case IrOpcode::kSelect: {
499        new_type = TypeSelect(node);
500        break;
501      }
502
503      default:
504        // Shortcut for operations that we do not handle.
505        if (type.IsInvalid()) {
506          GetInfo(node)->set_feedback_type(NodeProperties::GetType(node));
507          return true;
508        }
509        return false;
510    }
511    // We need to guarantee that the feedback type is a subtype of the upper
512    // bound. Naively that should hold, but weakening can actually produce
513    // a bigger type if we are unlucky with ordering of phi typing. To be
514    // really sure, just intersect the upper bound with the feedback type.
515    new_type = Type::Intersect(GetUpperBound(node), new_type, graph_zone());
516
517    if (!type.IsInvalid() && new_type.Is(type)) return false;
518    GetInfo(node)->set_feedback_type(new_type);
519    if (FLAG_trace_representation) {
520      PrintNodeFeedbackType(node);
521    }
522    return true;
523  }
524
525  void PrintNodeFeedbackType(Node* n) {
526    StdoutStream os;
527    os << "#" << n->id() << ":" << *n->op() << "(";
528    int j = 0;
529    for (Node* const i : n->inputs()) {
530      if (j++ > 0) os << ", ";
531      os << "#" << i->id() << ":" << i->op()->mnemonic();
532    }
533    os << ")";
534    if (NodeProperties::IsTyped(n)) {
535      Type static_type = NodeProperties::GetType(n);
536      os << "  [Static type: " << static_type;
537      Type feedback_type = GetInfo(n)->feedback_type();
538      if (!feedback_type.IsInvalid() && feedback_type != static_type) {
539        os << ", Feedback type: " << feedback_type;
540      }
541      os << "]";
542    }
543    os << std::endl;
544  }
545
546  Type Weaken(Node* node, Type previous_type, Type current_type) {
547    // If the types have nothing to do with integers, return the types.
548    Type const integer = type_cache_->kInteger;
549    if (!previous_type.Maybe(integer)) {
550      return current_type;
551    }
552    DCHECK(current_type.Maybe(integer));
553
554    Type current_integer = Type::Intersect(current_type, integer, graph_zone());
555    DCHECK(!current_integer.IsNone());
556    Type previous_integer =
557        Type::Intersect(previous_type, integer, graph_zone());
558    DCHECK(!previous_integer.IsNone());
559
560    // Once we start weakening a node, we should always weaken.
561    if (!GetInfo(node)->weakened()) {
562      // Only weaken if there is range involved; we should converge quickly
563      // for all other types (the exception is a union of many constants,
564      // but we currently do not increase the number of constants in unions).
565      Type previous = previous_integer.GetRange();
566      Type current = current_integer.GetRange();
567      if (current.IsInvalid() || previous.IsInvalid()) {
568        return current_type;
569      }
570      // Range is involved => we are weakening.
571      GetInfo(node)->set_weakened();
572    }
573
574    return Type::Union(current_type,
575                       op_typer_.WeakenRange(previous_integer, current_integer),
576                       graph_zone());
577  }
578
579  // Generates a pre-order traversal of the nodes, starting with End.
580  void GenerateTraversal() {
581    // Reset previous state.
582    ResetNodeInfoState();
583    traversal_nodes_.clear();
584    count_ = graph()->NodeCount();
585    info_.resize(count_);
586
587    ZoneStack<NodeState> stack(zone_);
588
589    stack.push({graph()->end(), 0});
590    GetInfo(graph()->end())->set_pushed();
591    while (!stack.empty()) {
592      NodeState& current = stack.top();
593      Node* node = current.node;
594
595      // If there is an unvisited input, push it and continue with that node.
596      bool pushed_unvisited = false;
597      while (current.input_index < node->InputCount()) {
598        Node* input = node->InputAt(current.input_index);
599        NodeInfo* input_info = GetInfo(input);
600        current.input_index++;
601        if (input_info->unvisited()) {
602          input_info->set_pushed();
603          stack.push({input, 0});
604          pushed_unvisited = true;
605          break;
606        } else if (input_info->pushed()) {
607          // Optimization for the Retype phase.
608          // If we had already pushed (and not visited) an input, it means that
609          // the current node will be visited in the Retype phase before one of
610          // its inputs. If this happens, the current node might need to be
611          // revisited.
612          MarkAsPossibleRevisit(node, input);
613        }
614      }
615
616      if (pushed_unvisited) continue;
617
618      stack.pop();
619      NodeInfo* info = GetInfo(node);
620      info->set_visited();
621
622      // Generate the traversal
623      traversal_nodes_.push_back(node);
624    }
625  }
626
627  void PushNodeToRevisitIfVisited(Node* node) {
628    NodeInfo* info = GetInfo(node);
629    if (info->visited()) {
630      TRACE(" QUEUEING #%d: %s\n", node->id(), node->op()->mnemonic());
631      info->set_queued();
632      revisit_queue_.push(node);
633    }
634  }
635
636  // Tries to update the feedback type of the node, as well as setting its
637  // machine representation (in VisitNode). Returns true iff updating the
638  // feedback type is successful.
639  bool RetypeNode(Node* node) {
640    NodeInfo* info = GetInfo(node);
641    info->set_visited();
642    bool updated = UpdateFeedbackType(node);
643    TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
644    VisitNode<RETYPE>(node, info->truncation(), nullptr);
645    TRACE("  ==> output %s\n", MachineReprToString(info->representation()));
646    return updated;
647  }
648
649  // Visits the node and marks it as visited. Inside of VisitNode, we might
650  // change the truncation of one of our inputs (see EnqueueInput<PROPAGATE> for
651  // this). If we change the truncation of an already visited node, we will add
652  // it to the revisit queue.
653  void PropagateTruncation(Node* node) {
654    NodeInfo* info = GetInfo(node);
655    info->set_visited();
656    TRACE(" visit #%d: %s (trunc: %s)\n", node->id(), node->op()->mnemonic(),
657          info->truncation().description());
658    VisitNode<PROPAGATE>(node, info->truncation(), nullptr);
659  }
660
661  // Backward propagation of truncations to a fixpoint.
662  void RunPropagatePhase() {
663    TRACE("--{Propagate phase}--\n");
664    ResetNodeInfoState();
665    DCHECK(revisit_queue_.empty());
666
667    // Process nodes in reverse post order, with End as the root.
668    for (auto it = traversal_nodes_.crbegin(); it != traversal_nodes_.crend();
669         ++it) {
670      PropagateTruncation(*it);
671
672      while (!revisit_queue_.empty()) {
673        Node* node = revisit_queue_.front();
674        revisit_queue_.pop();
675        PropagateTruncation(node);
676      }
677    }
678  }
679
680  // Forward propagation of types from type feedback to a fixpoint.
681  void RunRetypePhase() {
682    TRACE("--{Retype phase}--\n");
683    ResetNodeInfoState();
684    DCHECK(revisit_queue_.empty());
685
686    for (auto it = traversal_nodes_.cbegin(); it != traversal_nodes_.cend();
687         ++it) {
688      Node* node = *it;
689      if (!RetypeNode(node)) continue;
690
691      auto revisit_it = might_need_revisit_.find(node);
692      if (revisit_it == might_need_revisit_.end()) continue;
693
694      for (Node* const user : revisit_it->second) {
695        PushNodeToRevisitIfVisited(user);
696      }
697
698      // Process the revisit queue.
699      while (!revisit_queue_.empty()) {
700        Node* revisit_node = revisit_queue_.front();
701        revisit_queue_.pop();
702        if (!RetypeNode(revisit_node)) continue;
703        // Here we need to check all uses since we can't easily know which
704        // nodes will need to be revisited due to having an input which was
705        // a revisited node.
706        for (Node* const user : revisit_node->uses()) {
707          PushNodeToRevisitIfVisited(user);
708        }
709      }
710    }
711  }
712
713  // Lowering and change insertion phase.
714  void RunLowerPhase(SimplifiedLowering* lowering) {
715    TRACE("--{Lower phase}--\n");
716    for (auto it = traversal_nodes_.cbegin(); it != traversal_nodes_.cend();
717         ++it) {
718      Node* node = *it;
719      NodeInfo* info = GetInfo(node);
720      TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
721      // Reuse {VisitNode()} so the representation rules are in one place.
722      SourcePositionTable::Scope scope(
723          source_positions_, source_positions_->GetSourcePosition(node));
724      NodeOriginTable::Scope origin_scope(node_origins_, "simplified lowering",
725                                          node);
726      VisitNode<LOWER>(node, info->truncation(), lowering);
727    }
728
729    // Perform the final replacements.
730    for (NodeVector::iterator i = replacements_.begin();
731         i != replacements_.end(); ++i) {
732      Node* node = *i;
733      Node* replacement = *(++i);
734      node->ReplaceUses(replacement);
735      node->Kill();
736      // We also need to replace the node in the rest of the vector.
737      for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
738        ++j;
739        if (*j == node) *j = replacement;
740      }
741    }
742  }
743
744  void RunVerifyPhase(OptimizedCompilationInfo* info) {
745    DCHECK_NOT_NULL(verifier_);
746
747    TRACE("--{Verify Phase}--\n");
748
749    // Generate a new traversal containing all the new nodes created during
750    // lowering.
751    GenerateTraversal();
752
753    // Set node types to the refined types computed during retyping.
754    for (Node* node : traversal_nodes_) {
755      NodeInfo* info = GetInfo(node);
756      if (!info->feedback_type().IsInvalid()) {
757        NodeProperties::SetType(node, info->feedback_type());
758      }
759    }
760
761    // Verify all nodes.
762    for (Node* node : traversal_nodes_) verifier_->VisitNode(node, op_typer_);
763
764    // Print graph.
765    if (info != nullptr && info->trace_turbo_json()) {
766      UnparkedScopeIfNeeded scope(broker_);
767      AllowHandleDereference allow_deref;
768
769      TurboJsonFile json_of(info, std::ios_base::app);
770      JSONGraphWriterWithVerifierTypes writer(
771          json_of, graph(), source_positions_, node_origins_, verifier_);
772      writer.PrintPhase("V8.TFSimplifiedLoweringVerifier");
773    }
774
775    // Eliminate all introduced hints.
776    for (Node* node : verifier_->inserted_hints()) {
777      Node* input = node->InputAt(0);
778      node->ReplaceUses(input);
779      node->Kill();
780    }
781  }
782
783  void Run(SimplifiedLowering* lowering) {
784    GenerateTraversal();
785    RunPropagatePhase();
786    RunRetypePhase();
787    RunLowerPhase(lowering);
788
789    if (verification_enabled()) {
790      RunVerifyPhase(lowering->info_);
791    }
792  }
793
794  // Just assert for Retype and Lower. Propagate specialized below.
795  template <Phase T>
796  void EnqueueInput(Node* use_node, int index,
797                    UseInfo use_info = UseInfo::None()) {
798    static_assert(retype<T>() || lower<T>(),
799                  "This version of EnqueueInput has to be called in "
800                  "the Retype or Lower phase.");
801  }
802
803  template <Phase T>
804  static constexpr bool propagate() {
805    return T == PROPAGATE;
806  }
807
808  template <Phase T>
809  static constexpr bool retype() {
810    return T == RETYPE;
811  }
812
813  template <Phase T>
814  static constexpr bool lower() {
815    return T == LOWER;
816  }
817
818  template <Phase T>
819  void SetOutput(Node* node, MachineRepresentation representation,
820                 Type restriction_type = Type::Any());
821
822  Type GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
823
824  bool InputCannotBe(Node* node, Type type) {
825    DCHECK_EQ(1, node->op()->ValueInputCount());
826    return !GetUpperBound(node->InputAt(0)).Maybe(type);
827  }
828
829  bool InputIs(Node* node, Type type) {
830    DCHECK_EQ(1, node->op()->ValueInputCount());
831    return GetUpperBound(node->InputAt(0)).Is(type);
832  }
833
834  bool BothInputsAreSigned32(Node* node) {
835    return BothInputsAre(node, Type::Signed32());
836  }
837
838  bool BothInputsAreUnsigned32(Node* node) {
839    return BothInputsAre(node, Type::Unsigned32());
840  }
841
842  bool BothInputsAre(Node* node, Type type) {
843    DCHECK_EQ(2, node->op()->ValueInputCount());
844    return GetUpperBound(node->InputAt(0)).Is(type) &&
845           GetUpperBound(node->InputAt(1)).Is(type);
846  }
847
848  bool IsNodeRepresentationTagged(Node* node) {
849    MachineRepresentation representation = GetInfo(node)->representation();
850    return IsAnyTagged(representation);
851  }
852
853  bool OneInputCannotBe(Node* node, Type type) {
854    DCHECK_EQ(2, node->op()->ValueInputCount());
855    return !GetUpperBound(node->InputAt(0)).Maybe(type) ||
856           !GetUpperBound(node->InputAt(1)).Maybe(type);
857  }
858
859  void ChangeToDeadValue(Node* node, Node* effect, Node* control) {
860    DCHECK(TypeOf(node).IsNone());
861    // If the node is unreachable, insert an Unreachable node and mark the
862    // value dead.
863    // TODO(jarin,turbofan) Find a way to unify/merge this insertion with
864    // InsertUnreachableIfNecessary.
865    Node* unreachable = effect =
866        graph()->NewNode(common()->Unreachable(), effect, control);
867    const Operator* dead_value =
868        common()->DeadValue(GetInfo(node)->representation());
869    node->ReplaceInput(0, unreachable);
870    node->TrimInputCount(dead_value->ValueInputCount());
871    ReplaceEffectControlUses(node, effect, control);
872    ChangeOp(node, dead_value);
873  }
874
875  // This function is a generalization of ChangeToPureOp. It can be used to
876  // replace a node that is part of the effect and control chain by a pure node.
877  void ReplaceWithPureNode(Node* node, Node* pure_node) {
878    DCHECK(pure_node->op()->HasProperty(Operator::kPure));
879    if (node->op()->EffectInputCount() > 0) {
880      DCHECK_LT(0, node->op()->ControlInputCount());
881      Node* control = NodeProperties::GetControlInput(node);
882      Node* effect = NodeProperties::GetEffectInput(node);
883      if (TypeOf(node).IsNone()) {
884        ChangeToDeadValue(node, effect, control);
885        return;
886      }
887      // Rewire the effect and control chains.
888      ReplaceEffectControlUses(node, effect, control);
889    } else {
890      DCHECK_EQ(0, node->op()->ControlInputCount());
891    }
892    DeferReplacement(node, pure_node);
893  }
894
895  void ChangeToPureOp(Node* node, const Operator* new_op) {
896    DCHECK(new_op->HasProperty(Operator::kPure));
897    DCHECK_EQ(new_op->ValueInputCount(), node->op()->ValueInputCount());
898    if (node->op()->EffectInputCount() > 0) {
899      DCHECK_LT(0, node->op()->ControlInputCount());
900      Node* control = NodeProperties::GetControlInput(node);
901      Node* effect = NodeProperties::GetEffectInput(node);
902      if (TypeOf(node).IsNone()) {
903        ChangeToDeadValue(node, effect, control);
904        return;
905      }
906      // Rewire the effect and control chains.
907      node->TrimInputCount(new_op->ValueInputCount());
908      ReplaceEffectControlUses(node, effect, control);
909    } else {
910      DCHECK_EQ(0, node->op()->ControlInputCount());
911    }
912    ChangeOp(node, new_op);
913  }
914
915  void ChangeUnaryToPureBinaryOp(Node* node, const Operator* new_op,
916                                 int new_input_index, Node* new_input) {
917    DCHECK(new_op->HasProperty(Operator::kPure));
918    DCHECK_EQ(new_op->ValueInputCount(), 2);
919    DCHECK_EQ(node->op()->ValueInputCount(), 1);
920    DCHECK_LE(0, new_input_index);
921    DCHECK_LE(new_input_index, 1);
922    if (node->op()->EffectInputCount() > 0) {
923      DCHECK_LT(0, node->op()->ControlInputCount());
924      Node* control = NodeProperties::GetControlInput(node);
925      Node* effect = NodeProperties::GetEffectInput(node);
926      if (TypeOf(node).IsNone()) {
927        ChangeToDeadValue(node, effect, control);
928        return;
929      }
930      node->TrimInputCount(node->op()->ValueInputCount());
931      ReplaceEffectControlUses(node, effect, control);
932    } else {
933      DCHECK_EQ(0, node->op()->ControlInputCount());
934    }
935    if (new_input_index == 0) {
936      node->InsertInput(jsgraph_->zone(), 0, new_input);
937    } else {
938      DCHECK_EQ(new_input_index, 1);
939      DCHECK_EQ(node->InputCount(), 1);
940      node->AppendInput(jsgraph_->zone(), new_input);
941    }
942    ChangeOp(node, new_op);
943  }
944
945  // Converts input {index} of {node} according to given UseInfo {use},
946  // assuming the type of the input is {input_type}. If {input_type} is null,
947  // it takes the input from the input node {TypeOf(node->InputAt(index))}.
948  void ConvertInput(Node* node, int index, UseInfo use,
949                    Type input_type = Type::Invalid()) {
950    // In the change phase, insert a change before the use if necessary.
951    if (use.representation() == MachineRepresentation::kNone)
952      return;  // No input requirement on the use.
953    Node* input = node->InputAt(index);
954    DCHECK_NOT_NULL(input);
955    NodeInfo* input_info = GetInfo(input);
956    MachineRepresentation input_rep = input_info->representation();
957    if (input_rep != use.representation() ||
958        use.type_check() != TypeCheckKind::kNone) {
959      // Output representation doesn't match usage.
960      TRACE("  change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
961            index, input->id(), input->op()->mnemonic());
962      TRACE("from %s to %s:%s\n",
963            MachineReprToString(input_info->representation()),
964            MachineReprToString(use.representation()),
965            use.truncation().description());
966      if (input_type.IsInvalid()) {
967        input_type = TypeOf(input);
968      }
969      Node* n = changer_->GetRepresentationFor(input, input_rep, input_type,
970                                               node, use);
971      node->ReplaceInput(index, n);
972    }
973  }
974
975  template <Phase T>
976  void ProcessInput(Node* node, int index, UseInfo use);
977
978  // Just assert for Retype and Lower. Propagate specialized below.
979  template <Phase T>
980  void ProcessRemainingInputs(Node* node, int index) {
981    static_assert(retype<T>() || lower<T>(),
982                  "This version of ProcessRemainingInputs has to be called in "
983                  "the Retype or Lower phase.");
984    DCHECK_GE(index, NodeProperties::PastValueIndex(node));
985    DCHECK_GE(index, NodeProperties::PastContextIndex(node));
986  }
987
988  // Marks node as a possible revisit since it is a use of input that will be
989  // visited before input is visited.
990  void MarkAsPossibleRevisit(Node* node, Node* input) {
991    auto it = might_need_revisit_.find(input);
992    if (it == might_need_revisit_.end()) {
993      it = might_need_revisit_.insert({input, ZoneVector<Node*>(zone())}).first;
994    }
995    it->second.push_back(node);
996    TRACE(" Marking #%d: %s as needing revisit due to #%d: %s\n", node->id(),
997          node->op()->mnemonic(), input->id(), input->op()->mnemonic());
998  }
999
1000  // Just assert for Retype. Propagate and Lower specialized below.
1001  template <Phase T>
1002  void VisitInputs(Node* node) {
1003    static_assert(
1004        retype<T>(),
1005        "This version of VisitInputs has to be called in the Retype phase.");
1006  }
1007
1008  template <Phase T>
1009  void VisitReturn(Node* node) {
1010    int first_effect_index = NodeProperties::FirstEffectIndex(node);
1011    // Visit integer slot count to pop
1012    ProcessInput<T>(node, 0, UseInfo::TruncatingWord32());
1013
1014    // Visit value, context and frame state inputs as tagged.
1015    for (int i = 1; i < first_effect_index; i++) {
1016      ProcessInput<T>(node, i, UseInfo::AnyTagged());
1017    }
1018    // Only enqueue other inputs (effects, control).
1019    for (int i = first_effect_index; i < node->InputCount(); i++) {
1020      EnqueueInput<T>(node, i);
1021    }
1022  }
1023
1024  // Helper for an unused node.
1025  template <Phase T>
1026  void VisitUnused(Node* node) {
1027    int first_effect_index = NodeProperties::FirstEffectIndex(node);
1028    for (int i = 0; i < first_effect_index; i++) {
1029      ProcessInput<T>(node, i, UseInfo::None());
1030    }
1031    ProcessRemainingInputs<T>(node, first_effect_index);
1032
1033    if (lower<T>()) {
1034      TRACE("disconnecting unused #%d:%s\n", node->id(),
1035            node->op()->mnemonic());
1036      DisconnectFromEffectAndControl(node);
1037      node->NullAllInputs();  // Node is now dead.
1038      DeferReplacement(node, graph()->NewNode(common()->Plug()));
1039    }
1040  }
1041
1042  // Helper for no-op node.
1043  template <Phase T>
1044  void VisitNoop(Node* node, Truncation truncation) {
1045    if (truncation.IsUnused()) return VisitUnused<T>(node);
1046    MachineRepresentation representation =
1047        GetOutputInfoForPhi(node, TypeOf(node), truncation);
1048    VisitUnop<T>(node, UseInfo(representation, truncation), representation);
1049    if (lower<T>()) DeferReplacement(node, node->InputAt(0));
1050  }
1051
1052  // Helper for binops of the R x L -> O variety.
1053  template <Phase T>
1054  void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
1055                  MachineRepresentation output,
1056                  Type restriction_type = Type::Any()) {
1057    DCHECK_EQ(2, node->op()->ValueInputCount());
1058    ProcessInput<T>(node, 0, left_use);
1059    ProcessInput<T>(node, 1, right_use);
1060    for (int i = 2; i < node->InputCount(); i++) {
1061      EnqueueInput<T>(node, i);
1062    }
1063    SetOutput<T>(node, output, restriction_type);
1064  }
1065
1066  // Helper for binops of the I x I -> O variety.
1067  template <Phase T>
1068  void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output,
1069                  Type restriction_type = Type::Any()) {
1070    VisitBinop<T>(node, input_use, input_use, output, restriction_type);
1071  }
1072
1073  template <Phase T>
1074  void VisitSpeculativeInt32Binop(Node* node) {
1075    DCHECK_EQ(2, node->op()->ValueInputCount());
1076    if (BothInputsAre(node, Type::NumberOrOddball())) {
1077      return VisitBinop<T>(node, UseInfo::TruncatingWord32(),
1078                           MachineRepresentation::kWord32);
1079    }
1080    NumberOperationHint hint = NumberOperationHintOf(node->op());
1081    return VisitBinop<T>(node,
1082                         CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros),
1083                         MachineRepresentation::kWord32);
1084  }
1085
1086  // Helper for unops of the I -> O variety.
1087  template <Phase T>
1088  void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output,
1089                 Type restriction_type = Type::Any()) {
1090    DCHECK_EQ(1, node->op()->ValueInputCount());
1091    ProcessInput<T>(node, 0, input_use);
1092    ProcessRemainingInputs<T>(node, 1);
1093    SetOutput<T>(node, output, restriction_type);
1094  }
1095
1096  // Helper for leaf nodes.
1097  template <Phase T>
1098  void VisitLeaf(Node* node, MachineRepresentation output) {
1099    DCHECK_EQ(0, node->InputCount());
1100    SetOutput<T>(node, output);
1101  }
1102
1103  // Helpers for specific types of binops.
1104
1105  template <Phase T>
1106  void VisitFloat64Binop(Node* node) {
1107    VisitBinop<T>(node, UseInfo::TruncatingFloat64(),
1108                  MachineRepresentation::kFloat64);
1109  }
1110
1111  template <Phase T>
1112  void VisitInt64Binop(Node* node) {
1113    VisitBinop<T>(node, UseInfo::Word64(), MachineRepresentation::kWord64);
1114  }
1115
1116  template <Phase T>
1117  void VisitWord32TruncatingBinop(Node* node) {
1118    VisitBinop<T>(node, UseInfo::TruncatingWord32(),
1119                  MachineRepresentation::kWord32);
1120  }
1121
1122  // Infer representation for phi-like nodes.
1123  // The {node} parameter is only used to decide on the int64 representation.
1124  // Once the type system supports an external pointer type, the {node}
1125  // parameter can be removed.
1126  MachineRepresentation GetOutputInfoForPhi(Node* node, Type type,
1127                                            Truncation use) {
1128    // Compute the representation.
1129    if (type.Is(Type::None())) {
1130      return MachineRepresentation::kNone;
1131    } else if (type.Is(Type::Signed32()) || type.Is(Type::Unsigned32())) {
1132      return MachineRepresentation::kWord32;
1133    } else if (type.Is(Type::NumberOrOddball()) && use.IsUsedAsWord32()) {
1134      return MachineRepresentation::kWord32;
1135    } else if (type.Is(Type::Boolean())) {
1136      return MachineRepresentation::kBit;
1137    } else if (type.Is(Type::NumberOrOddball()) &&
1138               use.TruncatesOddballAndBigIntToNumber()) {
1139      return MachineRepresentation::kFloat64;
1140    } else if (type.Is(Type::Union(Type::SignedSmall(), Type::NaN(), zone()))) {
1141      // TODO(turbofan): For Phis that return either NaN or some Smi, it's
1142      // beneficial to not go all the way to double, unless the uses are
1143      // double uses. For tagging that just means some potentially expensive
1144      // allocation code; we might want to do the same for -0 as well?
1145      return MachineRepresentation::kTagged;
1146    } else if (type.Is(Type::Number())) {
1147      return MachineRepresentation::kFloat64;
1148    } else if (type.Is(Type::BigInt()) && use.IsUsedAsWord64()) {
1149      return MachineRepresentation::kWord64;
1150    } else if (type.Is(Type::ExternalPointer()) ||
1151               type.Is(Type::SandboxedPointer())) {
1152      return MachineType::PointerRepresentation();
1153    }
1154    return MachineRepresentation::kTagged;
1155  }
1156
1157  // Helper for handling selects.
1158  template <Phase T>
1159  void VisitSelect(Node* node, Truncation truncation,
1160                   SimplifiedLowering* lowering) {
1161    DCHECK(TypeOf(node->InputAt(0)).Is(Type::Boolean()));
1162    ProcessInput<T>(node, 0, UseInfo::Bool());
1163
1164    MachineRepresentation output =
1165        GetOutputInfoForPhi(node, TypeOf(node), truncation);
1166    SetOutput<T>(node, output);
1167
1168    if (lower<T>()) {
1169      // Update the select operator.
1170      SelectParameters p = SelectParametersOf(node->op());
1171      if (output != p.representation()) {
1172        ChangeOp(node, lowering->common()->Select(output, p.hint()));
1173      }
1174    }
1175    // Convert inputs to the output representation of this phi, pass the
1176    // truncation truncation along.
1177    UseInfo input_use(output, truncation);
1178    ProcessInput<T>(node, 1, input_use);
1179    ProcessInput<T>(node, 2, input_use);
1180  }
1181
1182  // Helper for handling phis.
1183  template <Phase T>
1184  void VisitPhi(Node* node, Truncation truncation,
1185                SimplifiedLowering* lowering) {
1186    MachineRepresentation output =
1187        GetOutputInfoForPhi(node, TypeOf(node), truncation);
1188    // Only set the output representation if not running with type
1189    // feedback. (Feedback typing will set the representation.)
1190    SetOutput<T>(node, output);
1191
1192    int values = node->op()->ValueInputCount();
1193    if (lower<T>()) {
1194      // Update the phi operator.
1195      if (output != PhiRepresentationOf(node->op())) {
1196        ChangeOp(node, lowering->common()->Phi(output, values));
1197      }
1198    }
1199
1200    // Convert inputs to the output representation of this phi, pass the
1201    // truncation along.
1202    UseInfo input_use(output, truncation);
1203    for (int i = 0; i < node->InputCount(); i++) {
1204      ProcessInput<T>(node, i, i < values ? input_use : UseInfo::None());
1205    }
1206  }
1207
1208  template <Phase T>
1209  void VisitObjectIs(Node* node, Type type, SimplifiedLowering* lowering) {
1210    Type const input_type = TypeOf(node->InputAt(0));
1211    if (input_type.Is(type)) {
1212      VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit);
1213      if (lower<T>()) {
1214        DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
1215      }
1216    } else {
1217      VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
1218      if (lower<T>() && !input_type.Maybe(type)) {
1219        DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
1220      }
1221    }
1222  }
1223
1224  template <Phase T>
1225  void VisitCheck(Node* node, Type type, SimplifiedLowering* lowering) {
1226    if (InputIs(node, type)) {
1227      VisitUnop<T>(node, UseInfo::AnyTagged(),
1228                   MachineRepresentation::kTaggedPointer);
1229      if (lower<T>()) DeferReplacement(node, node->InputAt(0));
1230    } else {
1231      VisitUnop<T>(node,
1232                   UseInfo::CheckedHeapObjectAsTaggedPointer(FeedbackSource()),
1233                   MachineRepresentation::kTaggedPointer);
1234    }
1235  }
1236
1237  template <Phase T>
1238  void VisitCall(Node* node, SimplifiedLowering* lowering) {
1239    auto call_descriptor = CallDescriptorOf(node->op());
1240    int params = static_cast<int>(call_descriptor->ParameterCount());
1241    int value_input_count = node->op()->ValueInputCount();
1242
1243    DCHECK_GT(value_input_count, 0);
1244    DCHECK_GE(value_input_count, params);
1245
1246    // The target of the call.
1247    ProcessInput<T>(node, 0, UseInfo::Any());
1248
1249    // For the parameters (indexes [1, ..., params]), propagate representation
1250    // information from call descriptor.
1251    for (int i = 1; i <= params; i++) {
1252      ProcessInput<T>(node, i,
1253                      TruncatingUseInfoFromRepresentation(
1254                          call_descriptor->GetInputType(i).representation()));
1255    }
1256
1257    // Rest of the value inputs.
1258    for (int i = params + 1; i < value_input_count; i++) {
1259      ProcessInput<T>(node, i, UseInfo::AnyTagged());
1260    }
1261
1262    // Effect and Control.
1263    ProcessRemainingInputs<T>(node, value_input_count);
1264
1265    if (call_descriptor->ReturnCount() > 0) {
1266      SetOutput<T>(node, call_descriptor->GetReturnType(0).representation());
1267    } else {
1268      SetOutput<T>(node, MachineRepresentation::kTagged);
1269    }
1270  }
1271
1272  void MaskShiftOperand(Node* node, Type rhs_type) {
1273    if (!rhs_type.Is(type_cache_->kZeroToThirtyOne)) {
1274      Node* const rhs = NodeProperties::GetValueInput(node, 1);
1275      node->ReplaceInput(1,
1276                         graph()->NewNode(jsgraph_->machine()->Word32And(), rhs,
1277                                          jsgraph_->Int32Constant(0x1F)));
1278    }
1279  }
1280
1281  static MachineSemantic DeoptValueSemanticOf(Type type) {
1282    // We only need signedness to do deopt correctly.
1283    if (type.Is(Type::Signed32())) {
1284      return MachineSemantic::kInt32;
1285    } else if (type.Is(Type::Unsigned32())) {
1286      return MachineSemantic::kUint32;
1287    } else {
1288      return MachineSemantic::kAny;
1289    }
1290  }
1291
1292  static MachineType DeoptMachineTypeOf(MachineRepresentation rep, Type type) {
1293    if (type.IsNone()) {
1294      return MachineType::None();
1295    }
1296    // Do not distinguish between various Tagged variations.
1297    if (IsAnyTagged(rep)) {
1298      return MachineType::AnyTagged();
1299    }
1300    if (rep == MachineRepresentation::kWord64) {
1301      if (type.Is(Type::BigInt())) {
1302        return MachineType::AnyTagged();
1303      }
1304
1305      DCHECK(type.Is(TypeCache::Get()->kSafeInteger));
1306      return MachineType(rep, MachineSemantic::kInt64);
1307    }
1308    MachineType machine_type(rep, DeoptValueSemanticOf(type));
1309    DCHECK(machine_type.representation() != MachineRepresentation::kWord32 ||
1310           machine_type.semantic() == MachineSemantic::kInt32 ||
1311           machine_type.semantic() == MachineSemantic::kUint32);
1312    DCHECK(machine_type.representation() != MachineRepresentation::kBit ||
1313           type.Is(Type::Boolean()));
1314    return machine_type;
1315  }
1316
1317  template <Phase T>
1318  void VisitStateValues(Node* node) {
1319    if (propagate<T>()) {
1320      for (int i = 0; i < node->InputCount(); i++) {
1321        // When lowering 64 bit BigInts to Word64 representation, we have to
1322        // make sure they are rematerialized before deoptimization. By
1323        // propagating a AnyTagged use, the RepresentationChanger is going to
1324        // insert the necessary conversions.
1325        // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize
1326        // truncated BigInts.
1327        if (TypeOf(node->InputAt(i)).Is(Type::BigInt())) {
1328          EnqueueInput<T>(node, i, UseInfo::AnyTagged());
1329        } else {
1330          EnqueueInput<T>(node, i, UseInfo::Any());
1331        }
1332      }
1333    } else if (lower<T>()) {
1334      Zone* zone = jsgraph_->zone();
1335      ZoneVector<MachineType>* types =
1336          zone->New<ZoneVector<MachineType>>(node->InputCount(), zone);
1337      for (int i = 0; i < node->InputCount(); i++) {
1338        Node* input = node->InputAt(i);
1339        // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize
1340        // truncated BigInts.
1341        if (TypeOf(input).Is(Type::BigInt())) {
1342          ConvertInput(node, i, UseInfo::AnyTagged());
1343        }
1344
1345        (*types)[i] =
1346            DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input));
1347      }
1348      SparseInputMask mask = SparseInputMaskOf(node->op());
1349      ChangeOp(node, common()->TypedStateValues(types, mask));
1350    }
1351    SetOutput<T>(node, MachineRepresentation::kTagged);
1352  }
1353
1354  template <Phase T>
1355  void VisitFrameState(FrameState node) {
1356    DCHECK_EQ(5, node->op()->ValueInputCount());
1357    DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
1358    DCHECK_EQ(FrameState::kFrameStateInputCount, node->InputCount());
1359
1360    ProcessInput<T>(node, FrameState::kFrameStateParametersInput,
1361                    UseInfo::AnyTagged());
1362    ProcessInput<T>(node, FrameState::kFrameStateLocalsInput,
1363                    UseInfo::AnyTagged());
1364
1365    // Accumulator is a special flower - we need to remember its type in
1366    // a singleton typed-state-values node (as if it was a singleton
1367    // state-values node).
1368    Node* accumulator = node.stack();
1369    if (propagate<T>()) {
1370      // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize
1371      // truncated BigInts.
1372      if (TypeOf(accumulator).Is(Type::BigInt())) {
1373        EnqueueInput<T>(node, FrameState::kFrameStateStackInput,
1374                        UseInfo::AnyTagged());
1375      } else {
1376        EnqueueInput<T>(node, FrameState::kFrameStateStackInput,
1377                        UseInfo::Any());
1378      }
1379    } else if (lower<T>()) {
1380      // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize
1381      // truncated BigInts.
1382      if (TypeOf(accumulator).Is(Type::BigInt())) {
1383        ConvertInput(node, FrameState::kFrameStateStackInput,
1384                     UseInfo::AnyTagged());
1385      }
1386      Zone* zone = jsgraph_->zone();
1387      if (accumulator == jsgraph_->OptimizedOutConstant()) {
1388        node->ReplaceInput(FrameState::kFrameStateStackInput,
1389                           jsgraph_->SingleDeadTypedStateValues());
1390      } else {
1391        ZoneVector<MachineType>* types =
1392            zone->New<ZoneVector<MachineType>>(1, zone);
1393        (*types)[0] = DeoptMachineTypeOf(GetInfo(accumulator)->representation(),
1394                                         TypeOf(accumulator));
1395
1396        node->ReplaceInput(
1397            FrameState::kFrameStateStackInput,
1398            jsgraph_->graph()->NewNode(
1399                common()->TypedStateValues(types, SparseInputMask::Dense()),
1400                node.stack()));
1401      }
1402    }
1403
1404    ProcessInput<T>(node, FrameState::kFrameStateContextInput,
1405                    UseInfo::AnyTagged());
1406    ProcessInput<T>(node, FrameState::kFrameStateFunctionInput,
1407                    UseInfo::AnyTagged());
1408    ProcessInput<T>(node, FrameState::kFrameStateOuterStateInput,
1409                    UseInfo::AnyTagged());
1410    return SetOutput<T>(node, MachineRepresentation::kTagged);
1411  }
1412
1413  template <Phase T>
1414  void VisitObjectState(Node* node) {
1415    if (propagate<T>()) {
1416      for (int i = 0; i < node->InputCount(); i++) {
1417        // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize
1418        // truncated BigInts.
1419        if (TypeOf(node->InputAt(i)).Is(Type::BigInt())) {
1420          EnqueueInput<T>(node, i, UseInfo::AnyTagged());
1421        } else {
1422          EnqueueInput<T>(node, i, UseInfo::Any());
1423        }
1424      }
1425    } else if (lower<T>()) {
1426      Zone* zone = jsgraph_->zone();
1427      ZoneVector<MachineType>* types =
1428          zone->New<ZoneVector<MachineType>>(node->InputCount(), zone);
1429      for (int i = 0; i < node->InputCount(); i++) {
1430        Node* input = node->InputAt(i);
1431        (*types)[i] =
1432            DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input));
1433        // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize
1434        // truncated BigInts.
1435        if (TypeOf(node->InputAt(i)).Is(Type::BigInt())) {
1436          ConvertInput(node, i, UseInfo::AnyTagged());
1437        }
1438      }
1439      ChangeOp(node, common()->TypedObjectState(ObjectIdOf(node->op()), types));
1440    }
1441    SetOutput<T>(node, MachineRepresentation::kTagged);
1442  }
1443
1444  const Operator* Int32Op(Node* node) {
1445    return changer_->Int32OperatorFor(node->opcode());
1446  }
1447
1448  const Operator* Int32OverflowOp(Node* node) {
1449    return changer_->Int32OverflowOperatorFor(node->opcode());
1450  }
1451
1452  const Operator* Int64Op(Node* node) {
1453    return changer_->Int64OperatorFor(node->opcode());
1454  }
1455
1456  const Operator* Uint32Op(Node* node) {
1457    return changer_->Uint32OperatorFor(node->opcode());
1458  }
1459
1460  const Operator* Uint32OverflowOp(Node* node) {
1461    return changer_->Uint32OverflowOperatorFor(node->opcode());
1462  }
1463
1464  const Operator* Float64Op(Node* node) {
1465    return changer_->Float64OperatorFor(node->opcode());
1466  }
1467
1468  WriteBarrierKind WriteBarrierKindFor(
1469      BaseTaggedness base_taggedness,
1470      MachineRepresentation field_representation, Type field_type,
1471      MachineRepresentation value_representation, Node* value) {
1472    if (base_taggedness == kTaggedBase &&
1473        CanBeTaggedPointer(field_representation)) {
1474      Type value_type = NodeProperties::GetType(value);
1475      if (value_representation == MachineRepresentation::kTaggedSigned) {
1476        // Write barriers are only for stores of heap objects.
1477        return kNoWriteBarrier;
1478      }
1479      if (field_type.Is(Type::BooleanOrNullOrUndefined()) ||
1480          value_type.Is(Type::BooleanOrNullOrUndefined())) {
1481        // Write barriers are not necessary when storing true, false, null or
1482        // undefined, because these special oddballs are always in the root set.
1483        return kNoWriteBarrier;
1484      }
1485      if (value_type.IsHeapConstant()) {
1486        RootIndex root_index;
1487        const RootsTable& roots_table = jsgraph_->isolate()->roots_table();
1488        if (roots_table.IsRootHandle(value_type.AsHeapConstant()->Value(),
1489                                     &root_index)) {
1490          if (RootsTable::IsImmortalImmovable(root_index)) {
1491            // Write barriers are unnecessary for immortal immovable roots.
1492            return kNoWriteBarrier;
1493          }
1494        }
1495      }
1496      if (field_representation == MachineRepresentation::kTaggedPointer ||
1497          value_representation == MachineRepresentation::kTaggedPointer) {
1498        // Write barriers for heap objects are cheaper.
1499        return kPointerWriteBarrier;
1500      }
1501      NumberMatcher m(value);
1502      if (m.HasResolvedValue()) {
1503        if (IsSmiDouble(m.ResolvedValue())) {
1504          // Storing a smi doesn't need a write barrier.
1505          return kNoWriteBarrier;
1506        }
1507        // The NumberConstant will be represented as HeapNumber.
1508        return kPointerWriteBarrier;
1509      }
1510      return kFullWriteBarrier;
1511    }
1512    return kNoWriteBarrier;
1513  }
1514
1515  WriteBarrierKind WriteBarrierKindFor(
1516      BaseTaggedness base_taggedness,
1517      MachineRepresentation field_representation, int field_offset,
1518      Type field_type, MachineRepresentation value_representation,
1519      Node* value) {
1520    WriteBarrierKind write_barrier_kind =
1521        WriteBarrierKindFor(base_taggedness, field_representation, field_type,
1522                            value_representation, value);
1523    if (write_barrier_kind != kNoWriteBarrier) {
1524      if (base_taggedness == kTaggedBase &&
1525          field_offset == HeapObject::kMapOffset) {
1526        write_barrier_kind = kMapWriteBarrier;
1527      }
1528    }
1529    return write_barrier_kind;
1530  }
1531
1532  Graph* graph() const { return jsgraph_->graph(); }
1533  CommonOperatorBuilder* common() const { return jsgraph_->common(); }
1534  SimplifiedOperatorBuilder* simplified() const {
1535    return jsgraph_->simplified();
1536  }
1537
1538  template <Phase T>
1539  void VisitForCheckedInt32Mul(Node* node, Truncation truncation,
1540                               Type input0_type, Type input1_type,
1541                               UseInfo input_use) {
1542    DCHECK_EQ(node->opcode(), IrOpcode::kSpeculativeNumberMultiply);
1543    // A -0 input is impossible or will cause a deopt.
1544    DCHECK(BothInputsAre(node, Type::Signed32()) ||
1545           !input_use.truncation().IdentifiesZeroAndMinusZero());
1546
1547    CheckForMinusZeroMode mz_mode;
1548    Type restriction;
1549    if (IsSomePositiveOrderedNumber(input0_type) ||
1550        IsSomePositiveOrderedNumber(input1_type)) {
1551      mz_mode = CheckForMinusZeroMode::kDontCheckForMinusZero;
1552      restriction = Type::Signed32();
1553    } else if (truncation.IdentifiesZeroAndMinusZero()) {
1554      mz_mode = CheckForMinusZeroMode::kDontCheckForMinusZero;
1555      restriction = Type::Signed32OrMinusZero();
1556    } else {
1557      mz_mode = CheckForMinusZeroMode::kCheckForMinusZero;
1558      restriction = Type::Signed32();
1559    }
1560
1561    VisitBinop<T>(node, input_use, MachineRepresentation::kWord32, restriction);
1562    if (lower<T>()) ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode));
1563  }
1564
1565  void ChangeToInt32OverflowOp(Node* node) {
1566    ChangeOp(node, Int32OverflowOp(node));
1567  }
1568
1569  void ChangeToUint32OverflowOp(Node* node) {
1570    ChangeOp(node, Uint32OverflowOp(node));
1571  }
1572
1573  template <Phase T>
1574  void VisitSpeculativeIntegerAdditiveOp(Node* node, Truncation truncation,
1575                                         SimplifiedLowering* lowering) {
1576    Type left_upper = GetUpperBound(node->InputAt(0));
1577    Type right_upper = GetUpperBound(node->InputAt(1));
1578
1579    if (left_upper.Is(type_cache_->kAdditiveSafeIntegerOrMinusZero) &&
1580        right_upper.Is(type_cache_->kAdditiveSafeIntegerOrMinusZero)) {
1581      // Only eliminate the node if its typing rule can be satisfied, namely
1582      // that a safe integer is produced.
1583      if (truncation.IsUnused()) return VisitUnused<T>(node);
1584
1585      // If we know how to interpret the result or if the users only care
1586      // about the low 32-bits, we can truncate to Word32 do a wrapping
1587      // addition.
1588      if (GetUpperBound(node).Is(Type::Signed32()) ||
1589          GetUpperBound(node).Is(Type::Unsigned32()) ||
1590          truncation.IsUsedAsWord32()) {
1591        // => Int32Add/Sub
1592        VisitWord32TruncatingBinop<T>(node);
1593        if (lower<T>()) ChangeToPureOp(node, Int32Op(node));
1594        return;
1595      }
1596    }
1597
1598    // Try to use type feedback.
1599    NumberOperationHint const hint = NumberOperationHint::kSignedSmall;
1600    DCHECK_EQ(hint, NumberOperationHintOf(node->op()));
1601
1602    Type left_feedback_type = TypeOf(node->InputAt(0));
1603    Type right_feedback_type = TypeOf(node->InputAt(1));
1604
1605    // Using Signed32 as restriction type amounts to promising there won't be
1606    // signed overflow. This is incompatible with relying on a Word32 truncation
1607    // in order to skip the overflow check.  Similarly, we must not drop -0 from
1608    // the result type unless we deopt for -0 inputs.
1609    Type const restriction =
1610        truncation.IsUsedAsWord32()
1611            ? Type::Any()
1612            : (truncation.identify_zeros() == kIdentifyZeros)
1613                  ? Type::Signed32OrMinusZero()
1614                  : Type::Signed32();
1615
1616    // Handle the case when no int32 checks on inputs are necessary (but
1617    // an overflow check is needed on the output). Note that we do not
1618    // have to do any check if at most one side can be minus zero. For
1619    // subtraction we need to handle the case of -0 - 0 properly, since
1620    // that can produce -0.
1621    Type left_constraint_type =
1622        node->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd
1623            ? Type::Signed32OrMinusZero()
1624            : Type::Signed32();
1625    if (left_upper.Is(left_constraint_type) &&
1626        right_upper.Is(Type::Signed32OrMinusZero()) &&
1627        (left_upper.Is(Type::Signed32()) || right_upper.Is(Type::Signed32()))) {
1628      VisitBinop<T>(node, UseInfo::TruncatingWord32(),
1629                    MachineRepresentation::kWord32, restriction);
1630    } else {
1631      // If the output's truncation is identify-zeros, we can pass it
1632      // along. Moreover, if the operation is addition and we know the
1633      // right-hand side is not minus zero, we do not have to distinguish
1634      // between 0 and -0.
1635      IdentifyZeros left_identify_zeros = truncation.identify_zeros();
1636      if (node->opcode() == IrOpcode::kSpeculativeSafeIntegerAdd &&
1637          !right_feedback_type.Maybe(Type::MinusZero())) {
1638        left_identify_zeros = kIdentifyZeros;
1639      }
1640      UseInfo left_use =
1641          CheckedUseInfoAsWord32FromHint(hint, left_identify_zeros);
1642      // For CheckedInt32Add and CheckedInt32Sub, we don't need to do
1643      // a minus zero check for the right hand side, since we already
1644      // know that the left hand side is a proper Signed32 value,
1645      // potentially guarded by a check.
1646      UseInfo right_use = CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros);
1647      VisitBinop<T>(node, left_use, right_use, MachineRepresentation::kWord32,
1648                    restriction);
1649    }
1650
1651    if (lower<T>()) {
1652      if (truncation.IsUsedAsWord32() ||
1653          !CanOverflowSigned32(node->op(), left_feedback_type,
1654                               right_feedback_type, type_cache_,
1655                               graph_zone())) {
1656        ChangeToPureOp(node, Int32Op(node));
1657      } else {
1658        ChangeToInt32OverflowOp(node);
1659      }
1660    }
1661    return;
1662  }
1663
1664  template <Phase T>
1665  void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
1666                                  SimplifiedLowering* lowering) {
1667    if (BothInputsAre(node, type_cache_->kAdditiveSafeIntegerOrMinusZero) &&
1668        (GetUpperBound(node).Is(Type::Signed32()) ||
1669         GetUpperBound(node).Is(Type::Unsigned32()) ||
1670         truncation.IsUsedAsWord32())) {
1671      // => Int32Add/Sub
1672      VisitWord32TruncatingBinop<T>(node);
1673      if (lower<T>()) ChangeToPureOp(node, Int32Op(node));
1674      return;
1675    }
1676
1677    // default case => Float64Add/Sub
1678    VisitBinop<T>(node,
1679                  UseInfo::CheckedNumberOrOddballAsFloat64(kDistinguishZeros,
1680                                                           FeedbackSource()),
1681                  MachineRepresentation::kFloat64, Type::Number());
1682    if (lower<T>()) {
1683      ChangeToPureOp(node, Float64Op(node));
1684    }
1685    return;
1686  }
1687
1688  template <Phase T>
1689  void VisitSpeculativeNumberModulus(Node* node, Truncation truncation,
1690                                     SimplifiedLowering* lowering) {
1691    if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) &&
1692        (truncation.IsUsedAsWord32() ||
1693         NodeProperties::GetType(node).Is(Type::Unsigned32()))) {
1694      // => unsigned Uint32Mod
1695      VisitWord32TruncatingBinop<T>(node);
1696      if (lower<T>()) DeferReplacement(node, lowering->Uint32Mod(node));
1697      return;
1698    }
1699    if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) &&
1700        (truncation.IsUsedAsWord32() ||
1701         NodeProperties::GetType(node).Is(Type::Signed32()))) {
1702      // => signed Int32Mod
1703      VisitWord32TruncatingBinop<T>(node);
1704      if (lower<T>()) DeferReplacement(node, lowering->Int32Mod(node));
1705      return;
1706    }
1707
1708    // Try to use type feedback.
1709    NumberOperationHint hint = NumberOperationHintOf(node->op());
1710
1711    // Handle the case when no uint32 checks on inputs are necessary
1712    // (but an overflow check is needed on the output).
1713    if (BothInputsAreUnsigned32(node)) {
1714      if (hint == NumberOperationHint::kSignedSmall) {
1715        VisitBinop<T>(node, UseInfo::TruncatingWord32(),
1716                      MachineRepresentation::kWord32, Type::Unsigned32());
1717        if (lower<T>()) ChangeToUint32OverflowOp(node);
1718        return;
1719      }
1720    }
1721
1722    // Handle the case when no int32 checks on inputs are necessary
1723    // (but an overflow check is needed on the output).
1724    if (BothInputsAre(node, Type::Signed32())) {
1725      // If both the inputs the feedback are int32, use the overflow op.
1726      if (hint == NumberOperationHint::kSignedSmall) {
1727        VisitBinop<T>(node, UseInfo::TruncatingWord32(),
1728                      MachineRepresentation::kWord32, Type::Signed32());
1729        if (lower<T>()) ChangeToInt32OverflowOp(node);
1730        return;
1731      }
1732    }
1733
1734    if (hint == NumberOperationHint::kSignedSmall) {
1735      // If the result is truncated, we only need to check the inputs.
1736      // For the left hand side we just propagate the identify zeros
1737      // mode of the {truncation}; and for modulus the sign of the
1738      // right hand side doesn't matter anyways, so in particular there's
1739      // no observable difference between a 0 and a -0 then.
1740      UseInfo const lhs_use =
1741          CheckedUseInfoAsWord32FromHint(hint, truncation.identify_zeros());
1742      UseInfo const rhs_use =
1743          CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros);
1744      if (truncation.IsUsedAsWord32()) {
1745        VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kWord32);
1746        if (lower<T>()) DeferReplacement(node, lowering->Int32Mod(node));
1747      } else if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN())) {
1748        Type const restriction =
1749            truncation.IdentifiesZeroAndMinusZero() &&
1750                    TypeOf(node->InputAt(0)).Maybe(Type::MinusZero())
1751                ? Type::Unsigned32OrMinusZero()
1752                : Type::Unsigned32();
1753        VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kWord32,
1754                      restriction);
1755        if (lower<T>()) ChangeToUint32OverflowOp(node);
1756      } else {
1757        Type const restriction =
1758            truncation.IdentifiesZeroAndMinusZero() &&
1759                    TypeOf(node->InputAt(0)).Maybe(Type::MinusZero())
1760                ? Type::Signed32OrMinusZero()
1761                : Type::Signed32();
1762        VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kWord32,
1763                      restriction);
1764        if (lower<T>()) ChangeToInt32OverflowOp(node);
1765      }
1766      return;
1767    }
1768
1769    if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) &&
1770        TypeOf(node->InputAt(1)).Is(Type::Unsigned32()) &&
1771        (truncation.IsUsedAsWord32() ||
1772         NodeProperties::GetType(node).Is(Type::Unsigned32()))) {
1773      VisitBinop<T>(node, UseInfo::TruncatingWord32(),
1774                    MachineRepresentation::kWord32, Type::Number());
1775      if (lower<T>()) DeferReplacement(node, lowering->Uint32Mod(node));
1776      return;
1777    }
1778    if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) &&
1779        TypeOf(node->InputAt(1)).Is(Type::Signed32()) &&
1780        (truncation.IsUsedAsWord32() ||
1781         NodeProperties::GetType(node).Is(Type::Signed32()))) {
1782      VisitBinop<T>(node, UseInfo::TruncatingWord32(),
1783                    MachineRepresentation::kWord32, Type::Number());
1784      if (lower<T>()) DeferReplacement(node, lowering->Int32Mod(node));
1785      return;
1786    }
1787
1788    // default case => Float64Mod
1789    // For the left hand side we just propagate the identify zeros
1790    // mode of the {truncation}; and for modulus the sign of the
1791    // right hand side doesn't matter anyways, so in particular there's
1792    // no observable difference between a 0 and a -0 then.
1793    UseInfo const lhs_use = UseInfo::CheckedNumberOrOddballAsFloat64(
1794        truncation.identify_zeros(), FeedbackSource());
1795    UseInfo const rhs_use = UseInfo::CheckedNumberOrOddballAsFloat64(
1796        kIdentifyZeros, FeedbackSource());
1797    VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kFloat64,
1798                  Type::Number());
1799    if (lower<T>()) ChangeToPureOp(node, Float64Op(node));
1800    return;
1801  }
1802
1803  // Just assert for Propagate and Retype. Lower specialized below.
1804  template <Phase T>
1805  void InsertUnreachableIfNecessary(Node* node) {
1806    static_assert(propagate<T>() || retype<T>(),
1807                  "This version of InsertUnreachableIfNecessary has to be "
1808                  "called in the Propagate or Retype phase.");
1809  }
1810
1811  template <Phase T>
1812  void VisitCheckBounds(Node* node, SimplifiedLowering* lowering) {
1813    CheckBoundsParameters const& p = CheckBoundsParametersOf(node->op());
1814    FeedbackSource const& feedback = p.check_parameters().feedback();
1815    Type const index_type = TypeOf(node->InputAt(0));
1816    Type const length_type = TypeOf(node->InputAt(1));
1817
1818    // Conversions, if requested and needed, will be handled by the
1819    // representation changer, not by the lower-level Checked*Bounds operators.
1820    CheckBoundsFlags new_flags =
1821        p.flags().without(CheckBoundsFlag::kConvertStringAndMinusZero);
1822
1823    if (length_type.Is(Type::Unsigned31())) {
1824      if (index_type.Is(Type::Integral32()) ||
1825          (index_type.Is(Type::Integral32OrMinusZero()) &&
1826           p.flags() & CheckBoundsFlag::kConvertStringAndMinusZero)) {
1827        // Map the values in the [-2^31,-1] range to the [2^31,2^32-1] range,
1828        // which will be considered out-of-bounds because the {length_type} is
1829        // limited to Unsigned31. This also converts -0 to 0.
1830        VisitBinop<T>(node, UseInfo::TruncatingWord32(),
1831                      MachineRepresentation::kWord32);
1832        if (lower<T>()) {
1833          if (index_type.IsNone() || length_type.IsNone() ||
1834              (index_type.Min() >= 0.0 &&
1835               index_type.Max() < length_type.Min())) {
1836            // The bounds check is redundant if we already know that
1837            // the index is within the bounds of [0.0, length[.
1838            // TODO(neis): Move this into TypedOptimization?
1839            new_flags |= CheckBoundsFlag::kAbortOnOutOfBounds;
1840          }
1841          ChangeOp(node,
1842                   simplified()->CheckedUint32Bounds(feedback, new_flags));
1843        }
1844      } else if (p.flags() & CheckBoundsFlag::kConvertStringAndMinusZero) {
1845        VisitBinop<T>(node, UseInfo::CheckedTaggedAsArrayIndex(feedback),
1846                      UseInfo::Word(), MachineType::PointerRepresentation());
1847        if (lower<T>()) {
1848          if (jsgraph_->machine()->Is64()) {
1849            ChangeOp(node,
1850                     simplified()->CheckedUint64Bounds(feedback, new_flags));
1851          } else {
1852            ChangeOp(node,
1853                     simplified()->CheckedUint32Bounds(feedback, new_flags));
1854          }
1855        }
1856      } else {
1857        VisitBinop<T>(
1858            node, UseInfo::CheckedSigned32AsWord32(kDistinguishZeros, feedback),
1859            UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1860        if (lower<T>()) {
1861          ChangeOp(node,
1862                   simplified()->CheckedUint32Bounds(feedback, new_flags));
1863        }
1864      }
1865    } else {
1866      CHECK(length_type.Is(type_cache_->kPositiveSafeInteger));
1867      IdentifyZeros zero_handling =
1868          (p.flags() & CheckBoundsFlag::kConvertStringAndMinusZero)
1869              ? kIdentifyZeros
1870              : kDistinguishZeros;
1871      VisitBinop<T>(node,
1872                    UseInfo::CheckedSigned64AsWord64(zero_handling, feedback),
1873                    UseInfo::Word64(), MachineRepresentation::kWord64);
1874      if (lower<T>()) {
1875        ChangeOp(node, simplified()->CheckedUint64Bounds(feedback, new_flags));
1876      }
1877    }
1878  }
1879
1880  UseInfo UseInfoForFastApiCallArgument(CTypeInfo type,
1881                                        FeedbackSource const& feedback) {
1882    switch (type.GetSequenceType()) {
1883      case CTypeInfo::SequenceType::kScalar: {
1884        switch (type.GetType()) {
1885          case CTypeInfo::Type::kVoid:
1886            UNREACHABLE();
1887          case CTypeInfo::Type::kBool:
1888            return UseInfo::Bool();
1889          case CTypeInfo::Type::kInt32:
1890          case CTypeInfo::Type::kUint32:
1891            return UseInfo::CheckedNumberAsWord32(feedback);
1892          // TODO(mslekova): We deopt for unsafe integers, but ultimately we
1893          // want to make this less restrictive in order to stay on the fast
1894          // path.
1895          case CTypeInfo::Type::kInt64:
1896          case CTypeInfo::Type::kUint64:
1897          case CTypeInfo::Type::kAny:
1898            return UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, feedback);
1899          case CTypeInfo::Type::kFloat32:
1900          case CTypeInfo::Type::kFloat64:
1901            return UseInfo::CheckedNumberAsFloat64(kDistinguishZeros, feedback);
1902          case CTypeInfo::Type::kV8Value:
1903          case CTypeInfo::Type::kApiObject:
1904            return UseInfo::AnyTagged();
1905        }
1906      }
1907      case CTypeInfo::SequenceType::kIsSequence: {
1908        CHECK_EQ(type.GetType(), CTypeInfo::Type::kVoid);
1909        return UseInfo::AnyTagged();
1910      }
1911      case CTypeInfo::SequenceType::kIsTypedArray: {
1912        return UseInfo::AnyTagged();
1913      }
1914      default: {
1915        UNREACHABLE();  // TODO(mslekova): Implement array buffers.
1916      }
1917    }
1918  }
1919
1920  static constexpr int kInitialArgumentsCount = 10;
1921
1922  template <Phase T>
1923  void VisitFastApiCall(Node* node, SimplifiedLowering* lowering) {
1924    FastApiCallParameters const& op_params =
1925        FastApiCallParametersOf(node->op());
1926    // We only consider the first function signature here. In case of function
1927    // overloads, we only support the case of two functions that differ for one
1928    // argument, which must be a JSArray in one function and a TypedArray in the
1929    // other function, and both JSArrays and TypedArrays have the same UseInfo
1930    // UseInfo::AnyTagged(). All the other argument types must match.
1931    const CFunctionInfo* c_signature = op_params.c_functions()[0].signature;
1932    const int c_arg_count = c_signature->ArgumentCount();
1933    CallDescriptor* call_descriptor = op_params.descriptor();
1934    int js_arg_count = static_cast<int>(call_descriptor->ParameterCount());
1935    const int value_input_count = node->op()->ValueInputCount();
1936    CHECK_EQ(FastApiCallNode::ArityForArgc(c_arg_count, js_arg_count),
1937             value_input_count);
1938
1939    base::SmallVector<UseInfo, kInitialArgumentsCount> arg_use_info(
1940        c_arg_count);
1941    // Propagate representation information from TypeInfo.
1942    for (int i = 0; i < c_arg_count; i++) {
1943      arg_use_info[i] = UseInfoForFastApiCallArgument(
1944          c_signature->ArgumentInfo(i), op_params.feedback());
1945      ProcessInput<T>(node, i, arg_use_info[i]);
1946    }
1947
1948    // The call code for the slow call.
1949    ProcessInput<T>(node, c_arg_count, UseInfo::AnyTagged());
1950    for (int i = 1; i <= js_arg_count; i++) {
1951      ProcessInput<T>(node, c_arg_count + i,
1952                      TruncatingUseInfoFromRepresentation(
1953                          call_descriptor->GetInputType(i).representation()));
1954    }
1955    for (int i = c_arg_count + js_arg_count; i < value_input_count; ++i) {
1956      ProcessInput<T>(node, i, UseInfo::AnyTagged());
1957    }
1958    ProcessRemainingInputs<T>(node, value_input_count);
1959    SetOutput<T>(node, MachineRepresentation::kTagged);
1960  }
1961
1962#if V8_ENABLE_WEBASSEMBLY
1963  static MachineType MachineTypeForWasmReturnType(wasm::ValueType type) {
1964    switch (type.kind()) {
1965      case wasm::kI32:
1966        return MachineType::Int32();
1967      case wasm::kF32:
1968        return MachineType::Float32();
1969      case wasm::kF64:
1970        return MachineType::Float64();
1971      case wasm::kI64:
1972        // Not used for i64, see VisitJSWasmCall().
1973      default:
1974        UNREACHABLE();
1975    }
1976  }
1977
1978  UseInfo UseInfoForJSWasmCallArgument(Node* input, wasm::ValueType type,
1979                                       FeedbackSource const& feedback) {
1980    // If the input type is a Number or Oddball, we can directly convert the
1981    // input into the Wasm native type of the argument. If not, we return
1982    // UseInfo::AnyTagged to signal that WasmWrapperGraphBuilder will need to
1983    // add Nodes to perform the conversion (in WasmWrapperGraphBuilder::FromJS).
1984    switch (type.kind()) {
1985      case wasm::kI32:
1986        return UseInfo::CheckedNumberOrOddballAsWord32(feedback);
1987      case wasm::kI64:
1988        return UseInfo::AnyTagged();
1989      case wasm::kF32:
1990      case wasm::kF64:
1991        // For Float32, TruncateFloat64ToFloat32 will be inserted later in
1992        // WasmWrapperGraphBuilder::BuildJSToWasmWrapper.
1993        return UseInfo::CheckedNumberOrOddballAsFloat64(kDistinguishZeros,
1994                                                        feedback);
1995      default:
1996        UNREACHABLE();
1997    }
1998  }
1999
2000  template <Phase T>
2001  void VisitJSWasmCall(Node* node, SimplifiedLowering* lowering) {
2002    DCHECK_EQ(JSWasmCallNode::TargetIndex(), 0);
2003    DCHECK_EQ(JSWasmCallNode::ReceiverIndex(), 1);
2004    DCHECK_EQ(JSWasmCallNode::FirstArgumentIndex(), 2);
2005
2006    JSWasmCallNode n(node);
2007
2008    JSWasmCallParameters const& params = n.Parameters();
2009    const wasm::FunctionSig* wasm_signature = params.signature();
2010    int wasm_arg_count = static_cast<int>(wasm_signature->parameter_count());
2011    DCHECK_EQ(wasm_arg_count, n.ArgumentCount());
2012
2013    base::SmallVector<UseInfo, kInitialArgumentsCount> arg_use_info(
2014        wasm_arg_count);
2015
2016    // Visit JSFunction and Receiver nodes.
2017    ProcessInput<T>(node, JSWasmCallNode::TargetIndex(), UseInfo::Any());
2018    ProcessInput<T>(node, JSWasmCallNode::ReceiverIndex(), UseInfo::Any());
2019
2020    // Propagate representation information from TypeInfo.
2021    for (int i = 0; i < wasm_arg_count; i++) {
2022      TNode<Object> input = n.Argument(i);
2023      DCHECK_NOT_NULL(input);
2024      arg_use_info[i] = UseInfoForJSWasmCallArgument(
2025          input, wasm_signature->GetParam(i), params.feedback());
2026      ProcessInput<T>(node, JSWasmCallNode::ArgumentIndex(i), arg_use_info[i]);
2027    }
2028
2029    // Visit value, context and frame state inputs as tagged.
2030    int first_effect_index = NodeProperties::FirstEffectIndex(node);
2031    DCHECK(first_effect_index >
2032           JSWasmCallNode::FirstArgumentIndex() + wasm_arg_count);
2033    for (int i = JSWasmCallNode::FirstArgumentIndex() + wasm_arg_count;
2034         i < first_effect_index; i++) {
2035      ProcessInput<T>(node, i, UseInfo::AnyTagged());
2036    }
2037
2038    // Effect and Control.
2039    ProcessRemainingInputs<T>(node, NodeProperties::FirstEffectIndex(node));
2040
2041    if (wasm_signature->return_count() == 1) {
2042      if (wasm_signature->GetReturn().kind() == wasm::kI64) {
2043        // Conversion between negative int64 and BigInt not supported yet.
2044        // Do not bypass the type conversion when the result type is i64.
2045        SetOutput<T>(node, MachineRepresentation::kTagged);
2046      } else {
2047        MachineType return_type =
2048            MachineTypeForWasmReturnType(wasm_signature->GetReturn());
2049        SetOutput<T>(
2050            node, return_type.representation(),
2051            JSWasmCallNode::TypeForWasmReturnType(wasm_signature->GetReturn()));
2052      }
2053    } else {
2054      DCHECK_EQ(wasm_signature->return_count(), 0);
2055      SetOutput<T>(node, MachineRepresentation::kTagged);
2056    }
2057
2058    // The actual lowering of JSWasmCall nodes happens later, in the subsequent
2059    // "wasm-inlining" phase.
2060  }
2061#endif  // V8_ENABLE_WEBASSEMBLY
2062
2063  // Dispatching routine for visiting the node {node} with the usage {use}.
2064  // Depending on the operator, propagate new usage info to the inputs.
2065  template <Phase T>
2066  void VisitNode(Node* node, Truncation truncation,
2067                 SimplifiedLowering* lowering) {
2068    tick_counter_->TickAndMaybeEnterSafepoint();
2069
2070    if (lower<T>()) {
2071      // Kill non-effectful operations that have a None-type input and are thus
2072      // dead code. Otherwise we might end up lowering the operation in a way,
2073      // e.g. by replacing it with a constant, that cuts the dependency on a
2074      // deopting operation (the producer of the None type), possibly resulting
2075      // in a nonsense schedule.
2076      if (node->op()->EffectOutputCount() == 0 &&
2077          node->op()->ControlOutputCount() == 0 &&
2078          node->opcode() != IrOpcode::kDeadValue &&
2079          node->opcode() != IrOpcode::kStateValues &&
2080          node->opcode() != IrOpcode::kFrameState &&
2081          node->opcode() != IrOpcode::kPhi) {
2082        for (int i = 0; i < node->op()->ValueInputCount(); i++) {
2083          Node* input = node->InputAt(i);
2084          if (TypeOf(input).IsNone()) {
2085            node->ReplaceInput(0, input);
2086            node->TrimInputCount(1);
2087            ChangeOp(node,
2088                     common()->DeadValue(GetInfo(node)->representation()));
2089            return;
2090          }
2091        }
2092      } else {
2093        InsertUnreachableIfNecessary<T>(node);
2094      }
2095    }
2096
2097    // Unconditionally eliminate unused pure nodes (only relevant if there's
2098    // a pure operation in between two effectful ones, where the last one
2099    // is unused).
2100    // Note: We must not do this for constants, as they are cached and we
2101    // would thus kill the cached {node} during lowering (i.e. replace all
2102    // uses with Dead), but at that point some node lowering might have
2103    // already taken the constant {node} from the cache (while it was not
2104    // yet killed) and we would afterwards replace that use with Dead as well.
2105    if (node->op()->ValueInputCount() > 0 &&
2106        node->op()->HasProperty(Operator::kPure) && truncation.IsUnused()) {
2107      return VisitUnused<T>(node);
2108    }
2109
2110    switch (node->opcode()) {
2111      //------------------------------------------------------------------
2112      // Common operators.
2113      //------------------------------------------------------------------
2114      case IrOpcode::kStart:
2115        // We use Start as a terminator for the frame state chain, so even
2116        // tho Start doesn't really produce a value, we have to say Tagged
2117        // here, otherwise the input conversion will fail.
2118        return VisitLeaf<T>(node, MachineRepresentation::kTagged);
2119      case IrOpcode::kParameter:
2120        return VisitUnop<T>(node, UseInfo::None(),
2121                            linkage()
2122                                ->GetParameterType(ParameterIndexOf(node->op()))
2123                                .representation());
2124      case IrOpcode::kInt32Constant:
2125        return VisitLeaf<T>(node, MachineRepresentation::kWord32);
2126      case IrOpcode::kInt64Constant:
2127        return VisitLeaf<T>(node, MachineRepresentation::kWord64);
2128      case IrOpcode::kExternalConstant:
2129        return VisitLeaf<T>(node, MachineType::PointerRepresentation());
2130      case IrOpcode::kNumberConstant: {
2131        double const value = OpParameter<double>(node->op());
2132        int value_as_int;
2133        if (DoubleToSmiInteger(value, &value_as_int)) {
2134          VisitLeaf<T>(node, MachineRepresentation::kTaggedSigned);
2135          if (lower<T>()) {
2136            intptr_t smi = bit_cast<intptr_t>(Smi::FromInt(value_as_int));
2137            Node* constant = InsertTypeOverrideForVerifier(
2138                NodeProperties::GetType(node),
2139                lowering->jsgraph()->IntPtrConstant(smi));
2140            DeferReplacement(node, constant);
2141          }
2142          return;
2143        }
2144        VisitLeaf<T>(node, MachineRepresentation::kTagged);
2145        return;
2146      }
2147      case IrOpcode::kHeapConstant:
2148      case IrOpcode::kDelayedStringConstant:
2149        return VisitLeaf<T>(node, MachineRepresentation::kTaggedPointer);
2150      case IrOpcode::kPointerConstant: {
2151        VisitLeaf<T>(node, MachineType::PointerRepresentation());
2152        if (lower<T>()) {
2153          intptr_t const value = OpParameter<intptr_t>(node->op());
2154          DeferReplacement(node, lowering->jsgraph()->IntPtrConstant(value));
2155        }
2156        return;
2157      }
2158
2159      case IrOpcode::kBranch: {
2160        DCHECK(TypeOf(node->InputAt(0)).Is(Type::Boolean()));
2161        ProcessInput<T>(node, 0, UseInfo::Bool());
2162        EnqueueInput<T>(node, NodeProperties::FirstControlIndex(node));
2163        return;
2164      }
2165      case IrOpcode::kSwitch:
2166        ProcessInput<T>(node, 0, UseInfo::TruncatingWord32());
2167        EnqueueInput<T>(node, NodeProperties::FirstControlIndex(node));
2168        return;
2169      case IrOpcode::kSelect:
2170        return VisitSelect<T>(node, truncation, lowering);
2171      case IrOpcode::kPhi:
2172        return VisitPhi<T>(node, truncation, lowering);
2173      case IrOpcode::kCall:
2174        return VisitCall<T>(node, lowering);
2175
2176      //------------------------------------------------------------------
2177      // JavaScript operators.
2178      //------------------------------------------------------------------
2179      case IrOpcode::kJSToNumber:
2180      case IrOpcode::kJSToNumberConvertBigInt:
2181      case IrOpcode::kJSToNumeric: {
2182        DCHECK(NodeProperties::GetType(node).Is(Type::Union(
2183            Type::BigInt(), Type::NumberOrOddball(), graph()->zone())));
2184        VisitInputs<T>(node);
2185        // TODO(bmeurer): Optimize somewhat based on input type?
2186        if (truncation.IsUsedAsWord32()) {
2187          SetOutput<T>(node, MachineRepresentation::kWord32);
2188          if (lower<T>())
2189            lowering->DoJSToNumberOrNumericTruncatesToWord32(node, this);
2190        } else if (truncation.TruncatesOddballAndBigIntToNumber()) {
2191          SetOutput<T>(node, MachineRepresentation::kFloat64);
2192          if (lower<T>())
2193            lowering->DoJSToNumberOrNumericTruncatesToFloat64(node, this);
2194        } else {
2195          SetOutput<T>(node, MachineRepresentation::kTagged);
2196        }
2197        return;
2198      }
2199
2200      //------------------------------------------------------------------
2201      // Simplified operators.
2202      //------------------------------------------------------------------
2203      case IrOpcode::kToBoolean: {
2204        if (truncation.IsUsedAsBool()) {
2205          ProcessInput<T>(node, 0, UseInfo::Bool());
2206          SetOutput<T>(node, MachineRepresentation::kBit);
2207          if (lower<T>()) DeferReplacement(node, node->InputAt(0));
2208        } else {
2209          VisitInputs<T>(node);
2210          SetOutput<T>(node, MachineRepresentation::kTaggedPointer);
2211        }
2212        return;
2213      }
2214      case IrOpcode::kBooleanNot: {
2215        if (lower<T>()) {
2216          NodeInfo* input_info = GetInfo(node->InputAt(0));
2217          if (input_info->representation() == MachineRepresentation::kBit) {
2218            // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
2219            node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
2220            ChangeOp(node, lowering->machine()->Word32Equal());
2221          } else if (CanBeTaggedPointer(input_info->representation())) {
2222            // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
2223            node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
2224            ChangeOp(node, lowering->machine()->WordEqual());
2225          } else {
2226            DCHECK(TypeOf(node->InputAt(0)).IsNone());
2227            DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
2228          }
2229        } else {
2230          // No input representation requirement; adapt during lowering.
2231          ProcessInput<T>(node, 0, UseInfo::AnyTruncatingToBool());
2232          SetOutput<T>(node, MachineRepresentation::kBit);
2233        }
2234        return;
2235      }
2236      case IrOpcode::kNumberEqual: {
2237        Type const lhs_type = TypeOf(node->InputAt(0));
2238        Type const rhs_type = TypeOf(node->InputAt(1));
2239        // Regular number comparisons in JavaScript generally identify zeros,
2240        // so we always pass kIdentifyZeros for the inputs, and in addition
2241        // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs.
2242        // For equality we also handle the case that one side is non-zero, in
2243        // which case we allow to truncate NaN to 0 on the other side.
2244        if ((lhs_type.Is(Type::Unsigned32OrMinusZero()) &&
2245             rhs_type.Is(Type::Unsigned32OrMinusZero())) ||
2246            (lhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
2247             rhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
2248             OneInputCannotBe(node, type_cache_->kZeroish))) {
2249          // => unsigned Int32Cmp
2250          VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2251                        MachineRepresentation::kBit);
2252          if (lower<T>()) ChangeOp(node, Uint32Op(node));
2253          return;
2254        }
2255        if ((lhs_type.Is(Type::Signed32OrMinusZero()) &&
2256             rhs_type.Is(Type::Signed32OrMinusZero())) ||
2257            (lhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) &&
2258             rhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) &&
2259             OneInputCannotBe(node, type_cache_->kZeroish))) {
2260          // => signed Int32Cmp
2261          VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2262                        MachineRepresentation::kBit);
2263          if (lower<T>()) ChangeOp(node, Int32Op(node));
2264          return;
2265        }
2266        // => Float64Cmp
2267        VisitBinop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
2268                      MachineRepresentation::kBit);
2269        if (lower<T>()) ChangeOp(node, Float64Op(node));
2270        return;
2271      }
2272      case IrOpcode::kNumberLessThan:
2273      case IrOpcode::kNumberLessThanOrEqual: {
2274        Type const lhs_type = TypeOf(node->InputAt(0));
2275        Type const rhs_type = TypeOf(node->InputAt(1));
2276        // Regular number comparisons in JavaScript generally identify zeros,
2277        // so we always pass kIdentifyZeros for the inputs, and in addition
2278        // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs.
2279        if (lhs_type.Is(Type::Unsigned32OrMinusZero()) &&
2280            rhs_type.Is(Type::Unsigned32OrMinusZero())) {
2281          // => unsigned Int32Cmp
2282          VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2283                        MachineRepresentation::kBit);
2284          if (lower<T>()) ChangeOp(node, Uint32Op(node));
2285        } else if (lhs_type.Is(Type::Signed32OrMinusZero()) &&
2286                   rhs_type.Is(Type::Signed32OrMinusZero())) {
2287          // => signed Int32Cmp
2288          VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2289                        MachineRepresentation::kBit);
2290          if (lower<T>()) ChangeOp(node, Int32Op(node));
2291        } else {
2292          // => Float64Cmp
2293          VisitBinop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
2294                        MachineRepresentation::kBit);
2295          if (lower<T>()) ChangeOp(node, Float64Op(node));
2296        }
2297        return;
2298      }
2299
2300      case IrOpcode::kSpeculativeSafeIntegerAdd:
2301      case IrOpcode::kSpeculativeSafeIntegerSubtract:
2302        return VisitSpeculativeIntegerAdditiveOp<T>(node, truncation, lowering);
2303
2304      case IrOpcode::kSpeculativeNumberAdd:
2305      case IrOpcode::kSpeculativeNumberSubtract:
2306        return VisitSpeculativeAdditiveOp<T>(node, truncation, lowering);
2307
2308      case IrOpcode::kSpeculativeNumberLessThan:
2309      case IrOpcode::kSpeculativeNumberLessThanOrEqual:
2310      case IrOpcode::kSpeculativeNumberEqual: {
2311        Type const lhs_type = TypeOf(node->InputAt(0));
2312        Type const rhs_type = TypeOf(node->InputAt(1));
2313        // Regular number comparisons in JavaScript generally identify zeros,
2314        // so we always pass kIdentifyZeros for the inputs, and in addition
2315        // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs.
2316        if (lhs_type.Is(Type::Unsigned32OrMinusZero()) &&
2317            rhs_type.Is(Type::Unsigned32OrMinusZero())) {
2318          // => unsigned Int32Cmp
2319          VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2320                        MachineRepresentation::kBit);
2321          if (lower<T>()) ChangeToPureOp(node, Uint32Op(node));
2322          return;
2323        } else if (lhs_type.Is(Type::Signed32OrMinusZero()) &&
2324                   rhs_type.Is(Type::Signed32OrMinusZero())) {
2325          // => signed Int32Cmp
2326          VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2327                        MachineRepresentation::kBit);
2328          if (lower<T>()) ChangeToPureOp(node, Int32Op(node));
2329          return;
2330        }
2331        // Try to use type feedback.
2332        NumberOperationHint hint = NumberOperationHintOf(node->op());
2333        switch (hint) {
2334          case NumberOperationHint::kSignedSmall:
2335            if (propagate<T>()) {
2336              VisitBinop<T>(
2337                  node, CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros),
2338                  MachineRepresentation::kBit);
2339            } else if (retype<T>()) {
2340              SetOutput<T>(node, MachineRepresentation::kBit, Type::Any());
2341            } else {
2342              DCHECK(lower<T>());
2343              Node* lhs = node->InputAt(0);
2344              Node* rhs = node->InputAt(1);
2345              if (IsNodeRepresentationTagged(lhs) &&
2346                  IsNodeRepresentationTagged(rhs)) {
2347                VisitBinop<T>(node,
2348                              UseInfo::CheckedSignedSmallAsTaggedSigned(
2349                                  FeedbackSource(), kIdentifyZeros),
2350                              MachineRepresentation::kBit);
2351                ChangeToPureOp(
2352                    node, changer_->TaggedSignedOperatorFor(node->opcode()));
2353
2354              } else {
2355                VisitBinop<T>(
2356                    node, CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros),
2357                    MachineRepresentation::kBit);
2358                ChangeToPureOp(node, Int32Op(node));
2359              }
2360            }
2361            return;
2362          case NumberOperationHint::kSignedSmallInputs:
2363            // This doesn't make sense for compare operations.
2364            UNREACHABLE();
2365          case NumberOperationHint::kNumberOrOddball:
2366            // Abstract and strict equality don't perform ToNumber conversions
2367            // on Oddballs, so make sure we don't accidentially sneak in a
2368            // hint with Oddball feedback here.
2369            DCHECK_NE(IrOpcode::kSpeculativeNumberEqual, node->opcode());
2370            V8_FALLTHROUGH;
2371          case NumberOperationHint::kNumberOrBoolean:
2372          case NumberOperationHint::kNumber:
2373            VisitBinop<T>(node,
2374                          CheckedUseInfoAsFloat64FromHint(
2375                              hint, FeedbackSource(), kIdentifyZeros),
2376                          MachineRepresentation::kBit);
2377            if (lower<T>()) ChangeToPureOp(node, Float64Op(node));
2378            return;
2379        }
2380        UNREACHABLE();
2381        return;
2382      }
2383
2384      case IrOpcode::kNumberAdd:
2385      case IrOpcode::kNumberSubtract: {
2386        if (TypeOf(node->InputAt(0))
2387                .Is(type_cache_->kAdditiveSafeIntegerOrMinusZero) &&
2388            TypeOf(node->InputAt(1))
2389                .Is(type_cache_->kAdditiveSafeIntegerOrMinusZero) &&
2390            (TypeOf(node).Is(Type::Signed32()) ||
2391             TypeOf(node).Is(Type::Unsigned32()) ||
2392             truncation.IsUsedAsWord32())) {
2393          // => Int32Add/Sub
2394          VisitWord32TruncatingBinop<T>(node);
2395          if (lower<T>()) ChangeToPureOp(node, Int32Op(node));
2396        } else if (jsgraph_->machine()->Is64() &&
2397                   BothInputsAre(node, type_cache_->kSafeInteger) &&
2398                   GetUpperBound(node).Is(type_cache_->kSafeInteger)) {
2399          // => Int64Add/Sub
2400          VisitInt64Binop<T>(node);
2401          if (lower<T>()) ChangeToPureOp(node, Int64Op(node));
2402        } else {
2403          // => Float64Add/Sub
2404          VisitFloat64Binop<T>(node);
2405          if (lower<T>()) ChangeToPureOp(node, Float64Op(node));
2406        }
2407        return;
2408      }
2409      case IrOpcode::kSpeculativeNumberMultiply: {
2410        if (BothInputsAre(node, Type::Integral32()) &&
2411            (NodeProperties::GetType(node).Is(Type::Signed32()) ||
2412             NodeProperties::GetType(node).Is(Type::Unsigned32()) ||
2413             (truncation.IsUsedAsWord32() &&
2414              NodeProperties::GetType(node).Is(
2415                  type_cache_->kSafeIntegerOrMinusZero)))) {
2416          // Multiply reduces to Int32Mul if the inputs are integers, and
2417          // (a) the output is either known to be Signed32, or
2418          // (b) the output is known to be Unsigned32, or
2419          // (c) the uses are truncating and the result is in the safe
2420          //     integer range.
2421          VisitWord32TruncatingBinop<T>(node);
2422          if (lower<T>()) ChangeToPureOp(node, Int32Op(node));
2423          return;
2424        }
2425        // Try to use type feedback.
2426        NumberOperationHint hint = NumberOperationHintOf(node->op());
2427        Type input0_type = TypeOf(node->InputAt(0));
2428        Type input1_type = TypeOf(node->InputAt(1));
2429
2430        // Handle the case when no int32 checks on inputs are necessary
2431        // (but an overflow check is needed on the output).
2432        if (BothInputsAre(node, Type::Signed32())) {
2433          // If both inputs and feedback are int32, use the overflow op.
2434          if (hint == NumberOperationHint::kSignedSmall) {
2435            VisitForCheckedInt32Mul<T>(node, truncation, input0_type,
2436                                       input1_type,
2437                                       UseInfo::TruncatingWord32());
2438            return;
2439          }
2440        }
2441
2442        if (hint == NumberOperationHint::kSignedSmall) {
2443          VisitForCheckedInt32Mul<T>(node, truncation, input0_type, input1_type,
2444                                     CheckedUseInfoAsWord32FromHint(hint));
2445          return;
2446        }
2447
2448        // Checked float64 x float64 => float64
2449        VisitBinop<T>(node,
2450                      UseInfo::CheckedNumberOrOddballAsFloat64(
2451                          kDistinguishZeros, FeedbackSource()),
2452                      MachineRepresentation::kFloat64, Type::Number());
2453        if (lower<T>()) ChangeToPureOp(node, Float64Op(node));
2454        return;
2455      }
2456      case IrOpcode::kNumberMultiply: {
2457        if (TypeOf(node->InputAt(0)).Is(Type::Integral32()) &&
2458            TypeOf(node->InputAt(1)).Is(Type::Integral32()) &&
2459            (TypeOf(node).Is(Type::Signed32()) ||
2460             TypeOf(node).Is(Type::Unsigned32()) ||
2461             (truncation.IsUsedAsWord32() &&
2462              TypeOf(node).Is(type_cache_->kSafeIntegerOrMinusZero)))) {
2463          // Multiply reduces to Int32Mul if the inputs are integers, and
2464          // (a) the output is either known to be Signed32, or
2465          // (b) the output is known to be Unsigned32, or
2466          // (c) the uses are truncating and the result is in the safe
2467          //     integer range.
2468          VisitWord32TruncatingBinop<T>(node);
2469          if (lower<T>()) ChangeToPureOp(node, Int32Op(node));
2470          return;
2471        }
2472        // Number x Number => Float64Mul
2473        VisitFloat64Binop<T>(node);
2474        if (lower<T>()) ChangeToPureOp(node, Float64Op(node));
2475        return;
2476      }
2477      case IrOpcode::kSpeculativeNumberDivide: {
2478        if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) {
2479          // => unsigned Uint32Div
2480          VisitWord32TruncatingBinop<T>(node);
2481          if (lower<T>()) DeferReplacement(node, lowering->Uint32Div(node));
2482          return;
2483        }
2484        if (BothInputsAreSigned32(node)) {
2485          if (NodeProperties::GetType(node).Is(Type::Signed32())) {
2486            // => signed Int32Div
2487            VisitWord32TruncatingBinop<T>(node);
2488            if (lower<T>()) DeferReplacement(node, lowering->Int32Div(node));
2489            return;
2490          }
2491          if (truncation.IsUsedAsWord32()) {
2492            // => signed Int32Div
2493            VisitWord32TruncatingBinop<T>(node);
2494            if (lower<T>()) DeferReplacement(node, lowering->Int32Div(node));
2495            return;
2496          }
2497        }
2498
2499        // Try to use type feedback.
2500        NumberOperationHint hint = NumberOperationHintOf(node->op());
2501
2502        // Handle the case when no uint32 checks on inputs are necessary
2503        // (but an overflow check is needed on the output).
2504        if (BothInputsAreUnsigned32(node)) {
2505          if (hint == NumberOperationHint::kSignedSmall) {
2506            VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2507                          MachineRepresentation::kWord32, Type::Unsigned32());
2508            if (lower<T>()) ChangeToUint32OverflowOp(node);
2509            return;
2510          }
2511        }
2512
2513        // Handle the case when no int32 checks on inputs are necessary
2514        // (but an overflow check is needed on the output).
2515        if (BothInputsAreSigned32(node)) {
2516          // If both the inputs the feedback are int32, use the overflow op.
2517          if (hint == NumberOperationHint::kSignedSmall) {
2518            VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2519                          MachineRepresentation::kWord32, Type::Signed32());
2520            if (lower<T>()) ChangeToInt32OverflowOp(node);
2521            return;
2522          }
2523        }
2524
2525        if (hint == NumberOperationHint::kSignedSmall ||
2526            hint == NumberOperationHint::kSignedSmallInputs) {
2527          // If the result is truncated, we only need to check the inputs.
2528          if (truncation.IsUsedAsWord32()) {
2529            VisitBinop<T>(node, CheckedUseInfoAsWord32FromHint(hint),
2530                          MachineRepresentation::kWord32);
2531            if (lower<T>()) DeferReplacement(node, lowering->Int32Div(node));
2532            return;
2533          } else if (hint != NumberOperationHint::kSignedSmallInputs) {
2534            VisitBinop<T>(node, CheckedUseInfoAsWord32FromHint(hint),
2535                          MachineRepresentation::kWord32, Type::Signed32());
2536            if (lower<T>()) ChangeToInt32OverflowOp(node);
2537            return;
2538          }
2539        }
2540
2541        // default case => Float64Div
2542        VisitBinop<T>(node,
2543                      UseInfo::CheckedNumberOrOddballAsFloat64(
2544                          kDistinguishZeros, FeedbackSource()),
2545                      MachineRepresentation::kFloat64, Type::Number());
2546        if (lower<T>()) ChangeToPureOp(node, Float64Op(node));
2547        return;
2548      }
2549      case IrOpcode::kNumberDivide: {
2550        if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) &&
2551            TypeOf(node->InputAt(1)).Is(Type::Unsigned32()) &&
2552            (truncation.IsUsedAsWord32() ||
2553             TypeOf(node).Is(Type::Unsigned32()))) {
2554          // => unsigned Uint32Div
2555          VisitWord32TruncatingBinop<T>(node);
2556          if (lower<T>()) DeferReplacement(node, lowering->Uint32Div(node));
2557          return;
2558        }
2559        if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) &&
2560            TypeOf(node->InputAt(1)).Is(Type::Signed32()) &&
2561            (truncation.IsUsedAsWord32() ||
2562             TypeOf(node).Is(Type::Signed32()))) {
2563          // => signed Int32Div
2564          VisitWord32TruncatingBinop<T>(node);
2565          if (lower<T>()) DeferReplacement(node, lowering->Int32Div(node));
2566          return;
2567        }
2568        // Number x Number => Float64Div
2569        VisitFloat64Binop<T>(node);
2570        if (lower<T>()) ChangeToPureOp(node, Float64Op(node));
2571        return;
2572      }
2573      case IrOpcode::kSpeculativeNumberModulus:
2574        return VisitSpeculativeNumberModulus<T>(node, truncation, lowering);
2575      case IrOpcode::kNumberModulus: {
2576        Type const lhs_type = TypeOf(node->InputAt(0));
2577        Type const rhs_type = TypeOf(node->InputAt(1));
2578        if ((lhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
2579             rhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN())) &&
2580            (truncation.IsUsedAsWord32() ||
2581             TypeOf(node).Is(Type::Unsigned32()))) {
2582          // => unsigned Uint32Mod
2583          VisitWord32TruncatingBinop<T>(node);
2584          if (lower<T>()) DeferReplacement(node, lowering->Uint32Mod(node));
2585          return;
2586        }
2587        if ((lhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) &&
2588             rhs_type.Is(Type::Signed32OrMinusZeroOrNaN())) &&
2589            (truncation.IsUsedAsWord32() || TypeOf(node).Is(Type::Signed32()) ||
2590             (truncation.IdentifiesZeroAndMinusZero() &&
2591              TypeOf(node).Is(Type::Signed32OrMinusZero())))) {
2592          // => signed Int32Mod
2593          VisitWord32TruncatingBinop<T>(node);
2594          if (lower<T>()) DeferReplacement(node, lowering->Int32Mod(node));
2595          return;
2596        }
2597        // => Float64Mod
2598        // For the left hand side we just propagate the identify zeros
2599        // mode of the {truncation}; and for modulus the sign of the
2600        // right hand side doesn't matter anyways, so in particular there's
2601        // no observable difference between a 0 and a -0 then.
2602        UseInfo const lhs_use =
2603            UseInfo::TruncatingFloat64(truncation.identify_zeros());
2604        UseInfo const rhs_use = UseInfo::TruncatingFloat64(kIdentifyZeros);
2605        VisitBinop<T>(node, lhs_use, rhs_use, MachineRepresentation::kFloat64);
2606        if (lower<T>()) ChangeToPureOp(node, Float64Op(node));
2607        return;
2608      }
2609      case IrOpcode::kNumberBitwiseOr:
2610      case IrOpcode::kNumberBitwiseXor:
2611      case IrOpcode::kNumberBitwiseAnd: {
2612        VisitWord32TruncatingBinop<T>(node);
2613        if (lower<T>()) ChangeOp(node, Int32Op(node));
2614        return;
2615      }
2616      case IrOpcode::kSpeculativeNumberBitwiseOr:
2617      case IrOpcode::kSpeculativeNumberBitwiseXor:
2618      case IrOpcode::kSpeculativeNumberBitwiseAnd:
2619        VisitSpeculativeInt32Binop<T>(node);
2620        if (lower<T>()) {
2621          ChangeToPureOp(node, Int32Op(node));
2622        }
2623        return;
2624      case IrOpcode::kNumberShiftLeft: {
2625        Type rhs_type = GetUpperBound(node->InputAt(1));
2626        VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2627                      UseInfo::TruncatingWord32(),
2628                      MachineRepresentation::kWord32);
2629        if (lower<T>()) {
2630          MaskShiftOperand(node, rhs_type);
2631          ChangeToPureOp(node, lowering->machine()->Word32Shl());
2632        }
2633        return;
2634      }
2635      case IrOpcode::kSpeculativeNumberShiftLeft: {
2636        if (BothInputsAre(node, Type::NumberOrOddball())) {
2637          Type rhs_type = GetUpperBound(node->InputAt(1));
2638          VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2639                        UseInfo::TruncatingWord32(),
2640                        MachineRepresentation::kWord32);
2641          if (lower<T>()) {
2642            MaskShiftOperand(node, rhs_type);
2643            ChangeToPureOp(node, lowering->machine()->Word32Shl());
2644          }
2645          return;
2646        }
2647        NumberOperationHint hint = NumberOperationHintOf(node->op());
2648        Type rhs_type = GetUpperBound(node->InputAt(1));
2649        VisitBinop<T>(node,
2650                      CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros),
2651                      MachineRepresentation::kWord32, Type::Signed32());
2652        if (lower<T>()) {
2653          MaskShiftOperand(node, rhs_type);
2654          ChangeToPureOp(node, lowering->machine()->Word32Shl());
2655        }
2656        return;
2657      }
2658      case IrOpcode::kNumberShiftRight: {
2659        Type rhs_type = GetUpperBound(node->InputAt(1));
2660        VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2661                      UseInfo::TruncatingWord32(),
2662                      MachineRepresentation::kWord32);
2663        if (lower<T>()) {
2664          MaskShiftOperand(node, rhs_type);
2665          ChangeToPureOp(node, lowering->machine()->Word32Sar());
2666        }
2667        return;
2668      }
2669      case IrOpcode::kSpeculativeNumberShiftRight: {
2670        if (BothInputsAre(node, Type::NumberOrOddball())) {
2671          Type rhs_type = GetUpperBound(node->InputAt(1));
2672          VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2673                        UseInfo::TruncatingWord32(),
2674                        MachineRepresentation::kWord32);
2675          if (lower<T>()) {
2676            MaskShiftOperand(node, rhs_type);
2677            ChangeToPureOp(node, lowering->machine()->Word32Sar());
2678          }
2679          return;
2680        }
2681        NumberOperationHint hint = NumberOperationHintOf(node->op());
2682        Type rhs_type = GetUpperBound(node->InputAt(1));
2683        VisitBinop<T>(node,
2684                      CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros),
2685                      MachineRepresentation::kWord32, Type::Signed32());
2686        if (lower<T>()) {
2687          MaskShiftOperand(node, rhs_type);
2688          ChangeToPureOp(node, lowering->machine()->Word32Sar());
2689        }
2690        return;
2691      }
2692      case IrOpcode::kNumberShiftRightLogical: {
2693        Type rhs_type = GetUpperBound(node->InputAt(1));
2694        VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2695                      UseInfo::TruncatingWord32(),
2696                      MachineRepresentation::kWord32);
2697        if (lower<T>()) {
2698          MaskShiftOperand(node, rhs_type);
2699          ChangeToPureOp(node, lowering->machine()->Word32Shr());
2700        }
2701        return;
2702      }
2703      case IrOpcode::kSpeculativeNumberShiftRightLogical: {
2704        NumberOperationHint hint = NumberOperationHintOf(node->op());
2705        Type rhs_type = GetUpperBound(node->InputAt(1));
2706        if (rhs_type.Is(type_cache_->kZeroish) &&
2707            hint == NumberOperationHint::kSignedSmall &&
2708            !truncation.IsUsedAsWord32()) {
2709          // The SignedSmall or Signed32 feedback means that the results that we
2710          // have seen so far were of type Unsigned31.  We speculate that this
2711          // will continue to hold.  Moreover, since the RHS is 0, the result
2712          // will just be the (converted) LHS.
2713          VisitBinop<T>(node,
2714                        CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros),
2715                        MachineRepresentation::kWord32, Type::Unsigned31());
2716          if (lower<T>()) {
2717            node->RemoveInput(1);
2718            ChangeOp(node,
2719                     simplified()->CheckedUint32ToInt32(FeedbackSource()));
2720          }
2721          return;
2722        }
2723        if (BothInputsAre(node, Type::NumberOrOddball())) {
2724          VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2725                        UseInfo::TruncatingWord32(),
2726                        MachineRepresentation::kWord32);
2727          if (lower<T>()) {
2728            MaskShiftOperand(node, rhs_type);
2729            ChangeToPureOp(node, lowering->machine()->Word32Shr());
2730          }
2731          return;
2732        }
2733        VisitBinop<T>(node,
2734                      CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros),
2735                      MachineRepresentation::kWord32, Type::Unsigned32());
2736        if (lower<T>()) {
2737          MaskShiftOperand(node, rhs_type);
2738          ChangeToPureOp(node, lowering->machine()->Word32Shr());
2739        }
2740        return;
2741      }
2742      case IrOpcode::kNumberAbs: {
2743        // NumberAbs maps both 0 and -0 to 0, so we can generally
2744        // pass the kIdentifyZeros truncation to its input, and
2745        // choose to ignore minus zero in all cases.
2746        Type const input_type = TypeOf(node->InputAt(0));
2747        if (input_type.Is(Type::Unsigned32OrMinusZero())) {
2748          VisitUnop<T>(node, UseInfo::TruncatingWord32(),
2749                       MachineRepresentation::kWord32);
2750          if (lower<T>()) DeferReplacement(node, node->InputAt(0));
2751        } else if (input_type.Is(Type::Signed32OrMinusZero())) {
2752          VisitUnop<T>(node, UseInfo::TruncatingWord32(),
2753                       MachineRepresentation::kWord32);
2754          if (lower<T>()) DeferReplacement(node, lowering->Int32Abs(node));
2755        } else if (input_type.Is(type_cache_->kPositiveIntegerOrNaN)) {
2756          VisitUnop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
2757                       MachineRepresentation::kFloat64);
2758          if (lower<T>()) DeferReplacement(node, node->InputAt(0));
2759        } else {
2760          VisitUnop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
2761                       MachineRepresentation::kFloat64);
2762          if (lower<T>()) ChangeOp(node, Float64Op(node));
2763        }
2764        return;
2765      }
2766      case IrOpcode::kNumberClz32: {
2767        VisitUnop<T>(node, UseInfo::TruncatingWord32(),
2768                     MachineRepresentation::kWord32);
2769        if (lower<T>()) ChangeOp(node, Uint32Op(node));
2770        return;
2771      }
2772      case IrOpcode::kNumberImul: {
2773        VisitBinop<T>(node, UseInfo::TruncatingWord32(),
2774                      UseInfo::TruncatingWord32(),
2775                      MachineRepresentation::kWord32);
2776        if (lower<T>()) ChangeOp(node, Uint32Op(node));
2777        return;
2778      }
2779      case IrOpcode::kNumberFround: {
2780        VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
2781                     MachineRepresentation::kFloat32);
2782        if (lower<T>()) ChangeOp(node, Float64Op(node));
2783        return;
2784      }
2785      case IrOpcode::kNumberMax: {
2786        // It is safe to use the feedback types for left and right hand side
2787        // here, since we can only narrow those types and thus we can only
2788        // promise a more specific truncation.
2789        // For NumberMax we generally propagate whether the truncation
2790        // identifies zeros to the inputs, and we choose to ignore minus
2791        // zero in those cases.
2792        Type const lhs_type = TypeOf(node->InputAt(0));
2793        Type const rhs_type = TypeOf(node->InputAt(1));
2794        if ((lhs_type.Is(Type::Unsigned32()) &&
2795             rhs_type.Is(Type::Unsigned32())) ||
2796            (lhs_type.Is(Type::Unsigned32OrMinusZero()) &&
2797             rhs_type.Is(Type::Unsigned32OrMinusZero()) &&
2798             truncation.IdentifiesZeroAndMinusZero())) {
2799          VisitWord32TruncatingBinop<T>(node);
2800          if (lower<T>()) {
2801            lowering->DoMax(node, lowering->machine()->Uint32LessThan(),
2802                            MachineRepresentation::kWord32);
2803          }
2804        } else if ((lhs_type.Is(Type::Signed32()) &&
2805                    rhs_type.Is(Type::Signed32())) ||
2806                   (lhs_type.Is(Type::Signed32OrMinusZero()) &&
2807                    rhs_type.Is(Type::Signed32OrMinusZero()) &&
2808                    truncation.IdentifiesZeroAndMinusZero())) {
2809          VisitWord32TruncatingBinop<T>(node);
2810          if (lower<T>()) {
2811            lowering->DoMax(node, lowering->machine()->Int32LessThan(),
2812                            MachineRepresentation::kWord32);
2813          }
2814        } else if (jsgraph_->machine()->Is64() &&
2815                   lhs_type.Is(type_cache_->kSafeInteger) &&
2816                   rhs_type.Is(type_cache_->kSafeInteger)) {
2817          VisitInt64Binop<T>(node);
2818          if (lower<T>()) {
2819            lowering->DoMax(node, lowering->machine()->Int64LessThan(),
2820                            MachineRepresentation::kWord64);
2821          }
2822        } else {
2823          VisitBinop<T>(node,
2824                        UseInfo::TruncatingFloat64(truncation.identify_zeros()),
2825                        MachineRepresentation::kFloat64);
2826          if (lower<T>()) {
2827            // If the right hand side is not NaN, and the left hand side
2828            // is not NaN (or -0 if the difference between the zeros is
2829            // observed), we can do a simple floating point comparison here.
2830            if (lhs_type.Is(truncation.IdentifiesZeroAndMinusZero()
2831                                ? Type::OrderedNumber()
2832                                : Type::PlainNumber()) &&
2833                rhs_type.Is(Type::OrderedNumber())) {
2834              lowering->DoMax(node, lowering->machine()->Float64LessThan(),
2835                              MachineRepresentation::kFloat64);
2836            } else {
2837              ChangeOp(node, Float64Op(node));
2838            }
2839          }
2840        }
2841        return;
2842      }
2843      case IrOpcode::kNumberMin: {
2844        // It is safe to use the feedback types for left and right hand side
2845        // here, since we can only narrow those types and thus we can only
2846        // promise a more specific truncation.
2847        // For NumberMin we generally propagate whether the truncation
2848        // identifies zeros to the inputs, and we choose to ignore minus
2849        // zero in those cases.
2850        Type const lhs_type = TypeOf(node->InputAt(0));
2851        Type const rhs_type = TypeOf(node->InputAt(1));
2852        if ((lhs_type.Is(Type::Unsigned32()) &&
2853             rhs_type.Is(Type::Unsigned32())) ||
2854            (lhs_type.Is(Type::Unsigned32OrMinusZero()) &&
2855             rhs_type.Is(Type::Unsigned32OrMinusZero()) &&
2856             truncation.IdentifiesZeroAndMinusZero())) {
2857          VisitWord32TruncatingBinop<T>(node);
2858          if (lower<T>()) {
2859            lowering->DoMin(node, lowering->machine()->Uint32LessThan(),
2860                            MachineRepresentation::kWord32);
2861          }
2862        } else if ((lhs_type.Is(Type::Signed32()) &&
2863                    rhs_type.Is(Type::Signed32())) ||
2864                   (lhs_type.Is(Type::Signed32OrMinusZero()) &&
2865                    rhs_type.Is(Type::Signed32OrMinusZero()) &&
2866                    truncation.IdentifiesZeroAndMinusZero())) {
2867          VisitWord32TruncatingBinop<T>(node);
2868          if (lower<T>()) {
2869            lowering->DoMin(node, lowering->machine()->Int32LessThan(),
2870                            MachineRepresentation::kWord32);
2871          }
2872        } else if (jsgraph_->machine()->Is64() &&
2873                   lhs_type.Is(type_cache_->kSafeInteger) &&
2874                   rhs_type.Is(type_cache_->kSafeInteger)) {
2875          VisitInt64Binop<T>(node);
2876          if (lower<T>()) {
2877            lowering->DoMin(node, lowering->machine()->Int64LessThan(),
2878                            MachineRepresentation::kWord64);
2879          }
2880        } else {
2881          VisitBinop<T>(node,
2882                        UseInfo::TruncatingFloat64(truncation.identify_zeros()),
2883                        MachineRepresentation::kFloat64);
2884          if (lower<T>()) {
2885            // If the left hand side is not NaN, and the right hand side
2886            // is not NaN (or -0 if the difference between the zeros is
2887            // observed), we can do a simple floating point comparison here.
2888            if (lhs_type.Is(Type::OrderedNumber()) &&
2889                rhs_type.Is(truncation.IdentifiesZeroAndMinusZero()
2890                                ? Type::OrderedNumber()
2891                                : Type::PlainNumber())) {
2892              lowering->DoMin(node,
2893                              lowering->machine()->Float64LessThanOrEqual(),
2894                              MachineRepresentation::kFloat64);
2895            } else {
2896              ChangeOp(node, Float64Op(node));
2897            }
2898          }
2899        }
2900        return;
2901      }
2902      case IrOpcode::kSpeculativeNumberPow: {
2903        // Checked float64 ** float64 => float64
2904        VisitBinop<T>(node,
2905                      UseInfo::CheckedNumberOrOddballAsFloat64(
2906                          kDistinguishZeros, FeedbackSource()),
2907                      MachineRepresentation::kFloat64, Type::Number());
2908        if (lower<T>()) ChangeToPureOp(node, Float64Op(node));
2909        return;
2910      }
2911      case IrOpcode::kNumberAtan2:
2912      case IrOpcode::kNumberPow: {
2913        VisitBinop<T>(node, UseInfo::TruncatingFloat64(),
2914                      MachineRepresentation::kFloat64);
2915        if (lower<T>()) ChangeOp(node, Float64Op(node));
2916        return;
2917      }
2918      case IrOpcode::kNumberCeil:
2919      case IrOpcode::kNumberFloor:
2920      case IrOpcode::kNumberRound:
2921      case IrOpcode::kNumberTrunc: {
2922        // For NumberCeil, NumberFloor, NumberRound and NumberTrunc we propagate
2923        // the zero identification part of the truncation, and we turn them into
2924        // no-ops if we figure out (late) that their input is already an
2925        // integer, NaN or -0.
2926        Type const input_type = TypeOf(node->InputAt(0));
2927        VisitUnop<T>(node,
2928                     UseInfo::TruncatingFloat64(truncation.identify_zeros()),
2929                     MachineRepresentation::kFloat64);
2930        if (lower<T>()) {
2931          if (input_type.Is(type_cache_->kIntegerOrMinusZeroOrNaN)) {
2932            DeferReplacement(node, node->InputAt(0));
2933          } else if (node->opcode() == IrOpcode::kNumberRound) {
2934            DeferReplacement(node, lowering->Float64Round(node));
2935          } else {
2936            ChangeOp(node, Float64Op(node));
2937          }
2938        }
2939        return;
2940      }
2941      case IrOpcode::kCheckBigInt: {
2942        if (InputIs(node, Type::BigInt())) {
2943          VisitNoop<T>(node, truncation);
2944        } else {
2945          VisitUnop<T>(node, UseInfo::AnyTagged(),
2946                       MachineRepresentation::kTaggedPointer);
2947        }
2948        return;
2949      }
2950      case IrOpcode::kSpeculativeBigIntAsIntN:
2951      case IrOpcode::kSpeculativeBigIntAsUintN: {
2952        const bool is_asuintn =
2953            node->opcode() == IrOpcode::kSpeculativeBigIntAsUintN;
2954        const auto p = SpeculativeBigIntAsNParametersOf(node->op());
2955        DCHECK_LE(0, p.bits());
2956        DCHECK_LE(p.bits(), 64);
2957
2958        ProcessInput<T>(node, 0,
2959                        UseInfo::CheckedBigIntTruncatingWord64(p.feedback()));
2960        SetOutput<T>(
2961            node, MachineRepresentation::kWord64,
2962            is_asuintn ? Type::UnsignedBigInt64() : Type::SignedBigInt64());
2963        if (lower<T>()) {
2964          if (p.bits() == 0) {
2965            DeferReplacement(
2966                node, InsertTypeOverrideForVerifier(Type::UnsignedBigInt63(),
2967                                                    jsgraph_->ZeroConstant()));
2968          } else if (p.bits() == 64) {
2969            DeferReplacement(node, node->InputAt(0));
2970          } else {
2971            if (is_asuintn) {
2972              const uint64_t mask = (1ULL << p.bits()) - 1ULL;
2973              ChangeUnaryToPureBinaryOp(node, lowering->machine()->Word64And(),
2974                                        1, jsgraph_->Int64Constant(mask));
2975            } else {
2976              // We truncate the value to N bits, but to correctly interpret
2977              // negative values, we have to fill the top (64-N) bits with the
2978              // sign. This is done by shifting the value left and then back
2979              // with an arithmetic right shift. E.g. for {value} =
2980              // 0..0'0001'1101 (29n) and N = 3: {shifted} is 1010'0000'0..0
2981              // after left shift by 61 bits, {unshifted} is 1..1'1111'1101
2982              // after arithmetic right shift by 61. This is the 64 bit
2983              // representation of -3 we expect for the signed 3 bit integer
2984              // 101.
2985              const uint64_t shift = 64 - p.bits();
2986              Node* value = node->InputAt(0);
2987              Node* shifted =
2988                  graph()->NewNode(lowering->machine()->Word64Shl(), value,
2989                                   jsgraph_->Uint64Constant(shift));
2990              Node* unshifted =
2991                  graph()->NewNode(lowering->machine()->Word64Sar(), shifted,
2992                                   jsgraph_->Uint64Constant(shift));
2993
2994              ReplaceWithPureNode(node, unshifted);
2995            }
2996          }
2997        }
2998        return;
2999      }
3000      case IrOpcode::kNumberAcos:
3001      case IrOpcode::kNumberAcosh:
3002      case IrOpcode::kNumberAsin:
3003      case IrOpcode::kNumberAsinh:
3004      case IrOpcode::kNumberAtan:
3005      case IrOpcode::kNumberAtanh:
3006      case IrOpcode::kNumberCos:
3007      case IrOpcode::kNumberCosh:
3008      case IrOpcode::kNumberExp:
3009      case IrOpcode::kNumberExpm1:
3010      case IrOpcode::kNumberLog:
3011      case IrOpcode::kNumberLog1p:
3012      case IrOpcode::kNumberLog2:
3013      case IrOpcode::kNumberLog10:
3014      case IrOpcode::kNumberCbrt:
3015      case IrOpcode::kNumberSin:
3016      case IrOpcode::kNumberSinh:
3017      case IrOpcode::kNumberTan:
3018      case IrOpcode::kNumberTanh: {
3019        VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3020                     MachineRepresentation::kFloat64);
3021        if (lower<T>()) ChangeOp(node, Float64Op(node));
3022        return;
3023      }
3024      case IrOpcode::kNumberSign: {
3025        if (InputIs(node, Type::Signed32())) {
3026          VisitUnop<T>(node, UseInfo::TruncatingWord32(),
3027                       MachineRepresentation::kWord32);
3028          if (lower<T>()) DeferReplacement(node, lowering->Int32Sign(node));
3029        } else {
3030          VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3031                       MachineRepresentation::kFloat64);
3032          if (lower<T>()) DeferReplacement(node, lowering->Float64Sign(node));
3033        }
3034        return;
3035      }
3036      case IrOpcode::kNumberSilenceNaN: {
3037        Type const input_type = TypeOf(node->InputAt(0));
3038        if (input_type.Is(Type::OrderedNumber())) {
3039          // No need to silence anything if the input cannot be NaN.
3040          VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3041                       MachineRepresentation::kFloat64);
3042          if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3043        } else {
3044          VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3045                       MachineRepresentation::kFloat64);
3046          if (lower<T>()) ChangeOp(node, Float64Op(node));
3047        }
3048        return;
3049      }
3050      case IrOpcode::kNumberSqrt: {
3051        VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3052                     MachineRepresentation::kFloat64);
3053        if (lower<T>()) ChangeOp(node, Float64Op(node));
3054        return;
3055      }
3056      case IrOpcode::kNumberToBoolean: {
3057        // For NumberToBoolean we don't care whether the input is 0 or
3058        // -0, since both of them are mapped to false anyways, so we
3059        // can generally pass kIdentifyZeros truncation.
3060        Type const input_type = TypeOf(node->InputAt(0));
3061        if (input_type.Is(Type::Integral32OrMinusZeroOrNaN())) {
3062          // 0, -0 and NaN all map to false, so we can safely truncate
3063          // all of them to zero here.
3064          VisitUnop<T>(node, UseInfo::TruncatingWord32(),
3065                       MachineRepresentation::kBit);
3066          if (lower<T>()) lowering->DoIntegral32ToBit(node);
3067        } else if (input_type.Is(Type::OrderedNumber())) {
3068          VisitUnop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
3069                       MachineRepresentation::kBit);
3070          if (lower<T>()) lowering->DoOrderedNumberToBit(node);
3071        } else {
3072          VisitUnop<T>(node, UseInfo::TruncatingFloat64(kIdentifyZeros),
3073                       MachineRepresentation::kBit);
3074          if (lower<T>()) lowering->DoNumberToBit(node);
3075        }
3076        return;
3077      }
3078      case IrOpcode::kNumberToInt32: {
3079        // Just change representation if necessary.
3080        VisitUnop<T>(node, UseInfo::TruncatingWord32(),
3081                     MachineRepresentation::kWord32);
3082        if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3083        return;
3084      }
3085      case IrOpcode::kNumberToString: {
3086        VisitUnop<T>(node, UseInfo::AnyTagged(),
3087                     MachineRepresentation::kTaggedPointer);
3088        return;
3089      }
3090      case IrOpcode::kNumberToUint32: {
3091        // Just change representation if necessary.
3092        VisitUnop<T>(node, UseInfo::TruncatingWord32(),
3093                     MachineRepresentation::kWord32);
3094        if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3095        return;
3096      }
3097      case IrOpcode::kNumberToUint8Clamped: {
3098        Type const input_type = TypeOf(node->InputAt(0));
3099        if (input_type.Is(type_cache_->kUint8OrMinusZeroOrNaN)) {
3100          VisitUnop<T>(node, UseInfo::TruncatingWord32(),
3101                       MachineRepresentation::kWord32);
3102          if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3103        } else if (input_type.Is(Type::Unsigned32OrMinusZeroOrNaN())) {
3104          VisitUnop<T>(node, UseInfo::TruncatingWord32(),
3105                       MachineRepresentation::kWord32);
3106          if (lower<T>()) lowering->DoUnsigned32ToUint8Clamped(node);
3107        } else if (input_type.Is(Type::Signed32OrMinusZeroOrNaN())) {
3108          VisitUnop<T>(node, UseInfo::TruncatingWord32(),
3109                       MachineRepresentation::kWord32);
3110          if (lower<T>()) lowering->DoSigned32ToUint8Clamped(node);
3111        } else if (input_type.Is(type_cache_->kIntegerOrMinusZeroOrNaN)) {
3112          VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3113                       MachineRepresentation::kFloat64);
3114          if (lower<T>()) lowering->DoIntegerToUint8Clamped(node);
3115        } else {
3116          VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3117                       MachineRepresentation::kFloat64);
3118          if (lower<T>()) lowering->DoNumberToUint8Clamped(node);
3119        }
3120        return;
3121      }
3122      case IrOpcode::kReferenceEqual: {
3123        VisitBinop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
3124        if (lower<T>()) {
3125          if (COMPRESS_POINTERS_BOOL) {
3126            ChangeOp(node, lowering->machine()->Word32Equal());
3127          } else {
3128            ChangeOp(node, lowering->machine()->WordEqual());
3129          }
3130        }
3131        return;
3132      }
3133      case IrOpcode::kSameValueNumbersOnly: {
3134        VisitBinop<T>(node, UseInfo::AnyTagged(),
3135                      MachineRepresentation::kTaggedPointer);
3136        return;
3137      }
3138      case IrOpcode::kSameValue: {
3139        if (truncation.IsUnused()) return VisitUnused<T>(node);
3140        if (BothInputsAre(node, Type::Number())) {
3141          VisitBinop<T>(node, UseInfo::TruncatingFloat64(),
3142                        MachineRepresentation::kBit);
3143          if (lower<T>()) {
3144            ChangeOp(node, lowering->simplified()->NumberSameValue());
3145          }
3146        } else {
3147          VisitBinop<T>(node, UseInfo::AnyTagged(),
3148                        MachineRepresentation::kTaggedPointer);
3149        }
3150        return;
3151      }
3152      case IrOpcode::kTypeOf: {
3153        return VisitUnop<T>(node, UseInfo::AnyTagged(),
3154                            MachineRepresentation::kTaggedPointer);
3155      }
3156      case IrOpcode::kNewConsString: {
3157        ProcessInput<T>(node, 0, UseInfo::TruncatingWord32());  // length
3158        ProcessInput<T>(node, 1, UseInfo::AnyTagged());         // first
3159        ProcessInput<T>(node, 2, UseInfo::AnyTagged());         // second
3160        SetOutput<T>(node, MachineRepresentation::kTaggedPointer);
3161        return;
3162      }
3163      case IrOpcode::kSpeculativeBigIntAdd: {
3164        // TODO(nicohartmann@, chromium:1073440): There should be special
3165        // handling for trunction.IsUnused() that correctly propagates deadness,
3166        // but preserves type checking which may throw exceptions. Until this
3167        // is fully supported, we lower to int64 operations but keep pushing
3168        // type constraints.
3169        if (truncation.IsUsedAsWord64()) {
3170          VisitBinop<T>(
3171              node, UseInfo::CheckedBigIntTruncatingWord64(FeedbackSource{}),
3172              MachineRepresentation::kWord64);
3173          if (lower<T>()) {
3174            ChangeToPureOp(node, lowering->machine()->Int64Add());
3175          }
3176        } else {
3177          VisitBinop<T>(node,
3178                        UseInfo::CheckedBigIntAsTaggedPointer(FeedbackSource{}),
3179                        MachineRepresentation::kTaggedPointer);
3180          if (lower<T>()) {
3181            ChangeOp(node, lowering->simplified()->BigIntAdd());
3182          }
3183        }
3184        return;
3185      }
3186      case IrOpcode::kSpeculativeBigIntSubtract: {
3187        if (truncation.IsUsedAsWord64()) {
3188          VisitBinop<T>(
3189              node, UseInfo::CheckedBigIntTruncatingWord64(FeedbackSource{}),
3190              MachineRepresentation::kWord64);
3191          if (lower<T>()) {
3192            ChangeToPureOp(node, lowering->machine()->Int64Sub());
3193          }
3194        } else {
3195          VisitBinop<T>(node,
3196                        UseInfo::CheckedBigIntAsTaggedPointer(FeedbackSource{}),
3197                        MachineRepresentation::kTaggedPointer);
3198          if (lower<T>()) {
3199            ChangeOp(node, lowering->simplified()->BigIntSubtract());
3200          }
3201        }
3202        return;
3203      }
3204      case IrOpcode::kSpeculativeBigIntNegate: {
3205        if (truncation.IsUsedAsWord64()) {
3206          VisitUnop<T>(node,
3207                       UseInfo::CheckedBigIntTruncatingWord64(FeedbackSource{}),
3208                       MachineRepresentation::kWord64);
3209          if (lower<T>()) {
3210            ChangeUnaryToPureBinaryOp(node, lowering->machine()->Int64Sub(), 0,
3211                                      jsgraph_->Int64Constant(0));
3212          }
3213        } else {
3214          VisitUnop<T>(node,
3215                       UseInfo::CheckedBigIntAsTaggedPointer(FeedbackSource{}),
3216                       MachineRepresentation::kTaggedPointer);
3217          if (lower<T>()) {
3218            ChangeToPureOp(node, lowering->simplified()->BigIntNegate());
3219          }
3220        }
3221        return;
3222      }
3223      case IrOpcode::kStringConcat: {
3224        // TODO(turbofan): We currently depend on having this first length input
3225        // to make sure that the overflow check is properly scheduled before the
3226        // actual string concatenation. We should also use the length to pass it
3227        // to the builtin or decide in optimized code how to construct the
3228        // resulting string (i.e. cons string or sequential string).
3229        ProcessInput<T>(node, 0, UseInfo::TaggedSigned());  // length
3230        ProcessInput<T>(node, 1, UseInfo::AnyTagged());     // first
3231        ProcessInput<T>(node, 2, UseInfo::AnyTagged());     // second
3232        SetOutput<T>(node, MachineRepresentation::kTaggedPointer);
3233        return;
3234      }
3235      case IrOpcode::kStringEqual:
3236      case IrOpcode::kStringLessThan:
3237      case IrOpcode::kStringLessThanOrEqual: {
3238        return VisitBinop<T>(node, UseInfo::AnyTagged(),
3239                             MachineRepresentation::kTaggedPointer);
3240      }
3241      case IrOpcode::kStringCharCodeAt: {
3242        return VisitBinop<T>(node, UseInfo::AnyTagged(), UseInfo::Word(),
3243                             MachineRepresentation::kWord32);
3244      }
3245      case IrOpcode::kStringCodePointAt: {
3246        return VisitBinop<T>(node, UseInfo::AnyTagged(), UseInfo::Word(),
3247                             MachineRepresentation::kWord32);
3248      }
3249      case IrOpcode::kStringFromSingleCharCode: {
3250        VisitUnop<T>(node, UseInfo::TruncatingWord32(),
3251                     MachineRepresentation::kTaggedPointer);
3252        return;
3253      }
3254      case IrOpcode::kStringFromSingleCodePoint: {
3255        VisitUnop<T>(node, UseInfo::TruncatingWord32(),
3256                     MachineRepresentation::kTaggedPointer);
3257        return;
3258      }
3259      case IrOpcode::kStringFromCodePointAt: {
3260        return VisitBinop<T>(node, UseInfo::AnyTagged(), UseInfo::Word(),
3261                             MachineRepresentation::kTaggedPointer);
3262      }
3263      case IrOpcode::kStringIndexOf: {
3264        ProcessInput<T>(node, 0, UseInfo::AnyTagged());
3265        ProcessInput<T>(node, 1, UseInfo::AnyTagged());
3266        ProcessInput<T>(node, 2, UseInfo::TaggedSigned());
3267        SetOutput<T>(node, MachineRepresentation::kTaggedSigned);
3268        return;
3269      }
3270      case IrOpcode::kStringLength: {
3271        // TODO(bmeurer): The input representation should be TaggedPointer.
3272        // Fix this once we have a dedicated StringConcat/JSStringAdd
3273        // operator, which marks it's output as TaggedPointer properly.
3274        VisitUnop<T>(node, UseInfo::AnyTagged(),
3275                     MachineRepresentation::kWord32);
3276        return;
3277      }
3278      case IrOpcode::kStringSubstring: {
3279        ProcessInput<T>(node, 0, UseInfo::AnyTagged());
3280        ProcessInput<T>(node, 1, UseInfo::TruncatingWord32());
3281        ProcessInput<T>(node, 2, UseInfo::TruncatingWord32());
3282        ProcessRemainingInputs<T>(node, 3);
3283        SetOutput<T>(node, MachineRepresentation::kTaggedPointer);
3284        return;
3285      }
3286      case IrOpcode::kStringToLowerCaseIntl:
3287      case IrOpcode::kStringToUpperCaseIntl: {
3288        VisitUnop<T>(node, UseInfo::AnyTagged(),
3289                     MachineRepresentation::kTaggedPointer);
3290        return;
3291      }
3292      case IrOpcode::kCheckBounds:
3293        return VisitCheckBounds<T>(node, lowering);
3294      case IrOpcode::kCheckHeapObject: {
3295        if (InputCannotBe(node, Type::SignedSmall())) {
3296          VisitUnop<T>(node, UseInfo::AnyTagged(),
3297                       MachineRepresentation::kTaggedPointer);
3298        } else {
3299          VisitUnop<T>(
3300              node, UseInfo::CheckedHeapObjectAsTaggedPointer(FeedbackSource()),
3301              MachineRepresentation::kTaggedPointer);
3302        }
3303        if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3304        return;
3305      }
3306      case IrOpcode::kCheckIf: {
3307        ProcessInput<T>(node, 0, UseInfo::Bool());
3308        ProcessRemainingInputs<T>(node, 1);
3309        SetOutput<T>(node, MachineRepresentation::kNone);
3310        return;
3311      }
3312      case IrOpcode::kCheckInternalizedString: {
3313        VisitCheck<T>(node, Type::InternalizedString(), lowering);
3314        return;
3315      }
3316      case IrOpcode::kCheckNumber: {
3317        Type const input_type = TypeOf(node->InputAt(0));
3318        if (input_type.Is(Type::Number())) {
3319          VisitNoop<T>(node, truncation);
3320        } else {
3321          VisitUnop<T>(node, UseInfo::AnyTagged(),
3322                       MachineRepresentation::kTagged);
3323        }
3324        return;
3325      }
3326      case IrOpcode::kCheckReceiver: {
3327        VisitCheck<T>(node, Type::Receiver(), lowering);
3328        return;
3329      }
3330      case IrOpcode::kCheckReceiverOrNullOrUndefined: {
3331        VisitCheck<T>(node, Type::ReceiverOrNullOrUndefined(), lowering);
3332        return;
3333      }
3334      case IrOpcode::kCheckSmi: {
3335        const CheckParameters& params = CheckParametersOf(node->op());
3336        if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) {
3337          VisitUnop<T>(node,
3338                       UseInfo::CheckedSignedSmallAsWord32(kDistinguishZeros,
3339                                                           params.feedback()),
3340                       MachineRepresentation::kWord32);
3341        } else {
3342          VisitUnop<T>(
3343              node,
3344              UseInfo::CheckedSignedSmallAsTaggedSigned(params.feedback()),
3345              MachineRepresentation::kTaggedSigned);
3346        }
3347        if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3348        return;
3349      }
3350      case IrOpcode::kCheckString: {
3351        const CheckParameters& params = CheckParametersOf(node->op());
3352        if (InputIs(node, Type::String())) {
3353          VisitUnop<T>(node, UseInfo::AnyTagged(),
3354                       MachineRepresentation::kTaggedPointer);
3355          if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3356        } else {
3357          VisitUnop<T>(
3358              node,
3359              UseInfo::CheckedHeapObjectAsTaggedPointer(params.feedback()),
3360              MachineRepresentation::kTaggedPointer);
3361        }
3362        return;
3363      }
3364      case IrOpcode::kCheckSymbol: {
3365        VisitCheck<T>(node, Type::Symbol(), lowering);
3366        return;
3367      }
3368
3369      case IrOpcode::kAllocate: {
3370        ProcessInput<T>(node, 0, UseInfo::Word());
3371        ProcessRemainingInputs<T>(node, 1);
3372        SetOutput<T>(node, MachineRepresentation::kTaggedPointer);
3373        return;
3374      }
3375      case IrOpcode::kLoadFramePointer: {
3376        SetOutput<T>(node, MachineType::PointerRepresentation());
3377        return;
3378      }
3379      case IrOpcode::kLoadMessage: {
3380        if (truncation.IsUnused()) return VisitUnused<T>(node);
3381        VisitUnop<T>(node, UseInfo::Word(), MachineRepresentation::kTagged);
3382        return;
3383      }
3384      case IrOpcode::kStoreMessage: {
3385        ProcessInput<T>(node, 0, UseInfo::Word());
3386        ProcessInput<T>(node, 1, UseInfo::AnyTagged());
3387        ProcessRemainingInputs<T>(node, 2);
3388        SetOutput<T>(node, MachineRepresentation::kNone);
3389        return;
3390      }
3391      case IrOpcode::kLoadFieldByIndex: {
3392        if (truncation.IsUnused()) return VisitUnused<T>(node);
3393        VisitBinop<T>(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
3394                      MachineRepresentation::kTagged);
3395        return;
3396      }
3397      case IrOpcode::kLoadField: {
3398        if (truncation.IsUnused()) return VisitUnused<T>(node);
3399        FieldAccess access = FieldAccessOf(node->op());
3400        MachineRepresentation const representation =
3401            access.machine_type.representation();
3402        VisitUnop<T>(node, UseInfoForBasePointer(access), representation);
3403        return;
3404      }
3405      case IrOpcode::kStoreField: {
3406        FieldAccess access = FieldAccessOf(node->op());
3407        Node* value_node = node->InputAt(1);
3408        NodeInfo* input_info = GetInfo(value_node);
3409        MachineRepresentation field_representation =
3410            access.machine_type.representation();
3411
3412        // Convert to Smi if possible, such that we can avoid a write barrier.
3413        if (field_representation == MachineRepresentation::kTagged &&
3414            TypeOf(value_node).Is(Type::SignedSmall())) {
3415          field_representation = MachineRepresentation::kTaggedSigned;
3416        }
3417        WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
3418            access.base_is_tagged, field_representation, access.offset,
3419            access.type, input_info->representation(), value_node);
3420
3421        ProcessInput<T>(node, 0, UseInfoForBasePointer(access));
3422        ProcessInput<T>(
3423            node, 1, TruncatingUseInfoFromRepresentation(field_representation));
3424        ProcessRemainingInputs<T>(node, 2);
3425        SetOutput<T>(node, MachineRepresentation::kNone);
3426        if (lower<T>()) {
3427          if (write_barrier_kind < access.write_barrier_kind) {
3428            access.write_barrier_kind = write_barrier_kind;
3429            ChangeOp(node, jsgraph_->simplified()->StoreField(access));
3430          }
3431        }
3432        return;
3433      }
3434      case IrOpcode::kLoadElement: {
3435        if (truncation.IsUnused()) return VisitUnused<T>(node);
3436        ElementAccess access = ElementAccessOf(node->op());
3437        VisitBinop<T>(node, UseInfoForBasePointer(access), UseInfo::Word(),
3438                      access.machine_type.representation());
3439        return;
3440      }
3441      case IrOpcode::kLoadStackArgument: {
3442        if (truncation.IsUnused()) return VisitUnused<T>(node);
3443        VisitBinop<T>(node, UseInfo::Word(), MachineRepresentation::kTagged);
3444        return;
3445      }
3446      case IrOpcode::kStoreElement: {
3447        ElementAccess access = ElementAccessOf(node->op());
3448        Node* value_node = node->InputAt(2);
3449        NodeInfo* input_info = GetInfo(value_node);
3450        MachineRepresentation element_representation =
3451            access.machine_type.representation();
3452
3453        // Convert to Smi if possible, such that we can avoid a write barrier.
3454        if (element_representation == MachineRepresentation::kTagged &&
3455            TypeOf(value_node).Is(Type::SignedSmall())) {
3456          element_representation = MachineRepresentation::kTaggedSigned;
3457        }
3458        WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
3459            access.base_is_tagged, element_representation, access.type,
3460            input_info->representation(), value_node);
3461        ProcessInput<T>(node, 0, UseInfoForBasePointer(access));  // base
3462        ProcessInput<T>(node, 1, UseInfo::Word());                // index
3463        ProcessInput<T>(node, 2,
3464                        TruncatingUseInfoFromRepresentation(
3465                            element_representation));  // value
3466        ProcessRemainingInputs<T>(node, 3);
3467        SetOutput<T>(node, MachineRepresentation::kNone);
3468        if (lower<T>()) {
3469          if (write_barrier_kind < access.write_barrier_kind) {
3470            access.write_barrier_kind = write_barrier_kind;
3471            ChangeOp(node, jsgraph_->simplified()->StoreElement(access));
3472          }
3473        }
3474        return;
3475      }
3476      case IrOpcode::kNumberIsFloat64Hole: {
3477        VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3478                     MachineRepresentation::kBit);
3479        return;
3480      }
3481      case IrOpcode::kTransitionAndStoreElement: {
3482        Type value_type = TypeOf(node->InputAt(2));
3483
3484        ProcessInput<T>(node, 0, UseInfo::AnyTagged());  // array
3485        ProcessInput<T>(node, 1, UseInfo::Word());       // index
3486
3487        if (value_type.Is(Type::SignedSmall())) {
3488          ProcessInput<T>(node, 2, UseInfo::TruncatingWord32());  // value
3489          if (lower<T>()) {
3490            ChangeOp(node, simplified()->StoreSignedSmallElement());
3491          }
3492        } else if (value_type.Is(Type::Number())) {
3493          ProcessInput<T>(node, 2, UseInfo::TruncatingFloat64());  // value
3494          if (lower<T>()) {
3495            Handle<Map> double_map = DoubleMapParameterOf(node->op());
3496            ChangeOp(node,
3497                     simplified()->TransitionAndStoreNumberElement(double_map));
3498          }
3499        } else if (value_type.Is(Type::NonNumber())) {
3500          ProcessInput<T>(node, 2, UseInfo::AnyTagged());  // value
3501          if (lower<T>()) {
3502            Handle<Map> fast_map = FastMapParameterOf(node->op());
3503            ChangeOp(node, simplified()->TransitionAndStoreNonNumberElement(
3504                               fast_map, value_type));
3505          }
3506        } else {
3507          ProcessInput<T>(node, 2, UseInfo::AnyTagged());  // value
3508        }
3509
3510        ProcessRemainingInputs<T>(node, 3);
3511        SetOutput<T>(node, MachineRepresentation::kNone);
3512        return;
3513      }
3514      case IrOpcode::kLoadTypedElement: {
3515        MachineRepresentation const rep =
3516            MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
3517        ProcessInput<T>(node, 0, UseInfo::AnyTagged());  // buffer
3518        ProcessInput<T>(node, 1, UseInfo::AnyTagged());  // base pointer
3519        ProcessInput<T>(node, 2, UseInfo::Word());       // external pointer
3520        ProcessInput<T>(node, 3, UseInfo::Word());       // index
3521        ProcessRemainingInputs<T>(node, 4);
3522        SetOutput<T>(node, rep);
3523        return;
3524      }
3525      case IrOpcode::kLoadDataViewElement: {
3526        MachineRepresentation const rep =
3527            MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
3528        ProcessInput<T>(node, 0, UseInfo::AnyTagged());  // object
3529        ProcessInput<T>(node, 1, UseInfo::Word());       // base
3530        ProcessInput<T>(node, 2, UseInfo::Word());       // index
3531        ProcessInput<T>(node, 3, UseInfo::Bool());       // little-endian
3532        ProcessRemainingInputs<T>(node, 4);
3533        SetOutput<T>(node, rep);
3534        return;
3535      }
3536      case IrOpcode::kStoreTypedElement: {
3537        MachineRepresentation const rep =
3538            MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
3539        ProcessInput<T>(node, 0, UseInfo::AnyTagged());  // buffer
3540        ProcessInput<T>(node, 1, UseInfo::AnyTagged());  // base pointer
3541        ProcessInput<T>(node, 2, UseInfo::Word());       // external pointer
3542        ProcessInput<T>(node, 3, UseInfo::Word());       // index
3543        ProcessInput<T>(node, 4,
3544                        TruncatingUseInfoFromRepresentation(rep));  // value
3545        ProcessRemainingInputs<T>(node, 5);
3546        SetOutput<T>(node, MachineRepresentation::kNone);
3547        return;
3548      }
3549      case IrOpcode::kStoreDataViewElement: {
3550        MachineRepresentation const rep =
3551            MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
3552        ProcessInput<T>(node, 0, UseInfo::AnyTagged());  // object
3553        ProcessInput<T>(node, 1, UseInfo::Word());       // base
3554        ProcessInput<T>(node, 2, UseInfo::Word());       // index
3555        ProcessInput<T>(node, 3,
3556                        TruncatingUseInfoFromRepresentation(rep));  // value
3557        ProcessInput<T>(node, 4, UseInfo::Bool());  // little-endian
3558        ProcessRemainingInputs<T>(node, 5);
3559        SetOutput<T>(node, MachineRepresentation::kNone);
3560        return;
3561      }
3562      case IrOpcode::kConvertReceiver: {
3563        Type input_type = TypeOf(node->InputAt(0));
3564        VisitBinop<T>(node, UseInfo::AnyTagged(),
3565                      MachineRepresentation::kTaggedPointer);
3566        if (lower<T>()) {
3567          // Try to optimize the {node} based on the input type.
3568          if (input_type.Is(Type::Receiver())) {
3569            DeferReplacement(node, node->InputAt(0));
3570          } else if (input_type.Is(Type::NullOrUndefined())) {
3571            DeferReplacement(node, node->InputAt(1));
3572          } else if (!input_type.Maybe(Type::NullOrUndefined())) {
3573            ChangeOp(node, lowering->simplified()->ConvertReceiver(
3574                               ConvertReceiverMode::kNotNullOrUndefined));
3575          }
3576        }
3577        return;
3578      }
3579      case IrOpcode::kPlainPrimitiveToNumber: {
3580        if (InputIs(node, Type::Boolean())) {
3581          VisitUnop<T>(node, UseInfo::Bool(), MachineRepresentation::kWord32);
3582          if (lower<T>()) {
3583            ChangeToSemanticsHintForVerifier(node, node->op());
3584          }
3585        } else if (InputIs(node, Type::String())) {
3586          VisitUnop<T>(node, UseInfo::AnyTagged(),
3587                       MachineRepresentation::kTagged);
3588          if (lower<T>()) {
3589            ChangeOp(node, simplified()->StringToNumber());
3590          }
3591        } else if (truncation.IsUsedAsWord32()) {
3592          if (InputIs(node, Type::NumberOrOddball())) {
3593            VisitUnop<T>(node, UseInfo::TruncatingWord32(),
3594                         MachineRepresentation::kWord32);
3595            if (lower<T>()) {
3596              ChangeToSemanticsHintForVerifier(node, node->op());
3597            }
3598          } else {
3599            VisitUnop<T>(node, UseInfo::AnyTagged(),
3600                         MachineRepresentation::kWord32);
3601            if (lower<T>()) {
3602              ChangeOp(node, simplified()->PlainPrimitiveToWord32());
3603            }
3604          }
3605        } else if (truncation.TruncatesOddballAndBigIntToNumber()) {
3606          if (InputIs(node, Type::NumberOrOddball())) {
3607            VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3608                         MachineRepresentation::kFloat64);
3609            if (lower<T>()) {
3610              ChangeToSemanticsHintForVerifier(node, node->op());
3611            }
3612          } else {
3613            VisitUnop<T>(node, UseInfo::AnyTagged(),
3614                         MachineRepresentation::kFloat64);
3615            if (lower<T>()) {
3616              ChangeOp(node, simplified()->PlainPrimitiveToFloat64());
3617            }
3618          }
3619        } else {
3620          VisitUnop<T>(node, UseInfo::AnyTagged(),
3621                       MachineRepresentation::kTagged);
3622        }
3623        return;
3624      }
3625      case IrOpcode::kSpeculativeToNumber: {
3626        NumberOperationParameters const& p =
3627            NumberOperationParametersOf(node->op());
3628        switch (p.hint()) {
3629          case NumberOperationHint::kSignedSmall:
3630          case NumberOperationHint::kSignedSmallInputs:
3631            VisitUnop<T>(node,
3632                         CheckedUseInfoAsWord32FromHint(
3633                             p.hint(), kDistinguishZeros, p.feedback()),
3634                         MachineRepresentation::kWord32, Type::Signed32());
3635            break;
3636          case NumberOperationHint::kNumber:
3637          case NumberOperationHint::kNumberOrBoolean:
3638          case NumberOperationHint::kNumberOrOddball:
3639            VisitUnop<T>(
3640                node, CheckedUseInfoAsFloat64FromHint(p.hint(), p.feedback()),
3641                MachineRepresentation::kFloat64);
3642            break;
3643        }
3644        if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3645        return;
3646      }
3647      case IrOpcode::kObjectIsArrayBufferView: {
3648        // TODO(turbofan): Introduce a Type::ArrayBufferView?
3649        VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
3650        return;
3651      }
3652      case IrOpcode::kObjectIsBigInt: {
3653        VisitObjectIs<T>(node, Type::BigInt(), lowering);
3654        return;
3655      }
3656      case IrOpcode::kObjectIsCallable: {
3657        VisitObjectIs<T>(node, Type::Callable(), lowering);
3658        return;
3659      }
3660      case IrOpcode::kObjectIsConstructor: {
3661        // TODO(turbofan): Introduce a Type::Constructor?
3662        VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
3663        return;
3664      }
3665      case IrOpcode::kObjectIsDetectableCallable: {
3666        VisitObjectIs<T>(node, Type::DetectableCallable(), lowering);
3667        return;
3668      }
3669      case IrOpcode::kObjectIsFiniteNumber: {
3670        Type const input_type = GetUpperBound(node->InputAt(0));
3671        if (input_type.Is(type_cache_->kSafeInteger)) {
3672          VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit);
3673          if (lower<T>()) {
3674            DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
3675          }
3676        } else if (!input_type.Maybe(Type::Number())) {
3677          VisitUnop<T>(node, UseInfo::Any(), MachineRepresentation::kBit);
3678          if (lower<T>()) {
3679            DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
3680          }
3681        } else if (input_type.Is(Type::Number())) {
3682          VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3683                       MachineRepresentation::kBit);
3684          if (lower<T>()) {
3685            ChangeOp(node, lowering->simplified()->NumberIsFinite());
3686          }
3687        } else {
3688          VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
3689        }
3690        return;
3691      }
3692      case IrOpcode::kNumberIsFinite: {
3693        VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3694                     MachineRepresentation::kBit);
3695        return;
3696      }
3697      case IrOpcode::kObjectIsSafeInteger: {
3698        Type const input_type = GetUpperBound(node->InputAt(0));
3699        if (input_type.Is(type_cache_->kSafeInteger)) {
3700          VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit);
3701          if (lower<T>()) {
3702            DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
3703          }
3704        } else if (!input_type.Maybe(Type::Number())) {
3705          VisitUnop<T>(node, UseInfo::Any(), MachineRepresentation::kBit);
3706          if (lower<T>()) {
3707            DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
3708          }
3709        } else if (input_type.Is(Type::Number())) {
3710          VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3711                       MachineRepresentation::kBit);
3712          if (lower<T>()) {
3713            ChangeOp(node, lowering->simplified()->NumberIsSafeInteger());
3714          }
3715        } else {
3716          VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
3717        }
3718        return;
3719      }
3720      case IrOpcode::kNumberIsSafeInteger: {
3721        UNREACHABLE();
3722      }
3723      case IrOpcode::kObjectIsInteger: {
3724        Type const input_type = GetUpperBound(node->InputAt(0));
3725        if (input_type.Is(type_cache_->kSafeInteger)) {
3726          VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit);
3727          if (lower<T>()) {
3728            DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
3729          }
3730        } else if (!input_type.Maybe(Type::Number())) {
3731          VisitUnop<T>(node, UseInfo::Any(), MachineRepresentation::kBit);
3732          if (lower<T>()) {
3733            DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
3734          }
3735        } else if (input_type.Is(Type::Number())) {
3736          VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3737                       MachineRepresentation::kBit);
3738          if (lower<T>()) {
3739            ChangeOp(node, lowering->simplified()->NumberIsInteger());
3740          }
3741        } else {
3742          VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
3743        }
3744        return;
3745      }
3746      case IrOpcode::kNumberIsInteger: {
3747        VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3748                     MachineRepresentation::kBit);
3749        return;
3750      }
3751      case IrOpcode::kObjectIsMinusZero: {
3752        Type const input_type = GetUpperBound(node->InputAt(0));
3753        if (input_type.Is(Type::MinusZero())) {
3754          VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit);
3755          if (lower<T>()) {
3756            DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
3757          }
3758        } else if (!input_type.Maybe(Type::MinusZero())) {
3759          VisitUnop<T>(node, UseInfo::Any(), MachineRepresentation::kBit);
3760          if (lower<T>()) {
3761            DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
3762          }
3763        } else if (input_type.Is(Type::Number())) {
3764          VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3765                       MachineRepresentation::kBit);
3766          if (lower<T>()) {
3767            ChangeOp(node, simplified()->NumberIsMinusZero());
3768          }
3769        } else {
3770          VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
3771        }
3772        return;
3773      }
3774      case IrOpcode::kObjectIsNaN: {
3775        Type const input_type = GetUpperBound(node->InputAt(0));
3776        if (input_type.Is(Type::NaN())) {
3777          VisitUnop<T>(node, UseInfo::None(), MachineRepresentation::kBit);
3778          if (lower<T>()) {
3779            DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
3780          }
3781        } else if (!input_type.Maybe(Type::NaN())) {
3782          VisitUnop<T>(node, UseInfo::Any(), MachineRepresentation::kBit);
3783          if (lower<T>()) {
3784            DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
3785          }
3786        } else if (input_type.Is(Type::Number())) {
3787          VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3788                       MachineRepresentation::kBit);
3789          if (lower<T>()) {
3790            ChangeOp(node, simplified()->NumberIsNaN());
3791          }
3792        } else {
3793          VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
3794        }
3795        return;
3796      }
3797      case IrOpcode::kNumberIsNaN: {
3798        VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3799                     MachineRepresentation::kBit);
3800        return;
3801      }
3802      case IrOpcode::kObjectIsNonCallable: {
3803        VisitObjectIs<T>(node, Type::NonCallable(), lowering);
3804        return;
3805      }
3806      case IrOpcode::kObjectIsNumber: {
3807        VisitObjectIs<T>(node, Type::Number(), lowering);
3808        return;
3809      }
3810      case IrOpcode::kObjectIsReceiver: {
3811        VisitObjectIs<T>(node, Type::Receiver(), lowering);
3812        return;
3813      }
3814      case IrOpcode::kObjectIsSmi: {
3815        // TODO(turbofan): Optimize based on input representation.
3816        VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
3817        return;
3818      }
3819      case IrOpcode::kObjectIsString: {
3820        VisitObjectIs<T>(node, Type::String(), lowering);
3821        return;
3822      }
3823      case IrOpcode::kObjectIsSymbol: {
3824        VisitObjectIs<T>(node, Type::Symbol(), lowering);
3825        return;
3826      }
3827      case IrOpcode::kObjectIsUndetectable: {
3828        VisitObjectIs<T>(node, Type::Undetectable(), lowering);
3829        return;
3830      }
3831      case IrOpcode::kArgumentsLength:
3832      case IrOpcode::kRestLength: {
3833        SetOutput<T>(node, MachineRepresentation::kTaggedSigned);
3834        return;
3835      }
3836      case IrOpcode::kNewDoubleElements:
3837      case IrOpcode::kNewSmiOrObjectElements: {
3838        VisitUnop<T>(node, UseInfo::Word(),
3839                     MachineRepresentation::kTaggedPointer);
3840        return;
3841      }
3842      case IrOpcode::kNewArgumentsElements: {
3843        VisitUnop<T>(node, UseInfo::TaggedSigned(),
3844                     MachineRepresentation::kTaggedPointer);
3845        return;
3846      }
3847      case IrOpcode::kCheckFloat64Hole: {
3848        Type const input_type = TypeOf(node->InputAt(0));
3849        CheckFloat64HoleMode mode =
3850            CheckFloat64HoleParametersOf(node->op()).mode();
3851        if (mode == CheckFloat64HoleMode::kAllowReturnHole) {
3852          // If {mode} is allow-return-hole _and_ the {truncation}
3853          // identifies NaN and undefined, we can just pass along
3854          // the {truncation} and completely wipe the {node}.
3855          if (truncation.IsUnused()) return VisitUnused<T>(node);
3856          if (truncation.TruncatesOddballAndBigIntToNumber()) {
3857            VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3858                         MachineRepresentation::kFloat64);
3859            if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3860            return;
3861          }
3862        }
3863        VisitUnop<T>(
3864            node, UseInfo(MachineRepresentation::kFloat64, Truncation::Any()),
3865            MachineRepresentation::kFloat64, Type::Number());
3866        if (lower<T>() && input_type.Is(Type::Number())) {
3867          DeferReplacement(node, node->InputAt(0));
3868        }
3869        return;
3870      }
3871      case IrOpcode::kCheckNotTaggedHole: {
3872        VisitUnop<T>(node, UseInfo::AnyTagged(),
3873                     MachineRepresentation::kTagged);
3874        return;
3875      }
3876      case IrOpcode::kCheckClosure: {
3877        VisitUnop<T>(
3878            node, UseInfo::CheckedHeapObjectAsTaggedPointer(FeedbackSource()),
3879            MachineRepresentation::kTaggedPointer);
3880        return;
3881      }
3882      case IrOpcode::kConvertTaggedHoleToUndefined: {
3883        if (InputIs(node, Type::NumberOrOddball()) &&
3884            truncation.IsUsedAsWord32()) {
3885          // Propagate the Word32 truncation.
3886          VisitUnop<T>(node, UseInfo::TruncatingWord32(),
3887                       MachineRepresentation::kWord32);
3888          if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3889        } else if (InputIs(node, Type::NumberOrOddball()) &&
3890                   truncation.TruncatesOddballAndBigIntToNumber()) {
3891          // Propagate the Float64 truncation.
3892          VisitUnop<T>(node, UseInfo::TruncatingFloat64(),
3893                       MachineRepresentation::kFloat64);
3894          if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3895        } else if (InputIs(node, Type::NonInternal())) {
3896          VisitUnop<T>(node, UseInfo::AnyTagged(),
3897                       MachineRepresentation::kTagged);
3898          if (lower<T>()) DeferReplacement(node, node->InputAt(0));
3899        } else {
3900          // TODO(turbofan): Add a (Tagged) truncation that identifies hole
3901          // and undefined, i.e. for a[i] === obj cases.
3902          VisitUnop<T>(node, UseInfo::AnyTagged(),
3903                       MachineRepresentation::kTagged);
3904        }
3905        return;
3906      }
3907      case IrOpcode::kCheckEqualsSymbol:
3908      case IrOpcode::kCheckEqualsInternalizedString:
3909        return VisitBinop<T>(node, UseInfo::AnyTagged(),
3910                             MachineRepresentation::kNone);
3911      case IrOpcode::kMapGuard:
3912        // Eliminate MapGuard nodes here.
3913        return VisitUnused<T>(node);
3914      case IrOpcode::kCheckMaps: {
3915        CheckMapsParameters const& p = CheckMapsParametersOf(node->op());
3916        return VisitUnop<T>(
3917            node, UseInfo::CheckedHeapObjectAsTaggedPointer(p.feedback()),
3918            MachineRepresentation::kNone);
3919      }
3920      case IrOpcode::kTransitionElementsKind: {
3921        return VisitUnop<T>(
3922            node, UseInfo::CheckedHeapObjectAsTaggedPointer(FeedbackSource()),
3923            MachineRepresentation::kNone);
3924      }
3925      case IrOpcode::kCompareMaps:
3926        return VisitUnop<T>(
3927            node, UseInfo::CheckedHeapObjectAsTaggedPointer(FeedbackSource()),
3928            MachineRepresentation::kBit);
3929      case IrOpcode::kEnsureWritableFastElements:
3930        return VisitBinop<T>(node, UseInfo::AnyTagged(),
3931                             MachineRepresentation::kTaggedPointer);
3932      case IrOpcode::kMaybeGrowFastElements: {
3933        ProcessInput<T>(node, 0, UseInfo::AnyTagged());         // object
3934        ProcessInput<T>(node, 1, UseInfo::AnyTagged());         // elements
3935        ProcessInput<T>(node, 2, UseInfo::TruncatingWord32());  // index
3936        ProcessInput<T>(node, 3, UseInfo::TruncatingWord32());  // length
3937        ProcessRemainingInputs<T>(node, 4);
3938        SetOutput<T>(node, MachineRepresentation::kTaggedPointer);
3939        return;
3940      }
3941
3942      case IrOpcode::kDateNow:
3943        VisitInputs<T>(node);
3944        return SetOutput<T>(node, MachineRepresentation::kTagged);
3945      case IrOpcode::kFrameState:
3946        return VisitFrameState<T>(FrameState{node});
3947      case IrOpcode::kStateValues:
3948        return VisitStateValues<T>(node);
3949      case IrOpcode::kObjectState:
3950        return VisitObjectState<T>(node);
3951      case IrOpcode::kObjectId:
3952        return SetOutput<T>(node, MachineRepresentation::kTaggedPointer);
3953
3954      case IrOpcode::kTypeGuard: {
3955        if (truncation.IsUnused()) return VisitUnused<T>(node);
3956
3957        // We just get rid of the sigma here, choosing the best representation
3958        // for the sigma's type.
3959        Type type = TypeOf(node);
3960        MachineRepresentation representation =
3961            GetOutputInfoForPhi(node, type, truncation);
3962
3963        // Here we pretend that the input has the sigma's type for the
3964        // conversion.
3965        UseInfo use(representation, truncation);
3966        if (propagate<T>()) {
3967          EnqueueInput<T>(node, 0, use);
3968        } else if (lower<T>()) {
3969          ConvertInput(node, 0, use, type);
3970        }
3971        ProcessRemainingInputs<T>(node, 1);
3972        SetOutput<T>(node, representation);
3973        return;
3974      }
3975
3976      case IrOpcode::kFoldConstant:
3977        VisitInputs<T>(node);
3978        return SetOutput<T>(node, MachineRepresentation::kTaggedPointer);
3979
3980      case IrOpcode::kFinishRegion:
3981        VisitInputs<T>(node);
3982        // Assume the output is tagged pointer.
3983        return SetOutput<T>(node, MachineRepresentation::kTaggedPointer);
3984
3985      case IrOpcode::kReturn:
3986        VisitReturn<T>(node);
3987        // Assume the output is tagged.
3988        return SetOutput<T>(node, MachineRepresentation::kTagged);
3989
3990      case IrOpcode::kFindOrderedHashMapEntry: {
3991        Type const key_type = TypeOf(node->InputAt(1));
3992        if (key_type.Is(Type::Signed32OrMinusZero())) {
3993          VisitBinop<T>(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
3994                        MachineType::PointerRepresentation());
3995          if (lower<T>()) {
3996            ChangeOp(
3997                node,
3998                lowering->simplified()->FindOrderedHashMapEntryForInt32Key());
3999          }
4000        } else {
4001          VisitBinop<T>(node, UseInfo::AnyTagged(),
4002                        MachineRepresentation::kTaggedSigned);
4003        }
4004        return;
4005      }
4006
4007      case IrOpcode::kFastApiCall: {
4008        VisitFastApiCall<T>(node, lowering);
4009        return;
4010      }
4011
4012      // Operators with all inputs tagged and no or tagged output have uniform
4013      // handling.
4014      case IrOpcode::kEnd:
4015      case IrOpcode::kIfSuccess:
4016      case IrOpcode::kIfException:
4017      case IrOpcode::kIfTrue:
4018      case IrOpcode::kIfFalse:
4019      case IrOpcode::kIfValue:
4020      case IrOpcode::kIfDefault:
4021      case IrOpcode::kDeoptimize:
4022      case IrOpcode::kEffectPhi:
4023      case IrOpcode::kTerminate:
4024      case IrOpcode::kCheckpoint:
4025      case IrOpcode::kLoop:
4026      case IrOpcode::kMerge:
4027      case IrOpcode::kThrow:
4028      case IrOpcode::kBeginRegion:
4029      case IrOpcode::kProjection:
4030      case IrOpcode::kOsrValue:
4031      case IrOpcode::kArgumentsElementsState:
4032      case IrOpcode::kArgumentsLengthState:
4033      case IrOpcode::kUnreachable:
4034      case IrOpcode::kRuntimeAbort:
4035// All JavaScript operators except JSToNumber, JSToNumberConvertBigInt,
4036// kJSToNumeric and JSWasmCall have uniform handling.
4037#define OPCODE_CASE(name, ...) case IrOpcode::k##name:
4038        JS_SIMPLE_BINOP_LIST(OPCODE_CASE)
4039        JS_OBJECT_OP_LIST(OPCODE_CASE)
4040        JS_CONTEXT_OP_LIST(OPCODE_CASE)
4041        JS_OTHER_OP_LIST(OPCODE_CASE)
4042#undef OPCODE_CASE
4043      case IrOpcode::kJSBitwiseNot:
4044      case IrOpcode::kJSDecrement:
4045      case IrOpcode::kJSIncrement:
4046      case IrOpcode::kJSNegate:
4047      case IrOpcode::kJSToLength:
4048      case IrOpcode::kJSToName:
4049      case IrOpcode::kJSToObject:
4050      case IrOpcode::kJSToString:
4051      case IrOpcode::kJSParseInt:
4052#if V8_ENABLE_WEBASSEMBLY
4053        if (node->opcode() == IrOpcode::kJSWasmCall) {
4054          return VisitJSWasmCall<T>(node, lowering);
4055        }
4056#endif  // V8_ENABLE_WEBASSEMBLY
4057        VisitInputs<T>(node);
4058        // Assume the output is tagged.
4059        return SetOutput<T>(node, MachineRepresentation::kTagged);
4060      case IrOpcode::kDeadValue:
4061        ProcessInput<T>(node, 0, UseInfo::Any());
4062        return SetOutput<T>(node, MachineRepresentation::kNone);
4063      case IrOpcode::kStaticAssert:
4064        DCHECK(TypeOf(node->InputAt(0)).Is(Type::Boolean()));
4065        return VisitUnop<T>(node, UseInfo::Bool(),
4066                            MachineRepresentation::kTagged);
4067      case IrOpcode::kAssertType:
4068        return VisitUnop<T>(node, UseInfo::AnyTagged(),
4069                            MachineRepresentation::kTagged);
4070      case IrOpcode::kVerifyType: {
4071        Type inputType = TypeOf(node->InputAt(0));
4072        VisitUnop<T>(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged,
4073                     inputType);
4074        if (lower<T>()) {
4075          if (inputType.CanBeAsserted()) {
4076            ChangeOp(node, simplified()->AssertType(inputType));
4077          } else {
4078            if (!FLAG_fuzzing) {
4079#ifdef DEBUG
4080              inputType.Print();
4081#endif
4082              FATAL("%%VerifyType: unsupported type");
4083            }
4084            DeferReplacement(node, node->InputAt(0));
4085          }
4086        }
4087        return;
4088      }
4089
4090      default:
4091        FATAL(
4092            "Representation inference: unsupported opcode %i (%s), node #%i\n.",
4093            node->opcode(), node->op()->mnemonic(), node->id());
4094        break;
4095    }
4096    UNREACHABLE();
4097  }
4098
4099  void DisconnectFromEffectAndControl(Node* node) {
4100    if (node->op()->EffectInputCount() == 1) {
4101      Node* control = NodeProperties::GetControlInput(node);
4102      Node* effect = NodeProperties::GetEffectInput(node);
4103      ReplaceEffectControlUses(node, effect, control);
4104    } else {
4105      DCHECK_EQ(0, node->op()->EffectInputCount());
4106      DCHECK_EQ(0, node->op()->ControlOutputCount());
4107      DCHECK_EQ(0, node->op()->EffectOutputCount());
4108    }
4109  }
4110
4111  void DeferReplacement(Node* node, Node* replacement) {
4112    TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(),
4113          node->op()->mnemonic(), replacement->id(),
4114          replacement->op()->mnemonic());
4115
4116    DisconnectFromEffectAndControl(node);
4117    node->NullAllInputs();  // Node is now dead.
4118
4119    replacements_.push_back(node);
4120    replacements_.push_back(replacement);
4121
4122    NotifyNodeReplaced(node, replacement);
4123  }
4124
4125  Node* InsertTypeOverrideForVerifier(const Type& type, Node* node) {
4126    if (verification_enabled()) {
4127      DCHECK(!type.IsInvalid());
4128      node = graph()->NewNode(common()->SLVerifierHint(nullptr, type), node);
4129      verifier_->RecordHint(node);
4130    }
4131    return node;
4132  }
4133
4134  void ChangeToSemanticsHintForVerifier(Node* node, const Operator* semantics) {
4135    DCHECK_EQ(node->op()->ValueInputCount(), 1);
4136    DCHECK_EQ(node->op()->EffectInputCount(), 0);
4137    DCHECK_EQ(node->op()->ControlInputCount(), 0);
4138    if (verification_enabled()) {
4139      ChangeOp(node, common()->SLVerifierHint(semantics, base::nullopt));
4140      verifier_->RecordHint(node);
4141    } else {
4142      DeferReplacement(node, node->InputAt(0));
4143    }
4144  }
4145
4146 private:
4147  void ChangeOp(Node* node, const Operator* new_op) {
4148    compiler::NodeProperties::ChangeOp(node, new_op);
4149
4150    if (V8_UNLIKELY(observe_node_manager_ != nullptr))
4151      observe_node_manager_->OnNodeChanged(kSimplifiedLoweringReducerName, node,
4152                                           node);
4153  }
4154
4155  void NotifyNodeReplaced(Node* node, Node* replacement) {
4156    if (V8_UNLIKELY(observe_node_manager_ != nullptr))
4157      observe_node_manager_->OnNodeChanged(kSimplifiedLoweringReducerName, node,
4158                                           replacement);
4159  }
4160
4161  JSGraph* jsgraph_;
4162  JSHeapBroker* broker_;
4163  Zone* zone_;                      // Temporary zone.
4164  // Map from node to its uses that might need to be revisited.
4165  ZoneMap<Node*, ZoneVector<Node*>> might_need_revisit_;
4166  size_t count_;                    // number of nodes in the graph
4167  ZoneVector<NodeInfo> info_;       // node id -> usage information
4168#ifdef DEBUG
4169  ZoneVector<InputUseInfos> node_input_use_infos_;  // Debug information about
4170                                                    // requirements on inputs.
4171#endif                                              // DEBUG
4172  NodeVector replacements_;         // replacements to be done after lowering
4173  RepresentationChanger* changer_;  // for inserting representation changes
4174  ZoneQueue<Node*> revisit_queue_;  // Queue for revisiting nodes.
4175
4176  struct NodeState {
4177    Node* node;
4178    int input_index;
4179  };
4180  NodeVector traversal_nodes_;  // Order in which to traverse the nodes.
4181  // TODO(danno): RepresentationSelector shouldn't know anything about the
4182  // source positions table, but must for now since there currently is no other
4183  // way to pass down source position information to nodes created during
4184  // lowering. Once this phase becomes a vanilla reducer, it should get source
4185  // position information via the SourcePositionWrapper like all other reducers.
4186  SourcePositionTable* source_positions_;
4187  NodeOriginTable* node_origins_;
4188  TypeCache const* type_cache_;
4189  OperationTyper op_typer_;  // helper for the feedback typer
4190  TickCounter* const tick_counter_;
4191  Linkage* const linkage_;
4192  ObserveNodeManager* const observe_node_manager_;
4193  SimplifiedLoweringVerifier* verifier_;  // Used to verify output graph.
4194
4195  NodeInfo* GetInfo(Node* node) {
4196    DCHECK(node->id() < count_);
4197    return &info_[node->id()];
4198  }
4199  Zone* zone() { return zone_; }
4200  Zone* graph_zone() { return jsgraph_->zone(); }
4201  Linkage* linkage() { return linkage_; }
4202};
4203
4204// Template specializations
4205
4206// Enqueue {use_node}'s {index} input if the {use_info} contains new information
4207// for that input node.
4208template <>
4209void RepresentationSelector::EnqueueInput<PROPAGATE>(Node* use_node, int index,
4210                                                     UseInfo use_info) {
4211  Node* node = use_node->InputAt(index);
4212  NodeInfo* info = GetInfo(node);
4213#ifdef DEBUG
4214  // Check monotonicity of input requirements.
4215  node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
4216                                                         use_info);
4217#endif  // DEBUG
4218  if (info->unvisited()) {
4219    info->AddUse(use_info);
4220    TRACE("  initial #%i: %s\n", node->id(), info->truncation().description());
4221    return;
4222  }
4223  TRACE("   queue #%i?: %s\n", node->id(), info->truncation().description());
4224  if (info->AddUse(use_info)) {
4225    // New usage information for the node is available.
4226    if (!info->queued()) {
4227      DCHECK(info->visited());
4228      revisit_queue_.push(node);
4229      info->set_queued();
4230      TRACE("   added: %s\n", info->truncation().description());
4231    } else {
4232      TRACE(" inqueue: %s\n", info->truncation().description());
4233    }
4234  }
4235}
4236
4237template <>
4238void RepresentationSelector::SetOutput<PROPAGATE>(
4239    Node* node, MachineRepresentation representation, Type restriction_type) {
4240  NodeInfo* const info = GetInfo(node);
4241  info->set_restriction_type(restriction_type);
4242}
4243
4244template <>
4245void RepresentationSelector::SetOutput<RETYPE>(
4246    Node* node, MachineRepresentation representation, Type restriction_type) {
4247  NodeInfo* const info = GetInfo(node);
4248  DCHECK(restriction_type.Is(info->restriction_type()));
4249  info->set_output(representation);
4250}
4251
4252template <>
4253void RepresentationSelector::SetOutput<LOWER>(
4254    Node* node, MachineRepresentation representation, Type restriction_type) {
4255  NodeInfo* const info = GetInfo(node);
4256  DCHECK_EQ(info->representation(), representation);
4257  DCHECK(restriction_type.Is(info->restriction_type()));
4258  USE(info);
4259}
4260
4261template <>
4262void RepresentationSelector::ProcessInput<PROPAGATE>(Node* node, int index,
4263                                                     UseInfo use) {
4264  DCHECK_IMPLIES(use.type_check() != TypeCheckKind::kNone,
4265                 !node->op()->HasProperty(Operator::kNoDeopt) &&
4266                     node->op()->EffectInputCount() > 0);
4267  EnqueueInput<PROPAGATE>(node, index, use);
4268}
4269
4270template <>
4271void RepresentationSelector::ProcessInput<RETYPE>(Node* node, int index,
4272                                                  UseInfo use) {
4273  DCHECK_IMPLIES(use.type_check() != TypeCheckKind::kNone,
4274                 !node->op()->HasProperty(Operator::kNoDeopt) &&
4275                     node->op()->EffectInputCount() > 0);
4276}
4277
4278template <>
4279void RepresentationSelector::ProcessInput<LOWER>(Node* node, int index,
4280                                                 UseInfo use) {
4281  DCHECK_IMPLIES(use.type_check() != TypeCheckKind::kNone,
4282                 !node->op()->HasProperty(Operator::kNoDeopt) &&
4283                     node->op()->EffectInputCount() > 0);
4284  ConvertInput(node, index, use);
4285}
4286
4287template <>
4288void RepresentationSelector::ProcessRemainingInputs<PROPAGATE>(Node* node,
4289                                                               int index) {
4290  DCHECK_GE(index, NodeProperties::PastContextIndex(node));
4291
4292  // Enqueue other inputs (effects, control).
4293  for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
4294       i < node->InputCount(); ++i) {
4295    EnqueueInput<PROPAGATE>(node, i);
4296  }
4297}
4298
4299// The default, most general visitation case. For {node}, process all value,
4300// context, frame state, effect, and control inputs, assuming that value
4301// inputs should have {kRepTagged} representation and can observe all output
4302// values {kTypeAny}.
4303template <>
4304void RepresentationSelector::VisitInputs<PROPAGATE>(Node* node) {
4305  int first_effect_index = NodeProperties::FirstEffectIndex(node);
4306  // Visit value, context and frame state inputs as tagged.
4307  for (int i = 0; i < first_effect_index; i++) {
4308    ProcessInput<PROPAGATE>(node, i, UseInfo::AnyTagged());
4309  }
4310  // Only enqueue other inputs (effects, control).
4311  for (int i = first_effect_index; i < node->InputCount(); i++) {
4312    EnqueueInput<PROPAGATE>(node, i);
4313  }
4314}
4315
4316template <>
4317void RepresentationSelector::VisitInputs<LOWER>(Node* node) {
4318  int first_effect_index = NodeProperties::FirstEffectIndex(node);
4319  // Visit value, context and frame state inputs as tagged.
4320  for (int i = 0; i < first_effect_index; i++) {
4321    ProcessInput<LOWER>(node, i, UseInfo::AnyTagged());
4322  }
4323}
4324
4325template <>
4326void RepresentationSelector::InsertUnreachableIfNecessary<LOWER>(Node* node) {
4327  // If the node is effectful and it produces an impossible value, then we
4328  // insert Unreachable node after it.
4329  if (node->op()->ValueOutputCount() > 0 &&
4330      node->op()->EffectOutputCount() > 0 &&
4331      node->opcode() != IrOpcode::kUnreachable && TypeOf(node).IsNone()) {
4332    Node* control = (node->op()->ControlOutputCount() == 0)
4333                        ? NodeProperties::GetControlInput(node, 0)
4334                        : NodeProperties::FindSuccessfulControlProjection(node);
4335
4336    Node* unreachable =
4337        graph()->NewNode(common()->Unreachable(), node, control);
4338
4339    // Insert unreachable node and replace all the effect uses of the {node}
4340    // with the new unreachable node.
4341    for (Edge edge : node->use_edges()) {
4342      if (!NodeProperties::IsEffectEdge(edge)) continue;
4343      // Make sure to not overwrite the unreachable node's input. That would
4344      // create a cycle.
4345      if (edge.from() == unreachable) continue;
4346      // Avoid messing up the exceptional path.
4347      if (edge.from()->opcode() == IrOpcode::kIfException) {
4348        DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
4349        DCHECK_EQ(NodeProperties::GetControlInput(edge.from()), node);
4350        continue;
4351      }
4352
4353      edge.UpdateTo(unreachable);
4354    }
4355  }
4356}
4357
4358SimplifiedLowering::SimplifiedLowering(
4359    JSGraph* jsgraph, JSHeapBroker* broker, Zone* zone,
4360    SourcePositionTable* source_positions, NodeOriginTable* node_origins,
4361    TickCounter* tick_counter, Linkage* linkage, OptimizedCompilationInfo* info,
4362    ObserveNodeManager* observe_node_manager)
4363    : jsgraph_(jsgraph),
4364      broker_(broker),
4365      zone_(zone),
4366      type_cache_(TypeCache::Get()),
4367      source_positions_(source_positions),
4368      node_origins_(node_origins),
4369      tick_counter_(tick_counter),
4370      linkage_(linkage),
4371      info_(info),
4372      observe_node_manager_(observe_node_manager) {}
4373
4374void SimplifiedLowering::LowerAllNodes() {
4375  SimplifiedLoweringVerifier* verifier = nullptr;
4376  if (FLAG_verify_simplified_lowering) {
4377    verifier = zone_->New<SimplifiedLoweringVerifier>(zone_, graph());
4378  }
4379  RepresentationChanger changer(jsgraph(), broker_, verifier);
4380  RepresentationSelector selector(
4381      jsgraph(), broker_, zone_, &changer, source_positions_, node_origins_,
4382      tick_counter_, linkage_, observe_node_manager_, verifier);
4383  selector.Run(this);
4384}
4385
4386void SimplifiedLowering::DoJSToNumberOrNumericTruncatesToFloat64(
4387    Node* node, RepresentationSelector* selector) {
4388  DCHECK(node->opcode() == IrOpcode::kJSToNumber ||
4389         node->opcode() == IrOpcode::kJSToNumberConvertBigInt ||
4390         node->opcode() == IrOpcode::kJSToNumeric);
4391  Node* value = node->InputAt(0);
4392  Node* context = node->InputAt(1);
4393  Node* frame_state = node->InputAt(2);
4394  Node* effect = node->InputAt(3);
4395  Node* control = node->InputAt(4);
4396
4397  Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
4398  Node* branch0 =
4399      graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
4400
4401  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
4402  Node* etrue0 = effect;
4403  Node* vtrue0;
4404  {
4405    vtrue0 = graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
4406    vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
4407  }
4408
4409  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
4410  Node* efalse0 = effect;
4411  Node* vfalse0;
4412  {
4413    Operator const* op =
4414        node->opcode() == IrOpcode::kJSToNumber
4415            ? (node->opcode() == IrOpcode::kJSToNumberConvertBigInt
4416                   ? ToNumberConvertBigIntOperator()
4417                   : ToNumberOperator())
4418            : ToNumericOperator();
4419    Node* code = node->opcode() == IrOpcode::kJSToNumber
4420                     ? ToNumberCode()
4421                     : (node->opcode() == IrOpcode::kJSToNumberConvertBigInt
4422                            ? ToNumberConvertBigIntCode()
4423                            : ToNumericCode());
4424    vfalse0 = efalse0 = if_false0 = graph()->NewNode(
4425        op, code, value, context, frame_state, efalse0, if_false0);
4426
4427    // Update potential {IfException} uses of {node} to point to the above
4428    // stub call node instead.
4429    Node* on_exception = nullptr;
4430    if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
4431      NodeProperties::ReplaceControlInput(on_exception, vfalse0);
4432      NodeProperties::ReplaceEffectInput(on_exception, efalse0);
4433      if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
4434    }
4435
4436    Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
4437    Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
4438
4439    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
4440    Node* etrue1 = efalse0;
4441    Node* vtrue1;
4442    {
4443      vtrue1 =
4444          graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
4445      vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
4446    }
4447
4448    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
4449    Node* efalse1 = efalse0;
4450    Node* vfalse1;
4451    {
4452      vfalse1 = efalse1 = graph()->NewNode(
4453          simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
4454          efalse1, if_false1);
4455    }
4456
4457    if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
4458    efalse0 =
4459        graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
4460    vfalse0 =
4461        graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
4462                         vtrue1, vfalse1, if_false0);
4463  }
4464
4465  control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
4466  effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
4467  value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
4468                           vtrue0, vfalse0, control);
4469
4470  // Replace effect and control uses appropriately.
4471  for (Edge edge : node->use_edges()) {
4472    if (NodeProperties::IsControlEdge(edge)) {
4473      if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
4474        edge.from()->ReplaceUses(control);
4475        edge.from()->Kill();
4476      } else {
4477        DCHECK_NE(IrOpcode::kIfException, edge.from()->opcode());
4478        edge.UpdateTo(control);
4479      }
4480    } else if (NodeProperties::IsEffectEdge(edge)) {
4481      edge.UpdateTo(effect);
4482    }
4483  }
4484
4485  selector->DeferReplacement(node, value);
4486}
4487
4488void SimplifiedLowering::DoJSToNumberOrNumericTruncatesToWord32(
4489    Node* node, RepresentationSelector* selector) {
4490  DCHECK(node->opcode() == IrOpcode::kJSToNumber ||
4491         node->opcode() == IrOpcode::kJSToNumberConvertBigInt ||
4492         node->opcode() == IrOpcode::kJSToNumeric);
4493  Node* value = node->InputAt(0);
4494  Node* context = node->InputAt(1);
4495  Node* frame_state = node->InputAt(2);
4496  Node* effect = node->InputAt(3);
4497  Node* control = node->InputAt(4);
4498
4499  Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
4500  Node* branch0 =
4501      graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
4502
4503  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
4504  Node* etrue0 = effect;
4505  Node* vtrue0 =
4506      graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
4507
4508  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
4509  Node* efalse0 = effect;
4510  Node* vfalse0;
4511  {
4512    Operator const* op =
4513        node->opcode() == IrOpcode::kJSToNumber
4514            ? (node->opcode() == IrOpcode::kJSToNumberConvertBigInt
4515                   ? ToNumberConvertBigIntOperator()
4516                   : ToNumberOperator())
4517            : ToNumericOperator();
4518    Node* code = node->opcode() == IrOpcode::kJSToNumber
4519                     ? ToNumberCode()
4520                     : (node->opcode() == IrOpcode::kJSToNumberConvertBigInt
4521                            ? ToNumberConvertBigIntCode()
4522                            : ToNumericCode());
4523    vfalse0 = efalse0 = if_false0 = graph()->NewNode(
4524        op, code, value, context, frame_state, efalse0, if_false0);
4525
4526    // Update potential {IfException} uses of {node} to point to the above
4527    // stub call node instead.
4528    Node* on_exception = nullptr;
4529    if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
4530      NodeProperties::ReplaceControlInput(on_exception, vfalse0);
4531      NodeProperties::ReplaceEffectInput(on_exception, efalse0);
4532      if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
4533    }
4534
4535    Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
4536    Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
4537
4538    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
4539    Node* etrue1 = efalse0;
4540    Node* vtrue1 =
4541        graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
4542
4543    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
4544    Node* efalse1 = efalse0;
4545    Node* vfalse1;
4546    {
4547      vfalse1 = efalse1 = graph()->NewNode(
4548          simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
4549          efalse1, if_false1);
4550      vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
4551    }
4552
4553    if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
4554    efalse0 =
4555        graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
4556    vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
4557                               vtrue1, vfalse1, if_false0);
4558  }
4559
4560  control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
4561  effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
4562  value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
4563                           vtrue0, vfalse0, control);
4564
4565  // Replace effect and control uses appropriately.
4566  for (Edge edge : node->use_edges()) {
4567    if (NodeProperties::IsControlEdge(edge)) {
4568      if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
4569        edge.from()->ReplaceUses(control);
4570        edge.from()->Kill();
4571      } else {
4572        DCHECK_NE(IrOpcode::kIfException, edge.from()->opcode());
4573        edge.UpdateTo(control);
4574      }
4575    } else if (NodeProperties::IsEffectEdge(edge)) {
4576      edge.UpdateTo(effect);
4577    }
4578  }
4579
4580  selector->DeferReplacement(node, value);
4581}
4582
4583Node* SimplifiedLowering::Float64Round(Node* const node) {
4584  Node* const one = jsgraph()->Float64Constant(1.0);
4585  Node* const one_half = jsgraph()->Float64Constant(0.5);
4586  Node* const input = node->InputAt(0);
4587
4588  // Round up towards Infinity, and adjust if the difference exceeds 0.5.
4589  Node* result = graph()->NewNode(machine()->Float64RoundUp().placeholder(),
4590                                  node->InputAt(0));
4591  return graph()->NewNode(
4592      common()->Select(MachineRepresentation::kFloat64),
4593      graph()->NewNode(
4594          machine()->Float64LessThanOrEqual(),
4595          graph()->NewNode(machine()->Float64Sub(), result, one_half), input),
4596      result, graph()->NewNode(machine()->Float64Sub(), result, one));
4597}
4598
4599Node* SimplifiedLowering::Float64Sign(Node* const node) {
4600  Node* const minus_one = jsgraph()->Float64Constant(-1.0);
4601  Node* const zero = jsgraph()->Float64Constant(0.0);
4602  Node* const one = jsgraph()->Float64Constant(1.0);
4603
4604  Node* const input = node->InputAt(0);
4605
4606  return graph()->NewNode(
4607      common()->Select(MachineRepresentation::kFloat64),
4608      graph()->NewNode(machine()->Float64LessThan(), input, zero), minus_one,
4609      graph()->NewNode(
4610          common()->Select(MachineRepresentation::kFloat64),
4611          graph()->NewNode(machine()->Float64LessThan(), zero, input), one,
4612          input));
4613}
4614
4615Node* SimplifiedLowering::Int32Abs(Node* const node) {
4616  Node* const input = node->InputAt(0);
4617
4618  // Generate case for absolute integer value.
4619  //
4620  //    let sign = input >> 31 in
4621  //    (input ^ sign) - sign
4622
4623  Node* sign = graph()->NewNode(machine()->Word32Sar(), input,
4624                                jsgraph()->Int32Constant(31));
4625  return graph()->NewNode(machine()->Int32Sub(),
4626                          graph()->NewNode(machine()->Word32Xor(), input, sign),
4627                          sign);
4628}
4629
4630Node* SimplifiedLowering::Int32Div(Node* const node) {
4631  Int32BinopMatcher m(node);
4632  Node* const zero = jsgraph()->Int32Constant(0);
4633  Node* const minus_one = jsgraph()->Int32Constant(-1);
4634  Node* const lhs = m.left().node();
4635  Node* const rhs = m.right().node();
4636
4637  if (m.right().Is(-1)) {
4638    return graph()->NewNode(machine()->Int32Sub(), zero, lhs);
4639  } else if (m.right().Is(0)) {
4640    return rhs;
4641  } else if (machine()->Int32DivIsSafe() || m.right().HasResolvedValue()) {
4642    return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
4643  }
4644
4645  // General case for signed integer division.
4646  //
4647  //    if 0 < rhs then
4648  //      lhs / rhs
4649  //    else
4650  //      if rhs < -1 then
4651  //        lhs / rhs
4652  //      else if rhs == 0 then
4653  //        0
4654  //      else
4655  //        0 - lhs
4656  //
4657  // Note: We do not use the Diamond helper class here, because it really hurts
4658  // readability with nested diamonds.
4659  const Operator* const merge_op = common()->Merge(2);
4660  const Operator* const phi_op =
4661      common()->Phi(MachineRepresentation::kWord32, 2);
4662
4663  Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
4664  Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
4665                                   graph()->start());
4666
4667  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
4668  Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0);
4669
4670  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
4671  Node* false0;
4672  {
4673    Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
4674    Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
4675
4676    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
4677    Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1);
4678
4679    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
4680    Node* false1;
4681    {
4682      Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
4683      Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
4684
4685      Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
4686      Node* true2 = zero;
4687
4688      Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
4689      Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
4690
4691      if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
4692      false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
4693    }
4694
4695    if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
4696    false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
4697  }
4698
4699  Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
4700  return graph()->NewNode(phi_op, true0, false0, merge0);
4701}
4702
4703Node* SimplifiedLowering::Int32Mod(Node* const node) {
4704  Int32BinopMatcher m(node);
4705  Node* const zero = jsgraph()->Int32Constant(0);
4706  Node* const minus_one = jsgraph()->Int32Constant(-1);
4707  Node* const lhs = m.left().node();
4708  Node* const rhs = m.right().node();
4709
4710  if (m.right().Is(-1) || m.right().Is(0)) {
4711    return zero;
4712  } else if (m.right().HasResolvedValue()) {
4713    return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
4714  }
4715
4716  // General case for signed integer modulus, with optimization for (unknown)
4717  // power of 2 right hand side.
4718  //
4719  //   if 0 < rhs then
4720  //     msk = rhs - 1
4721  //     if rhs & msk != 0 then
4722  //       lhs % rhs
4723  //     else
4724  //       if lhs < 0 then
4725  //         -(-lhs & msk)
4726  //       else
4727  //         lhs & msk
4728  //   else
4729  //     if rhs < -1 then
4730  //       lhs % rhs
4731  //     else
4732  //       zero
4733  //
4734  // Note: We do not use the Diamond helper class here, because it really hurts
4735  // readability with nested diamonds.
4736  const Operator* const merge_op = common()->Merge(2);
4737  const Operator* const phi_op =
4738      common()->Phi(MachineRepresentation::kWord32, 2);
4739
4740  Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
4741  Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
4742                                   graph()->start());
4743
4744  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
4745  Node* true0;
4746  {
4747    Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
4748
4749    Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
4750    Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
4751
4752    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
4753    Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
4754
4755    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
4756    Node* false1;
4757    {
4758      Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
4759      Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
4760                                       check2, if_false1);
4761
4762      Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
4763      Node* true2 = graph()->NewNode(
4764          machine()->Int32Sub(), zero,
4765          graph()->NewNode(machine()->Word32And(),
4766                           graph()->NewNode(machine()->Int32Sub(), zero, lhs),
4767                           msk));
4768
4769      Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
4770      Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
4771
4772      if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
4773      false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
4774    }
4775
4776    if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
4777    true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
4778  }
4779
4780  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
4781  Node* false0;
4782  {
4783    Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
4784    Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
4785                                     check1, if_false0);
4786
4787    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
4788    Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
4789
4790    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
4791    Node* false1 = zero;
4792
4793    if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
4794    false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
4795  }
4796
4797  Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
4798  return graph()->NewNode(phi_op, true0, false0, merge0);
4799}
4800
4801Node* SimplifiedLowering::Int32Sign(Node* const node) {
4802  Node* const minus_one = jsgraph()->Int32Constant(-1);
4803  Node* const zero = jsgraph()->Int32Constant(0);
4804  Node* const one = jsgraph()->Int32Constant(1);
4805
4806  Node* const input = node->InputAt(0);
4807
4808  return graph()->NewNode(
4809      common()->Select(MachineRepresentation::kWord32),
4810      graph()->NewNode(machine()->Int32LessThan(), input, zero), minus_one,
4811      graph()->NewNode(
4812          common()->Select(MachineRepresentation::kWord32),
4813          graph()->NewNode(machine()->Int32LessThan(), zero, input), one,
4814          zero));
4815}
4816
4817Node* SimplifiedLowering::Uint32Div(Node* const node) {
4818  Uint32BinopMatcher m(node);
4819  Node* const zero = jsgraph()->Uint32Constant(0);
4820  Node* const lhs = m.left().node();
4821  Node* const rhs = m.right().node();
4822
4823  if (m.right().Is(0)) {
4824    return zero;
4825  } else if (machine()->Uint32DivIsSafe() || m.right().HasResolvedValue()) {
4826    return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
4827  }
4828
4829  Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
4830  Diamond d(graph(), common(), check, BranchHint::kFalse);
4831  Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
4832  return d.Phi(MachineRepresentation::kWord32, zero, div);
4833}
4834
4835Node* SimplifiedLowering::Uint32Mod(Node* const node) {
4836  Uint32BinopMatcher m(node);
4837  Node* const minus_one = jsgraph()->Int32Constant(-1);
4838  Node* const zero = jsgraph()->Uint32Constant(0);
4839  Node* const lhs = m.left().node();
4840  Node* const rhs = m.right().node();
4841
4842  if (m.right().Is(0)) {
4843    return zero;
4844  } else if (m.right().HasResolvedValue()) {
4845    return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
4846  }
4847
4848  // General case for unsigned integer modulus, with optimization for (unknown)
4849  // power of 2 right hand side.
4850  //
4851  //   if rhs == 0 then
4852  //     zero
4853  //   else
4854  //     msk = rhs - 1
4855  //     if rhs & msk != 0 then
4856  //       lhs % rhs
4857  //     else
4858  //       lhs & msk
4859  //
4860  // Note: We do not use the Diamond helper class here, because it really hurts
4861  // readability with nested diamonds.
4862  const Operator* const merge_op = common()->Merge(2);
4863  const Operator* const phi_op =
4864      common()->Phi(MachineRepresentation::kWord32, 2);
4865
4866  Node* check0 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
4867  Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse), check0,
4868                                   graph()->start());
4869
4870  Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
4871  Node* true0 = zero;
4872
4873  Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
4874  Node* false0;
4875  {
4876    Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
4877
4878    Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
4879    Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
4880
4881    Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
4882    Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1);
4883
4884    Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
4885    Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk);
4886
4887    if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
4888    false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
4889  }
4890
4891  Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
4892  return graph()->NewNode(phi_op, true0, false0, merge0);
4893}
4894
4895void SimplifiedLowering::DoMax(Node* node, Operator const* op,
4896                               MachineRepresentation rep) {
4897  Node* const lhs = node->InputAt(0);
4898  Node* const rhs = node->InputAt(1);
4899
4900  node->ReplaceInput(0, graph()->NewNode(op, lhs, rhs));
4901  DCHECK_EQ(rhs, node->InputAt(1));
4902  node->AppendInput(graph()->zone(), lhs);
4903  ChangeOp(node, common()->Select(rep));
4904}
4905
4906void SimplifiedLowering::DoMin(Node* node, Operator const* op,
4907                               MachineRepresentation rep) {
4908  Node* const lhs = node->InputAt(0);
4909  Node* const rhs = node->InputAt(1);
4910
4911  node->InsertInput(graph()->zone(), 0, graph()->NewNode(op, lhs, rhs));
4912  DCHECK_EQ(lhs, node->InputAt(1));
4913  DCHECK_EQ(rhs, node->InputAt(2));
4914  ChangeOp(node, common()->Select(rep));
4915}
4916
4917void SimplifiedLowering::DoIntegral32ToBit(Node* node) {
4918  Node* const input = node->InputAt(0);
4919  Node* const zero = jsgraph()->Int32Constant(0);
4920  Operator const* const op = machine()->Word32Equal();
4921
4922  node->ReplaceInput(0, graph()->NewNode(op, input, zero));
4923  node->AppendInput(graph()->zone(), zero);
4924  ChangeOp(node, op);
4925}
4926
4927void SimplifiedLowering::DoOrderedNumberToBit(Node* node) {
4928  Node* const input = node->InputAt(0);
4929
4930  node->ReplaceInput(0, graph()->NewNode(machine()->Float64Equal(), input,
4931                                         jsgraph()->Float64Constant(0.0)));
4932  node->AppendInput(graph()->zone(), jsgraph()->Int32Constant(0));
4933  ChangeOp(node, machine()->Word32Equal());
4934}
4935
4936void SimplifiedLowering::DoNumberToBit(Node* node) {
4937  Node* const input = node->InputAt(0);
4938
4939  node->ReplaceInput(0, jsgraph()->Float64Constant(0.0));
4940  node->AppendInput(graph()->zone(),
4941                    graph()->NewNode(machine()->Float64Abs(), input));
4942  ChangeOp(node, machine()->Float64LessThan());
4943}
4944
4945void SimplifiedLowering::DoIntegerToUint8Clamped(Node* node) {
4946  Node* const input = node->InputAt(0);
4947  Node* const min = jsgraph()->Float64Constant(0.0);
4948  Node* const max = jsgraph()->Float64Constant(255.0);
4949
4950  node->ReplaceInput(
4951      0, graph()->NewNode(machine()->Float64LessThan(), min, input));
4952  node->AppendInput(
4953      graph()->zone(),
4954      graph()->NewNode(
4955          common()->Select(MachineRepresentation::kFloat64),
4956          graph()->NewNode(machine()->Float64LessThan(), input, max), input,
4957          max));
4958  node->AppendInput(graph()->zone(), min);
4959  ChangeOp(node, common()->Select(MachineRepresentation::kFloat64));
4960}
4961
4962void SimplifiedLowering::DoNumberToUint8Clamped(Node* node) {
4963  Node* const input = node->InputAt(0);
4964  Node* const min = jsgraph()->Float64Constant(0.0);
4965  Node* const max = jsgraph()->Float64Constant(255.0);
4966
4967  node->ReplaceInput(
4968      0, graph()->NewNode(
4969             common()->Select(MachineRepresentation::kFloat64),
4970             graph()->NewNode(machine()->Float64LessThan(), min, input),
4971             graph()->NewNode(
4972                 common()->Select(MachineRepresentation::kFloat64),
4973                 graph()->NewNode(machine()->Float64LessThan(), input, max),
4974                 input, max),
4975             min));
4976  ChangeOp(node, machine()->Float64RoundTiesEven().placeholder());
4977}
4978
4979void SimplifiedLowering::DoSigned32ToUint8Clamped(Node* node) {
4980  Node* const input = node->InputAt(0);
4981  Node* const min = jsgraph()->Int32Constant(0);
4982  Node* const max = jsgraph()->Int32Constant(255);
4983
4984  node->ReplaceInput(
4985      0, graph()->NewNode(machine()->Int32LessThanOrEqual(), input, max));
4986  node->AppendInput(
4987      graph()->zone(),
4988      graph()->NewNode(common()->Select(MachineRepresentation::kWord32),
4989                       graph()->NewNode(machine()->Int32LessThan(), input, min),
4990                       min, input));
4991  node->AppendInput(graph()->zone(), max);
4992  ChangeOp(node, common()->Select(MachineRepresentation::kWord32));
4993}
4994
4995void SimplifiedLowering::DoUnsigned32ToUint8Clamped(Node* node) {
4996  Node* const input = node->InputAt(0);
4997  Node* const max = jsgraph()->Uint32Constant(255u);
4998
4999  node->ReplaceInput(
5000      0, graph()->NewNode(machine()->Uint32LessThanOrEqual(), input, max));
5001  node->AppendInput(graph()->zone(), input);
5002  node->AppendInput(graph()->zone(), max);
5003  ChangeOp(node, common()->Select(MachineRepresentation::kWord32));
5004}
5005
5006Node* SimplifiedLowering::ToNumberCode() {
5007  if (!to_number_code_.is_set()) {
5008    Callable callable = Builtins::CallableFor(isolate(), Builtin::kToNumber);
5009    to_number_code_.set(jsgraph()->HeapConstant(callable.code()));
5010  }
5011  return to_number_code_.get();
5012}
5013
5014Node* SimplifiedLowering::ToNumberConvertBigIntCode() {
5015  if (!to_number_convert_big_int_code_.is_set()) {
5016    Callable callable =
5017        Builtins::CallableFor(isolate(), Builtin::kToNumberConvertBigInt);
5018    to_number_convert_big_int_code_.set(
5019        jsgraph()->HeapConstant(callable.code()));
5020  }
5021  return to_number_convert_big_int_code_.get();
5022}
5023
5024Node* SimplifiedLowering::ToNumericCode() {
5025  if (!to_numeric_code_.is_set()) {
5026    Callable callable = Builtins::CallableFor(isolate(), Builtin::kToNumeric);
5027    to_numeric_code_.set(jsgraph()->HeapConstant(callable.code()));
5028  }
5029  return to_numeric_code_.get();
5030}
5031
5032Operator const* SimplifiedLowering::ToNumberOperator() {
5033  if (!to_number_operator_.is_set()) {
5034    Callable callable = Builtins::CallableFor(isolate(), Builtin::kToNumber);
5035    CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
5036    auto call_descriptor = Linkage::GetStubCallDescriptor(
5037        graph()->zone(), callable.descriptor(),
5038        callable.descriptor().GetStackParameterCount(), flags,
5039        Operator::kNoProperties);
5040    to_number_operator_.set(common()->Call(call_descriptor));
5041  }
5042  return to_number_operator_.get();
5043}
5044
5045Operator const* SimplifiedLowering::ToNumberConvertBigIntOperator() {
5046  if (!to_number_convert_big_int_operator_.is_set()) {
5047    Callable callable =
5048        Builtins::CallableFor(isolate(), Builtin::kToNumberConvertBigInt);
5049    CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
5050    auto call_descriptor = Linkage::GetStubCallDescriptor(
5051        graph()->zone(), callable.descriptor(),
5052        callable.descriptor().GetStackParameterCount(), flags,
5053        Operator::kNoProperties);
5054    to_number_convert_big_int_operator_.set(common()->Call(call_descriptor));
5055  }
5056  return to_number_convert_big_int_operator_.get();
5057}
5058
5059Operator const* SimplifiedLowering::ToNumericOperator() {
5060  if (!to_numeric_operator_.is_set()) {
5061    Callable callable = Builtins::CallableFor(isolate(), Builtin::kToNumeric);
5062    CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
5063    auto call_descriptor = Linkage::GetStubCallDescriptor(
5064        graph()->zone(), callable.descriptor(),
5065        callable.descriptor().GetStackParameterCount(), flags,
5066        Operator::kNoProperties);
5067    to_numeric_operator_.set(common()->Call(call_descriptor));
5068  }
5069  return to_numeric_operator_.get();
5070}
5071
5072void SimplifiedLowering::ChangeOp(Node* node, const Operator* new_op) {
5073  compiler::NodeProperties::ChangeOp(node, new_op);
5074
5075  if (V8_UNLIKELY(observe_node_manager_ != nullptr))
5076    observe_node_manager_->OnNodeChanged(kSimplifiedLoweringReducerName, node,
5077                                         node);
5078}
5079
5080#undef TRACE
5081
5082}  // namespace compiler
5083}  // namespace internal
5084}  // namespace v8
5085