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