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