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