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