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