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