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 23207 : MachineRepresentation MachineRepresentationFromArrayType(
69 : ExternalArrayType array_type) {
70 23207 : switch (array_type) {
71 : case kExternalUint8Array:
72 : case kExternalUint8ClampedArray:
73 : case kExternalInt8Array:
74 : return MachineRepresentation::kWord8;
75 : case kExternalUint16Array:
76 : case kExternalInt16Array:
77 3171 : return MachineRepresentation::kWord16;
78 : case kExternalUint32Array:
79 : case kExternalInt32Array:
80 4129 : return MachineRepresentation::kWord32;
81 : case kExternalFloat32Array:
82 6664 : return MachineRepresentation::kFloat32;
83 : case kExternalFloat64Array:
84 2083 : return MachineRepresentation::kFloat64;
85 : }
86 0 : UNREACHABLE();
87 : return MachineRepresentation::kNone;
88 : }
89 :
90 1151120 : UseInfo CheckedUseInfoAsWord32FromHint(
91 : NumberOperationHint hint,
92 : IdentifyZeros identify_zeros = kDistinguishZeros) {
93 1151120 : switch (hint) {
94 : case NumberOperationHint::kSignedSmall:
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 : return UseInfo::None();
105 : }
106 :
107 36140 : UseInfo CheckedUseInfoAsFloat64FromHint(NumberOperationHint hint) {
108 36140 : switch (hint) {
109 : case NumberOperationHint::kSignedSmall:
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 : return UseInfo::None();
121 : }
122 :
123 18735578 : UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) {
124 18735578 : switch (rep) {
125 : case MachineRepresentation::kTaggedSigned:
126 : case MachineRepresentation::kTaggedPointer:
127 : case MachineRepresentation::kTagged:
128 : return UseInfo::AnyTagged();
129 : case MachineRepresentation::kFloat64:
130 : return UseInfo::TruncatingFloat64();
131 : case MachineRepresentation::kFloat32:
132 : return UseInfo::Float32();
133 : case MachineRepresentation::kWord64:
134 : return UseInfo::TruncatingWord64();
135 : case MachineRepresentation::kWord8:
136 : case MachineRepresentation::kWord16:
137 : case MachineRepresentation::kWord32:
138 : return UseInfo::TruncatingWord32();
139 : case MachineRepresentation::kBit:
140 : return UseInfo::Bool();
141 : case MachineRepresentation::kSimd128:
142 : case MachineRepresentation::kSimd1x4:
143 : case MachineRepresentation::kSimd1x8:
144 : case MachineRepresentation::kSimd1x16:
145 : case MachineRepresentation::kNone:
146 : break;
147 : }
148 0 : UNREACHABLE();
149 : return UseInfo::None();
150 : }
151 :
152 :
153 2760848 : UseInfo UseInfoForBasePointer(const FieldAccess& access) {
154 5596812 : return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
155 : }
156 :
157 :
158 494916 : UseInfo UseInfoForBasePointer(const ElementAccess& access) {
159 606839 : return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
160 : }
161 :
162 365091 : void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) {
163 2357476 : for (Edge edge : node->use_edges()) {
164 996192 : if (NodeProperties::IsControlEdge(edge)) {
165 0 : edge.UpdateTo(control);
166 996197 : } else if (NodeProperties::IsEffectEdge(edge)) {
167 441166 : edge.UpdateTo(effect);
168 : } else {
169 : DCHECK(NodeProperties::IsValueEdge(edge) ||
170 : NodeProperties::IsContextEdge(edge));
171 : }
172 : }
173 365092 : }
174 :
175 831483 : void ChangeToPureOp(Node* node, const Operator* new_op) {
176 : DCHECK(new_op->HasProperty(Operator::kPure));
177 784956 : if (node->op()->EffectInputCount() > 0) {
178 : DCHECK_LT(0, node->op()->ControlInputCount());
179 : // Disconnect the node from effect and control chains.
180 219499 : Node* control = NodeProperties::GetControlInput(node);
181 219501 : Node* effect = NodeProperties::GetEffectInput(node);
182 219498 : ReplaceEffectControlUses(node, effect, control);
183 219507 : node->TrimInputCount(new_op->ValueInputCount());
184 : } else {
185 : DCHECK_EQ(0, node->op()->ControlInputCount());
186 : }
187 392488 : NodeProperties::ChangeOp(node, new_op);
188 392491 : }
189 :
190 : #ifdef DEBUG
191 : // Helpers for monotonicity checking.
192 : class InputUseInfos {
193 : public:
194 : explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
195 :
196 : void SetAndCheckInput(Node* node, int index, UseInfo use_info) {
197 : if (input_use_infos_.empty()) {
198 : input_use_infos_.resize(node->InputCount(), UseInfo::None());
199 : }
200 : // Check that the new use informatin is a super-type of the old
201 : // one.
202 : CHECK(IsUseLessGeneral(input_use_infos_[index], use_info));
203 : input_use_infos_[index] = use_info;
204 : }
205 :
206 : private:
207 : ZoneVector<UseInfo> input_use_infos_;
208 :
209 : static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
210 : return use1.truncation().IsLessGeneralThan(use2.truncation());
211 : }
212 : };
213 :
214 : #endif // DEBUG
215 :
216 308489 : bool CanOverflowSigned32(const Operator* op, Type* left, Type* right,
217 : Zone* type_zone) {
218 : // We assume the inputs are checked Signed32 (or known statically
219 : // to be Signed32). Technically, theinputs could also be minus zero, but
220 : // that cannot cause overflow.
221 154247 : left = Type::Intersect(left, Type::Signed32(), type_zone);
222 154246 : right = Type::Intersect(right, Type::Signed32(), type_zone);
223 308493 : if (!left->IsInhabited() || !right->IsInhabited()) return false;
224 154242 : switch (op->opcode()) {
225 : case IrOpcode::kSpeculativeNumberAdd:
226 133525 : return (left->Max() + right->Max() > kMaxInt) ||
227 133525 : (left->Min() + right->Min() < kMinInt);
228 :
229 : case IrOpcode::kSpeculativeNumberSubtract:
230 30562 : return (left->Max() - right->Min() > kMaxInt) ||
231 30562 : (left->Min() - right->Max() < kMinInt);
232 :
233 : default:
234 0 : UNREACHABLE();
235 : }
236 : return true;
237 : }
238 :
239 : } // namespace
240 :
241 : class RepresentationSelector {
242 : public:
243 : // Information for each node tracked during the fixpoint.
244 394593 : class NodeInfo final {
245 : public:
246 : // Adds new use to the node. Returns true if something has changed
247 : // and the node has to be requeued.
248 87720780 : bool AddUse(UseInfo info) {
249 87720780 : Truncation old_truncation = truncation_;
250 87720780 : truncation_ = Truncation::Generalize(truncation_, info.truncation());
251 87718469 : return truncation_ != old_truncation;
252 : }
253 :
254 35819996 : void set_queued() { state_ = kQueued; }
255 64499146 : void set_visited() { state_ = kVisited; }
256 28679945 : void set_pushed() { state_ = kPushed; }
257 47374320 : void reset_state() { state_ = kUnvisited; }
258 : bool visited() const { return state_ == kVisited; }
259 : bool queued() const { return state_ == kQueued; }
260 : bool unvisited() const { return state_ == kUnvisited; }
261 : Truncation truncation() const { return truncation_; }
262 33664315 : void set_output(MachineRepresentation output) { representation_ = output; }
263 :
264 : MachineRepresentation representation() const { return representation_; }
265 :
266 : // Helpers for feedback typing.
267 20702598 : void set_feedback_type(Type* type) { feedback_type_ = type; }
268 : Type* feedback_type() const { return feedback_type_; }
269 110866 : void set_weakened() { weakened_ = true; }
270 : bool weakened() const { return weakened_; }
271 28709927 : void set_restriction_type(Type* type) { restriction_type_ = type; }
272 : Type* restriction_type() const { return restriction_type_; }
273 :
274 : private:
275 : enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued };
276 : State state_ = kUnvisited;
277 : MachineRepresentation representation_ =
278 : MachineRepresentation::kNone; // Output representation.
279 : Truncation truncation_ = Truncation::None(); // Information about uses.
280 :
281 : Type* restriction_type_ = Type::Any();
282 : Type* feedback_type_ = nullptr;
283 : bool weakened_ = false;
284 : };
285 :
286 1183780 : RepresentationSelector(JSGraph* jsgraph, Zone* zone,
287 : RepresentationChanger* changer,
288 394594 : SourcePositionTable* source_positions)
289 : : jsgraph_(jsgraph),
290 : zone_(zone),
291 394593 : count_(jsgraph->graph()->NodeCount()),
292 : info_(count_, zone),
293 : #ifdef DEBUG
294 : node_input_use_infos_(count_, InputUseInfos(zone), zone),
295 : #endif
296 : nodes_(zone),
297 : replacements_(zone),
298 : phase_(PROPAGATE),
299 : changer_(changer),
300 : queue_(zone),
301 : typing_stack_(zone),
302 : source_positions_(source_positions),
303 394593 : type_cache_(TypeCache::Get()),
304 1972967 : op_typer_(jsgraph->isolate(), graph_zone()) {
305 394593 : }
306 :
307 : // Forward propagation of types from type feedback.
308 1183762 : void RunTypePropagationPhase() {
309 : // Run type propagation.
310 394594 : TRACE("--{Type propagation phase}--\n");
311 394594 : phase_ = RETYPE;
312 : ResetNodeInfoState();
313 :
314 : DCHECK(typing_stack_.empty());
315 789168 : typing_stack_.push({graph()->end(), 0});
316 394574 : GetInfo(graph()->end())->set_pushed();
317 57357181 : while (!typing_stack_.empty()) {
318 : NodeState& current = typing_stack_.top();
319 :
320 : // If there is an unvisited input, push it and continue.
321 : bool pushed_unvisited = false;
322 280807297 : while (current.input_index < current.node->InputCount()) {
323 : Node* input = current.node->InputAt(current.input_index);
324 83245139 : NodeInfo* input_info = GetInfo(input);
325 83245139 : current.input_index++;
326 83245139 : if (input_info->unvisited()) {
327 : input_info->set_pushed();
328 56570998 : typing_stack_.push({input, 0});
329 : pushed_unvisited = true;
330 28285627 : break;
331 : }
332 : }
333 56962843 : if (pushed_unvisited) continue;
334 :
335 : // Process the top of the stack.
336 28679697 : Node* node = current.node;
337 : typing_stack_.pop();
338 : NodeInfo* info = GetInfo(node);
339 : info->set_visited();
340 28679697 : bool updated = UpdateFeedbackType(node);
341 28679697 : TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
342 28679697 : VisitNode(node, info->truncation(), nullptr);
343 28679274 : TRACE(" ==> output ");
344 28679274 : PrintOutputInfo(info);
345 28679334 : TRACE("\n");
346 28679548 : if (updated) {
347 154530776 : for (Node* const user : node->uses()) {
348 67809123 : if (GetInfo(user)->visited()) {
349 : GetInfo(user)->set_queued();
350 : queue_.push(user);
351 : }
352 : }
353 : }
354 : }
355 :
356 : // Process the revisit queue.
357 6298236 : while (!queue_.empty()) {
358 5903643 : Node* node = queue_.front();
359 : queue_.pop();
360 : NodeInfo* info = GetInfo(node);
361 : info->set_visited();
362 5903647 : bool updated = UpdateFeedbackType(node);
363 5903665 : TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
364 5903665 : VisitNode(node, info->truncation(), nullptr);
365 5903653 : TRACE(" ==> output ");
366 5903653 : PrintOutputInfo(info);
367 5903654 : TRACE("\n");
368 5903646 : if (updated) {
369 14434580 : for (Node* const user : node->uses()) {
370 6322428 : if (GetInfo(user)->visited()) {
371 : GetInfo(user)->set_queued();
372 : queue_.push(user);
373 : }
374 : }
375 : }
376 : }
377 394593 : }
378 :
379 : void ResetNodeInfoState() {
380 : // Clean up for the next phase.
381 47768914 : for (NodeInfo& info : info_) {
382 : info.reset_state();
383 : }
384 : }
385 :
386 : Type* TypeOf(Node* node) {
387 28400307 : Type* type = GetInfo(node)->feedback_type();
388 28400307 : return type == nullptr ? NodeProperties::GetType(node) : type;
389 : }
390 :
391 : Type* FeedbackTypeOf(Node* node) {
392 4434236 : Type* type = GetInfo(node)->feedback_type();
393 4434236 : return type == nullptr ? Type::None() : type;
394 : }
395 :
396 1036140 : Type* TypePhi(Node* node) {
397 1036140 : int arity = node->op()->ValueInputCount();
398 : Type* type = FeedbackTypeOf(node->InputAt(0));
399 2633050 : for (int i = 1; i < arity; ++i) {
400 1596920 : type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i)));
401 : }
402 1036130 : return type;
403 : }
404 :
405 10462 : Type* TypeSelect(Node* node) {
406 : return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)),
407 10462 : FeedbackTypeOf(node->InputAt(2)));
408 : }
409 :
410 36936492 : bool UpdateFeedbackType(Node* node) {
411 34583014 : if (node->op()->ValueOutputCount() == 0) return false;
412 :
413 25504989 : NodeInfo* info = GetInfo(node);
414 : Type* type = info->feedback_type();
415 : Type* new_type = type;
416 :
417 : // For any non-phi node just wait until we get all inputs typed. We only
418 : // allow untyped inputs for phi nodes because phis are the only places
419 : // where cycles need to be broken.
420 25143483 : if (node->opcode() != IrOpcode::kPhi) {
421 133468416 : for (int i = 0; i < node->op()->ValueInputCount(); i++) {
422 56116064 : if (GetInfo(node->InputAt(i))->feedback_type() == nullptr) {
423 : return false;
424 : }
425 : }
426 : }
427 :
428 23708022 : switch (node->opcode()) {
429 : #define DECLARE_CASE(Name) \
430 : case IrOpcode::k##Name: { \
431 : new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \
432 : FeedbackTypeOf(node->InputAt(1))); \
433 : break; \
434 : }
435 476107 : SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE)
436 : #undef DECLARE_CASE
437 :
438 : #define DECLARE_CASE(Name) \
439 : case IrOpcode::k##Name: { \
440 : new_type = \
441 : Type::Intersect(op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \
442 : FeedbackTypeOf(node->InputAt(1))), \
443 : info->restriction_type(), graph_zone()); \
444 : break; \
445 : }
446 358759 : SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE)
447 : #undef DECLARE_CASE
448 :
449 : #define DECLARE_CASE(Name) \
450 : case IrOpcode::k##Name: { \
451 : new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0))); \
452 : break; \
453 : }
454 67492 : SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE)
455 : #undef DECLARE_CASE
456 :
457 : #define DECLARE_CASE(Name) \
458 : case IrOpcode::k##Name: { \
459 : new_type = \
460 : Type::Intersect(op_typer_.Name(FeedbackTypeOf(node->InputAt(0))), \
461 : info->restriction_type(), graph_zone()); \
462 : break; \
463 : }
464 1469 : SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_CASE)
465 : #undef DECLARE_CASE
466 :
467 : case IrOpcode::kPlainPrimitiveToNumber:
468 16401 : new_type = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
469 16401 : break;
470 :
471 : case IrOpcode::kCheckFloat64Hole:
472 : new_type = Type::Intersect(
473 : op_typer_.CheckFloat64Hole(FeedbackTypeOf(node->InputAt(0))),
474 780 : info->restriction_type(), graph_zone());
475 780 : break;
476 :
477 : case IrOpcode::kCheckNumber:
478 : new_type = Type::Intersect(
479 : op_typer_.CheckNumber(FeedbackTypeOf(node->InputAt(0))),
480 498 : info->restriction_type(), graph_zone());
481 498 : break;
482 :
483 : case IrOpcode::kPhi: {
484 1036139 : new_type = TypePhi(node);
485 1036130 : if (type != nullptr) {
486 475727 : new_type = Weaken(node, type, new_type);
487 : }
488 : break;
489 : }
490 :
491 : case IrOpcode::kTypeGuard: {
492 : new_type = op_typer_.TypeTypeGuard(node->op(),
493 23880 : FeedbackTypeOf(node->InputAt(0)));
494 23880 : break;
495 : }
496 :
497 : case IrOpcode::kSelect: {
498 10462 : new_type = TypeSelect(node);
499 10462 : break;
500 : }
501 :
502 : default:
503 : // Shortcut for operations that we do not handle.
504 21716035 : if (type == nullptr) {
505 : GetInfo(node)->set_feedback_type(NodeProperties::GetType(node));
506 18908654 : return true;
507 : }
508 : return false;
509 : }
510 : // We need to guarantee that the feedback type is a subtype of the upper
511 : // bound. Naively that should hold, but weakening can actually produce
512 : // a bigger type if we are unlucky with ordering of phi typing. To be
513 : // really sure, just intersect the upper bound with the feedback type.
514 1991972 : new_type = Type::Intersect(GetUpperBound(node), new_type, graph_zone());
515 :
516 2818957 : if (type != nullptr && new_type->Is(type)) return false;
517 : GetInfo(node)->set_feedback_type(new_type);
518 1793944 : if (FLAG_trace_representation) {
519 0 : PrintNodeFeedbackType(node);
520 : }
521 : return true;
522 : }
523 :
524 0 : void PrintNodeFeedbackType(Node* n) {
525 0 : OFStream os(stdout);
526 0 : os << "#" << n->id() << ":" << *n->op() << "(";
527 : int j = 0;
528 0 : for (Node* const i : n->inputs()) {
529 0 : if (j++ > 0) os << ", ";
530 0 : os << "#" << i->id() << ":" << i->op()->mnemonic();
531 : }
532 0 : os << ")";
533 0 : if (NodeProperties::IsTyped(n)) {
534 0 : os << " [Static type: ";
535 : Type* static_type = NodeProperties::GetType(n);
536 0 : static_type->PrintTo(os);
537 0 : Type* feedback_type = GetInfo(n)->feedback_type();
538 0 : if (feedback_type != nullptr && feedback_type != static_type) {
539 0 : os << ", Feedback type: ";
540 0 : feedback_type->PrintTo(os);
541 : }
542 0 : os << "]";
543 : }
544 0 : os << std::endl;
545 0 : }
546 :
547 1704366 : Type* Weaken(Node* node, Type* previous_type, Type* current_type) {
548 : // If the types have nothing to do with integers, return the types.
549 475726 : Type* const integer = type_cache_.kInteger;
550 475726 : if (!previous_type->Maybe(integer)) {
551 : return current_type;
552 : }
553 : DCHECK(current_type->Maybe(integer));
554 :
555 : Type* current_integer =
556 411614 : Type::Intersect(current_type, integer, graph_zone());
557 : Type* previous_integer =
558 411615 : Type::Intersect(previous_type, integer, graph_zone());
559 :
560 : // Once we start weakening a node, we should always weaken.
561 411613 : if (!GetInfo(node)->weakened()) {
562 : // Only weaken if there is range involved; we should converge quickly
563 : // for all other types (the exception is a union of many constants,
564 : // but we currently do not increase the number of constants in unions).
565 117068 : Type* previous = previous_integer->GetRange();
566 117068 : Type* current = current_integer->GetRange();
567 117068 : if (current == nullptr || previous == nullptr) {
568 : return current_type;
569 : }
570 : // Range is involved => we are weakening.
571 : GetInfo(node)->set_weakened();
572 : }
573 :
574 : return Type::Union(current_type,
575 : op_typer_.WeakenRange(previous_integer, current_integer),
576 405411 : graph_zone());
577 : }
578 :
579 : // Backward propagation of truncations.
580 394593 : void RunTruncationPropagationPhase() {
581 : // Run propagation phase to a fixpoint.
582 394593 : TRACE("--{Propagation phase}--\n");
583 394593 : phase_ = PROPAGATE;
584 394593 : EnqueueInitial(jsgraph_->graph()->end());
585 : // Process nodes from the queue until it is empty.
586 30704908 : while (!queue_.empty()) {
587 29915723 : Node* node = queue_.front();
588 : NodeInfo* info = GetInfo(node);
589 : queue_.pop();
590 : info->set_visited();
591 29915802 : TRACE(" visit #%d: %s (trunc: %s)\n", node->id(), node->op()->mnemonic(),
592 : info->truncation().description());
593 29915802 : VisitNode(node, info->truncation(), nullptr);
594 : }
595 394594 : }
596 :
597 394593 : void Run(SimplifiedLowering* lowering) {
598 394593 : RunTruncationPropagationPhase();
599 :
600 394594 : RunTypePropagationPhase();
601 :
602 : // Run lowering and change insertion phase.
603 394594 : TRACE("--{Simplified lowering phase}--\n");
604 394617 : phase_ = LOWER;
605 : // Process nodes from the collected {nodes_} vector.
606 29469524 : for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
607 28680313 : Node* node = *i;
608 : NodeInfo* info = GetInfo(node);
609 28680313 : TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
610 : // Reuse {VisitNode()} so the representation rules are in one place.
611 : SourcePositionTable::Scope scope(
612 28680313 : source_positions_, source_positions_->GetSourcePosition(node));
613 28680312 : VisitNode(node, info->truncation(), lowering);
614 : }
615 :
616 : // Perform the final replacements.
617 1039808 : for (NodeVector::iterator i = replacements_.begin();
618 : i != replacements_.end(); ++i) {
619 250620 : Node* node = *i;
620 250620 : Node* replacement = *(++i);
621 250620 : node->ReplaceUses(replacement);
622 250620 : node->Kill();
623 : // We also need to replace the node in the rest of the vector.
624 16608306 : for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
625 : ++j;
626 16107066 : if (*j == node) *j = replacement;
627 : }
628 : }
629 394594 : }
630 :
631 394593 : void EnqueueInitial(Node* node) {
632 394593 : NodeInfo* info = GetInfo(node);
633 : info->set_queued();
634 394593 : nodes_.push_back(node);
635 : queue_.push(node);
636 394591 : }
637 :
638 : // Enqueue {use_node}'s {index} input if the {use} contains new information
639 : // for that input node. Add the input to {nodes_} if this is the first time
640 : // it's been visited.
641 139044269 : void EnqueueInput(Node* use_node, int index,
642 : UseInfo use_info = UseInfo::None()) {
643 139044269 : Node* node = use_node->InputAt(index);
644 218647550 : if (phase_ != PROPAGATE) return;
645 89610724 : NodeInfo* info = GetInfo(node);
646 : #ifdef DEBUG
647 : // Check monotonicity of input requirements.
648 : node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
649 : use_info);
650 : #endif // DEBUG
651 87726509 : if (info->unvisited()) {
652 : // First visit of this node.
653 : info->set_queued();
654 28285567 : nodes_.push_back(node);
655 : queue_.push(node);
656 28285547 : TRACE(" initial #%i: ", node->id());
657 28285547 : info->AddUse(use_info);
658 28285504 : PrintTruncation(info->truncation());
659 28285521 : return;
660 : }
661 59440942 : TRACE(" queue #%i?: ", node->id());
662 59440942 : PrintTruncation(info->truncation());
663 59440913 : if (info->AddUse(use_info)) {
664 : // New usage information for the node is available.
665 1884215 : if (!info->queued()) {
666 : queue_.push(node);
667 : info->set_queued();
668 1236105 : TRACE(" added: ");
669 : } else {
670 648108 : TRACE(" inqueue: ");
671 : }
672 1884213 : PrintTruncation(info->truncation());
673 : }
674 : }
675 :
676 : bool lower() const { return phase_ == LOWER; }
677 : bool retype() const { return phase_ == RETYPE; }
678 : bool propagate() const { return phase_ == PROPAGATE; }
679 :
680 : void SetOutput(Node* node, MachineRepresentation representation,
681 : Type* restriction_type = Type::Any()) {
682 : NodeInfo* const info = GetInfo(node);
683 90252732 : switch (phase_) {
684 : case PROPAGATE:
685 : info->set_restriction_type(restriction_type);
686 : break;
687 : case RETYPE:
688 : DCHECK(info->restriction_type()->Is(restriction_type));
689 : DCHECK(restriction_type->Is(info->restriction_type()));
690 : info->set_output(representation);
691 : break;
692 : case LOWER:
693 : DCHECK_EQ(info->representation(), representation);
694 : DCHECK(info->restriction_type()->Is(restriction_type));
695 : DCHECK(restriction_type->Is(info->restriction_type()));
696 : break;
697 : }
698 : }
699 :
700 : Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
701 :
702 57639 : bool InputCannotBe(Node* node, Type* type) {
703 : DCHECK_EQ(1, node->op()->ValueInputCount());
704 57639 : return !GetUpperBound(node->InputAt(0))->Maybe(type);
705 : }
706 :
707 182386 : bool InputIs(Node* node, Type* type) {
708 : DCHECK_EQ(1, node->op()->ValueInputCount());
709 182386 : return GetUpperBound(node->InputAt(0))->Is(type);
710 : }
711 :
712 : bool BothInputsAreSigned32(Node* node) {
713 98910 : return BothInputsAre(node, Type::Signed32());
714 : }
715 :
716 : bool BothInputsAreUnsigned32(Node* node) {
717 107906 : return BothInputsAre(node, Type::Unsigned32());
718 : }
719 :
720 4464200 : bool BothInputsAre(Node* node, Type* type) {
721 : DCHECK_EQ(2, node->op()->ValueInputCount());
722 6247724 : return GetUpperBound(node->InputAt(0))->Is(type) &&
723 4464154 : GetUpperBound(node->InputAt(1))->Is(type);
724 : }
725 :
726 : bool IsNodeRepresentationTagged(Node* node) {
727 42882 : MachineRepresentation representation = GetInfo(node)->representation();
728 : return IsAnyTagged(representation);
729 : }
730 :
731 2883 : bool OneInputCannotBe(Node* node, Type* type) {
732 : DCHECK_EQ(2, node->op()->ValueInputCount());
733 5766 : return !GetUpperBound(node->InputAt(0))->Maybe(type) ||
734 5766 : !GetUpperBound(node->InputAt(1))->Maybe(type);
735 : }
736 :
737 64016554 : void ConvertInput(Node* node, int index, UseInfo use) {
738 0 : Node* input = node->InputAt(index);
739 : // In the change phase, insert a change before the use if necessary.
740 50798013 : if (use.representation() == MachineRepresentation::kNone)
741 50798025 : return; // No input requirement on the use.
742 : DCHECK_NOT_NULL(input);
743 61643750 : NodeInfo* input_info = GetInfo(input);
744 : MachineRepresentation input_rep = input_info->representation();
745 83724337 : if (input_rep != use.representation() ||
746 35299111 : use.type_check() != TypeCheckKind::kNone) {
747 : // Output representation doesn't match usage.
748 13218543 : TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
749 : index, input->id(), input->op()->mnemonic());
750 13218538 : TRACE(" from ");
751 13218538 : PrintOutputInfo(input_info);
752 13218541 : TRACE(" to ");
753 13218541 : PrintUseInfo(use);
754 13218519 : TRACE("\n");
755 : Node* n = changer_->GetRepresentationFor(
756 13218524 : input, input_info->representation(), TypeOf(input), node, use);
757 13218556 : node->ReplaceInput(index, n);
758 : }
759 : }
760 :
761 167059102 : void ProcessInput(Node* node, int index, UseInfo use) {
762 167059102 : switch (phase_) {
763 : case PROPAGATE:
764 53688393 : EnqueueInput(node, index, use);
765 53687471 : break;
766 : case RETYPE:
767 : break;
768 : case LOWER:
769 50797820 : ConvertInput(node, index, use);
770 50797665 : break;
771 : }
772 167058025 : }
773 :
774 13107742 : void ProcessRemainingInputs(Node* node, int index) {
775 : DCHECK_GE(index, NodeProperties::PastValueIndex(node));
776 : DCHECK_GE(index, NodeProperties::PastContextIndex(node));
777 58126722 : for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
778 22509515 : i < NodeProperties::PastEffectIndex(node); ++i) {
779 9401794 : EnqueueInput(node, i); // Effect inputs: just visit
780 : }
781 58266923 : for (int i = std::max(index, NodeProperties::FirstControlIndex(node));
782 22579617 : i < NodeProperties::PastControlIndex(node); ++i) {
783 9471966 : EnqueueInput(node, i); // Control inputs: just visit
784 : }
785 13107695 : }
786 :
787 : // The default, most general visitation case. For {node}, process all value,
788 : // context, frame state, effect, and control inputs, assuming that value
789 : // inputs should have {kRepTagged} representation and can observe all output
790 : // values {kTypeAny}.
791 78619771 : void VisitInputs(Node* node) {
792 78619771 : int tagged_count = node->op()->ValueInputCount() +
793 : OperatorProperties::GetContextInputCount(node->op()) +
794 39308707 : OperatorProperties::GetFrameStateInputCount(node->op());
795 : // Visit value, context and frame state inputs as tagged.
796 149549339 : for (int i = 0; i < tagged_count; i++) {
797 110240520 : ProcessInput(node, i, UseInfo::AnyTagged());
798 : }
799 : // Only enqueue other inputs (effects, control).
800 136974641 : for (int i = tagged_count; i < node->InputCount(); i++) {
801 48832756 : EnqueueInput(node, i);
802 : }
803 39308974 : }
804 :
805 3186142 : void VisitReturn(Node* node) {
806 3186142 : int tagged_limit = node->op()->ValueInputCount() +
807 : OperatorProperties::GetContextInputCount(node->op()) +
808 1593072 : OperatorProperties::GetFrameStateInputCount(node->op());
809 : // Visit integer slot count to pop
810 1593072 : ProcessInput(node, 0, UseInfo::TruncatingWord32());
811 :
812 : // Visit value, context and frame state inputs as tagged.
813 3186137 : for (int i = 1; i < tagged_limit; i++) {
814 1593069 : ProcessInput(node, i, UseInfo::AnyTagged());
815 : }
816 : // Only enqueue other inputs (effects, control).
817 7965360 : for (int i = tagged_limit; i < node->InputCount(); i++) {
818 3186139 : EnqueueInput(node, i);
819 : }
820 1593075 : }
821 :
822 : // Helper for an unused node.
823 1708078 : void VisitUnused(Node* node) {
824 1138720 : int value_count = node->op()->ValueInputCount() +
825 : OperatorProperties::GetContextInputCount(node->op()) +
826 569356 : OperatorProperties::GetFrameStateInputCount(node->op());
827 1501477 : for (int i = 0; i < value_count; i++) {
828 932118 : ProcessInput(node, i, UseInfo::None());
829 : }
830 569359 : ProcessRemainingInputs(node, value_count);
831 569358 : if (lower()) Kill(node);
832 569358 : }
833 :
834 : // Helper for no-op node.
835 356 : void VisitNoop(Node* node, Truncation truncation) {
836 372 : if (truncation.IsUnused()) return VisitUnused(node);
837 : MachineRepresentation representation =
838 170 : GetOutputInfoForPhi(node, TypeOf(node), truncation);
839 170 : VisitUnop(node, UseInfo(representation, truncation), representation);
840 231 : if (lower()) DeferReplacement(node, node->InputAt(0));
841 : }
842 :
843 : // Helper for binops of the R x L -> O variety.
844 3706082 : void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
845 : MachineRepresentation output,
846 : Type* restriction_type = Type::Any()) {
847 : DCHECK_EQ(2, node->op()->ValueInputCount());
848 3706082 : ProcessInput(node, 0, left_use);
849 3706086 : ProcessInput(node, 1, right_use);
850 13914844 : for (int i = 2; i < node->InputCount(); i++) {
851 3251357 : EnqueueInput(node, i);
852 : }
853 : SetOutput(node, output, restriction_type);
854 3706065 : }
855 :
856 : // Helper for binops of the I x I -> O variety.
857 : void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output,
858 : Type* restriction_type = Type::Any()) {
859 2936964 : VisitBinop(node, input_use, input_use, output, restriction_type);
860 : }
861 :
862 104343 : void VisitSpeculativeInt32Binop(Node* node) {
863 : DCHECK_EQ(2, node->op()->ValueInputCount());
864 84022 : if (BothInputsAre(node, Type::NumberOrOddball())) {
865 : return VisitBinop(node, UseInfo::TruncatingWord32(),
866 : MachineRepresentation::kWord32);
867 : }
868 20321 : NumberOperationHint hint = NumberOperationHintOf(node->op());
869 : return VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
870 20321 : MachineRepresentation::kWord32);
871 : }
872 :
873 : // Helper for unops of the I -> O variety.
874 6620993 : void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output,
875 : Type* restriction_type = Type::Any()) {
876 : DCHECK_EQ(1, node->op()->ValueInputCount());
877 6620993 : ProcessInput(node, 0, input_use);
878 6620994 : ProcessRemainingInputs(node, 1);
879 : SetOutput(node, output, restriction_type);
880 6620983 : }
881 :
882 : // Helper for leaf nodes.
883 : void VisitLeaf(Node* node, MachineRepresentation output) {
884 : DCHECK_EQ(0, node->InputCount());
885 : SetOutput(node, output);
886 : }
887 :
888 : // Helpers for specific types of binops.
889 665475 : void VisitFloat64Binop(Node* node) {
890 : VisitBinop(node, UseInfo::TruncatingFloat64(),
891 : MachineRepresentation::kFloat64);
892 665478 : }
893 492900 : void VisitWord32TruncatingBinop(Node* node) {
894 : VisitBinop(node, UseInfo::TruncatingWord32(),
895 : MachineRepresentation::kWord32);
896 492902 : }
897 :
898 : // Infer representation for phi-like nodes.
899 : // The {node} parameter is only used to decide on the int64 representation.
900 : // Once the type system supports an external pointer type, the {node}
901 : // parameter can be removed.
902 2334158 : MachineRepresentation GetOutputInfoForPhi(Node* node, Type* type,
903 1730263 : Truncation use) {
904 : // Compute the representation.
905 2334158 : if (type->Is(Type::None())) {
906 : return MachineRepresentation::kNone;
907 4218192 : } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
908 : return MachineRepresentation::kWord32;
909 2729617 : } else if (type->Is(Type::NumberOrOddball()) && use.IsUsedAsWord32()) {
910 : return MachineRepresentation::kWord32;
911 1912732 : } else if (type->Is(Type::Boolean())) {
912 : return MachineRepresentation::kBit;
913 2516807 : } else if (type->Is(Type::NumberOrOddball()) && use.IsUsedAsFloat64()) {
914 : return MachineRepresentation::kFloat64;
915 1730259 : } else if (type->Is(
916 1730263 : Type::Union(Type::SignedSmall(), Type::NaN(), zone()))) {
917 : // TODO(turbofan): For Phis that return either NaN or some Smi, it's
918 : // beneficial to not go all the way to double, unless the uses are
919 : // double uses. For tagging that just means some potentially expensive
920 : // allocation code; we might want to do the same for -0 as well?
921 : return MachineRepresentation::kTagged;
922 1729552 : } else if (type->Is(Type::Number())) {
923 : return MachineRepresentation::kFloat64;
924 1122403 : } else if (type->Is(Type::ExternalPointer())) {
925 : return MachineType::PointerRepresentation();
926 : }
927 1122403 : return MachineRepresentation::kTagged;
928 : }
929 :
930 : // Helper for handling selects.
931 43055 : void VisitSelect(Node* node, Truncation truncation,
932 32593 : SimplifiedLowering* lowering) {
933 : DCHECK(TypeOf(node->InputAt(0))->Is(Type::Boolean()));
934 32593 : ProcessInput(node, 0, UseInfo::Bool());
935 :
936 : MachineRepresentation output =
937 32593 : GetOutputInfoForPhi(node, TypeOf(node), truncation);
938 : SetOutput(node, output);
939 :
940 32593 : if (lower()) {
941 : // Update the select operator.
942 10462 : SelectParameters p = SelectParametersOf(node->op());
943 10462 : if (output != p.representation()) {
944 : NodeProperties::ChangeOp(node,
945 10452 : lowering->common()->Select(output, p.hint()));
946 : }
947 : }
948 : // Convert inputs to the output representation of this phi, pass the
949 : // truncation truncation along.
950 : UseInfo input_use(output, truncation);
951 32593 : ProcessInput(node, 1, input_use);
952 32593 : ProcessInput(node, 2, input_use);
953 32593 : }
954 :
955 : // Helper for handling phis.
956 4463892 : void VisitPhi(Node* node, Truncation truncation,
957 2231950 : SimplifiedLowering* lowering) {
958 : MachineRepresentation output =
959 2231942 : GetOutputInfoForPhi(node, TypeOf(node), truncation);
960 : // Only set the output representation if not running with type
961 : // feedback. (Feedback typing will set the representation.)
962 : SetOutput(node, output);
963 :
964 2231950 : int values = node->op()->ValueInputCount();
965 2231950 : if (lower()) {
966 : // Update the phi operator.
967 560418 : if (output != PhiRepresentationOf(node->op())) {
968 206288 : NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values));
969 : }
970 : }
971 :
972 : // Convert inputs to the output representation of this phi, pass the
973 : // truncation along.
974 : UseInfo input_use(output, truncation);
975 20810324 : for (int i = 0; i < node->InputCount(); i++) {
976 8173231 : ProcessInput(node, i, i < values ? input_use : UseInfo::None());
977 : }
978 2231931 : }
979 :
980 453825 : void VisitObjectIs(Node* node, Type* type, SimplifiedLowering* lowering) {
981 : Type* const input_type = TypeOf(node->InputAt(0));
982 226699 : if (input_type->Is(type)) {
983 864 : VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
984 864 : if (lower()) {
985 237 : DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
986 : }
987 : } else {
988 225835 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
989 225835 : if (lower() && !input_type->Maybe(type)) {
990 190 : DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
991 : }
992 : }
993 226699 : }
994 :
995 4463222 : void VisitCall(Node* node, SimplifiedLowering* lowering) {
996 4463229 : const CallDescriptor* desc = CallDescriptorOf(node->op());
997 2231610 : int params = static_cast<int>(desc->ParameterCount());
998 2231610 : int value_input_count = node->op()->ValueInputCount();
999 : // Propagate representation information from call descriptor.
1000 22132370 : for (int i = 0; i < value_input_count; i++) {
1001 19900754 : if (i == 0) {
1002 : // The target of the call.
1003 2231577 : ProcessInput(node, i, UseInfo::Any());
1004 17669177 : } else if ((i - 1) < params) {
1005 : ProcessInput(node, i, TruncatingUseInfoFromRepresentation(
1006 30909090 : desc->GetInputType(i).representation()));
1007 : } else {
1008 2214632 : ProcessInput(node, i, UseInfo::AnyTagged());
1009 : }
1010 : }
1011 2231616 : ProcessRemainingInputs(node, value_input_count);
1012 :
1013 2231617 : if (desc->ReturnCount() > 0) {
1014 : SetOutput(node, desc->GetReturnType(0).representation());
1015 : } else {
1016 : SetOutput(node, MachineRepresentation::kTagged);
1017 : }
1018 2231617 : }
1019 :
1020 525377 : static MachineSemantic DeoptValueSemanticOf(Type* type) {
1021 : // We only need signedness to do deopt correctly.
1022 525386 : if (type->Is(Type::Signed32())) {
1023 : return MachineSemantic::kInt32;
1024 322856 : } else if (type->Is(Type::Unsigned32())) {
1025 : return MachineSemantic::kUint32;
1026 : } else {
1027 322079 : return MachineSemantic::kAny;
1028 : }
1029 : }
1030 :
1031 8870648 : static MachineType DeoptMachineTypeOf(MachineRepresentation rep, Type* type) {
1032 8870670 : if (!type->IsInhabited()) {
1033 : return MachineType::None();
1034 : }
1035 : // TODO(turbofan): Special treatment for ExternalPointer here,
1036 : // to avoid incompatible truncations. We really need a story
1037 : // for the JSFunction::entry field.
1038 8870666 : if (type->Is(Type::ExternalPointer())) {
1039 : return MachineType::Pointer();
1040 : }
1041 : // Do not distinguish between various Tagged variations.
1042 8870666 : if (IsAnyTagged(rep)) {
1043 : return MachineType::AnyTagged();
1044 : }
1045 525373 : MachineType machine_type(rep, DeoptValueSemanticOf(type));
1046 : DCHECK(machine_type.representation() != MachineRepresentation::kWord32 ||
1047 : machine_type.semantic() == MachineSemantic::kInt32 ||
1048 : machine_type.semantic() == MachineSemantic::kUint32);
1049 : DCHECK(machine_type.representation() != MachineRepresentation::kBit ||
1050 : type->Is(Type::Boolean()));
1051 525386 : return machine_type;
1052 : }
1053 :
1054 20404025 : void VisitStateValues(Node* node) {
1055 15883366 : if (propagate()) {
1056 22175816 : for (int i = 0; i < node->InputCount(); i++) {
1057 8827620 : EnqueueInput(node, i, UseInfo::Any());
1058 : }
1059 11362798 : } else if (lower()) {
1060 9041310 : Zone* zone = jsgraph_->zone();
1061 : ZoneVector<MachineType>* types =
1062 : new (zone->New(sizeof(ZoneVector<MachineType>)))
1063 4520654 : ZoneVector<MachineType>(node->InputCount(), zone);
1064 26696628 : for (int i = 0; i < node->InputCount(); i++) {
1065 : Node* input = node->InputAt(i);
1066 8827655 : (*types)[i] =
1067 8827655 : DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input));
1068 : }
1069 4520659 : SparseInputMask mask = SparseInputMaskOf(node->op());
1070 : NodeProperties::ChangeOp(
1071 9041312 : node, jsgraph_->common()->TypedStateValues(types, mask));
1072 : }
1073 : SetOutput(node, MachineRepresentation::kTagged);
1074 15883364 : }
1075 :
1076 28124 : void VisitObjectState(Node* node) {
1077 28124 : if (propagate()) {
1078 94884 : for (int i = 0; i < node->InputCount(); i++) {
1079 : Node* input = node->InputAt(i);
1080 : Type* input_type = TypeOf(input);
1081 : // TODO(turbofan): Special treatment for ExternalPointer here,
1082 : // to avoid incompatible truncations. We really need a story
1083 : // for the JSFunction::entry field.
1084 42991 : UseInfo use_info = UseInfo::None();
1085 42991 : if (input_type->IsInhabited()) {
1086 42991 : if (input_type->Is(Type::ExternalPointer())) {
1087 0 : use_info = UseInfo::PointerInt();
1088 : } else {
1089 42991 : use_info = UseInfo::Any();
1090 : }
1091 : }
1092 42991 : EnqueueInput(node, i, use_info);
1093 : }
1094 19222 : } else if (lower()) {
1095 17804 : Zone* zone = jsgraph_->zone();
1096 : ZoneVector<MachineType>* types =
1097 : new (zone->New(sizeof(ZoneVector<MachineType>)))
1098 8902 : ZoneVector<MachineType>(node->InputCount(), zone);
1099 103786 : for (int i = 0; i < node->InputCount(); i++) {
1100 : Node* input = node->InputAt(i);
1101 42991 : (*types)[i] =
1102 42991 : DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input));
1103 : }
1104 : NodeProperties::ChangeOp(node,
1105 17804 : jsgraph_->common()->TypedObjectState(types));
1106 : }
1107 : SetOutput(node, MachineRepresentation::kTagged);
1108 28124 : }
1109 :
1110 257998 : const Operator* Int32Op(Node* node) {
1111 257998 : return changer_->Int32OperatorFor(node->opcode());
1112 : }
1113 :
1114 150668 : const Operator* Int32OverflowOp(Node* node) {
1115 150668 : return changer_->Int32OverflowOperatorFor(node->opcode());
1116 : }
1117 :
1118 69475 : const Operator* Uint32Op(Node* node) {
1119 69475 : return changer_->Uint32OperatorFor(node->opcode());
1120 : }
1121 :
1122 190 : const Operator* Uint32OverflowOp(Node* node) {
1123 190 : return changer_->Uint32OverflowOperatorFor(node->opcode());
1124 : }
1125 :
1126 183795 : const Operator* Float64Op(Node* node) {
1127 183795 : return changer_->Float64OperatorFor(node->opcode());
1128 : }
1129 :
1130 2969420 : WriteBarrierKind WriteBarrierKindFor(
1131 : BaseTaggedness base_taggedness,
1132 : MachineRepresentation field_representation, Type* field_type,
1133 : MachineRepresentation value_representation, Node* value) {
1134 5813949 : if (base_taggedness == kTaggedBase &&
1135 : CanBeTaggedPointer(field_representation)) {
1136 : Type* value_type = NodeProperties::GetType(value);
1137 5065960 : if (field_representation == MachineRepresentation::kTaggedSigned ||
1138 2532980 : value_representation == MachineRepresentation::kTaggedSigned) {
1139 : // Write barriers are only for stores of heap objects.
1140 : return kNoWriteBarrier;
1141 : }
1142 5053940 : if (field_type->Is(Type::BooleanOrNullOrUndefined()) ||
1143 : value_type->Is(Type::BooleanOrNullOrUndefined())) {
1144 : // Write barriers are not necessary when storing true, false, null or
1145 : // undefined, because these special oddballs are always in the root set.
1146 : return kNoWriteBarrier;
1147 : }
1148 2243704 : if (value_type->IsHeapConstant()) {
1149 : Heap::RootListIndex root_index;
1150 820727 : Heap* heap = jsgraph_->isolate()->heap();
1151 820727 : if (heap->IsRootHandle(value_type->AsHeapConstant()->Value(),
1152 : &root_index)) {
1153 443799 : if (heap->RootIsImmortalImmovable(root_index)) {
1154 : // Write barriers are unnecessary for immortal immovable roots.
1155 : return kNoWriteBarrier;
1156 : }
1157 : }
1158 : }
1159 3599812 : if (field_representation == MachineRepresentation::kTaggedPointer ||
1160 1799906 : value_representation == MachineRepresentation::kTaggedPointer) {
1161 : // Write barriers for heap objects are cheaper.
1162 : return kPointerWriteBarrier;
1163 : }
1164 : NumberMatcher m(value);
1165 1407978 : if (m.HasValue()) {
1166 552168 : if (IsSmiDouble(m.Value())) {
1167 : // Storing a smi doesn't need a write barrier.
1168 : return kNoWriteBarrier;
1169 : }
1170 : // The NumberConstant will be represented as HeapNumber.
1171 618 : return kPointerWriteBarrier;
1172 : }
1173 : return kFullWriteBarrier;
1174 : }
1175 : return kNoWriteBarrier;
1176 : }
1177 :
1178 : WriteBarrierKind WriteBarrierKindFor(
1179 : BaseTaggedness base_taggedness,
1180 : MachineRepresentation field_representation, int field_offset,
1181 : Type* field_type, MachineRepresentation value_representation,
1182 : Node* value) {
1183 5521690 : if (base_taggedness == kTaggedBase &&
1184 2760845 : field_offset == HeapObject::kMapOffset) {
1185 : return kMapWriteBarrier;
1186 : }
1187 : return WriteBarrierKindFor(base_taggedness, field_representation,
1188 2474504 : field_type, value_representation, value);
1189 : }
1190 :
1191 789168 : Graph* graph() const { return jsgraph_->graph(); }
1192 : CommonOperatorBuilder* common() const { return jsgraph_->common(); }
1193 : SimplifiedOperatorBuilder* simplified() const {
1194 15527 : return jsgraph_->simplified();
1195 : }
1196 :
1197 7215 : void LowerToCheckedInt32Mul(Node* node, Truncation truncation,
1198 7215 : Type* input0_type, Type* input1_type) {
1199 : // If one of the inputs is positive and/or truncation is being applied,
1200 : // there is no need to return -0.
1201 : CheckForMinusZeroMode mz_mode =
1202 5515 : truncation.IdentifiesZeroAndMinusZero() ||
1203 1721 : (input0_type->Is(Type::OrderedNumber()) &&
1204 7217 : input0_type->Min() > 0) ||
1205 5396 : (input1_type->Is(Type::OrderedNumber()) &&
1206 5396 : input1_type->Min() > 0)
1207 : ? CheckForMinusZeroMode::kDontCheckForMinusZero
1208 7215 : : CheckForMinusZeroMode::kCheckForMinusZero;
1209 :
1210 7215 : NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode));
1211 7215 : }
1212 :
1213 150668 : void ChangeToInt32OverflowOp(Node* node) {
1214 150667 : NodeProperties::ChangeOp(node, Int32OverflowOp(node));
1215 150667 : }
1216 :
1217 190 : void ChangeToUint32OverflowOp(Node* node) {
1218 190 : NodeProperties::ChangeOp(node, Uint32OverflowOp(node));
1219 190 : }
1220 :
1221 2033343 : void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
1222 1030972 : SimplifiedLowering* lowering) {
1223 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we can
1224 : // only eliminate an unused speculative number operation if we know that
1225 : // the inputs are PlainPrimitive, which excludes everything that's might
1226 : // have side effects or throws during a ToNumber conversion. We are only
1227 : // allowed to perform a number addition if neither input is a String, even
1228 : // if the value is never used, so we further limit to NumberOrOddball in
1229 : // order to explicitly exclude String inputs.
1230 853137 : if (BothInputsAre(node, Type::NumberOrOddball())) {
1231 560225 : if (truncation.IsUnused()) return VisitUnused(node);
1232 : }
1233 :
1234 1924831 : if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) &&
1235 46472 : (GetUpperBound(node)->Is(Type::Signed32()) ||
1236 43282 : GetUpperBound(node)->Is(Type::Unsigned32()) ||
1237 : truncation.IsUsedAsWord32())) {
1238 : // => Int32Add/Sub
1239 272606 : VisitWord32TruncatingBinop(node);
1240 336646 : if (lower()) ChangeToPureOp(node, Int32Op(node));
1241 : return;
1242 : }
1243 :
1244 : // Try to use type feedback.
1245 533753 : NumberOperationHint hint = NumberOperationHintOf(node->op());
1246 :
1247 533756 : if (hint == NumberOperationHint::kSignedSmall ||
1248 : hint == NumberOperationHint::kSigned32) {
1249 : Type* left_feedback_type = TypeOf(node->InputAt(0));
1250 : Type* right_feedback_type = TypeOf(node->InputAt(1));
1251 : // Handle the case when no int32 checks on inputs are necessary (but
1252 : // an overflow check is needed on the output).
1253 : // TODO(jarin) We should not look at the upper bound because the typer
1254 : // could have already baked in some feedback into the upper bound.
1255 1552572 : if (BothInputsAre(node, Type::Signed32()) ||
1256 492204 : (BothInputsAre(node, Type::Signed32OrMinusZero()) &&
1257 0 : GetUpperBound(node)->Is(type_cache_.kSafeInteger))) {
1258 : VisitBinop(node, UseInfo::TruncatingWord32(),
1259 : MachineRepresentation::kWord32, Type::Signed32());
1260 : } else {
1261 : // If the output's truncation is identify-zeros, we can pass it
1262 : // along. Moreover, if the operation is addition and we know the
1263 : // right-hand side is not minus zero, we do not have to distinguish
1264 : // between 0 and -0.
1265 492206 : IdentifyZeros left_identify_zeros = truncation.identify_zeros();
1266 927257 : if (node->opcode() == IrOpcode::kSpeculativeNumberAdd &&
1267 435037 : !right_feedback_type->Maybe(Type::MinusZero())) {
1268 : left_identify_zeros = kIdentifyZeros;
1269 : }
1270 : UseInfo left_use =
1271 492220 : CheckedUseInfoAsWord32FromHint(hint, left_identify_zeros);
1272 : // For CheckedInt32Add and CheckedInt32Sub, we don't need to do
1273 : // a minus zero check for the right hand side, since we already
1274 : // know that the left hand side is a proper Signed32 value,
1275 : // potentially guarded by a check.
1276 : UseInfo right_use =
1277 492216 : CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros);
1278 : VisitBinop(node, left_use, right_use, MachineRepresentation::kWord32,
1279 492205 : Type::Signed32());
1280 : }
1281 530225 : if (lower()) {
1282 154247 : if (CanOverflowSigned32(node->op(), left_feedback_type,
1283 : right_feedback_type, graph_zone())) {
1284 149013 : ChangeToInt32OverflowOp(node);
1285 : } else {
1286 5239 : ChangeToPureOp(node, Int32Op(node));
1287 : }
1288 : }
1289 : return;
1290 : }
1291 :
1292 : // default case => Float64Add/Sub
1293 : VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
1294 : MachineRepresentation::kFloat64, Type::Number());
1295 3575 : if (lower()) {
1296 1040 : ChangeToPureOp(node, Float64Op(node));
1297 : }
1298 : return;
1299 : }
1300 :
1301 22379 : void VisitSpeculativeNumberModulus(Node* node, Truncation truncation,
1302 14639 : SimplifiedLowering* lowering) {
1303 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
1304 : // can only eliminate an unused speculative number operation if we know
1305 : // that the inputs are PlainPrimitive, which excludes everything that's
1306 : // might have side effects or throws during a ToNumber conversion.
1307 14709 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1308 8895 : if (truncation.IsUnused()) return VisitUnused(node);
1309 : }
1310 30031 : if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) &&
1311 291 : (truncation.IsUsedAsWord32() ||
1312 : NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
1313 : // => unsigned Uint32Mod
1314 803 : VisitWord32TruncatingBinop(node);
1315 803 : if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
1316 : return;
1317 : }
1318 34928 : if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) &&
1319 1570 : (truncation.IsUsedAsWord32() ||
1320 : NodeProperties::GetType(node)->Is(Type::Signed32()))) {
1321 : // => signed Int32Mod
1322 6006 : VisitWord32TruncatingBinop(node);
1323 6006 : if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1324 : return;
1325 : }
1326 :
1327 : // Try to use type feedback.
1328 7670 : NumberOperationHint hint = NumberOperationHintOf(node->op());
1329 :
1330 : // Handle the case when no uint32 checks on inputs are necessary
1331 : // (but an overflow check is needed on the output).
1332 7670 : if (BothInputsAreUnsigned32(node)) {
1333 270 : if (hint == NumberOperationHint::kSignedSmall ||
1334 : hint == NumberOperationHint::kSigned32) {
1335 : VisitBinop(node, UseInfo::TruncatingWord32(),
1336 : MachineRepresentation::kWord32, Type::Unsigned32());
1337 270 : if (lower()) ChangeToUint32OverflowOp(node);
1338 : return;
1339 : }
1340 : }
1341 :
1342 : // Handle the case when no int32 checks on inputs are necessary
1343 : // (but an overflow check is needed on the output).
1344 7400 : if (BothInputsAre(node, Type::Signed32())) {
1345 : // If both the inputs the feedback are int32, use the overflow op.
1346 1300 : if (hint == NumberOperationHint::kSignedSmall ||
1347 : hint == NumberOperationHint::kSigned32) {
1348 : VisitBinop(node, UseInfo::TruncatingWord32(),
1349 : MachineRepresentation::kWord32, Type::Signed32());
1350 1300 : if (lower()) ChangeToInt32OverflowOp(node);
1351 : return;
1352 : }
1353 : }
1354 :
1355 6100 : if (hint == NumberOperationHint::kSignedSmall ||
1356 : hint == NumberOperationHint::kSigned32) {
1357 : // If the result is truncated, we only need to check the inputs.
1358 5458 : if (truncation.IsUsedAsWord32()) {
1359 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1360 1133 : MachineRepresentation::kWord32);
1361 1133 : if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1362 4325 : } else if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN())) {
1363 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1364 0 : MachineRepresentation::kWord32, Type::Unsigned32());
1365 0 : if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
1366 : } else {
1367 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1368 4325 : MachineRepresentation::kWord32, Type::Signed32());
1369 4325 : if (lower()) ChangeToInt32OverflowOp(node);
1370 : }
1371 : return;
1372 : }
1373 :
1374 702 : if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
1375 642 : TypeOf(node->InputAt(1))->Is(Type::Unsigned32()) &&
1376 0 : (truncation.IsUsedAsWord32() ||
1377 : NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
1378 : // We can only promise Float64 truncation here, as the decision is
1379 : // based on the feedback types of the inputs.
1380 : VisitBinop(node,
1381 : UseInfo(MachineRepresentation::kWord32, Truncation::Float64()),
1382 : MachineRepresentation::kWord32, Type::Number());
1383 0 : if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
1384 : return;
1385 : }
1386 770 : if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
1387 656 : TypeOf(node->InputAt(1))->Is(Type::Signed32()) &&
1388 0 : (truncation.IsUsedAsWord32() ||
1389 : NodeProperties::GetType(node)->Is(Type::Signed32()))) {
1390 : // We can only promise Float64 truncation here, as the decision is
1391 : // based on the feedback types of the inputs.
1392 : VisitBinop(node,
1393 : UseInfo(MachineRepresentation::kWord32, Truncation::Float64()),
1394 : MachineRepresentation::kWord32, Type::Number());
1395 14 : if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1396 : return;
1397 : }
1398 : // default case => Float64Mod
1399 : VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
1400 : MachineRepresentation::kFloat64, Type::Number());
1401 788 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1402 : return;
1403 : }
1404 :
1405 503055 : void VisitOsrGuard(Node* node) {
1406 167685 : VisitInputs(node);
1407 :
1408 : // Insert a dynamic check for the OSR value type if necessary.
1409 167685 : switch (OsrGuardTypeOf(node->op())) {
1410 : case OsrGuardType::kUninitialized:
1411 : // At this point, we should always have a type for the OsrValue.
1412 0 : UNREACHABLE();
1413 : break;
1414 : case OsrGuardType::kSignedSmall:
1415 0 : if (lower()) {
1416 : NodeProperties::ChangeOp(node,
1417 0 : simplified()->CheckedTaggedToTaggedSigned());
1418 : }
1419 : return SetOutput(node, MachineRepresentation::kTaggedSigned);
1420 : case OsrGuardType::kAny: // Nothing to check.
1421 167685 : if (lower()) {
1422 54052 : DeferReplacement(node, node->InputAt(0));
1423 : }
1424 : return SetOutput(node, MachineRepresentation::kTagged);
1425 : }
1426 0 : UNREACHABLE();
1427 : }
1428 :
1429 : // Dispatching routine for visiting the node {node} with the usage {use}.
1430 : // Depending on the operator, propagate new usage info to the inputs.
1431 93502208 : void VisitNode(Node* node, Truncation truncation,
1432 7241730 : SimplifiedLowering* lowering) {
1433 : // Unconditionally eliminate unused pure nodes (only relevant if there's
1434 : // a pure operation in between two effectful ones, where the last one
1435 : // is unused).
1436 : // Note: We must not do this for constants, as they are cached and we
1437 : // would thus kill the cached {node} during lowering (i.e. replace all
1438 : // uses with Dead), but at that point some node lowering might have
1439 : // already taken the constant {node} from the cache (while it was in
1440 : // a sane state still) and we would afterwards replace that use with
1441 : // Dead as well.
1442 242650481 : if (node->op()->ValueInputCount() > 0 &&
1443 : node->op()->HasProperty(Operator::kPure)) {
1444 36017269 : if (truncation.IsUnused()) return VisitUnused(node);
1445 : }
1446 93011899 : switch (node->opcode()) {
1447 : //------------------------------------------------------------------
1448 : // Common operators.
1449 : //------------------------------------------------------------------
1450 : case IrOpcode::kStart:
1451 : // We use Start as a terminator for the frame state chain, so even
1452 : // tho Start doesn't really produce a value, we have to say Tagged
1453 : // here, otherwise the input conversion will fail.
1454 : return VisitLeaf(node, MachineRepresentation::kTagged);
1455 : case IrOpcode::kParameter:
1456 : // TODO(titzer): use representation from linkage.
1457 3068982 : return VisitUnop(node, UseInfo::None(), MachineRepresentation::kTagged);
1458 : case IrOpcode::kInt32Constant:
1459 : return VisitLeaf(node, MachineRepresentation::kWord32);
1460 : case IrOpcode::kInt64Constant:
1461 : return VisitLeaf(node, MachineRepresentation::kWord64);
1462 : case IrOpcode::kExternalConstant:
1463 : return VisitLeaf(node, MachineType::PointerRepresentation());
1464 : case IrOpcode::kNumberConstant:
1465 : return VisitLeaf(node, MachineRepresentation::kTagged);
1466 : case IrOpcode::kHeapConstant:
1467 : return VisitLeaf(node, MachineRepresentation::kTaggedPointer);
1468 : case IrOpcode::kPointerConstant: {
1469 : VisitLeaf(node, MachineType::PointerRepresentation());
1470 4266 : if (lower()) {
1471 1337 : intptr_t const value = OpParameter<intptr_t>(node);
1472 1337 : DeferReplacement(node, lowering->jsgraph()->IntPtrConstant(value));
1473 : }
1474 : return;
1475 : }
1476 :
1477 : case IrOpcode::kBranch: {
1478 : DCHECK(TypeOf(node->InputAt(0))->Is(Type::Boolean()));
1479 2348129 : ProcessInput(node, 0, UseInfo::Bool());
1480 2348125 : EnqueueInput(node, NodeProperties::FirstControlIndex(node));
1481 2348128 : return;
1482 : }
1483 : case IrOpcode::kSwitch:
1484 0 : ProcessInput(node, 0, UseInfo::TruncatingWord32());
1485 0 : EnqueueInput(node, NodeProperties::FirstControlIndex(node));
1486 0 : return;
1487 : case IrOpcode::kSelect:
1488 32593 : return VisitSelect(node, truncation, lowering);
1489 : case IrOpcode::kPhi:
1490 2231943 : return VisitPhi(node, truncation, lowering);
1491 : case IrOpcode::kCall:
1492 2231612 : return VisitCall(node, lowering);
1493 :
1494 : //------------------------------------------------------------------
1495 : // JavaScript operators.
1496 : //------------------------------------------------------------------
1497 : case IrOpcode::kJSToBoolean: {
1498 530996 : if (truncation.IsUsedAsBool()) {
1499 261391 : ProcessInput(node, 0, UseInfo::Bool());
1500 261391 : ProcessInput(node, 1, UseInfo::None());
1501 : SetOutput(node, MachineRepresentation::kBit);
1502 344147 : if (lower()) DeferReplacement(node, node->InputAt(0));
1503 : } else {
1504 4107 : VisitInputs(node);
1505 : SetOutput(node, MachineRepresentation::kTaggedPointer);
1506 : }
1507 : return;
1508 : }
1509 : case IrOpcode::kJSToNumber: {
1510 17870 : VisitInputs(node);
1511 : // TODO(bmeurer): Optimize somewhat based on input type?
1512 35740 : if (truncation.IsUsedAsWord32()) {
1513 : SetOutput(node, MachineRepresentation::kWord32);
1514 9574 : if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this);
1515 16592 : } else if (truncation.IsUsedAsFloat64()) {
1516 : SetOutput(node, MachineRepresentation::kFloat64);
1517 646 : if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this);
1518 : } else {
1519 : SetOutput(node, MachineRepresentation::kTagged);
1520 : }
1521 : return;
1522 : }
1523 :
1524 : //------------------------------------------------------------------
1525 : // Simplified operators.
1526 : //------------------------------------------------------------------
1527 : case IrOpcode::kBooleanNot: {
1528 31527 : if (lower()) {
1529 9811 : NodeInfo* input_info = GetInfo(node->InputAt(0));
1530 9811 : if (input_info->representation() == MachineRepresentation::kBit) {
1531 : // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
1532 602258 : node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
1533 9123 : NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
1534 688 : } else if (CanBeTaggedPointer(input_info->representation())) {
1535 : // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
1536 1374 : node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
1537 687 : NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
1538 : } else {
1539 : DCHECK_EQ(MachineRepresentation::kNone,
1540 : input_info->representation());
1541 1 : DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
1542 : }
1543 : } else {
1544 : // No input representation requirement; adapt during lowering.
1545 21716 : ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
1546 : SetOutput(node, MachineRepresentation::kBit);
1547 : }
1548 : return;
1549 : }
1550 : case IrOpcode::kNumberEqual: {
1551 : Type* const lhs_type = TypeOf(node->InputAt(0));
1552 : Type* const rhs_type = TypeOf(node->InputAt(1));
1553 : // Number comparisons reduce to integer comparisons for integer inputs.
1554 412243 : if ((lhs_type->Is(Type::Unsigned32()) &&
1555 425017 : rhs_type->Is(Type::Unsigned32())) ||
1556 1264 : (lhs_type->Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
1557 977 : rhs_type->Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
1558 977 : OneInputCannotBe(node, type_cache_.kZeroish))) {
1559 : // => unsigned Int32Cmp
1560 : VisitBinop(node, UseInfo::TruncatingWord32(),
1561 : MachineRepresentation::kBit);
1562 175775 : if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
1563 : return;
1564 : }
1565 250552 : if ((lhs_type->Is(Type::Signed32()) &&
1566 187234 : rhs_type->Is(Type::Signed32())) ||
1567 2040 : (lhs_type->Is(Type::Signed32OrMinusZeroOrNaN()) &&
1568 1906 : rhs_type->Is(Type::Signed32OrMinusZeroOrNaN()) &&
1569 1906 : OneInputCannotBe(node, type_cache_.kZeroish))) {
1570 : // => signed Int32Cmp
1571 : VisitBinop(node, UseInfo::TruncatingWord32(),
1572 : MachineRepresentation::kBit);
1573 138631 : if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
1574 : return;
1575 : }
1576 : // => Float64Cmp
1577 : VisitBinop(node, UseInfo::TruncatingFloat64(),
1578 : MachineRepresentation::kBit);
1579 52926 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
1580 : return;
1581 : }
1582 : case IrOpcode::kNumberLessThan:
1583 : case IrOpcode::kNumberLessThanOrEqual: {
1584 : // Number comparisons reduce to integer comparisons for integer inputs.
1585 254512 : if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
1586 : TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
1587 : // => unsigned Int32Cmp
1588 : VisitBinop(node, UseInfo::TruncatingWord32(),
1589 : MachineRepresentation::kBit);
1590 120497 : if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
1591 76286 : } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
1592 : TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
1593 : // => signed Int32Cmp
1594 : VisitBinop(node, UseInfo::TruncatingWord32(),
1595 : MachineRepresentation::kBit);
1596 21192 : if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
1597 : } else {
1598 : // => Float64Cmp
1599 : VisitBinop(node, UseInfo::TruncatingFloat64(),
1600 : MachineRepresentation::kBit);
1601 32035 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
1602 : }
1603 : return;
1604 : }
1605 :
1606 : case IrOpcode::kSpeculativeNumberAdd:
1607 : case IrOpcode::kSpeculativeNumberSubtract:
1608 853139 : return VisitSpeculativeAdditiveOp(node, truncation, lowering);
1609 :
1610 : case IrOpcode::kSpeculativeNumberLessThan:
1611 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1612 : case IrOpcode::kSpeculativeNumberEqual: {
1613 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
1614 : // can only eliminate an unused speculative number operation if we know
1615 : // that the inputs are PlainPrimitive, which excludes everything that's
1616 : // might have side effects or throws during a ToNumber conversion.
1617 426024 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1618 309900 : if (truncation.IsUnused()) return VisitUnused(node);
1619 : }
1620 : // Number comparisons reduce to integer comparisons for integer inputs.
1621 653583 : if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
1622 : TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
1623 : // => unsigned Int32Cmp
1624 : VisitBinop(node, UseInfo::TruncatingWord32(),
1625 : MachineRepresentation::kBit);
1626 7469 : if (lower()) ChangeToPureOp(node, Uint32Op(node));
1627 : return;
1628 654706 : } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
1629 : TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
1630 : // => signed Int32Cmp
1631 : VisitBinop(node, UseInfo::TruncatingWord32(),
1632 : MachineRepresentation::kBit);
1633 252974 : if (lower()) ChangeToPureOp(node, Int32Op(node));
1634 : return;
1635 : }
1636 : // Try to use type feedback.
1637 200732 : NumberOperationHint hint = NumberOperationHintOf(node->op());
1638 200732 : switch (hint) {
1639 : case NumberOperationHint::kSignedSmall:
1640 : case NumberOperationHint::kSigned32: {
1641 164592 : if (propagate()) {
1642 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1643 106926 : MachineRepresentation::kBit);
1644 57666 : } else if (retype()) {
1645 : SetOutput(node, MachineRepresentation::kBit, Type::Any());
1646 : } else {
1647 : DCHECK(lower());
1648 : Node* lhs = node->InputAt(0);
1649 : Node* rhs = node->InputAt(1);
1650 42882 : if (IsNodeRepresentationTagged(lhs) &&
1651 : IsNodeRepresentationTagged(rhs)) {
1652 : VisitBinop(node, UseInfo::CheckedSignedSmallAsTaggedSigned(),
1653 : MachineRepresentation::kBit);
1654 : ChangeToPureOp(
1655 19616 : node, changer_->TaggedSignedOperatorFor(node->opcode()));
1656 :
1657 : } else {
1658 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1659 2683 : MachineRepresentation::kBit);
1660 2683 : ChangeToPureOp(node, Int32Op(node));
1661 : }
1662 : }
1663 : return;
1664 : }
1665 : case NumberOperationHint::kNumberOrOddball:
1666 : // Abstract and strict equality don't perform ToNumber conversions
1667 : // on Oddballs, so make sure we don't accidentially sneak in a
1668 : // hint with Oddball feedback here.
1669 : DCHECK_NE(IrOpcode::kSpeculativeNumberEqual, node->opcode());
1670 : // Fallthrough
1671 : case NumberOperationHint::kNumber:
1672 : VisitBinop(node, CheckedUseInfoAsFloat64FromHint(hint),
1673 36140 : MachineRepresentation::kBit);
1674 45380 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1675 : return;
1676 : }
1677 0 : UNREACHABLE();
1678 : return;
1679 : }
1680 :
1681 : case IrOpcode::kNumberAdd:
1682 : case IrOpcode::kNumberSubtract: {
1683 1403147 : if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) &&
1684 90787 : (GetUpperBound(node)->Is(Type::Signed32()) ||
1685 90344 : GetUpperBound(node)->Is(Type::Unsigned32()) ||
1686 90344 : truncation.IsUsedAsWord32())) {
1687 : // => Int32Add/Sub
1688 75492 : VisitWord32TruncatingBinop(node);
1689 96895 : if (lower()) ChangeToPureOp(node, Int32Op(node));
1690 : } else {
1691 : // => Float64Add/Sub
1692 565494 : VisitFloat64Binop(node);
1693 656760 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1694 : }
1695 : return;
1696 : }
1697 : case IrOpcode::kSpeculativeNumberMultiply: {
1698 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
1699 : // can only eliminate an unused speculative number operation if we know
1700 : // that the inputs are PlainPrimitive, which excludes everything that's
1701 : // might have side effects or throws during a ToNumber conversion.
1702 65100 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1703 18309 : if (truncation.IsUnused()) return VisitUnused(node);
1704 : }
1705 133321 : if (BothInputsAre(node, Type::Integral32()) &&
1706 2273 : (NodeProperties::GetType(node)->Is(Type::Signed32()) ||
1707 2267 : NodeProperties::GetType(node)->Is(Type::Unsigned32()) ||
1708 2400 : (truncation.IsUsedAsWord32() &&
1709 : NodeProperties::GetType(node)->Is(
1710 133 : type_cache_.kSafeIntegerOrMinusZero)))) {
1711 : // Multiply reduces to Int32Mul if the inputs are integers, and
1712 : // (a) the output is either known to be Signed32, or
1713 : // (b) the output is known to be Unsigned32, or
1714 : // (c) the uses are truncating and the result is in the safe
1715 : // integer range.
1716 1593 : VisitWord32TruncatingBinop(node);
1717 2012 : if (lower()) ChangeToPureOp(node, Int32Op(node));
1718 : return;
1719 : }
1720 : // Try to use type feedback.
1721 63180 : NumberOperationHint hint = NumberOperationHintOf(node->op());
1722 : Type* input0_type = TypeOf(node->InputAt(0));
1723 : Type* input1_type = TypeOf(node->InputAt(1));
1724 :
1725 : // Handle the case when no int32 checks on inputs are necessary
1726 : // (but an overflow check is needed on the output).
1727 63180 : if (BothInputsAre(node, Type::Signed32())) {
1728 : // If both the inputs the feedback are int32, use the overflow op.
1729 2182 : if (hint == NumberOperationHint::kSignedSmall ||
1730 : hint == NumberOperationHint::kSigned32) {
1731 : VisitBinop(node, UseInfo::TruncatingWord32(),
1732 : MachineRepresentation::kWord32, Type::Signed32());
1733 2182 : if (lower()) {
1734 : LowerToCheckedInt32Mul(node, truncation, input0_type,
1735 677 : input1_type);
1736 : }
1737 : return;
1738 : }
1739 : }
1740 :
1741 60998 : if (hint == NumberOperationHint::kSignedSmall ||
1742 : hint == NumberOperationHint::kSigned32) {
1743 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1744 21365 : MachineRepresentation::kWord32, Type::Signed32());
1745 21365 : if (lower()) {
1746 6538 : LowerToCheckedInt32Mul(node, truncation, input0_type, input1_type);
1747 : }
1748 : return;
1749 : }
1750 :
1751 : // Checked float64 x float64 => float64
1752 : VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
1753 : MachineRepresentation::kFloat64, Type::Number());
1754 51664 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1755 : return;
1756 : }
1757 : case IrOpcode::kNumberMultiply: {
1758 135774 : if (BothInputsAre(node, Type::Integral32()) &&
1759 12844 : (NodeProperties::GetType(node)->Is(Type::Signed32()) ||
1760 12516 : NodeProperties::GetType(node)->Is(Type::Unsigned32()) ||
1761 19518 : (truncation.IsUsedAsWord32() &&
1762 : NodeProperties::GetType(node)->Is(
1763 7002 : type_cache_.kSafeIntegerOrMinusZero)))) {
1764 : // Multiply reduces to Int32Mul if the inputs are integers, and
1765 : // (a) the output is either known to be Signed32, or
1766 : // (b) the output is known to be Unsigned32, or
1767 : // (c) the uses are truncating and the result is in the safe
1768 : // integer range.
1769 7354 : VisitWord32TruncatingBinop(node);
1770 9268 : if (lower()) ChangeToPureOp(node, Int32Op(node));
1771 : return;
1772 : }
1773 : // Number x Number => Float64Mul
1774 53922 : VisitFloat64Binop(node);
1775 69370 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1776 : return;
1777 : }
1778 : case IrOpcode::kSpeculativeNumberDivide: {
1779 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
1780 : // can only eliminate an unused speculative number operation if we know
1781 : // that the inputs are PlainPrimitive, which excludes everything that's
1782 : // might have side effects or throws during a ToNumber conversion.
1783 26360 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1784 1373 : if (truncation.IsUnused()) return VisitUnused(node);
1785 : }
1786 26304 : if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) {
1787 : // => unsigned Uint32Div
1788 0 : VisitWord32TruncatingBinop(node);
1789 0 : if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
1790 : return;
1791 : }
1792 25835 : if (BothInputsAreSigned32(node)) {
1793 514 : if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
1794 : // => signed Int32Div
1795 0 : VisitWord32TruncatingBinop(node);
1796 0 : if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1797 : return;
1798 : }
1799 1028 : if (truncation.IsUsedAsWord32()) {
1800 : // => signed Int32Div
1801 45 : VisitWord32TruncatingBinop(node);
1802 45 : if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1803 : return;
1804 : }
1805 : }
1806 :
1807 : // Try to use type feedback.
1808 25790 : NumberOperationHint hint = NumberOperationHintOf(node->op());
1809 :
1810 : // Handle the case when no uint32 checks on inputs are necessary
1811 : // (but an overflow check is needed on the output).
1812 25790 : if (BothInputsAreUnsigned32(node)) {
1813 469 : if (hint == NumberOperationHint::kSignedSmall ||
1814 : hint == NumberOperationHint::kSigned32) {
1815 : VisitBinop(node, UseInfo::TruncatingWord32(),
1816 : MachineRepresentation::kWord32, Type::Unsigned32());
1817 469 : if (lower()) ChangeToUint32OverflowOp(node);
1818 : return;
1819 : }
1820 : }
1821 :
1822 : // Handle the case when no int32 checks on inputs are necessary
1823 : // (but an overflow check is needed on the output).
1824 25321 : if (BothInputsAreSigned32(node)) {
1825 : // If both the inputs the feedback are int32, use the overflow op.
1826 0 : if (hint == NumberOperationHint::kSignedSmall ||
1827 : hint == NumberOperationHint::kSigned32) {
1828 : VisitBinop(node, UseInfo::TruncatingWord32(),
1829 : MachineRepresentation::kWord32, Type::Signed32());
1830 0 : if (lower()) ChangeToInt32OverflowOp(node);
1831 : return;
1832 : }
1833 : }
1834 :
1835 25321 : if (hint == NumberOperationHint::kSignedSmall ||
1836 : hint == NumberOperationHint::kSigned32) {
1837 : // If the result is truncated, we only need to check the inputs.
1838 1714 : if (truncation.IsUsedAsWord32()) {
1839 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1840 108 : MachineRepresentation::kWord32);
1841 108 : if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1842 : } else {
1843 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1844 749 : MachineRepresentation::kWord32, Type::Signed32());
1845 749 : if (lower()) ChangeToInt32OverflowOp(node);
1846 : }
1847 : return;
1848 : }
1849 :
1850 : // default case => Float64Div
1851 : VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
1852 : MachineRepresentation::kFloat64, Type::Number());
1853 31370 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1854 : return;
1855 : }
1856 : case IrOpcode::kNumberDivide: {
1857 58008 : if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) {
1858 : // => unsigned Uint32Div
1859 856 : VisitWord32TruncatingBinop(node);
1860 856 : if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
1861 : return;
1862 : }
1863 47755 : if (BothInputsAreSigned32(node)) {
1864 21358 : if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
1865 : // => signed Int32Div
1866 0 : VisitWord32TruncatingBinop(node);
1867 0 : if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1868 : return;
1869 : }
1870 42716 : if (truncation.IsUsedAsWord32()) {
1871 : // => signed Int32Div
1872 8159 : VisitWord32TruncatingBinop(node);
1873 8158 : if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1874 : return;
1875 : }
1876 : }
1877 : // Number x Number => Float64Div
1878 39596 : VisitFloat64Binop(node);
1879 50775 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1880 : return;
1881 : }
1882 : case IrOpcode::kSpeculativeNumberModulus:
1883 14709 : return VisitSpeculativeNumberModulus(node, truncation, lowering);
1884 : case IrOpcode::kNumberModulus: {
1885 19804 : if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) &&
1886 1155 : (truncation.IsUsedAsWord32() ||
1887 : NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
1888 : // => unsigned Uint32Mod
1889 923 : VisitWord32TruncatingBinop(node);
1890 923 : if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
1891 : return;
1892 : }
1893 20222 : if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) &&
1894 4030 : (truncation.IsUsedAsWord32() ||
1895 : NodeProperties::GetType(node)->Is(Type::Signed32()))) {
1896 : // => signed Int32Mod
1897 2521 : VisitWord32TruncatingBinop(node);
1898 2521 : if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1899 : return;
1900 : }
1901 6522 : if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
1902 6101 : TypeOf(node->InputAt(1))->Is(Type::Unsigned32()) &&
1903 260 : (truncation.IsUsedAsWord32() ||
1904 : NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
1905 : // We can only promise Float64 truncation here, as the decision is
1906 : // based on the feedback types of the inputs.
1907 : VisitBinop(node, UseInfo(MachineRepresentation::kWord32,
1908 : Truncation::Float64()),
1909 : MachineRepresentation::kWord32);
1910 24 : if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
1911 : return;
1912 : }
1913 7764 : if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
1914 6724 : TypeOf(node->InputAt(1))->Is(Type::Signed32()) &&
1915 1578 : (truncation.IsUsedAsWord32() ||
1916 : NodeProperties::GetType(node)->Is(Type::Signed32()))) {
1917 : // We can only promise Float64 truncation here, as the decision is
1918 : // based on the feedback types of the inputs.
1919 : VisitBinop(node, UseInfo(MachineRepresentation::kWord32,
1920 : Truncation::Float64()),
1921 : MachineRepresentation::kWord32);
1922 0 : if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1923 : return;
1924 : }
1925 : // default case => Float64Mod
1926 5935 : VisitFloat64Binop(node);
1927 7653 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1928 : return;
1929 : }
1930 : case IrOpcode::kNumberBitwiseOr:
1931 : case IrOpcode::kNumberBitwiseXor:
1932 : case IrOpcode::kNumberBitwiseAnd: {
1933 116124 : VisitWord32TruncatingBinop(node);
1934 151867 : if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
1935 : return;
1936 : }
1937 : case IrOpcode::kSpeculativeNumberBitwiseOr:
1938 : case IrOpcode::kSpeculativeNumberBitwiseXor:
1939 : case IrOpcode::kSpeculativeNumberBitwiseAnd:
1940 84022 : VisitSpeculativeInt32Binop(node);
1941 84023 : if (lower()) {
1942 23071 : ChangeToPureOp(node, Int32Op(node));
1943 : }
1944 : return;
1945 : case IrOpcode::kNumberShiftLeft: {
1946 : Type* rhs_type = GetUpperBound(node->InputAt(1));
1947 : VisitBinop(node, UseInfo::TruncatingWord32(),
1948 42285 : UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1949 42285 : if (lower()) {
1950 12981 : lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
1951 : }
1952 : return;
1953 : }
1954 : case IrOpcode::kSpeculativeNumberShiftLeft: {
1955 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
1956 : // can only eliminate an unused speculative number operation if we know
1957 : // that the inputs are PlainPrimitive, which excludes everything that's
1958 : // might have side effects or throws during a ToNumber conversion.
1959 8526 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1960 7643 : if (truncation.IsUnused()) return VisitUnused(node);
1961 : }
1962 8462 : if (BothInputsAre(node, Type::NumberOrOddball())) {
1963 : Type* rhs_type = GetUpperBound(node->InputAt(1));
1964 : VisitBinop(node, UseInfo::TruncatingWord32(),
1965 : UseInfo::TruncatingWord32(),
1966 7555 : MachineRepresentation::kWord32);
1967 7555 : if (lower()) {
1968 1783 : lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
1969 : }
1970 : return;
1971 : }
1972 907 : NumberOperationHint hint = NumberOperationHintOf(node->op());
1973 : Type* rhs_type = GetUpperBound(node->InputAt(1));
1974 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1975 907 : MachineRepresentation::kWord32, Type::Signed32());
1976 907 : if (lower()) {
1977 286 : lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
1978 : }
1979 : return;
1980 : }
1981 : case IrOpcode::kNumberShiftRight: {
1982 : Type* rhs_type = GetUpperBound(node->InputAt(1));
1983 : VisitBinop(node, UseInfo::TruncatingWord32(),
1984 34869 : UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1985 34869 : if (lower()) {
1986 10805 : lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
1987 : }
1988 : return;
1989 : }
1990 : case IrOpcode::kSpeculativeNumberShiftRight: {
1991 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
1992 : // can only eliminate an unused speculative number operation if we know
1993 : // that the inputs are PlainPrimitive, which excludes everything that's
1994 : // might have side effects or throws during a ToNumber conversion.
1995 21554 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1996 20280 : if (truncation.IsUnused()) return VisitUnused(node);
1997 : }
1998 21409 : if (BothInputsAre(node, Type::NumberOrOddball())) {
1999 : Type* rhs_type = GetUpperBound(node->InputAt(1));
2000 : VisitBinop(node, UseInfo::TruncatingWord32(),
2001 : UseInfo::TruncatingWord32(),
2002 20111 : MachineRepresentation::kWord32);
2003 20111 : if (lower()) {
2004 4578 : lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
2005 : }
2006 : return;
2007 : }
2008 1298 : NumberOperationHint hint = NumberOperationHintOf(node->op());
2009 : Type* rhs_type = GetUpperBound(node->InputAt(1));
2010 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
2011 1298 : MachineRepresentation::kWord32, Type::Signed32());
2012 1298 : if (lower()) {
2013 378 : lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
2014 : }
2015 : return;
2016 : }
2017 : case IrOpcode::kNumberShiftRightLogical: {
2018 : Type* rhs_type = GetUpperBound(node->InputAt(1));
2019 : VisitBinop(node, UseInfo::TruncatingWord32(),
2020 19491 : UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
2021 19491 : if (lower()) {
2022 6278 : lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
2023 : }
2024 : return;
2025 : }
2026 : case IrOpcode::kSpeculativeNumberShiftRightLogical: {
2027 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
2028 : // can only eliminate an unused speculative number operation if we know
2029 : // that the inputs are PlainPrimitive, which excludes everything that's
2030 : // might have side effects or throws during a ToNumber conversion.
2031 7110 : if (BothInputsAre(node, Type::PlainPrimitive())) {
2032 5692 : if (truncation.IsUnused()) return VisitUnused(node);
2033 : }
2034 6748 : NumberOperationHint hint = NumberOperationHintOf(node->op());
2035 : Type* rhs_type = GetUpperBound(node->InputAt(1));
2036 16275 : if (rhs_type->Is(type_cache_.kZeroish) &&
2037 : (hint == NumberOperationHint::kSignedSmall ||
2038 7272 : hint == NumberOperationHint::kSigned32) &&
2039 524 : !truncation.IsUsedAsWord32()) {
2040 : // The SignedSmall or Signed32 feedback means that the results that we
2041 : // have seen so far were of type Unsigned31. We speculate that this
2042 : // will continue to hold. Moreover, since the RHS is 0, the result
2043 : // will just be the (converted) LHS.
2044 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
2045 259 : MachineRepresentation::kWord32, Type::Unsigned31());
2046 259 : if (lower()) {
2047 70 : node->RemoveInput(1);
2048 : NodeProperties::ChangeOp(node,
2049 70 : simplified()->CheckedUint32ToInt32());
2050 : }
2051 : return;
2052 : }
2053 6489 : if (BothInputsAre(node, Type::NumberOrOddball())) {
2054 : VisitBinop(node, UseInfo::TruncatingWord32(),
2055 : UseInfo::TruncatingWord32(),
2056 5179 : MachineRepresentation::kWord32);
2057 5180 : if (lower()) {
2058 1529 : lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
2059 : }
2060 : return;
2061 : }
2062 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
2063 1309 : MachineRepresentation::kWord32, Type::Unsigned32());
2064 1309 : if (lower()) {
2065 389 : lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
2066 : }
2067 : return;
2068 : }
2069 : case IrOpcode::kNumberAbs: {
2070 240 : if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32())) {
2071 : VisitUnop(node, UseInfo::TruncatingWord32(),
2072 0 : MachineRepresentation::kWord32);
2073 0 : if (lower()) DeferReplacement(node, node->InputAt(0));
2074 240 : } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32())) {
2075 : VisitUnop(node, UseInfo::TruncatingWord32(),
2076 99 : MachineRepresentation::kWord32);
2077 99 : if (lower()) DeferReplacement(node, lowering->Int32Abs(node));
2078 141 : } else if (TypeOf(node->InputAt(0))
2079 141 : ->Is(type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) {
2080 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2081 0 : MachineRepresentation::kFloat64);
2082 0 : if (lower()) DeferReplacement(node, node->InputAt(0));
2083 : } else {
2084 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2085 141 : MachineRepresentation::kFloat64);
2086 184 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2087 : }
2088 : return;
2089 : }
2090 : case IrOpcode::kNumberClz32: {
2091 : VisitUnop(node, UseInfo::TruncatingWord32(),
2092 78 : MachineRepresentation::kWord32);
2093 104 : if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
2094 : return;
2095 : }
2096 : case IrOpcode::kNumberImul: {
2097 : VisitBinop(node, UseInfo::TruncatingWord32(),
2098 187 : UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
2099 241 : if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
2100 : return;
2101 : }
2102 : case IrOpcode::kNumberFround: {
2103 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2104 1989 : MachineRepresentation::kFloat32);
2105 2646 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2106 : return;
2107 : }
2108 : case IrOpcode::kNumberMax: {
2109 : // It is safe to use the feedback types for left and right hand side
2110 : // here, since we can only narrow those types and thus we can only
2111 : // promise a more specific truncation.
2112 : Type* const lhs_type = TypeOf(node->InputAt(0));
2113 : Type* const rhs_type = TypeOf(node->InputAt(1));
2114 564 : if (lhs_type->Is(Type::Unsigned32()) &&
2115 : rhs_type->Is(Type::Unsigned32())) {
2116 21 : VisitWord32TruncatingBinop(node);
2117 21 : if (lower()) {
2118 : lowering->DoMax(node, lowering->machine()->Uint32LessThan(),
2119 7 : MachineRepresentation::kWord32);
2120 : }
2121 660 : } else if (lhs_type->Is(Type::Signed32()) &&
2122 : rhs_type->Is(Type::Signed32())) {
2123 178 : VisitWord32TruncatingBinop(node);
2124 178 : if (lower()) {
2125 : lowering->DoMax(node, lowering->machine()->Int32LessThan(),
2126 62 : MachineRepresentation::kWord32);
2127 : }
2128 406 : } else if (lhs_type->Is(Type::PlainNumber()) &&
2129 : rhs_type->Is(Type::PlainNumber())) {
2130 150 : VisitFloat64Binop(node);
2131 150 : if (lower()) {
2132 : lowering->DoMax(node, lowering->machine()->Float64LessThan(),
2133 50 : MachineRepresentation::kFloat64);
2134 : }
2135 : } else {
2136 65 : VisitFloat64Binop(node);
2137 84 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2138 : }
2139 : return;
2140 : }
2141 : case IrOpcode::kNumberMin: {
2142 : // It is safe to use the feedback types for left and right hand side
2143 : // here, since we can only narrow those types and thus we can only
2144 : // promise a more specific truncation.
2145 : Type* const lhs_type = TypeOf(node->InputAt(0));
2146 : Type* const rhs_type = TypeOf(node->InputAt(1));
2147 668 : if (lhs_type->Is(Type::Unsigned32()) &&
2148 : rhs_type->Is(Type::Unsigned32())) {
2149 21 : VisitWord32TruncatingBinop(node);
2150 21 : if (lower()) {
2151 : lowering->DoMin(node, lowering->machine()->Uint32LessThan(),
2152 7 : MachineRepresentation::kWord32);
2153 : }
2154 812 : } else if (lhs_type->Is(Type::Signed32()) &&
2155 : rhs_type->Is(Type::Signed32())) {
2156 200 : VisitWord32TruncatingBinop(node);
2157 200 : if (lower()) {
2158 : lowering->DoMin(node, lowering->machine()->Int32LessThan(),
2159 69 : MachineRepresentation::kWord32);
2160 : }
2161 472 : } else if (lhs_type->Is(Type::PlainNumber()) &&
2162 : rhs_type->Is(Type::PlainNumber())) {
2163 126 : VisitFloat64Binop(node);
2164 126 : if (lower()) {
2165 : lowering->DoMin(node, lowering->machine()->Float64LessThan(),
2166 42 : MachineRepresentation::kFloat64);
2167 : }
2168 : } else {
2169 187 : VisitFloat64Binop(node);
2170 247 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2171 : }
2172 : return;
2173 : }
2174 : case IrOpcode::kNumberAtan2:
2175 : case IrOpcode::kNumberPow: {
2176 : VisitBinop(node, UseInfo::TruncatingFloat64(),
2177 : MachineRepresentation::kFloat64);
2178 3723 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2179 : return;
2180 : }
2181 : case IrOpcode::kNumberAcos:
2182 : case IrOpcode::kNumberAcosh:
2183 : case IrOpcode::kNumberAsin:
2184 : case IrOpcode::kNumberAsinh:
2185 : case IrOpcode::kNumberAtan:
2186 : case IrOpcode::kNumberAtanh:
2187 : case IrOpcode::kNumberCeil:
2188 : case IrOpcode::kNumberCos:
2189 : case IrOpcode::kNumberCosh:
2190 : case IrOpcode::kNumberExp:
2191 : case IrOpcode::kNumberExpm1:
2192 : case IrOpcode::kNumberFloor:
2193 : case IrOpcode::kNumberLog:
2194 : case IrOpcode::kNumberLog1p:
2195 : case IrOpcode::kNumberLog2:
2196 : case IrOpcode::kNumberLog10:
2197 : case IrOpcode::kNumberCbrt:
2198 : case IrOpcode::kNumberSin:
2199 : case IrOpcode::kNumberSinh:
2200 : case IrOpcode::kNumberTan:
2201 : case IrOpcode::kNumberTanh:
2202 : case IrOpcode::kNumberTrunc: {
2203 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2204 50147 : MachineRepresentation::kFloat64);
2205 66507 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2206 : return;
2207 : }
2208 : case IrOpcode::kNumberRound: {
2209 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2210 201 : MachineRepresentation::kFloat64);
2211 201 : if (lower()) DeferReplacement(node, lowering->Float64Round(node));
2212 : return;
2213 : }
2214 : case IrOpcode::kNumberSign: {
2215 63 : if (InputIs(node, Type::Signed32())) {
2216 : VisitUnop(node, UseInfo::TruncatingWord32(),
2217 21 : MachineRepresentation::kWord32);
2218 21 : if (lower()) DeferReplacement(node, lowering->Int32Sign(node));
2219 : } else {
2220 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2221 42 : MachineRepresentation::kFloat64);
2222 42 : if (lower()) DeferReplacement(node, lowering->Float64Sign(node));
2223 : }
2224 : return;
2225 : }
2226 : case IrOpcode::kNumberSqrt: {
2227 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2228 180 : MachineRepresentation::kFloat64);
2229 239 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2230 : return;
2231 : }
2232 : case IrOpcode::kNumberToBoolean: {
2233 : Type* const input_type = TypeOf(node->InputAt(0));
2234 1086 : if (input_type->Is(Type::Integral32())) {
2235 : VisitUnop(node, UseInfo::TruncatingWord32(),
2236 327 : MachineRepresentation::kBit);
2237 327 : if (lower()) lowering->DoIntegral32ToBit(node);
2238 759 : } else if (input_type->Is(Type::OrderedNumber())) {
2239 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2240 0 : MachineRepresentation::kBit);
2241 0 : if (lower()) lowering->DoOrderedNumberToBit(node);
2242 : } else {
2243 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2244 759 : MachineRepresentation::kBit);
2245 759 : if (lower()) lowering->DoNumberToBit(node);
2246 : }
2247 : return;
2248 : }
2249 : case IrOpcode::kNumberToInt32: {
2250 : // Just change representation if necessary.
2251 : VisitUnop(node, UseInfo::TruncatingWord32(),
2252 108639 : MachineRepresentation::kWord32);
2253 141524 : if (lower()) DeferReplacement(node, node->InputAt(0));
2254 : return;
2255 : }
2256 : case IrOpcode::kNumberToUint32: {
2257 : // Just change representation if necessary.
2258 : VisitUnop(node, UseInfo::TruncatingWord32(),
2259 32246 : MachineRepresentation::kWord32);
2260 42536 : if (lower()) DeferReplacement(node, node->InputAt(0));
2261 : return;
2262 : }
2263 : case IrOpcode::kNumberToUint8Clamped: {
2264 : Type* const input_type = TypeOf(node->InputAt(0));
2265 2976 : if (input_type->Is(type_cache_.kUint8OrMinusZeroOrNaN)) {
2266 : VisitUnop(node, UseInfo::TruncatingWord32(),
2267 54 : MachineRepresentation::kWord32);
2268 72 : if (lower()) DeferReplacement(node, node->InputAt(0));
2269 1434 : } else if (input_type->Is(Type::Unsigned32OrMinusZeroOrNaN())) {
2270 : VisitUnop(node, UseInfo::TruncatingWord32(),
2271 236 : MachineRepresentation::kWord32);
2272 236 : if (lower()) lowering->DoUnsigned32ToUint8Clamped(node);
2273 1198 : } else if (input_type->Is(Type::Signed32OrMinusZeroOrNaN())) {
2274 : VisitUnop(node, UseInfo::TruncatingWord32(),
2275 211 : MachineRepresentation::kWord32);
2276 211 : if (lower()) lowering->DoSigned32ToUint8Clamped(node);
2277 1974 : } else if (input_type->Is(type_cache_.kIntegerOrMinusZeroOrNaN)) {
2278 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2279 87 : MachineRepresentation::kFloat64);
2280 87 : if (lower()) lowering->DoIntegerToUint8Clamped(node);
2281 : } else {
2282 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2283 900 : MachineRepresentation::kFloat64);
2284 900 : if (lower()) lowering->DoNumberToUint8Clamped(node);
2285 : }
2286 : return;
2287 : }
2288 : case IrOpcode::kReferenceEqual: {
2289 : VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
2290 669825 : if (lower()) {
2291 219851 : NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
2292 : }
2293 : return;
2294 : }
2295 : case IrOpcode::kStringEqual:
2296 : case IrOpcode::kStringLessThan:
2297 : case IrOpcode::kStringLessThanOrEqual: {
2298 : return VisitBinop(node, UseInfo::AnyTagged(),
2299 : MachineRepresentation::kTaggedPointer);
2300 : }
2301 : case IrOpcode::kStringCharAt: {
2302 : VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
2303 1022 : MachineRepresentation::kTaggedPointer);
2304 1022 : return;
2305 : }
2306 : case IrOpcode::kStringCharCodeAt: {
2307 : // TODO(turbofan): Allow builtins to return untagged values.
2308 : VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
2309 1239 : MachineRepresentation::kTaggedSigned);
2310 1239 : return;
2311 : }
2312 : case IrOpcode::kStringFromCharCode: {
2313 : VisitUnop(node, UseInfo::TruncatingWord32(),
2314 2372 : MachineRepresentation::kTaggedPointer);
2315 2372 : return;
2316 : }
2317 : case IrOpcode::kStringFromCodePoint: {
2318 : VisitUnop(node, UseInfo::TruncatingWord32(),
2319 185 : MachineRepresentation::kTaggedPointer);
2320 185 : return;
2321 : }
2322 : case IrOpcode::kStringIndexOf: {
2323 499 : ProcessInput(node, 0, UseInfo::AnyTagged());
2324 499 : ProcessInput(node, 1, UseInfo::AnyTagged());
2325 499 : ProcessInput(node, 2, UseInfo::TaggedSigned());
2326 : SetOutput(node, MachineRepresentation::kTaggedSigned);
2327 : return;
2328 : }
2329 :
2330 : case IrOpcode::kCheckBounds: {
2331 : Type* index_type = TypeOf(node->InputAt(0));
2332 : Type* length_type = TypeOf(node->InputAt(1));
2333 114535 : if (index_type->Is(Type::Integral32OrMinusZero())) {
2334 : // Map -0 to 0, and the values in the [-2^31,-1] range to the
2335 : // [2^31,2^32-1] range, which will be considered out-of-bounds
2336 : // as well, because the {length_type} is limited to Unsigned31.
2337 : VisitBinop(node, UseInfo::TruncatingWord32(),
2338 : MachineRepresentation::kWord32);
2339 93168 : if (lower()) {
2340 47815 : if (index_type->Min() >= 0.0 &&
2341 21806 : index_type->Max() < length_type->Min()) {
2342 : // The bounds check is redundant if we already know that
2343 : // the index is within the bounds of [0.0, length[.
2344 3322 : DeferReplacement(node, node->InputAt(0));
2345 : }
2346 : }
2347 : } else {
2348 : VisitBinop(node, UseInfo::CheckedSigned32AsWord32(kIdentifyZeros),
2349 : UseInfo::TruncatingWord32(),
2350 21367 : MachineRepresentation::kWord32);
2351 : }
2352 : return;
2353 : }
2354 : case IrOpcode::kCheckHeapObject: {
2355 57639 : if (InputCannotBe(node, Type::SignedSmall())) {
2356 : VisitUnop(node, UseInfo::AnyTagged(),
2357 516 : MachineRepresentation::kTaggedPointer);
2358 : } else {
2359 : VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
2360 57123 : MachineRepresentation::kTaggedPointer);
2361 : }
2362 75505 : if (lower()) DeferReplacement(node, node->InputAt(0));
2363 : return;
2364 : }
2365 : case IrOpcode::kCheckIf: {
2366 92035 : ProcessInput(node, 0, UseInfo::Bool());
2367 92035 : ProcessRemainingInputs(node, 1);
2368 : SetOutput(node, MachineRepresentation::kNone);
2369 : return;
2370 : }
2371 : case IrOpcode::kCheckInternalizedString: {
2372 7190 : if (InputIs(node, Type::InternalizedString())) {
2373 : VisitUnop(node, UseInfo::AnyTagged(),
2374 332 : MachineRepresentation::kTaggedPointer);
2375 417 : if (lower()) DeferReplacement(node, node->InputAt(0));
2376 : } else {
2377 : VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
2378 6858 : MachineRepresentation::kTaggedPointer);
2379 : }
2380 : return;
2381 : }
2382 : case IrOpcode::kCheckNumber: {
2383 : Type* const input_type = TypeOf(node->InputAt(0));
2384 1479 : if (input_type->Is(Type::Number())) {
2385 42 : VisitNoop(node, truncation);
2386 : } else {
2387 1437 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2388 : }
2389 : return;
2390 : }
2391 : case IrOpcode::kCheckReceiver: {
2392 1649 : if (InputIs(node, Type::Receiver())) {
2393 : VisitUnop(node, UseInfo::AnyTagged(),
2394 12 : MachineRepresentation::kTaggedPointer);
2395 16 : if (lower()) DeferReplacement(node, node->InputAt(0));
2396 : } else {
2397 : VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
2398 1637 : MachineRepresentation::kTaggedPointer);
2399 : }
2400 : return;
2401 : }
2402 : case IrOpcode::kCheckSmi: {
2403 88768 : if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) {
2404 : VisitUnop(node,
2405 : UseInfo::CheckedSignedSmallAsWord32(kDistinguishZeros),
2406 1320 : MachineRepresentation::kWord32);
2407 : } else {
2408 : VisitUnop(node, UseInfo::CheckedSignedSmallAsTaggedSigned(),
2409 43064 : MachineRepresentation::kTaggedSigned);
2410 : }
2411 58078 : if (lower()) DeferReplacement(node, node->InputAt(0));
2412 : return;
2413 : }
2414 : case IrOpcode::kCheckString: {
2415 4056 : if (InputIs(node, Type::String())) {
2416 : VisitUnop(node, UseInfo::AnyTagged(),
2417 0 : MachineRepresentation::kTaggedPointer);
2418 0 : if (lower()) DeferReplacement(node, node->InputAt(0));
2419 : } else {
2420 : VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
2421 4056 : MachineRepresentation::kTaggedPointer);
2422 : }
2423 : return;
2424 : }
2425 :
2426 : case IrOpcode::kAllocate: {
2427 273628 : ProcessInput(node, 0, UseInfo::TruncatingWord32());
2428 273628 : ProcessRemainingInputs(node, 1);
2429 : SetOutput(node, MachineRepresentation::kTaggedPointer);
2430 : return;
2431 : }
2432 : case IrOpcode::kLoadField: {
2433 3146561 : if (truncation.IsUnused()) return VisitUnused(node);
2434 2835964 : FieldAccess access = FieldAccessOf(node->op());
2435 : MachineRepresentation const representation =
2436 : access.machine_type.representation();
2437 2835964 : VisitUnop(node, UseInfoForBasePointer(access), representation);
2438 : return;
2439 : }
2440 : case IrOpcode::kStoreField: {
2441 2760845 : FieldAccess access = FieldAccessOf(node->op());
2442 2760845 : NodeInfo* input_info = GetInfo(node->InputAt(1));
2443 : WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
2444 : access.base_is_tagged, access.machine_type.representation(),
2445 : access.offset, access.type, input_info->representation(),
2446 2760845 : node->InputAt(1));
2447 2760848 : ProcessInput(node, 0, UseInfoForBasePointer(access));
2448 : ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
2449 2760845 : access.machine_type.representation()));
2450 2760844 : ProcessRemainingInputs(node, 2);
2451 : SetOutput(node, MachineRepresentation::kNone);
2452 2760839 : if (lower()) {
2453 914431 : if (write_barrier_kind < access.write_barrier_kind) {
2454 436932 : access.write_barrier_kind = write_barrier_kind;
2455 : NodeProperties::ChangeOp(
2456 873864 : node, jsgraph_->simplified()->StoreField(access));
2457 : }
2458 : }
2459 : return;
2460 : }
2461 : case IrOpcode::kLoadBuffer: {
2462 24720 : if (truncation.IsUnused()) return VisitUnused(node);
2463 20469 : BufferAccess access = BufferAccessOf(node->op());
2464 20469 : ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
2465 20469 : ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
2466 20469 : ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
2467 20469 : ProcessRemainingInputs(node, 3);
2468 :
2469 : MachineRepresentation output;
2470 20469 : if (truncation.IdentifiesUndefinedAndNaNAndZero()) {
2471 19674 : if (truncation.IdentifiesNaNAndZero()) {
2472 : // If undefined is truncated to a non-NaN number, we can use
2473 : // the load's representation.
2474 14563 : output = access.machine_type().representation();
2475 : } else {
2476 : // If undefined is truncated to a number, but the use can
2477 : // observe NaN, we need to output at least the float32
2478 : // representation.
2479 5111 : if (access.machine_type().representation() ==
2480 : MachineRepresentation::kFloat32) {
2481 4678 : output = access.machine_type().representation();
2482 : } else {
2483 : output = MachineRepresentation::kFloat64;
2484 : }
2485 : }
2486 : } else {
2487 : // If undefined is not truncated away, we need to have the tagged
2488 : // representation.
2489 : output = MachineRepresentation::kTagged;
2490 : }
2491 : SetOutput(node, output);
2492 20469 : if (lower()) lowering->DoLoadBuffer(node, output, changer_);
2493 : return;
2494 : }
2495 : case IrOpcode::kStoreBuffer: {
2496 14228 : BufferAccess access = BufferAccessOf(node->op());
2497 14228 : ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
2498 14228 : ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
2499 14228 : ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
2500 : ProcessInput(node, 3,
2501 : TruncatingUseInfoFromRepresentation(
2502 14228 : access.machine_type().representation())); // value
2503 14228 : ProcessRemainingInputs(node, 4);
2504 : SetOutput(node, MachineRepresentation::kNone);
2505 14227 : if (lower()) lowering->DoStoreBuffer(node);
2506 : return;
2507 : }
2508 : case IrOpcode::kLoadElement: {
2509 117119 : if (truncation.IsUnused()) return VisitUnused(node);
2510 111923 : ElementAccess access = ElementAccessOf(node->op());
2511 : VisitBinop(node, UseInfoForBasePointer(access),
2512 : UseInfo::TruncatingWord32(),
2513 111923 : access.machine_type.representation());
2514 111923 : return;
2515 : }
2516 : case IrOpcode::kStoreElement: {
2517 494916 : ElementAccess access = ElementAccessOf(node->op());
2518 494916 : NodeInfo* input_info = GetInfo(node->InputAt(2));
2519 : WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
2520 : access.base_is_tagged, access.machine_type.representation(),
2521 494916 : access.type, input_info->representation(), node->InputAt(2));
2522 494916 : ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
2523 494916 : ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
2524 : ProcessInput(node, 2,
2525 : TruncatingUseInfoFromRepresentation(
2526 494916 : access.machine_type.representation())); // value
2527 494916 : ProcessRemainingInputs(node, 3);
2528 : SetOutput(node, MachineRepresentation::kNone);
2529 494916 : if (lower()) {
2530 162669 : if (write_barrier_kind < access.write_barrier_kind) {
2531 147063 : access.write_barrier_kind = write_barrier_kind;
2532 : NodeProperties::ChangeOp(
2533 294126 : node, jsgraph_->simplified()->StoreElement(access));
2534 : }
2535 : }
2536 : return;
2537 : }
2538 : case IrOpcode::kLoadTypedElement: {
2539 : MachineRepresentation const rep =
2540 12172 : MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
2541 12172 : ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer
2542 12172 : ProcessInput(node, 1, UseInfo::AnyTagged()); // base pointer
2543 12172 : ProcessInput(node, 2, UseInfo::PointerInt()); // external pointer
2544 12172 : ProcessInput(node, 3, UseInfo::TruncatingWord32()); // index
2545 12172 : ProcessRemainingInputs(node, 4);
2546 : SetOutput(node, rep);
2547 : return;
2548 : }
2549 : case IrOpcode::kStoreTypedElement: {
2550 : MachineRepresentation const rep =
2551 11035 : MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
2552 11035 : ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer
2553 11035 : ProcessInput(node, 1, UseInfo::AnyTagged()); // base pointer
2554 11035 : ProcessInput(node, 2, UseInfo::PointerInt()); // external pointer
2555 11035 : ProcessInput(node, 3, UseInfo::TruncatingWord32()); // index
2556 : ProcessInput(node, 4,
2557 11035 : TruncatingUseInfoFromRepresentation(rep)); // value
2558 11035 : ProcessRemainingInputs(node, 5);
2559 : SetOutput(node, MachineRepresentation::kNone);
2560 : return;
2561 : }
2562 : case IrOpcode::kPlainPrimitiveToNumber: {
2563 51955 : if (InputIs(node, Type::Boolean())) {
2564 1229 : VisitUnop(node, UseInfo::Bool(), MachineRepresentation::kWord32);
2565 1610 : if (lower()) DeferReplacement(node, node->InputAt(0));
2566 50726 : } else if (InputIs(node, Type::String())) {
2567 1716 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2568 1716 : if (lower()) lowering->DoStringToNumber(node);
2569 98020 : } else if (truncation.IsUsedAsWord32()) {
2570 35488 : if (InputIs(node, Type::NumberOrOddball())) {
2571 : VisitUnop(node, UseInfo::TruncatingWord32(),
2572 14821 : MachineRepresentation::kWord32);
2573 19310 : if (lower()) DeferReplacement(node, node->InputAt(0));
2574 : } else {
2575 : VisitUnop(node, UseInfo::AnyTagged(),
2576 20667 : MachineRepresentation::kWord32);
2577 20667 : if (lower()) {
2578 : NodeProperties::ChangeOp(node,
2579 6347 : simplified()->PlainPrimitiveToWord32());
2580 : }
2581 : }
2582 27044 : } else if (truncation.IsUsedAsFloat64()) {
2583 13414 : if (InputIs(node, Type::NumberOrOddball())) {
2584 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2585 6188 : MachineRepresentation::kFloat64);
2586 8109 : if (lower()) DeferReplacement(node, node->InputAt(0));
2587 : } else {
2588 : VisitUnop(node, UseInfo::AnyTagged(),
2589 7226 : MachineRepresentation::kFloat64);
2590 7226 : if (lower()) {
2591 : NodeProperties::ChangeOp(node,
2592 1895 : simplified()->PlainPrimitiveToFloat64());
2593 : }
2594 : }
2595 : } else {
2596 108 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2597 : }
2598 : return;
2599 : }
2600 : case IrOpcode::kSpeculativeToNumber: {
2601 5365 : NumberOperationHint const hint = NumberOperationHintOf(node->op());
2602 5365 : switch (hint) {
2603 : case NumberOperationHint::kSigned32:
2604 : case NumberOperationHint::kSignedSmall:
2605 : VisitUnop(node, CheckedUseInfoAsWord32FromHint(hint),
2606 5365 : MachineRepresentation::kWord32, Type::Signed32());
2607 5365 : break;
2608 : case NumberOperationHint::kNumber:
2609 : case NumberOperationHint::kNumberOrOddball:
2610 : VisitUnop(node, CheckedUseInfoAsFloat64FromHint(hint),
2611 0 : MachineRepresentation::kFloat64);
2612 0 : break;
2613 : }
2614 6813 : if (lower()) DeferReplacement(node, node->InputAt(0));
2615 : return;
2616 : }
2617 : case IrOpcode::kObjectIsDetectableCallable: {
2618 52920 : VisitObjectIs(node, Type::DetectableCallable(), lowering);
2619 52920 : return;
2620 : }
2621 : case IrOpcode::kObjectIsNaN: {
2622 : Type* const input_type = GetUpperBound(node->InputAt(0));
2623 8940 : if (input_type->Is(Type::NaN())) {
2624 0 : VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
2625 0 : if (lower()) {
2626 0 : DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
2627 : }
2628 8940 : } else if (!input_type->Maybe(Type::NaN())) {
2629 24 : VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit);
2630 24 : if (lower()) {
2631 8 : DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
2632 : }
2633 8916 : } else if (input_type->Is(Type::Number())) {
2634 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2635 51 : MachineRepresentation::kBit);
2636 51 : if (lower()) {
2637 : // ObjectIsNaN(x:kRepFloat64) => Word32Equal(Float64Equal(x,x),#0)
2638 : Node* const input = node->InputAt(0);
2639 : node->ReplaceInput(
2640 : 0, jsgraph_->graph()->NewNode(
2641 34 : lowering->machine()->Float64Equal(), input, input));
2642 34 : node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
2643 17 : NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
2644 : }
2645 : } else {
2646 8865 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
2647 : }
2648 : return;
2649 : }
2650 : case IrOpcode::kObjectIsNonCallable: {
2651 25828 : VisitObjectIs(node, Type::NonCallable(), lowering);
2652 25828 : return;
2653 : }
2654 : case IrOpcode::kObjectIsNumber: {
2655 34647 : VisitObjectIs(node, Type::Number(), lowering);
2656 34647 : return;
2657 : }
2658 : case IrOpcode::kObjectIsReceiver: {
2659 69160 : VisitObjectIs(node, Type::Receiver(), lowering);
2660 69160 : return;
2661 : }
2662 : case IrOpcode::kObjectIsSmi: {
2663 : // TODO(turbofan): Optimize based on input representation.
2664 10665 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
2665 10665 : return;
2666 : }
2667 : case IrOpcode::kObjectIsString: {
2668 14597 : VisitObjectIs(node, Type::String(), lowering);
2669 14597 : return;
2670 : }
2671 : case IrOpcode::kObjectIsSymbol: {
2672 1989 : VisitObjectIs(node, Type::Symbol(), lowering);
2673 1989 : return;
2674 : }
2675 : case IrOpcode::kObjectIsUndetectable: {
2676 27558 : VisitObjectIs(node, Type::Undetectable(), lowering);
2677 27558 : return;
2678 : }
2679 : case IrOpcode::kArgumentsFrame: {
2680 : SetOutput(node, MachineType::PointerRepresentation());
2681 : return;
2682 : }
2683 : case IrOpcode::kArgumentsLength: {
2684 : VisitUnop(node, UseInfo::PointerInt(),
2685 11958 : MachineRepresentation::kTaggedSigned);
2686 11958 : return;
2687 : }
2688 : case IrOpcode::kNewUnmappedArgumentsElements: {
2689 : VisitBinop(node, UseInfo::PointerInt(), UseInfo::TaggedSigned(),
2690 12227 : MachineRepresentation::kTaggedPointer);
2691 12227 : return;
2692 : }
2693 : case IrOpcode::kArrayBufferWasNeutered: {
2694 1035 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
2695 1035 : return;
2696 : }
2697 : case IrOpcode::kCheckFloat64Hole: {
2698 : Type* const input_type = TypeOf(node->InputAt(0));
2699 2442 : if (input_type->Is(Type::Number())) {
2700 144 : VisitNoop(node, truncation);
2701 : } else {
2702 2298 : CheckFloat64HoleMode mode = CheckFloat64HoleModeOf(node->op());
2703 2298 : switch (mode) {
2704 : case CheckFloat64HoleMode::kAllowReturnHole:
2705 2083 : if (truncation.IsUnused()) return VisitUnused(node);
2706 1970 : if (truncation.IsUsedAsFloat64()) {
2707 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2708 195 : MachineRepresentation::kFloat64);
2709 260 : if (lower()) DeferReplacement(node, node->InputAt(0));
2710 : } else {
2711 : VisitUnop(
2712 : node,
2713 : UseInfo(MachineRepresentation::kFloat64, Truncation::Any()),
2714 1775 : MachineRepresentation::kFloat64, Type::Number());
2715 : }
2716 : break;
2717 : case CheckFloat64HoleMode::kNeverReturnHole:
2718 : VisitUnop(
2719 : node,
2720 : UseInfo(MachineRepresentation::kFloat64, Truncation::Any()),
2721 215 : MachineRepresentation::kFloat64, Type::Number());
2722 215 : break;
2723 : }
2724 : }
2725 : return;
2726 : }
2727 : case IrOpcode::kCheckTaggedHole: {
2728 3564 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2729 3564 : return;
2730 : }
2731 : case IrOpcode::kConvertTaggedHoleToUndefined: {
2732 8240 : if (InputIs(node, Type::NumberOrOddball()) &&
2733 1920 : truncation.IsUsedAsWord32()) {
2734 : // Propagate the Word32 truncation.
2735 : VisitUnop(node, UseInfo::TruncatingWord32(),
2736 520 : MachineRepresentation::kWord32);
2737 652 : if (lower()) DeferReplacement(node, node->InputAt(0));
2738 7200 : } else if (InputIs(node, Type::NumberOrOddball()) &&
2739 1400 : truncation.IsUsedAsFloat64()) {
2740 : // Propagate the Float64 truncation.
2741 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2742 75 : MachineRepresentation::kFloat64);
2743 100 : if (lower()) DeferReplacement(node, node->InputAt(0));
2744 5725 : } else if (InputIs(node, Type::NonInternal())) {
2745 75 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2746 100 : if (lower()) DeferReplacement(node, node->InputAt(0));
2747 : } else {
2748 : // TODO(turbofan): Add a (Tagged) truncation that identifies hole
2749 : // and undefined, i.e. for a[i] === obj cases.
2750 5650 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2751 : }
2752 : return;
2753 : }
2754 : case IrOpcode::kCheckMaps:
2755 : case IrOpcode::kTransitionElementsKind: {
2756 153729 : VisitInputs(node);
2757 : return SetOutput(node, MachineRepresentation::kNone);
2758 : }
2759 : case IrOpcode::kEnsureWritableFastElements:
2760 : return VisitBinop(node, UseInfo::AnyTagged(),
2761 : MachineRepresentation::kTaggedPointer);
2762 : case IrOpcode::kMaybeGrowFastElements: {
2763 6498 : ProcessInput(node, 0, UseInfo::AnyTagged()); // object
2764 6498 : ProcessInput(node, 1, UseInfo::AnyTagged()); // elements
2765 6498 : ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index
2766 6498 : ProcessInput(node, 3, UseInfo::TruncatingWord32()); // length
2767 6498 : ProcessRemainingInputs(node, 4);
2768 : SetOutput(node, MachineRepresentation::kTaggedPointer);
2769 : return;
2770 : }
2771 :
2772 : case IrOpcode::kNumberSilenceNaN:
2773 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2774 2267 : MachineRepresentation::kFloat64);
2775 2995 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2776 : return;
2777 : case IrOpcode::kStateValues:
2778 15883379 : return VisitStateValues(node);
2779 : case IrOpcode::kObjectState:
2780 28124 : return VisitObjectState(node);
2781 : case IrOpcode::kTypeGuard: {
2782 : // We just get rid of the sigma here. In principle, it should be
2783 : // possible to refine the truncation and representation based on
2784 : // the sigma's type.
2785 :
2786 : // For now, we just handle specially the impossible case.
2787 : MachineRepresentation output =
2788 : TypeOf(node)->IsInhabited()
2789 : ? GetOutputInfoForPhi(node, TypeOf(node->InputAt(0)),
2790 : truncation)
2791 139124 : : MachineRepresentation::kNone;
2792 69668 : VisitUnop(node, UseInfo(output, truncation), output);
2793 85948 : if (lower()) DeferReplacement(node, node->InputAt(0));
2794 : return;
2795 : }
2796 :
2797 : case IrOpcode::kOsrGuard:
2798 167685 : return VisitOsrGuard(node);
2799 :
2800 : case IrOpcode::kFinishRegion:
2801 303764 : VisitInputs(node);
2802 : // Assume the output is tagged pointer.
2803 : return SetOutput(node, MachineRepresentation::kTaggedPointer);
2804 :
2805 : case IrOpcode::kReturn:
2806 1593070 : VisitReturn(node);
2807 : // Assume the output is tagged.
2808 : return SetOutput(node, MachineRepresentation::kTagged);
2809 :
2810 : // Operators with all inputs tagged and no or tagged output have uniform
2811 : // handling.
2812 : case IrOpcode::kEnd:
2813 : case IrOpcode::kIfSuccess:
2814 : case IrOpcode::kIfException:
2815 : case IrOpcode::kIfTrue:
2816 : case IrOpcode::kIfFalse:
2817 : case IrOpcode::kDeoptimize:
2818 : case IrOpcode::kEffectPhi:
2819 : case IrOpcode::kTerminate:
2820 : case IrOpcode::kFrameState:
2821 : case IrOpcode::kCheckpoint:
2822 : case IrOpcode::kLoop:
2823 : case IrOpcode::kMerge:
2824 : case IrOpcode::kThrow:
2825 : case IrOpcode::kBeginRegion:
2826 : case IrOpcode::kProjection:
2827 : case IrOpcode::kOsrValue:
2828 : case IrOpcode::kArgumentsElementsState:
2829 : case IrOpcode::kArgumentsLengthState:
2830 : // All JavaScript operators except JSToNumber have uniform handling.
2831 : #define OPCODE_CASE(name) case IrOpcode::k##name:
2832 : JS_SIMPLE_BINOP_LIST(OPCODE_CASE)
2833 : JS_OTHER_UNOP_LIST(OPCODE_CASE)
2834 : JS_OBJECT_OP_LIST(OPCODE_CASE)
2835 : JS_CONTEXT_OP_LIST(OPCODE_CASE)
2836 : JS_OTHER_OP_LIST(OPCODE_CASE)
2837 : #undef OPCODE_CASE
2838 : case IrOpcode::kJSToInteger:
2839 : case IrOpcode::kJSToLength:
2840 : case IrOpcode::kJSToName:
2841 : case IrOpcode::kJSToObject:
2842 : case IrOpcode::kJSToString:
2843 38662868 : VisitInputs(node);
2844 : // Assume the output is tagged.
2845 : return SetOutput(node, MachineRepresentation::kTagged);
2846 :
2847 : default:
2848 : V8_Fatal(
2849 : __FILE__, __LINE__,
2850 : "Representation inference: unsupported opcode %i (%s), node #%i\n.",
2851 0 : node->opcode(), node->op()->mnemonic(), node->id());
2852 : break;
2853 : }
2854 : UNREACHABLE();
2855 : }
2856 :
2857 250619 : void DeferReplacement(Node* node, Node* replacement) {
2858 596687 : TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(),
2859 : node->op()->mnemonic(), replacement->id(),
2860 : replacement->op()->mnemonic());
2861 :
2862 : // Disconnect the node from effect and control chains, if necessary.
2863 751857 : if (node->op()->EffectInputCount() > 0) {
2864 : DCHECK_LT(0, node->op()->ControlInputCount());
2865 : // Disconnect the node from effect and control chains.
2866 95449 : Node* control = NodeProperties::GetControlInput(node);
2867 95449 : Node* effect = NodeProperties::GetEffectInput(node);
2868 190898 : ReplaceEffectControlUses(node, effect, control);
2869 : }
2870 :
2871 250619 : replacements_.push_back(node);
2872 250618 : replacements_.push_back(replacement);
2873 :
2874 250619 : node->NullAllInputs(); // Node is now dead.
2875 250620 : }
2876 :
2877 150457 : void Kill(Node* node) {
2878 50160 : TRACE("killing #%d:%s\n", node->id(), node->op()->mnemonic());
2879 :
2880 50160 : if (node->op()->EffectInputCount() == 1) {
2881 : DCHECK_LT(0, node->op()->ControlInputCount());
2882 : // Disconnect the node from effect and control chains.
2883 50137 : Node* control = NodeProperties::GetControlInput(node);
2884 50137 : Node* effect = NodeProperties::GetEffectInput(node);
2885 50137 : ReplaceEffectControlUses(node, effect, control);
2886 : } else {
2887 : DCHECK_EQ(0, node->op()->EffectInputCount());
2888 : DCHECK_EQ(0, node->op()->ControlOutputCount());
2889 : DCHECK_EQ(0, node->op()->EffectOutputCount());
2890 : }
2891 :
2892 50160 : node->ReplaceUses(jsgraph_->Dead());
2893 :
2894 50160 : node->NullAllInputs(); // The {node} is now dead.
2895 50160 : }
2896 :
2897 47798444 : void PrintOutputInfo(NodeInfo* info) {
2898 47798444 : if (FLAG_trace_representation) {
2899 0 : OFStream os(stdout);
2900 0 : os << info->representation();
2901 : }
2902 47798444 : }
2903 :
2904 : void PrintRepresentation(MachineRepresentation rep) {
2905 : if (FLAG_trace_representation) {
2906 : OFStream os(stdout);
2907 : os << rep;
2908 : }
2909 : }
2910 :
2911 89604515 : void PrintTruncation(Truncation truncation) {
2912 89604515 : if (FLAG_trace_representation) {
2913 0 : OFStream os(stdout);
2914 0 : os << truncation.description() << std::endl;
2915 : }
2916 89604515 : }
2917 :
2918 13218542 : void PrintUseInfo(UseInfo info) {
2919 13218542 : if (FLAG_trace_representation) {
2920 0 : OFStream os(stdout);
2921 0 : os << info.representation() << ":" << info.truncation().description();
2922 : }
2923 13218542 : }
2924 :
2925 : private:
2926 : JSGraph* jsgraph_;
2927 : Zone* zone_; // Temporary zone.
2928 : size_t const count_; // number of nodes in the graph
2929 : ZoneVector<NodeInfo> info_; // node id -> usage information
2930 : #ifdef DEBUG
2931 : ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about
2932 : // requirements on inputs.
2933 : #endif // DEBUG
2934 : NodeVector nodes_; // collected nodes
2935 : NodeVector replacements_; // replacements to be done after lowering
2936 : Phase phase_; // current phase of algorithm
2937 : RepresentationChanger* changer_; // for inserting representation changes
2938 : ZoneQueue<Node*> queue_; // queue for traversing the graph
2939 :
2940 : struct NodeState {
2941 : Node* node;
2942 : int input_index;
2943 : };
2944 : ZoneStack<NodeState> typing_stack_; // stack for graph typing.
2945 : // TODO(danno): RepresentationSelector shouldn't know anything about the
2946 : // source positions table, but must for now since there currently is no other
2947 : // way to pass down source position information to nodes created during
2948 : // lowering. Once this phase becomes a vanilla reducer, it should get source
2949 : // position information via the SourcePositionWrapper like all other reducers.
2950 : SourcePositionTable* source_positions_;
2951 : TypeCache const& type_cache_;
2952 : OperationTyper op_typer_; // helper for the feedback typer
2953 :
2954 593762606 : NodeInfo* GetInfo(Node* node) {
2955 : DCHECK(node->id() < count_);
2956 597468671 : return &info_[node->id()];
2957 : }
2958 : Zone* zone() { return zone_; }
2959 : Zone* graph_zone() { return jsgraph_->zone(); }
2960 : };
2961 :
2962 394594 : SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
2963 : SourcePositionTable* source_positions)
2964 : : jsgraph_(jsgraph),
2965 : zone_(zone),
2966 394594 : type_cache_(TypeCache::Get()),
2967 1183782 : source_positions_(source_positions) {}
2968 :
2969 394593 : void SimplifiedLowering::LowerAllNodes() {
2970 394593 : RepresentationChanger changer(jsgraph(), jsgraph()->isolate());
2971 : RepresentationSelector selector(jsgraph(), zone_, &changer,
2972 394593 : source_positions_);
2973 394593 : selector.Run(this);
2974 394594 : }
2975 :
2976 162 : void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
2977 : Node* node, RepresentationSelector* selector) {
2978 : DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
2979 : Node* value = node->InputAt(0);
2980 : Node* context = node->InputAt(1);
2981 : Node* frame_state = node->InputAt(2);
2982 : Node* effect = node->InputAt(3);
2983 : Node* control = node->InputAt(4);
2984 :
2985 162 : Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
2986 : Node* branch0 =
2987 162 : graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
2988 :
2989 162 : Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2990 : Node* etrue0 = effect;
2991 : Node* vtrue0;
2992 : {
2993 162 : vtrue0 = graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
2994 162 : vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
2995 : }
2996 :
2997 162 : Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2998 : Node* efalse0 = effect;
2999 : Node* vfalse0;
3000 : {
3001 : vfalse0 = efalse0 = if_false0 =
3002 : graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
3003 162 : frame_state, efalse0, if_false0);
3004 :
3005 : // Update potential {IfException} uses of {node} to point to the above
3006 : // {ToNumber} stub call node instead.
3007 162 : Node* on_exception = nullptr;
3008 162 : if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
3009 0 : NodeProperties::ReplaceControlInput(on_exception, vfalse0);
3010 0 : NodeProperties::ReplaceEffectInput(on_exception, efalse0);
3011 0 : if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
3012 : }
3013 :
3014 162 : Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
3015 162 : Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
3016 :
3017 162 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3018 : Node* etrue1 = efalse0;
3019 : Node* vtrue1;
3020 : {
3021 : vtrue1 =
3022 162 : graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
3023 162 : vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
3024 : }
3025 :
3026 162 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3027 : Node* efalse1 = efalse0;
3028 : Node* vfalse1;
3029 : {
3030 : vfalse1 = efalse1 = graph()->NewNode(
3031 : simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
3032 486 : efalse1, if_false1);
3033 : }
3034 :
3035 162 : if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3036 : efalse0 =
3037 162 : graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
3038 : vfalse0 =
3039 : graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3040 162 : vtrue1, vfalse1, if_false0);
3041 : }
3042 :
3043 162 : control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
3044 162 : effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
3045 : value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3046 162 : vtrue0, vfalse0, control);
3047 :
3048 : // Replace effect and control uses appropriately.
3049 1740 : for (Edge edge : node->use_edges()) {
3050 789 : if (NodeProperties::IsControlEdge(edge)) {
3051 1077 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
3052 0 : edge.from()->ReplaceUses(control);
3053 0 : edge.from()->Kill();
3054 : } else {
3055 : DCHECK(edge.from()->opcode() != IrOpcode::kIfException);
3056 359 : edge.UpdateTo(control);
3057 : }
3058 430 : } else if (NodeProperties::IsEffectEdge(edge)) {
3059 238 : edge.UpdateTo(effect);
3060 : }
3061 : }
3062 :
3063 162 : selector->DeferReplacement(node, value);
3064 162 : }
3065 :
3066 2362 : void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
3067 : Node* node, RepresentationSelector* selector) {
3068 : DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
3069 : Node* value = node->InputAt(0);
3070 : Node* context = node->InputAt(1);
3071 : Node* frame_state = node->InputAt(2);
3072 : Node* effect = node->InputAt(3);
3073 : Node* control = node->InputAt(4);
3074 :
3075 2362 : Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
3076 : Node* branch0 =
3077 2362 : graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
3078 :
3079 2362 : Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3080 : Node* etrue0 = effect;
3081 : Node* vtrue0 =
3082 2362 : graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
3083 :
3084 2362 : Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3085 : Node* efalse0 = effect;
3086 : Node* vfalse0;
3087 : {
3088 : vfalse0 = efalse0 = if_false0 =
3089 : graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
3090 2362 : frame_state, efalse0, if_false0);
3091 :
3092 : // Update potential {IfException} uses of {node} to point to the above
3093 : // {ToNumber} stub call node instead.
3094 2362 : Node* on_exception = nullptr;
3095 2362 : if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
3096 0 : NodeProperties::ReplaceControlInput(on_exception, vfalse0);
3097 0 : NodeProperties::ReplaceEffectInput(on_exception, efalse0);
3098 0 : if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
3099 : }
3100 :
3101 2362 : Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
3102 2362 : Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
3103 :
3104 2362 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3105 : Node* etrue1 = efalse0;
3106 : Node* vtrue1 =
3107 2362 : graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
3108 :
3109 2362 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3110 : Node* efalse1 = efalse0;
3111 : Node* vfalse1;
3112 : {
3113 : vfalse1 = efalse1 = graph()->NewNode(
3114 : simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
3115 7086 : efalse1, if_false1);
3116 2362 : vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
3117 : }
3118 :
3119 2362 : if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3120 : efalse0 =
3121 2362 : graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
3122 : vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
3123 2362 : vtrue1, vfalse1, if_false0);
3124 : }
3125 :
3126 2362 : control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
3127 2362 : effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
3128 : value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
3129 2362 : vtrue0, vfalse0, control);
3130 :
3131 : // Replace effect and control uses appropriately.
3132 25970 : for (Edge edge : node->use_edges()) {
3133 11804 : if (NodeProperties::IsControlEdge(edge)) {
3134 17457 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
3135 0 : edge.from()->ReplaceUses(control);
3136 0 : edge.from()->Kill();
3137 : } else {
3138 : DCHECK(edge.from()->opcode() != IrOpcode::kIfException);
3139 5819 : edge.UpdateTo(control);
3140 : }
3141 5985 : } else if (NodeProperties::IsEffectEdge(edge)) {
3142 3746 : edge.UpdateTo(effect);
3143 : }
3144 : }
3145 :
3146 2362 : selector->DeferReplacement(node, value);
3147 2362 : }
3148 :
3149 5938 : void SimplifiedLowering::DoLoadBuffer(Node* node,
3150 : MachineRepresentation output_rep,
3151 616 : RepresentationChanger* changer) {
3152 : DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode());
3153 : DCHECK_NE(MachineRepresentation::kNone, output_rep);
3154 5938 : MachineType const access_type = BufferAccessOf(node->op()).machine_type();
3155 5938 : if (output_rep != access_type.representation()) {
3156 : Node* const buffer = node->InputAt(0);
3157 : Node* const offset = node->InputAt(1);
3158 : Node* const length = node->InputAt(2);
3159 : Node* const effect = node->InputAt(3);
3160 : Node* const control = node->InputAt(4);
3161 : Node* const index =
3162 : machine()->Is64()
3163 308 : ? graph()->NewNode(machine()->ChangeUint32ToUint64(), offset)
3164 308 : : offset;
3165 :
3166 308 : Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length);
3167 : Node* branch =
3168 308 : graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
3169 :
3170 308 : Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
3171 : Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
3172 308 : effect, if_true);
3173 : Type* element_type =
3174 308 : Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone());
3175 : Node* vtrue = changer->GetRepresentationFor(
3176 : etrue, access_type.representation(), element_type, node,
3177 308 : UseInfo(output_rep, Truncation::None()));
3178 :
3179 308 : Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
3180 : Node* efalse = effect;
3181 : Node* vfalse;
3182 308 : if (output_rep == MachineRepresentation::kTagged) {
3183 206 : vfalse = jsgraph()->UndefinedConstant();
3184 102 : } else if (output_rep == MachineRepresentation::kFloat64) {
3185 : vfalse =
3186 102 : jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
3187 0 : } else if (output_rep == MachineRepresentation::kFloat32) {
3188 : vfalse =
3189 0 : jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN());
3190 : } else {
3191 0 : vfalse = jsgraph()->Int32Constant(0);
3192 : }
3193 :
3194 308 : Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
3195 308 : Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
3196 :
3197 : // Replace effect uses of {node} with the {ephi}.
3198 308 : NodeProperties::ReplaceUses(node, node, ephi);
3199 :
3200 : // Turn the {node} into a Phi.
3201 308 : node->ReplaceInput(0, vtrue);
3202 308 : node->ReplaceInput(1, vfalse);
3203 308 : node->ReplaceInput(2, merge);
3204 308 : node->TrimInputCount(3);
3205 308 : NodeProperties::ChangeOp(node, common()->Phi(output_rep, 2));
3206 : } else {
3207 5630 : NodeProperties::ChangeOp(node, machine()->CheckedLoad(access_type));
3208 : }
3209 5938 : }
3210 :
3211 :
3212 4113 : void SimplifiedLowering::DoStoreBuffer(Node* node) {
3213 : DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode());
3214 : MachineRepresentation const rep =
3215 4113 : BufferAccessOf(node->op()).machine_type().representation();
3216 4113 : NodeProperties::ChangeOp(node, machine()->CheckedStore(rep));
3217 4113 : }
3218 :
3219 124 : Node* SimplifiedLowering::Float64Round(Node* const node) {
3220 62 : Node* const one = jsgraph()->Float64Constant(1.0);
3221 62 : Node* const one_half = jsgraph()->Float64Constant(0.5);
3222 : Node* const input = node->InputAt(0);
3223 :
3224 : // Round up towards Infinity, and adjust if the difference exceeds 0.5.
3225 : Node* result = graph()->NewNode(machine()->Float64RoundUp().placeholder(),
3226 124 : node->InputAt(0));
3227 : return graph()->NewNode(
3228 : common()->Select(MachineRepresentation::kFloat64),
3229 : graph()->NewNode(
3230 : machine()->Float64LessThanOrEqual(),
3231 : graph()->NewNode(machine()->Float64Sub(), result, one_half), input),
3232 310 : result, graph()->NewNode(machine()->Float64Sub(), result, one));
3233 : }
3234 :
3235 42 : Node* SimplifiedLowering::Float64Sign(Node* const node) {
3236 14 : Node* const minus_one = jsgraph()->Float64Constant(-1.0);
3237 14 : Node* const zero = jsgraph()->Float64Constant(0.0);
3238 14 : Node* const one = jsgraph()->Float64Constant(1.0);
3239 :
3240 : Node* const input = node->InputAt(0);
3241 :
3242 : return graph()->NewNode(
3243 : common()->Select(MachineRepresentation::kFloat64),
3244 : graph()->NewNode(machine()->Float64LessThan(), input, zero), minus_one,
3245 : graph()->NewNode(
3246 : common()->Select(MachineRepresentation::kFloat64),
3247 : graph()->NewNode(machine()->Float64LessThan(), zero, input), one,
3248 70 : input));
3249 : }
3250 :
3251 66 : Node* SimplifiedLowering::Int32Abs(Node* const node) {
3252 : Node* const input = node->InputAt(0);
3253 :
3254 : // Generate case for absolute integer value.
3255 : //
3256 : // let sign = input >> 31 in
3257 : // (input ^ sign) - sign
3258 :
3259 : Node* sign = graph()->NewNode(machine()->Word32Sar(), input,
3260 66 : jsgraph()->Int32Constant(31));
3261 : return graph()->NewNode(machine()->Int32Sub(),
3262 : graph()->NewNode(machine()->Word32Xor(), input, sign),
3263 99 : sign);
3264 : }
3265 :
3266 8298 : Node* SimplifiedLowering::Int32Div(Node* const node) {
3267 2766 : Int32BinopMatcher m(node);
3268 2766 : Node* const zero = jsgraph()->Int32Constant(0);
3269 2766 : Node* const minus_one = jsgraph()->Int32Constant(-1);
3270 : Node* const lhs = m.left().node();
3271 : Node* const rhs = m.right().node();
3272 :
3273 2766 : if (m.right().Is(-1)) {
3274 44 : return graph()->NewNode(machine()->Int32Sub(), zero, lhs);
3275 2744 : } else if (m.right().Is(0)) {
3276 : return rhs;
3277 2731 : } else if (machine()->Int32DivIsSafe() || m.right().HasValue()) {
3278 5272 : return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
3279 : }
3280 :
3281 : // General case for signed integer division.
3282 : //
3283 : // if 0 < rhs then
3284 : // lhs / rhs
3285 : // else
3286 : // if rhs < -1 then
3287 : // lhs / rhs
3288 : // else if rhs == 0 then
3289 : // 0
3290 : // else
3291 : // 0 - lhs
3292 : //
3293 : // Note: We do not use the Diamond helper class here, because it really hurts
3294 : // readability with nested diamonds.
3295 95 : const Operator* const merge_op = common()->Merge(2);
3296 : const Operator* const phi_op =
3297 95 : common()->Phi(MachineRepresentation::kWord32, 2);
3298 :
3299 95 : Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
3300 : Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
3301 190 : graph()->start());
3302 :
3303 95 : Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3304 95 : Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0);
3305 :
3306 95 : Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3307 : Node* false0;
3308 : {
3309 95 : Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
3310 95 : Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
3311 :
3312 95 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3313 95 : Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1);
3314 :
3315 95 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3316 : Node* false1;
3317 : {
3318 95 : Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
3319 95 : Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
3320 :
3321 95 : Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
3322 : Node* true2 = zero;
3323 :
3324 95 : Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
3325 95 : Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
3326 :
3327 : if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
3328 : false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
3329 : }
3330 :
3331 : if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
3332 : false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
3333 : }
3334 :
3335 : Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
3336 95 : return graph()->NewNode(phi_op, true0, false0, merge0);
3337 : }
3338 :
3339 :
3340 8556 : Node* SimplifiedLowering::Int32Mod(Node* const node) {
3341 2852 : Int32BinopMatcher m(node);
3342 2852 : Node* const zero = jsgraph()->Int32Constant(0);
3343 2852 : Node* const minus_one = jsgraph()->Int32Constant(-1);
3344 : Node* const lhs = m.left().node();
3345 : Node* const rhs = m.right().node();
3346 :
3347 5689 : if (m.right().Is(-1) || m.right().Is(0)) {
3348 : return zero;
3349 2837 : } else if (m.right().HasValue()) {
3350 8124 : return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
3351 : }
3352 :
3353 : // General case for signed integer modulus, with optimization for (unknown)
3354 : // power of 2 right hand side.
3355 : //
3356 : // if 0 < rhs then
3357 : // msk = rhs - 1
3358 : // if rhs & msk != 0 then
3359 : // lhs % rhs
3360 : // else
3361 : // if lhs < 0 then
3362 : // -(-lhs & msk)
3363 : // else
3364 : // lhs & msk
3365 : // else
3366 : // if rhs < -1 then
3367 : // lhs % rhs
3368 : // else
3369 : // zero
3370 : //
3371 : // Note: We do not use the Diamond helper class here, because it really hurts
3372 : // readability with nested diamonds.
3373 129 : const Operator* const merge_op = common()->Merge(2);
3374 : const Operator* const phi_op =
3375 129 : common()->Phi(MachineRepresentation::kWord32, 2);
3376 :
3377 129 : Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
3378 : Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
3379 258 : graph()->start());
3380 :
3381 129 : Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3382 : Node* true0;
3383 : {
3384 129 : Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
3385 :
3386 129 : Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
3387 129 : Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
3388 :
3389 129 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3390 129 : Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
3391 :
3392 129 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3393 : Node* false1;
3394 : {
3395 129 : Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
3396 : Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
3397 129 : check2, if_false1);
3398 :
3399 129 : Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
3400 : Node* true2 = graph()->NewNode(
3401 : machine()->Int32Sub(), zero,
3402 : graph()->NewNode(machine()->Word32And(),
3403 : graph()->NewNode(machine()->Int32Sub(), zero, lhs),
3404 387 : msk));
3405 :
3406 129 : Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
3407 129 : Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
3408 :
3409 : if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
3410 : false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
3411 : }
3412 :
3413 : if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
3414 : true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
3415 : }
3416 :
3417 129 : Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3418 : Node* false0;
3419 : {
3420 129 : Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
3421 : Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
3422 129 : check1, if_false0);
3423 :
3424 129 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3425 129 : Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
3426 :
3427 129 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3428 : Node* false1 = zero;
3429 :
3430 : if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
3431 : false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
3432 : }
3433 :
3434 : Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
3435 129 : return graph()->NewNode(phi_op, true0, false0, merge0);
3436 : }
3437 :
3438 21 : Node* SimplifiedLowering::Int32Sign(Node* const node) {
3439 7 : Node* const minus_one = jsgraph()->Int32Constant(-1);
3440 7 : Node* const zero = jsgraph()->Int32Constant(0);
3441 7 : Node* const one = jsgraph()->Int32Constant(1);
3442 :
3443 : Node* const input = node->InputAt(0);
3444 :
3445 : return graph()->NewNode(
3446 : common()->Select(MachineRepresentation::kWord32),
3447 : graph()->NewNode(machine()->Int32LessThan(), input, zero), minus_one,
3448 : graph()->NewNode(
3449 : common()->Select(MachineRepresentation::kWord32),
3450 : graph()->NewNode(machine()->Int32LessThan(), zero, input), one,
3451 35 : zero));
3452 : }
3453 :
3454 562 : Node* SimplifiedLowering::Uint32Div(Node* const node) {
3455 281 : Uint32BinopMatcher m(node);
3456 : Node* const zero = jsgraph()->Uint32Constant(0);
3457 : Node* const lhs = m.left().node();
3458 : Node* const rhs = m.right().node();
3459 :
3460 281 : if (m.right().Is(0)) {
3461 : return zero;
3462 261 : } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) {
3463 420 : return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
3464 : }
3465 :
3466 51 : Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
3467 51 : Diamond d(graph(), common(), check, BranchHint::kFalse);
3468 102 : Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
3469 51 : return d.Phi(MachineRepresentation::kWord32, zero, div);
3470 : }
3471 :
3472 :
3473 1527 : Node* SimplifiedLowering::Uint32Mod(Node* const node) {
3474 509 : Uint32BinopMatcher m(node);
3475 509 : Node* const minus_one = jsgraph()->Int32Constant(-1);
3476 : Node* const zero = jsgraph()->Uint32Constant(0);
3477 : Node* const lhs = m.left().node();
3478 : Node* const rhs = m.right().node();
3479 :
3480 509 : if (m.right().Is(0)) {
3481 : return zero;
3482 509 : } else if (m.right().HasValue()) {
3483 1374 : return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
3484 : }
3485 :
3486 : // General case for unsigned integer modulus, with optimization for (unknown)
3487 : // power of 2 right hand side.
3488 : //
3489 : // if rhs then
3490 : // msk = rhs - 1
3491 : // if rhs & msk != 0 then
3492 : // lhs % rhs
3493 : // else
3494 : // lhs & msk
3495 : // else
3496 : // zero
3497 : //
3498 : // Note: We do not use the Diamond helper class here, because it really hurts
3499 : // readability with nested diamonds.
3500 51 : const Operator* const merge_op = common()->Merge(2);
3501 : const Operator* const phi_op =
3502 51 : common()->Phi(MachineRepresentation::kWord32, 2);
3503 :
3504 : Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), rhs,
3505 102 : graph()->start());
3506 :
3507 51 : Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3508 : Node* true0;
3509 : {
3510 51 : Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
3511 :
3512 51 : Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
3513 51 : Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
3514 :
3515 51 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3516 51 : Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1);
3517 :
3518 51 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3519 51 : Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk);
3520 :
3521 : if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
3522 : true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
3523 : }
3524 :
3525 51 : Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3526 : Node* false0 = zero;
3527 :
3528 : Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
3529 51 : return graph()->NewNode(phi_op, true0, false0, merge0);
3530 : }
3531 :
3532 119 : void SimplifiedLowering::DoMax(Node* node, Operator const* op,
3533 : MachineRepresentation rep) {
3534 : Node* const lhs = node->InputAt(0);
3535 : Node* const rhs = node->InputAt(1);
3536 :
3537 119 : node->ReplaceInput(0, graph()->NewNode(op, lhs, rhs));
3538 : DCHECK_EQ(rhs, node->InputAt(1));
3539 119 : node->AppendInput(graph()->zone(), lhs);
3540 119 : NodeProperties::ChangeOp(node, common()->Select(rep));
3541 119 : }
3542 :
3543 118 : void SimplifiedLowering::DoMin(Node* node, Operator const* op,
3544 : MachineRepresentation rep) {
3545 : Node* const lhs = node->InputAt(0);
3546 : Node* const rhs = node->InputAt(1);
3547 :
3548 118 : node->InsertInput(graph()->zone(), 0, graph()->NewNode(op, lhs, rhs));
3549 : DCHECK_EQ(lhs, node->InputAt(1));
3550 : DCHECK_EQ(rhs, node->InputAt(2));
3551 118 : NodeProperties::ChangeOp(node, common()->Select(rep));
3552 118 : }
3553 :
3554 39005 : void SimplifiedLowering::DoShift(Node* node, Operator const* op,
3555 5074 : Type* rhs_type) {
3556 78009 : if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) {
3557 5074 : Node* const rhs = NodeProperties::GetValueInput(node, 1);
3558 : node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs,
3559 15222 : jsgraph()->Int32Constant(0x1f)));
3560 : }
3561 39004 : ChangeToPureOp(node, op);
3562 39005 : }
3563 :
3564 2244 : void SimplifiedLowering::DoStringToNumber(Node* node) {
3565 : Operator::Properties properties = Operator::kEliminatable;
3566 561 : Callable callable = CodeFactory::StringToNumber(isolate());
3567 : CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
3568 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
3569 1683 : isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
3570 : node->InsertInput(graph()->zone(), 0,
3571 1122 : jsgraph()->HeapConstant(callable.code()));
3572 561 : node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant());
3573 561 : node->AppendInput(graph()->zone(), graph()->start());
3574 561 : NodeProperties::ChangeOp(node, common()->Call(desc));
3575 561 : }
3576 :
3577 326 : void SimplifiedLowering::DoIntegral32ToBit(Node* node) {
3578 : Node* const input = node->InputAt(0);
3579 163 : Node* const zero = jsgraph()->Int32Constant(0);
3580 163 : Operator const* const op = machine()->Word32Equal();
3581 :
3582 163 : node->ReplaceInput(0, graph()->NewNode(op, input, zero));
3583 163 : node->AppendInput(graph()->zone(), zero);
3584 163 : NodeProperties::ChangeOp(node, op);
3585 163 : }
3586 :
3587 0 : void SimplifiedLowering::DoOrderedNumberToBit(Node* node) {
3588 : Node* const input = node->InputAt(0);
3589 :
3590 : node->ReplaceInput(0, graph()->NewNode(machine()->Float64Equal(), input,
3591 0 : jsgraph()->Float64Constant(0.0)));
3592 0 : node->AppendInput(graph()->zone(), jsgraph()->Int32Constant(0));
3593 0 : NodeProperties::ChangeOp(node, machine()->Word32Equal());
3594 0 : }
3595 :
3596 394 : void SimplifiedLowering::DoNumberToBit(Node* node) {
3597 : Node* const input = node->InputAt(0);
3598 :
3599 197 : node->ReplaceInput(0, jsgraph()->Float64Constant(0.0));
3600 : node->AppendInput(graph()->zone(),
3601 394 : graph()->NewNode(machine()->Float64Abs(), input));
3602 197 : NodeProperties::ChangeOp(node, machine()->Float64LessThan());
3603 197 : }
3604 :
3605 72 : void SimplifiedLowering::DoIntegerToUint8Clamped(Node* node) {
3606 : Node* const input = node->InputAt(0);
3607 24 : Node* const min = jsgraph()->Float64Constant(0.0);
3608 24 : Node* const max = jsgraph()->Float64Constant(255.0);
3609 :
3610 : node->ReplaceInput(
3611 48 : 0, graph()->NewNode(machine()->Float64LessThan(), min, input));
3612 : node->AppendInput(
3613 : graph()->zone(),
3614 : graph()->NewNode(
3615 : common()->Select(MachineRepresentation::kFloat64),
3616 : graph()->NewNode(machine()->Float64LessThan(), input, max), input,
3617 72 : max));
3618 24 : node->AppendInput(graph()->zone(), min);
3619 : NodeProperties::ChangeOp(node,
3620 24 : common()->Select(MachineRepresentation::kFloat64));
3621 24 : }
3622 :
3623 900 : void SimplifiedLowering::DoNumberToUint8Clamped(Node* node) {
3624 : Node* const input = node->InputAt(0);
3625 300 : Node* const min = jsgraph()->Float64Constant(0.0);
3626 300 : Node* const max = jsgraph()->Float64Constant(255.0);
3627 :
3628 : node->ReplaceInput(
3629 : 0, graph()->NewNode(
3630 : common()->Select(MachineRepresentation::kFloat64),
3631 : graph()->NewNode(machine()->Float64LessThan(), min, input),
3632 : graph()->NewNode(
3633 : common()->Select(MachineRepresentation::kFloat64),
3634 : graph()->NewNode(machine()->Float64LessThan(), input, max),
3635 : input, max),
3636 1500 : min));
3637 : NodeProperties::ChangeOp(node,
3638 300 : machine()->Float64RoundTiesEven().placeholder());
3639 300 : }
3640 :
3641 186 : void SimplifiedLowering::DoSigned32ToUint8Clamped(Node* node) {
3642 : Node* const input = node->InputAt(0);
3643 62 : Node* const min = jsgraph()->Int32Constant(0);
3644 62 : Node* const max = jsgraph()->Int32Constant(255);
3645 :
3646 : node->ReplaceInput(
3647 124 : 0, graph()->NewNode(machine()->Int32LessThanOrEqual(), input, max));
3648 : node->AppendInput(
3649 : graph()->zone(),
3650 : graph()->NewNode(common()->Select(MachineRepresentation::kWord32),
3651 : graph()->NewNode(machine()->Int32LessThan(), input, min),
3652 186 : min, input));
3653 62 : node->AppendInput(graph()->zone(), max);
3654 : NodeProperties::ChangeOp(node,
3655 62 : common()->Select(MachineRepresentation::kWord32));
3656 62 : }
3657 :
3658 144 : void SimplifiedLowering::DoUnsigned32ToUint8Clamped(Node* node) {
3659 : Node* const input = node->InputAt(0);
3660 : Node* const max = jsgraph()->Uint32Constant(255u);
3661 :
3662 : node->ReplaceInput(
3663 144 : 0, graph()->NewNode(machine()->Uint32LessThanOrEqual(), input, max));
3664 72 : node->AppendInput(graph()->zone(), input);
3665 72 : node->AppendInput(graph()->zone(), max);
3666 : NodeProperties::ChangeOp(node,
3667 72 : common()->Select(MachineRepresentation::kWord32));
3668 72 : }
3669 :
3670 5914 : Node* SimplifiedLowering::ToNumberCode() {
3671 2524 : if (!to_number_code_.is_set()) {
3672 1695 : Callable callable = CodeFactory::ToNumber(isolate());
3673 3390 : to_number_code_.set(jsgraph()->HeapConstant(callable.code()));
3674 : }
3675 2524 : return to_number_code_.get();
3676 : }
3677 :
3678 4219 : Operator const* SimplifiedLowering::ToNumberOperator() {
3679 2524 : if (!to_number_operator_.is_set()) {
3680 1695 : Callable callable = CodeFactory::ToNumber(isolate());
3681 : CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
3682 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
3683 : isolate(), graph()->zone(), callable.descriptor(), 0, flags,
3684 5085 : Operator::kNoProperties);
3685 1695 : to_number_operator_.set(common()->Call(desc));
3686 : }
3687 2524 : return to_number_operator_.get();
3688 : }
3689 :
3690 : } // namespace compiler
3691 : } // namespace internal
3692 : } // namespace v8
|