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