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