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 23199 : MachineRepresentation MachineRepresentationFromArrayType(
69 : ExternalArrayType array_type) {
70 23199 : switch (array_type) {
71 : case kExternalUint8Array:
72 : case kExternalUint8ClampedArray:
73 : case kExternalInt8Array:
74 : return MachineRepresentation::kWord8;
75 : case kExternalUint16Array:
76 : case kExternalInt16Array:
77 3111 : return MachineRepresentation::kWord16;
78 : case kExternalUint32Array:
79 : case kExternalInt32Array:
80 4169 : return MachineRepresentation::kWord32;
81 : case kExternalFloat32Array:
82 6633 : return MachineRepresentation::kFloat32;
83 : case kExternalFloat64Array:
84 2103 : return MachineRepresentation::kFloat64;
85 : }
86 0 : UNREACHABLE();
87 : return MachineRepresentation::kNone;
88 : }
89 :
90 1153798 : UseInfo CheckedUseInfoAsWord32FromHint(
91 : NumberOperationHint hint,
92 : IdentifyZeros identify_zeros = kDistinguishZeros) {
93 1153798 : 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 35079 : UseInfo CheckedUseInfoAsFloat64FromHint(NumberOperationHint hint) {
108 35079 : 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 18719642 : UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) {
124 18719642 : 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 2739697 : UseInfo UseInfoForBasePointer(const FieldAccess& access) {
154 5571027 : return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
155 : }
156 :
157 :
158 494881 : UseInfo UseInfoForBasePointer(const ElementAccess& access) {
159 606662 : return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
160 : }
161 :
162 368995 : void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) {
163 2379618 : for (Edge edge : node->use_edges()) {
164 1005310 : if (NodeProperties::IsControlEdge(edge)) {
165 0 : edge.UpdateTo(control);
166 1005315 : } else if (NodeProperties::IsEffectEdge(edge)) {
167 445511 : edge.UpdateTo(effect);
168 : } else {
169 : DCHECK(NodeProperties::IsValueEdge(edge) ||
170 : NodeProperties::IsContextEdge(edge));
171 : }
172 : }
173 368998 : }
174 :
175 843821 : void ChangeToPureOp(Node* node, const Operator* new_op) {
176 : DCHECK(new_op->HasProperty(Operator::kPure));
177 792850 : if (node->op()->EffectInputCount() > 0) {
178 : DCHECK_LT(0, node->op()->ControlInputCount());
179 : // Disconnect the node from effect and control chains.
180 223697 : Node* control = NodeProperties::GetControlInput(node);
181 223697 : Node* effect = NodeProperties::GetEffectInput(node);
182 223696 : ReplaceEffectControlUses(node, effect, control);
183 223700 : node->TrimInputCount(new_op->ValueInputCount());
184 : } else {
185 : DCHECK_EQ(0, node->op()->ControlInputCount());
186 : }
187 396429 : NodeProperties::ChangeOp(node, new_op);
188 396431 : }
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 309692 : 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 154852 : left = Type::Intersect(left, Type::Signed32(), type_zone);
222 154852 : right = Type::Intersect(right, Type::Signed32(), type_zone);
223 309694 : if (!left->IsInhabited() || !right->IsInhabited()) return false;
224 154840 : switch (op->opcode()) {
225 : case IrOpcode::kSpeculativeNumberAdd:
226 133931 : return (left->Max() + right->Max() > kMaxInt) ||
227 133929 : (left->Min() + right->Min() < kMinInt);
228 :
229 : case IrOpcode::kSpeculativeNumberSubtract:
230 31485 : return (left->Max() - right->Min() > kMaxInt) ||
231 31485 : (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 395303 : 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 87734905 : bool AddUse(UseInfo info) {
249 87734905 : Truncation old_truncation = truncation_;
250 87734905 : truncation_ = Truncation::Generalize(truncation_, info.truncation());
251 87733895 : return truncation_ != old_truncation;
252 : }
253 :
254 35831300 : void set_queued() { state_ = kQueued; }
255 64517056 : void set_visited() { state_ = kVisited; }
256 28687087 : void set_pushed() { state_ = kPushed; }
257 47359822 : 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 33678023 : void set_output(MachineRepresentation output) { representation_ = output; }
263 :
264 : MachineRepresentation representation() const { return representation_; }
265 :
266 : // Helpers for feedback typing.
267 20716139 : void set_feedback_type(Type* type) { feedback_type_ = type; }
268 : Type* feedback_type() const { return feedback_type_; }
269 110857 : void set_weakened() { weakened_ = true; }
270 : bool weakened() const { return weakened_; }
271 28717654 : 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 1185909 : RepresentationSelector(JSGraph* jsgraph, Zone* zone,
287 : RepresentationChanger* changer,
288 395303 : SourcePositionTable* source_positions)
289 : : jsgraph_(jsgraph),
290 : zone_(zone),
291 395303 : 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 395303 : type_cache_(TypeCache::Get()),
304 1976515 : op_typer_(jsgraph->isolate(), graph_zone()) {
305 395303 : }
306 :
307 : // Forward propagation of types from type feedback.
308 1185903 : void RunTypePropagationPhase() {
309 : // Run type propagation.
310 395302 : TRACE("--{Type propagation phase}--\n");
311 395303 : phase_ = RETYPE;
312 : ResetNodeInfoState();
313 :
314 : DCHECK(typing_stack_.empty());
315 790601 : typing_stack_.push({graph()->end(), 0});
316 395298 : GetInfo(graph()->end())->set_pushed();
317 57371186 : 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 280875285 : while (current.input_index < current.node->InputCount()) {
323 : Node* input = current.node->InputAt(current.input_index);
324 83265607 : NodeInfo* input_info = GetInfo(input);
325 83265607 : current.input_index++;
326 83265607 : if (input_info->unvisited()) {
327 : input_info->set_pushed();
328 56583963 : typing_stack_.push({input, 0});
329 : pushed_unvisited = true;
330 28292174 : break;
331 : }
332 : }
333 56976268 : if (pushed_unvisited) continue;
334 :
335 : // Process the top of the stack.
336 28686251 : Node* node = current.node;
337 : typing_stack_.pop();
338 : NodeInfo* info = GetInfo(node);
339 : info->set_visited();
340 28686251 : bool updated = UpdateFeedbackType(node);
341 28686134 : TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
342 28686134 : VisitNode(node, info->truncation(), nullptr);
343 28685621 : TRACE(" ==> output ");
344 28685621 : PrintOutputInfo(info);
345 28685725 : TRACE("\n");
346 28685884 : if (updated) {
347 154598601 : for (Node* const user : node->uses()) {
348 67836816 : if (GetInfo(user)->visited()) {
349 : GetInfo(user)->set_queued();
350 : queue_.push(user);
351 : }
352 : }
353 : }
354 : }
355 :
356 : // Process the revisit queue.
357 6304181 : while (!queue_.empty()) {
358 5908879 : Node* node = queue_.front();
359 : queue_.pop();
360 : NodeInfo* info = GetInfo(node);
361 : info->set_visited();
362 5908880 : bool updated = UpdateFeedbackType(node);
363 5908894 : TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
364 5908894 : VisitNode(node, info->truncation(), nullptr);
365 5908909 : TRACE(" ==> output ");
366 5908909 : PrintOutputInfo(info);
367 5908913 : TRACE("\n");
368 5908886 : if (updated) {
369 14450247 : for (Node* const user : node->uses()) {
370 6329772 : if (GetInfo(user)->visited()) {
371 : GetInfo(user)->set_queued();
372 : queue_.push(user);
373 : }
374 : }
375 : }
376 : }
377 395302 : }
378 :
379 : void ResetNodeInfoState() {
380 : // Clean up for the next phase.
381 47755125 : for (NodeInfo& info : info_) {
382 : info.reset_state();
383 : }
384 : }
385 :
386 : Type* TypeOf(Node* node) {
387 28321122 : Type* type = GetInfo(node)->feedback_type();
388 28321122 : return type == nullptr ? NodeProperties::GetType(node) : type;
389 : }
390 :
391 : Type* FeedbackTypeOf(Node* node) {
392 4441204 : Type* type = GetInfo(node)->feedback_type();
393 4441204 : return type == nullptr ? Type::None() : type;
394 : }
395 :
396 1035284 : Type* TypePhi(Node* node) {
397 1035284 : int arity = node->op()->ValueInputCount();
398 : Type* type = FeedbackTypeOf(node->InputAt(0));
399 2629896 : for (int i = 1; i < arity; ++i) {
400 1594618 : type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i)));
401 : }
402 1035278 : return type;
403 : }
404 :
405 10476 : Type* TypeSelect(Node* node) {
406 : return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)),
407 10476 : FeedbackTypeOf(node->InputAt(2)));
408 : }
409 :
410 36956840 : bool UpdateFeedbackType(Node* node) {
411 34594251 : if (node->op()->ValueOutputCount() == 0) return false;
412 :
413 25530006 : 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 25163264 : if (node->opcode() != IrOpcode::kPhi) {
421 133566754 : for (int i = 0; i < node->op()->ValueInputCount(); i++) {
422 56157631 : if (GetInfo(node->InputAt(i))->feedback_type() == nullptr) {
423 : return false;
424 : }
425 : }
426 : }
427 :
428 23725104 : 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 476241 : 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 364013 : 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 67414 : 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 1453 : SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_CASE)
465 : #undef DECLARE_CASE
466 :
467 : case IrOpcode::kPlainPrimitiveToNumber:
468 16418 : new_type = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
469 16418 : 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 496 : info->restriction_type(), graph_zone());
481 496 : break;
482 :
483 : case IrOpcode::kPhi: {
484 1035278 : new_type = TypePhi(node);
485 1035277 : if (type != nullptr) {
486 475974 : 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 23281 : FeedbackTypeOf(node->InputAt(0)));
494 23281 : break;
495 : }
496 :
497 : case IrOpcode::kSelect: {
498 10476 : new_type = TypeSelect(node);
499 10476 : break;
500 : }
501 :
502 : default:
503 : // Shortcut for operations that we do not handle.
504 21729254 : if (type == nullptr) {
505 : GetInfo(node)->set_feedback_type(NodeProperties::GetType(node));
506 18919648 : 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 1995847 : new_type = Type::Intersect(GetUpperBound(node), new_type, graph_zone());
515 :
516 2824388 : if (type != nullptr && new_type->Is(type)) return false;
517 : GetInfo(node)->set_feedback_type(new_type);
518 1796491 : 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 1705615 : Type* Weaken(Node* node, Type* previous_type, Type* current_type) {
548 : // If the types have nothing to do with integers, return the types.
549 475974 : Type* const integer = type_cache_.kInteger;
550 475974 : if (!previous_type->Maybe(integer)) {
551 : return current_type;
552 : }
553 : DCHECK(current_type->Maybe(integer));
554 :
555 : Type* current_integer =
556 411931 : Type::Intersect(current_type, integer, graph_zone());
557 : Type* previous_integer =
558 411930 : Type::Intersect(previous_type, integer, graph_zone());
559 :
560 : // Once we start weakening a node, we should always weaken.
561 411931 : 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 117008 : Type* previous = previous_integer->GetRange();
566 117009 : Type* current = current_integer->GetRange();
567 117009 : 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 405780 : graph_zone());
577 : }
578 :
579 : // Backward propagation of truncations.
580 395303 : void RunTruncationPropagationPhase() {
581 : // Run propagation phase to a fixpoint.
582 395303 : TRACE("--{Propagation phase}--\n");
583 395303 : phase_ = PROPAGATE;
584 395303 : EnqueueInitial(jsgraph_->graph()->end());
585 : // Process nodes from the queue until it is empty.
586 30712493 : while (!queue_.empty()) {
587 29921887 : Node* node = queue_.front();
588 : NodeInfo* info = GetInfo(node);
589 : queue_.pop();
590 : info->set_visited();
591 29921925 : TRACE(" visit #%d: %s (trunc: %s)\n", node->id(), node->op()->mnemonic(),
592 : info->truncation().description());
593 29921925 : VisitNode(node, info->truncation(), nullptr);
594 : }
595 395303 : }
596 :
597 395303 : void Run(SimplifiedLowering* lowering) {
598 395303 : RunTruncationPropagationPhase();
599 :
600 395303 : RunTypePropagationPhase();
601 :
602 : // Run lowering and change insertion phase.
603 395303 : TRACE("--{Simplified lowering phase}--\n");
604 395316 : phase_ = LOWER;
605 : // Process nodes from the collected {nodes_} vector.
606 29477498 : for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
607 28686880 : Node* node = *i;
608 : NodeInfo* info = GetInfo(node);
609 28686880 : 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 28686880 : source_positions_, source_positions_->GetSourcePosition(node));
613 28686887 : VisitNode(node, info->truncation(), lowering);
614 : }
615 :
616 : // Perform the final replacements.
617 1041189 : for (NodeVector::iterator i = replacements_.begin();
618 : i != replacements_.end(); ++i) {
619 250585 : Node* node = *i;
620 250585 : Node* replacement = *(++i);
621 250585 : node->ReplaceUses(replacement);
622 250585 : node->Kill();
623 : // We also need to replace the node in the rest of the vector.
624 16603650 : for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
625 : ++j;
626 16102480 : if (*j == node) *j = replacement;
627 : }
628 : }
629 395302 : }
630 :
631 395303 : void EnqueueInitial(Node* node) {
632 395303 : NodeInfo* info = GetInfo(node);
633 : info->set_queued();
634 395303 : nodes_.push_back(node);
635 : queue_.push(node);
636 395303 : }
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 139053108 : void EnqueueInput(Node* use_node, int index,
642 : UseInfo use_info = UseInfo::None()) {
643 139053108 : Node* node = use_node->InputAt(index);
644 218655409 : if (phase_ != PROPAGATE) return;
645 89627641 : 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 87742465 : if (info->unvisited()) {
652 : // First visit of this node.
653 : info->set_queued();
654 28291441 : nodes_.push_back(node);
655 : queue_.push(node);
656 28291449 : TRACE(" initial #%i: ", node->id());
657 28291449 : info->AddUse(use_info);
658 28291658 : PrintTruncation(info->truncation());
659 28291658 : return;
660 : }
661 59451024 : TRACE(" queue #%i?: ", node->id());
662 59451024 : PrintTruncation(info->truncation());
663 59451051 : if (info->AddUse(use_info)) {
664 : // New usage information for the node is available.
665 1885176 : if (!info->queued()) {
666 : queue_.push(node);
667 : info->set_queued();
668 1235545 : TRACE(" added: ");
669 : } else {
670 649621 : TRACE(" inqueue: ");
671 : }
672 1885166 : 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 90281497 : 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 57990 : bool InputCannotBe(Node* node, Type* type) {
703 : DCHECK_EQ(1, node->op()->ValueInputCount());
704 57990 : return !GetUpperBound(node->InputAt(0))->Maybe(type);
705 : }
706 :
707 182725 : bool InputIs(Node* node, Type* type) {
708 : DCHECK_EQ(1, node->op()->ValueInputCount());
709 182725 : return GetUpperBound(node->InputAt(0))->Is(type);
710 : }
711 :
712 : bool BothInputsAreSigned32(Node* node) {
713 98429 : return BothInputsAre(node, Type::Signed32());
714 : }
715 :
716 : bool BothInputsAreUnsigned32(Node* node) {
717 107363 : return BothInputsAre(node, Type::Unsigned32());
718 : }
719 :
720 4496496 : bool BothInputsAre(Node* node, Type* type) {
721 : DCHECK_EQ(2, node->op()->ValueInputCount());
722 6311344 : return GetUpperBound(node->InputAt(0))->Is(type) &&
723 4496561 : GetUpperBound(node->InputAt(1))->Is(type);
724 : }
725 :
726 : bool IsNodeRepresentationTagged(Node* node) {
727 43195 : 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 64034643 : 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 50818676 : if (use.representation() == MachineRepresentation::kNone)
741 50818698 : return; // No input requirement on the use.
742 : DCHECK_NOT_NULL(input);
743 61660353 : NodeInfo* input_info = GetInfo(input);
744 : MachineRepresentation input_rep = input_info->representation();
745 83765195 : if (input_rep != use.representation() ||
746 35320815 : use.type_check() != TypeCheckKind::kNone) {
747 : // Output representation doesn't match usage.
748 13215956 : TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
749 : index, input->id(), input->op()->mnemonic());
750 13215969 : TRACE(" from ");
751 13215969 : PrintOutputInfo(input_info);
752 13215967 : TRACE(" to ");
753 13215967 : PrintUseInfo(use);
754 13215968 : TRACE("\n");
755 : Node* n = changer_->GetRepresentationFor(
756 13215973 : input, input_info->representation(), TypeOf(input), node, use);
757 13215988 : node->ReplaceInput(index, n);
758 : }
759 : }
760 :
761 167104634 : void ProcessInput(Node* node, int index, UseInfo use) {
762 167104634 : switch (phase_) {
763 : case PROPAGATE:
764 53708852 : EnqueueInput(node, index, use);
765 53707791 : break;
766 : case RETYPE:
767 : break;
768 : case LOWER:
769 50818479 : ConvertInput(node, index, use);
770 50818317 : break;
771 : }
772 167103411 : }
773 :
774 13084650 : void ProcessRemainingInputs(Node* node, int index) {
775 : DCHECK_GE(index, NodeProperties::PastValueIndex(node));
776 : DCHECK_GE(index, NodeProperties::PastContextIndex(node));
777 58002030 : for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
778 22458814 : i < NodeProperties::PastEffectIndex(node); ++i) {
779 9374147 : EnqueueInput(node, i); // Effect inputs: just visit
780 : }
781 58136079 : for (int i = std::max(index, NodeProperties::FirstControlIndex(node));
782 22525887 : i < NodeProperties::PastControlIndex(node); ++i) {
783 9441481 : EnqueueInput(node, i); // Control inputs: just visit
784 : }
785 13084536 : }
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 78641612 : void VisitInputs(Node* node) {
792 78641612 : int tagged_count = node->op()->ValueInputCount() +
793 : OperatorProperties::GetContextInputCount(node->op()) +
794 39319389 : OperatorProperties::GetFrameStateInputCount(node->op());
795 : // Visit value, context and frame state inputs as tagged.
796 149636153 : for (int i = 0; i < tagged_count; i++) {
797 110316237 : ProcessInput(node, i, UseInfo::AnyTagged());
798 : }
799 : // Only enqueue other inputs (effects, control).
800 136998344 : for (int i = tagged_count; i < node->InputCount(); i++) {
801 48838901 : EnqueueInput(node, i);
802 : }
803 39320229 : }
804 :
805 3188761 : void VisitReturn(Node* node) {
806 3188761 : int tagged_limit = node->op()->ValueInputCount() +
807 : OperatorProperties::GetContextInputCount(node->op()) +
808 1594380 : OperatorProperties::GetFrameStateInputCount(node->op());
809 : // Visit integer slot count to pop
810 1594380 : ProcessInput(node, 0, UseInfo::TruncatingWord32());
811 :
812 : // Visit value, context and frame state inputs as tagged.
813 3188754 : for (int i = 1; i < tagged_limit; i++) {
814 1594378 : ProcessInput(node, i, UseInfo::AnyTagged());
815 : }
816 : // Only enqueue other inputs (effects, control).
817 7971888 : for (int i = tagged_limit; i < node->InputCount(); i++) {
818 3188755 : EnqueueInput(node, i);
819 : }
820 1594377 : }
821 :
822 : // Helper for an unused node.
823 1703678 : void VisitUnused(Node* node) {
824 1135792 : int value_count = node->op()->ValueInputCount() +
825 : OperatorProperties::GetContextInputCount(node->op()) +
826 567887 : OperatorProperties::GetFrameStateInputCount(node->op());
827 1498805 : for (int i = 0; i < value_count; i++) {
828 930911 : ProcessInput(node, i, UseInfo::None());
829 : }
830 567894 : ProcessRemainingInputs(node, value_count);
831 567886 : if (lower()) Kill(node);
832 567886 : }
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 3720414 : 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 3720414 : ProcessInput(node, 0, left_use);
849 3720309 : ProcessInput(node, 1, right_use);
850 14020462 : for (int i = 2; i < node->InputCount(); i++) {
851 3290052 : EnqueueInput(node, i);
852 : }
853 : SetOutput(node, output, restriction_type);
854 3720179 : }
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 2944373 : VisitBinop(node, input_use, input_use, output, restriction_type);
860 : }
861 :
862 114883 : void VisitSpeculativeInt32Binop(Node* node) {
863 : DCHECK_EQ(2, node->op()->ValueInputCount());
864 93383 : if (BothInputsAre(node, Type::NumberOrOddball())) {
865 : return VisitBinop(node, UseInfo::TruncatingWord32(),
866 : MachineRepresentation::kWord32);
867 : }
868 21500 : NumberOperationHint hint = NumberOperationHintOf(node->op());
869 : return VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
870 21499 : MachineRepresentation::kWord32);
871 : }
872 :
873 : // Helper for unops of the I -> O variety.
874 6621655 : void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output,
875 : Type* restriction_type = Type::Any()) {
876 : DCHECK_EQ(1, node->op()->ValueInputCount());
877 6621655 : ProcessInput(node, 0, input_use);
878 6621664 : ProcessRemainingInputs(node, 1);
879 : SetOutput(node, output, restriction_type);
880 6621642 : }
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 665643 : void VisitFloat64Binop(Node* node) {
890 : VisitBinop(node, UseInfo::TruncatingFloat64(),
891 : MachineRepresentation::kFloat64);
892 665644 : }
893 494513 : void VisitWord32TruncatingBinop(Node* node) {
894 : VisitBinop(node, UseInfo::TruncatingWord32(),
895 : MachineRepresentation::kWord32);
896 494484 : }
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 2328644 : MachineRepresentation GetOutputInfoForPhi(Node* node, Type* type,
903 1728841 : Truncation use) {
904 : // Compute the representation.
905 2328635 : if (type->Is(Type::None())) {
906 : return MachineRepresentation::kNone;
907 4209532 : } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
908 : return MachineRepresentation::kWord32;
909 2727946 : } else if (type->Is(Type::NumberOrOddball()) && use.IsUsedAsWord32()) {
910 : return MachineRepresentation::kWord32;
911 1910967 : } else if (type->Is(Type::Boolean())) {
912 : return MachineRepresentation::kBit;
913 2515687 : } else if (type->Is(Type::NumberOrOddball()) && use.IsUsedAsFloat64()) {
914 : return MachineRepresentation::kFloat64;
915 1728831 : } else if (type->Is(
916 1728841 : 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 1728127 : } else if (type->Is(Type::Number())) {
923 : return MachineRepresentation::kFloat64;
924 1120356 : } else if (type->Is(Type::ExternalPointer())) {
925 : return MachineType::PointerRepresentation();
926 : }
927 1120356 : return MachineRepresentation::kTagged;
928 : }
929 :
930 : // Helper for handling selects.
931 43085 : void VisitSelect(Node* node, Truncation truncation,
932 32609 : SimplifiedLowering* lowering) {
933 : DCHECK(TypeOf(node->InputAt(0))->Is(Type::Boolean()));
934 32609 : ProcessInput(node, 0, UseInfo::Bool());
935 :
936 : MachineRepresentation output =
937 32609 : GetOutputInfoForPhi(node, TypeOf(node), truncation);
938 : SetOutput(node, output);
939 :
940 32609 : if (lower()) {
941 : // Update the select operator.
942 10476 : SelectParameters p = SelectParametersOf(node->op());
943 10476 : 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 32609 : ProcessInput(node, 1, input_use);
952 32609 : ProcessInput(node, 2, input_use);
953 32609 : }
954 :
955 : // Helper for handling phis.
956 4457343 : void VisitPhi(Node* node, Truncation truncation,
957 2228662 : SimplifiedLowering* lowering) {
958 : MachineRepresentation output =
959 2228681 : 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 2228662 : int values = node->op()->ValueInputCount();
965 2228662 : if (lower()) {
966 : // Update the phi operator.
967 559323 : if (output != PhiRepresentationOf(node->op())) {
968 205904 : 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 20776996 : for (int i = 0; i < node->InputCount(); i++) {
976 8159818 : ProcessInput(node, i, i < values ? input_use : UseInfo::None());
977 : }
978 2228680 : }
979 :
980 454689 : void VisitObjectIs(Node* node, Type* type, SimplifiedLowering* lowering) {
981 : Type* const input_type = TypeOf(node->InputAt(0));
982 227069 : if (input_type->Is(type)) {
983 968 : VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
984 968 : if (lower()) {
985 272 : DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
986 : }
987 : } else {
988 226101 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
989 226101 : if (lower() && !input_type->Maybe(type)) {
990 279 : DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
991 : }
992 : }
993 227069 : }
994 :
995 4465370 : void VisitCall(Node* node, SimplifiedLowering* lowering) {
996 4465363 : const CallDescriptor* desc = CallDescriptorOf(node->op());
997 2232687 : int params = static_cast<int>(desc->ParameterCount());
998 2232687 : int value_input_count = node->op()->ValueInputCount();
999 : // Propagate representation information from call descriptor.
1000 22140757 : for (int i = 0; i < value_input_count; i++) {
1001 19908071 : if (i == 0) {
1002 : // The target of the call.
1003 2232637 : ProcessInput(node, i, UseInfo::Any());
1004 17675434 : } else if ((i - 1) < params) {
1005 : ProcessInput(node, i, TruncatingUseInfoFromRepresentation(
1006 30919622 : desc->GetInputType(i).representation()));
1007 : } else {
1008 2215623 : ProcessInput(node, i, UseInfo::AnyTagged());
1009 : }
1010 : }
1011 2232686 : ProcessRemainingInputs(node, value_input_count);
1012 :
1013 2232680 : if (desc->ReturnCount() > 0) {
1014 : SetOutput(node, desc->GetReturnType(0).representation());
1015 : } else {
1016 : SetOutput(node, MachineRepresentation::kTagged);
1017 : }
1018 2232680 : }
1019 :
1020 525378 : static MachineSemantic DeoptValueSemanticOf(Type* type) {
1021 : // We only need signedness to do deopt correctly.
1022 525377 : if (type->Is(Type::Signed32())) {
1023 : return MachineSemantic::kInt32;
1024 322728 : } else if (type->Is(Type::Unsigned32())) {
1025 : return MachineSemantic::kUint32;
1026 : } else {
1027 321952 : return MachineSemantic::kAny;
1028 : }
1029 : }
1030 :
1031 8874378 : static MachineType DeoptMachineTypeOf(MachineRepresentation rep, Type* type) {
1032 8874397 : 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 8874399 : if (type->Is(Type::ExternalPointer())) {
1039 : return MachineType::Pointer();
1040 : }
1041 : // Do not distinguish between various Tagged variations.
1042 8874399 : if (IsAnyTagged(rep)) {
1043 : return MachineType::AnyTagged();
1044 : }
1045 525374 : 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 525380 : return machine_type;
1052 : }
1053 :
1054 20424292 : void VisitStateValues(Node* node) {
1055 15899455 : if (propagate()) {
1056 22188015 : for (int i = 0; i < node->InputCount(); i++) {
1057 8831631 : EnqueueInput(node, i, UseInfo::Any());
1058 : }
1059 11374700 : } else if (lower()) {
1060 9049676 : Zone* zone = jsgraph_->zone();
1061 : ZoneVector<MachineType>* types =
1062 : new (zone->New(sizeof(ZoneVector<MachineType>)))
1063 4524838 : ZoneVector<MachineType>(node->InputCount(), zone);
1064 26712980 : for (int i = 0; i < node->InputCount(); i++) {
1065 : Node* input = node->InputAt(i);
1066 8831653 : (*types)[i] =
1067 8831653 : DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input));
1068 : }
1069 4524837 : SparseInputMask mask = SparseInputMaskOf(node->op());
1070 : NodeProperties::ChangeOp(
1071 9049676 : node, jsgraph_->common()->TypedStateValues(types, mask));
1072 : }
1073 : SetOutput(node, MachineRepresentation::kTagged);
1074 15899450 : }
1075 :
1076 27923 : void VisitObjectState(Node* node) {
1077 27923 : if (propagate()) {
1078 94286 : 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 42726 : UseInfo use_info = UseInfo::None();
1085 42726 : if (input_type->IsInhabited()) {
1086 42726 : if (input_type->Is(Type::ExternalPointer())) {
1087 0 : use_info = UseInfo::PointerInt();
1088 : } else {
1089 42726 : use_info = UseInfo::Any();
1090 : }
1091 : }
1092 42726 : EnqueueInput(node, i, use_info);
1093 : }
1094 19089 : } else if (lower()) {
1095 17668 : Zone* zone = jsgraph_->zone();
1096 : ZoneVector<MachineType>* types =
1097 : new (zone->New(sizeof(ZoneVector<MachineType>)))
1098 8834 : ZoneVector<MachineType>(node->InputCount(), zone);
1099 103120 : for (int i = 0; i < node->InputCount(); i++) {
1100 : Node* input = node->InputAt(i);
1101 42726 : (*types)[i] =
1102 42726 : DeoptMachineTypeOf(GetInfo(input)->representation(), TypeOf(input));
1103 : }
1104 : NodeProperties::ChangeOp(node,
1105 17668 : jsgraph_->common()->TypedObjectState(types));
1106 : }
1107 : SetOutput(node, MachineRepresentation::kTagged);
1108 27923 : }
1109 :
1110 259611 : const Operator* Int32Op(Node* node) {
1111 259611 : return changer_->Int32OperatorFor(node->opcode());
1112 : }
1113 :
1114 150537 : const Operator* Int32OverflowOp(Node* node) {
1115 150537 : return changer_->Int32OverflowOperatorFor(node->opcode());
1116 : }
1117 :
1118 69110 : const Operator* Uint32Op(Node* node) {
1119 69110 : return changer_->Uint32OperatorFor(node->opcode());
1120 : }
1121 :
1122 177 : const Operator* Uint32OverflowOp(Node* node) {
1123 177 : return changer_->Uint32OverflowOperatorFor(node->opcode());
1124 : }
1125 :
1126 183535 : const Operator* Float64Op(Node* node) {
1127 183535 : return changer_->Float64OperatorFor(node->opcode());
1128 : }
1129 :
1130 2949753 : WriteBarrierKind WriteBarrierKindFor(
1131 : BaseTaggedness base_taggedness,
1132 : MachineRepresentation field_representation, Type* field_type,
1133 : MachineRepresentation value_representation, Node* value) {
1134 5775056 : if (base_taggedness == kTaggedBase &&
1135 : CanBeTaggedPointer(field_representation)) {
1136 : Type* value_type = NodeProperties::GetType(value);
1137 5054172 : if (field_representation == MachineRepresentation::kTaggedSigned ||
1138 2527086 : value_representation == MachineRepresentation::kTaggedSigned) {
1139 : // Write barriers are only for stores of heap objects.
1140 : return kNoWriteBarrier;
1141 : }
1142 5029097 : 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 2233235 : if (value_type->IsHeapConstant()) {
1149 : Heap::RootListIndex root_index;
1150 814169 : Heap* heap = jsgraph_->isolate()->heap();
1151 814169 : if (heap->IsRootHandle(value_type->AsHeapConstant()->Value(),
1152 : &root_index)) {
1153 438069 : if (heap->RootIsImmortalImmovable(root_index)) {
1154 : // Write barriers are unnecessary for immortal immovable roots.
1155 : return kNoWriteBarrier;
1156 : }
1157 : }
1158 : }
1159 3590362 : if (field_representation == MachineRepresentation::kTaggedPointer ||
1160 1795181 : value_representation == MachineRepresentation::kTaggedPointer) {
1161 : // Write barriers for heap objects are cheaper.
1162 : return kPointerWriteBarrier;
1163 : }
1164 : NumberMatcher m(value);
1165 1404563 : if (m.HasValue()) {
1166 552476 : 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 621 : 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 5479460 : if (base_taggedness == kTaggedBase &&
1184 2739730 : field_offset == HeapObject::kMapOffset) {
1185 : return kMapWriteBarrier;
1186 : }
1187 : return WriteBarrierKindFor(base_taggedness, field_representation,
1188 2454871 : field_type, value_representation, value);
1189 : }
1190 :
1191 790601 : Graph* graph() const { return jsgraph_->graph(); }
1192 : CommonOperatorBuilder* common() const { return jsgraph_->common(); }
1193 : SimplifiedOperatorBuilder* simplified() const {
1194 15489 : return jsgraph_->simplified();
1195 : }
1196 :
1197 7143 : void LowerToCheckedInt32Mul(Node* node, Truncation truncation,
1198 7143 : 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 5469 : truncation.IdentifiesZeroAndMinusZero() ||
1203 1675 : (input0_type->Is(Type::OrderedNumber()) &&
1204 7125 : input0_type->Min() > 0) ||
1205 5350 : (input1_type->Is(Type::OrderedNumber()) &&
1206 5350 : input1_type->Min() > 0)
1207 : ? CheckForMinusZeroMode::kDontCheckForMinusZero
1208 7143 : : CheckForMinusZeroMode::kCheckForMinusZero;
1209 :
1210 7143 : NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode));
1211 7143 : }
1212 :
1213 150537 : void ChangeToInt32OverflowOp(Node* node) {
1214 150537 : NodeProperties::ChangeOp(node, Int32OverflowOp(node));
1215 150537 : }
1216 :
1217 177 : void ChangeToUint32OverflowOp(Node* node) {
1218 177 : NodeProperties::ChangeOp(node, Uint32OverflowOp(node));
1219 177 : }
1220 :
1221 2041074 : void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
1222 1036441 : 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 857112 : if (BothInputsAre(node, Type::NumberOrOddball())) {
1231 564347 : if (truncation.IsUnused()) return VisitUnused(node);
1232 : }
1233 :
1234 1936560 : if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) &&
1235 45390 : (GetUpperBound(node)->Is(Type::Signed32()) ||
1236 45381 : GetUpperBound(node)->Is(Type::Unsigned32()) ||
1237 : truncation.IsUsedAsWord32())) {
1238 : // => Int32Add/Sub
1239 274077 : VisitWord32TruncatingBinop(node);
1240 338181 : if (lower()) ChangeToPureOp(node, Int32Op(node));
1241 : return;
1242 : }
1243 :
1244 : // Try to use type feedback.
1245 536358 : NumberOperationHint hint = NumberOperationHintOf(node->op());
1246 :
1247 536357 : 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 1558335 : if (BothInputsAre(node, Type::Signed32()) ||
1256 492723 : (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 492752 : IdentifyZeros left_identify_zeros = truncation.identify_zeros();
1266 928087 : if (node->opcode() == IrOpcode::kSpeculativeNumberAdd &&
1267 435366 : !right_feedback_type->Maybe(Type::MinusZero())) {
1268 : left_identify_zeros = kIdentifyZeros;
1269 : }
1270 : UseInfo left_use =
1271 492721 : 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 492722 : CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros);
1278 : VisitBinop(node, left_use, right_use, MachineRepresentation::kWord32,
1279 492728 : Type::Signed32());
1280 : }
1281 532798 : if (lower()) {
1282 154852 : if (CanOverflowSigned32(node->op(), left_feedback_type,
1283 : right_feedback_type, graph_zone())) {
1284 148866 : ChangeToInt32OverflowOp(node);
1285 : } else {
1286 5982 : 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 3586 : if (lower()) {
1296 1042 : ChangeToPureOp(node, Float64Op(node));
1297 : }
1298 : return;
1299 : }
1300 :
1301 22717 : void VisitSpeculativeNumberModulus(Node* node, Truncation truncation,
1302 15006 : 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 15108 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1308 9328 : if (truncation.IsUnused()) return VisitUnused(node);
1309 : }
1310 30764 : if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) &&
1311 252 : (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 36108 : if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) &&
1319 1531 : (truncation.IsUsedAsWord32() ||
1320 : NodeProperties::GetType(node)->Is(Type::Signed32()))) {
1321 : // => signed Int32Mod
1322 6453 : VisitWord32TruncatingBinop(node);
1323 6453 : if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1324 : return;
1325 : }
1326 :
1327 : // Try to use type feedback.
1328 7609 : 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 7609 : if (BothInputsAreUnsigned32(node)) {
1333 231 : if (hint == NumberOperationHint::kSignedSmall ||
1334 : hint == NumberOperationHint::kSigned32) {
1335 : VisitBinop(node, UseInfo::TruncatingWord32(),
1336 : MachineRepresentation::kWord32, Type::Unsigned32());
1337 231 : 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 7378 : 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 6078 : if (hint == NumberOperationHint::kSignedSmall ||
1356 : hint == NumberOperationHint::kSigned32) {
1357 : // If the result is truncated, we only need to check the inputs.
1358 5516 : if (truncation.IsUsedAsWord32()) {
1359 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1360 1147 : MachineRepresentation::kWord32);
1361 1147 : if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1362 4369 : } 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 4369 : MachineRepresentation::kWord32, Type::Signed32());
1369 4369 : if (lower()) ChangeToInt32OverflowOp(node);
1370 : }
1371 : return;
1372 : }
1373 :
1374 616 : if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
1375 562 : 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 674 : if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
1387 576 : 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 689 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1402 : return;
1403 : }
1404 :
1405 501198 : void VisitOsrGuard(Node* node) {
1406 167066 : VisitInputs(node);
1407 :
1408 : // Insert a dynamic check for the OSR value type if necessary.
1409 167066 : 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 167066 : if (lower()) {
1422 53845 : 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 93527234 : void VisitNode(Node* node, Truncation truncation,
1432 7228821 : 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 242707651 : if (node->op()->ValueInputCount() > 0 &&
1443 : node->op()->HasProperty(Operator::kPure)) {
1444 36032678 : if (truncation.IsUnused()) return VisitUnused(node);
1445 : }
1446 93036826 : 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 3075466 : 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 4256 : if (lower()) {
1471 1334 : intptr_t const value = OpParameter<intptr_t>(node);
1472 1334 : 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 2345441 : ProcessInput(node, 0, UseInfo::Bool());
1480 2345418 : EnqueueInput(node, NodeProperties::FirstControlIndex(node));
1481 2345422 : 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 32609 : return VisitSelect(node, truncation, lowering);
1489 : case IrOpcode::kPhi:
1490 2228683 : return VisitPhi(node, truncation, lowering);
1491 : case IrOpcode::kCall:
1492 2232683 : return VisitCall(node, lowering);
1493 :
1494 : //------------------------------------------------------------------
1495 : // JavaScript operators.
1496 : //------------------------------------------------------------------
1497 : case IrOpcode::kJSToBoolean: {
1498 532072 : if (truncation.IsUsedAsBool()) {
1499 261887 : ProcessInput(node, 0, UseInfo::Bool());
1500 261887 : ProcessInput(node, 1, UseInfo::None());
1501 : SetOutput(node, MachineRepresentation::kBit);
1502 344810 : if (lower()) DeferReplacement(node, node->InputAt(0));
1503 : } else {
1504 4149 : VisitInputs(node);
1505 : SetOutput(node, MachineRepresentation::kTaggedPointer);
1506 : }
1507 : return;
1508 : }
1509 : case IrOpcode::kJSToNumber: {
1510 17899 : VisitInputs(node);
1511 : // TODO(bmeurer): Optimize somewhat based on input type?
1512 35798 : if (truncation.IsUsedAsWord32()) {
1513 : SetOutput(node, MachineRepresentation::kWord32);
1514 9526 : if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this);
1515 16746 : } else if (truncation.IsUsedAsFloat64()) {
1516 : SetOutput(node, MachineRepresentation::kFloat64);
1517 661 : 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 31388 : if (lower()) {
1529 9771 : NodeInfo* input_info = GetInfo(node->InputAt(0));
1530 9771 : if (input_info->representation() == MachineRepresentation::kBit) {
1531 : // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
1532 602627 : node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
1533 9082 : NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
1534 : } else {
1535 : DCHECK(CanBeTaggedPointer(input_info->representation()));
1536 : // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
1537 1378 : node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
1538 689 : NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
1539 : }
1540 : } else {
1541 : // No input representation requirement; adapt during lowering.
1542 21617 : ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
1543 : SetOutput(node, MachineRepresentation::kBit);
1544 : }
1545 : return;
1546 : }
1547 : case IrOpcode::kNumberEqual: {
1548 : Type* const lhs_type = TypeOf(node->InputAt(0));
1549 : Type* const rhs_type = TypeOf(node->InputAt(1));
1550 : // Number comparisons reduce to integer comparisons for integer inputs.
1551 407687 : if ((lhs_type->Is(Type::Unsigned32()) &&
1552 419167 : rhs_type->Is(Type::Unsigned32())) ||
1553 1231 : (lhs_type->Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
1554 977 : rhs_type->Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
1555 977 : OneInputCannotBe(node, type_cache_.kZeroish))) {
1556 : // => unsigned Int32Cmp
1557 : VisitBinop(node, UseInfo::TruncatingWord32(),
1558 : MachineRepresentation::kBit);
1559 174370 : if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
1560 : return;
1561 : }
1562 245388 : if ((lhs_type->Is(Type::Signed32()) &&
1563 185219 : rhs_type->Is(Type::Signed32())) ||
1564 2040 : (lhs_type->Is(Type::Signed32OrMinusZeroOrNaN()) &&
1565 1906 : rhs_type->Is(Type::Signed32OrMinusZeroOrNaN()) &&
1566 1906 : OneInputCannotBe(node, type_cache_.kZeroish))) {
1567 : // => signed Int32Cmp
1568 : VisitBinop(node, UseInfo::TruncatingWord32(),
1569 : MachineRepresentation::kBit);
1570 134971 : if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
1571 : return;
1572 : }
1573 : // => Float64Cmp
1574 : VisitBinop(node, UseInfo::TruncatingFloat64(),
1575 : MachineRepresentation::kBit);
1576 53371 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
1577 : return;
1578 : }
1579 : case IrOpcode::kNumberLessThan:
1580 : case IrOpcode::kNumberLessThanOrEqual: {
1581 : // Number comparisons reduce to integer comparisons for integer inputs.
1582 250142 : if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
1583 : TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
1584 : // => unsigned Int32Cmp
1585 : VisitBinop(node, UseInfo::TruncatingWord32(),
1586 : MachineRepresentation::kBit);
1587 118970 : if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
1588 74315 : } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
1589 : TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
1590 : // => signed Int32Cmp
1591 : VisitBinop(node, UseInfo::TruncatingWord32(),
1592 : MachineRepresentation::kBit);
1593 19888 : if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
1594 : } else {
1595 : // => Float64Cmp
1596 : VisitBinop(node, UseInfo::TruncatingFloat64(),
1597 : MachineRepresentation::kBit);
1598 32139 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
1599 : }
1600 : return;
1601 : }
1602 :
1603 : case IrOpcode::kSpeculativeNumberAdd:
1604 : case IrOpcode::kSpeculativeNumberSubtract:
1605 857104 : return VisitSpeculativeAdditiveOp(node, truncation, lowering);
1606 :
1607 : case IrOpcode::kSpeculativeNumberLessThan:
1608 : case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1609 : case IrOpcode::kSpeculativeNumberEqual: {
1610 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
1611 : // can only eliminate an unused speculative number operation if we know
1612 : // that the inputs are PlainPrimitive, which excludes everything that's
1613 : // might have side effects or throws during a ToNumber conversion.
1614 427084 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1615 310238 : if (truncation.IsUnused()) return VisitUnused(node);
1616 : }
1617 : // Number comparisons reduce to integer comparisons for integer inputs.
1618 656282 : if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
1619 : TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
1620 : // => unsigned Int32Cmp
1621 : VisitBinop(node, UseInfo::TruncatingWord32(),
1622 : MachineRepresentation::kBit);
1623 8645 : if (lower()) ChangeToPureOp(node, Uint32Op(node));
1624 : return;
1625 655506 : } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
1626 : TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
1627 : // => signed Int32Cmp
1628 : VisitBinop(node, UseInfo::TruncatingWord32(),
1629 : MachineRepresentation::kBit);
1630 252821 : if (lower()) ChangeToPureOp(node, Int32Op(node));
1631 : return;
1632 : }
1633 : // Try to use type feedback.
1634 200886 : NumberOperationHint hint = NumberOperationHintOf(node->op());
1635 200886 : switch (hint) {
1636 : case NumberOperationHint::kSignedSmall:
1637 : case NumberOperationHint::kSigned32: {
1638 165807 : if (propagate()) {
1639 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1640 107418 : MachineRepresentation::kBit);
1641 58389 : } else if (retype()) {
1642 : SetOutput(node, MachineRepresentation::kBit, Type::Any());
1643 : } else {
1644 : DCHECK(lower());
1645 : Node* lhs = node->InputAt(0);
1646 : Node* rhs = node->InputAt(1);
1647 43195 : if (IsNodeRepresentationTagged(lhs) &&
1648 : IsNodeRepresentationTagged(rhs)) {
1649 : VisitBinop(node, UseInfo::CheckedSignedSmallAsTaggedSigned(),
1650 : MachineRepresentation::kBit);
1651 : ChangeToPureOp(
1652 19708 : node, changer_->TaggedSignedOperatorFor(node->opcode()));
1653 :
1654 : } else {
1655 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1656 2824 : MachineRepresentation::kBit);
1657 2824 : ChangeToPureOp(node, Int32Op(node));
1658 : }
1659 : }
1660 : return;
1661 : }
1662 : case NumberOperationHint::kNumberOrOddball:
1663 : // Abstract and strict equality don't perform ToNumber conversions
1664 : // on Oddballs, so make sure we don't accidentially sneak in a
1665 : // hint with Oddball feedback here.
1666 : DCHECK_NE(IrOpcode::kSpeculativeNumberEqual, node->opcode());
1667 : // Fallthrough
1668 : case NumberOperationHint::kNumber:
1669 : VisitBinop(node, CheckedUseInfoAsFloat64FromHint(hint),
1670 35079 : MachineRepresentation::kBit);
1671 44082 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1672 : return;
1673 : }
1674 0 : UNREACHABLE();
1675 : return;
1676 : }
1677 :
1678 : case IrOpcode::kNumberAdd:
1679 : case IrOpcode::kNumberSubtract: {
1680 1402458 : if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) &&
1681 90515 : (GetUpperBound(node)->Is(Type::Signed32()) ||
1682 90305 : GetUpperBound(node)->Is(Type::Unsigned32()) ||
1683 90305 : truncation.IsUsedAsWord32())) {
1684 : // => Int32Add/Sub
1685 74845 : VisitWord32TruncatingBinop(node);
1686 96104 : if (lower()) ChangeToPureOp(node, Int32Op(node));
1687 : } else {
1688 : // => Float64Add/Sub
1689 566062 : VisitFloat64Binop(node);
1690 657344 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1691 : }
1692 : return;
1693 : }
1694 : case IrOpcode::kSpeculativeNumberMultiply: {
1695 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
1696 : // can only eliminate an unused speculative number operation if we know
1697 : // that the inputs are PlainPrimitive, which excludes everything that's
1698 : // might have side effects or throws during a ToNumber conversion.
1699 65023 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1700 18200 : if (truncation.IsUnused()) return VisitUnused(node);
1701 : }
1702 133146 : if (BothInputsAre(node, Type::Integral32()) &&
1703 2230 : (NodeProperties::GetType(node)->Is(Type::Signed32()) ||
1704 2227 : NodeProperties::GetType(node)->Is(Type::Unsigned32()) ||
1705 2360 : (truncation.IsUsedAsWord32() &&
1706 : NodeProperties::GetType(node)->Is(
1707 133 : type_cache_.kSafeIntegerOrMinusZero)))) {
1708 : // Multiply reduces to Int32Mul if the inputs are integers, and
1709 : // (a) the output is either known to be Signed32, or
1710 : // (b) the output is known to be Unsigned32, or
1711 : // (c) the uses are truncating and the result is in the safe
1712 : // integer range.
1713 1626 : VisitWord32TruncatingBinop(node);
1714 2054 : if (lower()) ChangeToPureOp(node, Int32Op(node));
1715 : return;
1716 : }
1717 : // Try to use type feedback.
1718 63063 : NumberOperationHint hint = NumberOperationHintOf(node->op());
1719 : Type* input0_type = TypeOf(node->InputAt(0));
1720 : Type* input1_type = TypeOf(node->InputAt(1));
1721 :
1722 : // Handle the case when no int32 checks on inputs are necessary
1723 : // (but an overflow check is needed on the output).
1724 63063 : if (BothInputsAre(node, Type::Signed32())) {
1725 : // If both the inputs the feedback are int32, use the overflow op.
1726 2142 : if (hint == NumberOperationHint::kSignedSmall ||
1727 : hint == NumberOperationHint::kSigned32) {
1728 : VisitBinop(node, UseInfo::TruncatingWord32(),
1729 : MachineRepresentation::kWord32, Type::Signed32());
1730 2142 : if (lower()) {
1731 : LowerToCheckedInt32Mul(node, truncation, input0_type,
1732 665 : input1_type);
1733 : }
1734 : return;
1735 : }
1736 : }
1737 :
1738 60921 : if (hint == NumberOperationHint::kSignedSmall ||
1739 : hint == NumberOperationHint::kSigned32) {
1740 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1741 21181 : MachineRepresentation::kWord32, Type::Signed32());
1742 21181 : if (lower()) {
1743 6478 : LowerToCheckedInt32Mul(node, truncation, input0_type, input1_type);
1744 : }
1745 : return;
1746 : }
1747 :
1748 : // Checked float64 x float64 => float64
1749 : VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
1750 : MachineRepresentation::kFloat64, Type::Number());
1751 51798 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1752 : return;
1753 : }
1754 : case IrOpcode::kNumberMultiply: {
1755 135519 : if (BothInputsAre(node, Type::Integral32()) &&
1756 12783 : (NodeProperties::GetType(node)->Is(Type::Signed32()) ||
1757 12461 : NodeProperties::GetType(node)->Is(Type::Unsigned32()) ||
1758 19418 : (truncation.IsUsedAsWord32() &&
1759 : NodeProperties::GetType(node)->Is(
1760 6957 : type_cache_.kSafeIntegerOrMinusZero)))) {
1761 : // Multiply reduces to Int32Mul if the inputs are integers, and
1762 : // (a) the output is either known to be Signed32, or
1763 : // (b) the output is known to be Unsigned32, or
1764 : // (c) the uses are truncating and the result is in the safe
1765 : // integer range.
1766 7303 : VisitWord32TruncatingBinop(node);
1767 9203 : if (lower()) ChangeToPureOp(node, Int32Op(node));
1768 : return;
1769 : }
1770 : // Number x Number => Float64Mul
1771 53876 : VisitFloat64Binop(node);
1772 69315 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1773 : return;
1774 : }
1775 : case IrOpcode::kSpeculativeNumberDivide: {
1776 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
1777 : // can only eliminate an unused speculative number operation if we know
1778 : // that the inputs are PlainPrimitive, which excludes everything that's
1779 : // might have side effects or throws during a ToNumber conversion.
1780 26045 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1781 1537 : if (truncation.IsUnused()) return VisitUnused(node);
1782 : }
1783 26053 : if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) {
1784 : // => unsigned Uint32Div
1785 0 : VisitWord32TruncatingBinop(node);
1786 0 : if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
1787 : return;
1788 : }
1789 25470 : if (BothInputsAreSigned32(node)) {
1790 628 : if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
1791 : // => signed Int32Div
1792 0 : VisitWord32TruncatingBinop(node);
1793 0 : if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1794 : return;
1795 : }
1796 1256 : if (truncation.IsUsedAsWord32()) {
1797 : // => signed Int32Div
1798 45 : VisitWord32TruncatingBinop(node);
1799 45 : if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1800 : return;
1801 : }
1802 : }
1803 :
1804 : // Try to use type feedback.
1805 25425 : NumberOperationHint hint = NumberOperationHintOf(node->op());
1806 :
1807 : // Handle the case when no uint32 checks on inputs are necessary
1808 : // (but an overflow check is needed on the output).
1809 25425 : if (BothInputsAreUnsigned32(node)) {
1810 583 : if (hint == NumberOperationHint::kSignedSmall ||
1811 : hint == NumberOperationHint::kSigned32) {
1812 : VisitBinop(node, UseInfo::TruncatingWord32(),
1813 : MachineRepresentation::kWord32, Type::Unsigned32());
1814 469 : if (lower()) ChangeToUint32OverflowOp(node);
1815 : return;
1816 : }
1817 : }
1818 :
1819 : // Handle the case when no int32 checks on inputs are necessary
1820 : // (but an overflow check is needed on the output).
1821 24956 : if (BothInputsAreSigned32(node)) {
1822 : // If both the inputs the feedback are int32, use the overflow op.
1823 114 : if (hint == NumberOperationHint::kSignedSmall ||
1824 : hint == NumberOperationHint::kSigned32) {
1825 : VisitBinop(node, UseInfo::TruncatingWord32(),
1826 : MachineRepresentation::kWord32, Type::Signed32());
1827 0 : if (lower()) ChangeToInt32OverflowOp(node);
1828 : return;
1829 : }
1830 : }
1831 :
1832 24956 : if (hint == NumberOperationHint::kSignedSmall ||
1833 : hint == NumberOperationHint::kSigned32) {
1834 : // If the result is truncated, we only need to check the inputs.
1835 1720 : if (truncation.IsUsedAsWord32()) {
1836 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1837 108 : MachineRepresentation::kWord32);
1838 108 : if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1839 : } else {
1840 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1841 752 : MachineRepresentation::kWord32, Type::Signed32());
1842 752 : if (lower()) ChangeToInt32OverflowOp(node);
1843 : }
1844 : return;
1845 : }
1846 :
1847 : // default case => Float64Div
1848 : VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
1849 : MachineRepresentation::kFloat64, Type::Number());
1850 30947 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1851 : return;
1852 : }
1853 : case IrOpcode::kNumberDivide: {
1854 58234 : if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) {
1855 : // => unsigned Uint32Div
1856 856 : VisitWord32TruncatingBinop(node);
1857 856 : if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
1858 : return;
1859 : }
1860 48003 : if (BothInputsAreSigned32(node)) {
1861 21839 : if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
1862 : // => signed Int32Div
1863 0 : VisitWord32TruncatingBinop(node);
1864 0 : if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1865 : return;
1866 : }
1867 43678 : if (truncation.IsUsedAsWord32()) {
1868 : // => signed Int32Div
1869 8762 : VisitWord32TruncatingBinop(node);
1870 8762 : if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1871 : return;
1872 : }
1873 : }
1874 : // Number x Number => Float64Div
1875 39241 : VisitFloat64Binop(node);
1876 50308 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1877 : return;
1878 : }
1879 : case IrOpcode::kSpeculativeNumberModulus:
1880 15108 : return VisitSpeculativeNumberModulus(node, truncation, lowering);
1881 : case IrOpcode::kNumberModulus: {
1882 19774 : if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) &&
1883 1145 : (truncation.IsUsedAsWord32() ||
1884 : NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
1885 : // => unsigned Uint32Mod
1886 913 : VisitWord32TruncatingBinop(node);
1887 913 : if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
1888 : return;
1889 : }
1890 20222 : if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) &&
1891 4030 : (truncation.IsUsedAsWord32() ||
1892 : NodeProperties::GetType(node)->Is(Type::Signed32()))) {
1893 : // => signed Int32Mod
1894 2521 : VisitWord32TruncatingBinop(node);
1895 2521 : if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1896 : return;
1897 : }
1898 6522 : if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
1899 6101 : TypeOf(node->InputAt(1))->Is(Type::Unsigned32()) &&
1900 260 : (truncation.IsUsedAsWord32() ||
1901 : NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
1902 : // We can only promise Float64 truncation here, as the decision is
1903 : // based on the feedback types of the inputs.
1904 : VisitBinop(node, UseInfo(MachineRepresentation::kWord32,
1905 : Truncation::Float64()),
1906 : MachineRepresentation::kWord32);
1907 24 : if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
1908 : return;
1909 : }
1910 7764 : if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
1911 6724 : TypeOf(node->InputAt(1))->Is(Type::Signed32()) &&
1912 1578 : (truncation.IsUsedAsWord32() ||
1913 : NodeProperties::GetType(node)->Is(Type::Signed32()))) {
1914 : // We can only promise Float64 truncation here, as the decision is
1915 : // based on the feedback types of the inputs.
1916 : VisitBinop(node, UseInfo(MachineRepresentation::kWord32,
1917 : Truncation::Float64()),
1918 : MachineRepresentation::kWord32);
1919 0 : if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1920 : return;
1921 : }
1922 : // default case => Float64Mod
1923 5935 : VisitFloat64Binop(node);
1924 7653 : if (lower()) ChangeToPureOp(node, Float64Op(node));
1925 : return;
1926 : }
1927 : case IrOpcode::kNumberBitwiseOr:
1928 : case IrOpcode::kNumberBitwiseXor:
1929 : case IrOpcode::kNumberBitwiseAnd: {
1930 115912 : VisitWord32TruncatingBinop(node);
1931 151626 : if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
1932 : return;
1933 : }
1934 : case IrOpcode::kSpeculativeNumberBitwiseOr:
1935 : case IrOpcode::kSpeculativeNumberBitwiseXor:
1936 : case IrOpcode::kSpeculativeNumberBitwiseAnd:
1937 93381 : VisitSpeculativeInt32Binop(node);
1938 93384 : if (lower()) {
1939 25054 : ChangeToPureOp(node, Int32Op(node));
1940 : }
1941 : return;
1942 : case IrOpcode::kNumberShiftLeft: {
1943 : Type* rhs_type = GetUpperBound(node->InputAt(1));
1944 : VisitBinop(node, UseInfo::TruncatingWord32(),
1945 42283 : UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1946 42281 : if (lower()) {
1947 12984 : lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
1948 : }
1949 : return;
1950 : }
1951 : case IrOpcode::kSpeculativeNumberShiftLeft: {
1952 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
1953 : // can only eliminate an unused speculative number operation if we know
1954 : // that the inputs are PlainPrimitive, which excludes everything that's
1955 : // might have side effects or throws during a ToNumber conversion.
1956 10050 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1957 9182 : if (truncation.IsUnused()) return VisitUnused(node);
1958 : }
1959 9986 : if (BothInputsAre(node, Type::NumberOrOddball())) {
1960 : Type* rhs_type = GetUpperBound(node->InputAt(1));
1961 : VisitBinop(node, UseInfo::TruncatingWord32(),
1962 : UseInfo::TruncatingWord32(),
1963 9094 : MachineRepresentation::kWord32);
1964 9094 : if (lower()) {
1965 2101 : lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
1966 : }
1967 : return;
1968 : }
1969 892 : NumberOperationHint hint = NumberOperationHintOf(node->op());
1970 : Type* rhs_type = GetUpperBound(node->InputAt(1));
1971 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
1972 892 : MachineRepresentation::kWord32, Type::Signed32());
1973 892 : if (lower()) {
1974 282 : lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
1975 : }
1976 : return;
1977 : }
1978 : case IrOpcode::kNumberShiftRight: {
1979 : Type* rhs_type = GetUpperBound(node->InputAt(1));
1980 : VisitBinop(node, UseInfo::TruncatingWord32(),
1981 34835 : UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1982 34833 : if (lower()) {
1983 10796 : lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
1984 : }
1985 : return;
1986 : }
1987 : case IrOpcode::kSpeculativeNumberShiftRight: {
1988 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
1989 : // can only eliminate an unused speculative number operation if we know
1990 : // that the inputs are PlainPrimitive, which excludes everything that's
1991 : // might have side effects or throws during a ToNumber conversion.
1992 25741 : if (BothInputsAre(node, Type::PlainPrimitive())) {
1993 24371 : if (truncation.IsUnused()) return VisitUnused(node);
1994 : }
1995 25594 : if (BothInputsAre(node, Type::NumberOrOddball())) {
1996 : Type* rhs_type = GetUpperBound(node->InputAt(1));
1997 : VisitBinop(node, UseInfo::TruncatingWord32(),
1998 : UseInfo::TruncatingWord32(),
1999 24200 : MachineRepresentation::kWord32);
2000 24200 : if (lower()) {
2001 5339 : lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
2002 : }
2003 : return;
2004 : }
2005 1394 : NumberOperationHint hint = NumberOperationHintOf(node->op());
2006 : Type* rhs_type = GetUpperBound(node->InputAt(1));
2007 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
2008 1394 : MachineRepresentation::kWord32, Type::Signed32());
2009 1394 : if (lower()) {
2010 402 : lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
2011 : }
2012 : return;
2013 : }
2014 : case IrOpcode::kNumberShiftRightLogical: {
2015 : Type* rhs_type = GetUpperBound(node->InputAt(1));
2016 : VisitBinop(node, UseInfo::TruncatingWord32(),
2017 19541 : UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
2018 19540 : if (lower()) {
2019 6299 : lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
2020 : }
2021 : return;
2022 : }
2023 : case IrOpcode::kSpeculativeNumberShiftRightLogical: {
2024 : // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
2025 : // can only eliminate an unused speculative number operation if we know
2026 : // that the inputs are PlainPrimitive, which excludes everything that's
2027 : // might have side effects or throws during a ToNumber conversion.
2028 7405 : if (BothInputsAre(node, Type::PlainPrimitive())) {
2029 5994 : if (truncation.IsUnused()) return VisitUnused(node);
2030 : }
2031 7041 : NumberOperationHint hint = NumberOperationHintOf(node->op());
2032 : Type* rhs_type = GetUpperBound(node->InputAt(1));
2033 16892 : if (rhs_type->Is(type_cache_.kZeroish) &&
2034 : (hint == NumberOperationHint::kSignedSmall ||
2035 7580 : hint == NumberOperationHint::kSigned32) &&
2036 539 : !truncation.IsUsedAsWord32()) {
2037 : // The SignedSmall or Signed32 feedback means that the results that we
2038 : // have seen so far were of type Unsigned31. We speculate that this
2039 : // will continue to hold. Moreover, since the RHS is 0, the result
2040 : // will just be the (converted) LHS.
2041 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
2042 259 : MachineRepresentation::kWord32, Type::Unsigned31());
2043 259 : if (lower()) {
2044 70 : node->RemoveInput(1);
2045 : NodeProperties::ChangeOp(node,
2046 70 : simplified()->CheckedUint32ToInt32());
2047 : }
2048 : return;
2049 : }
2050 6782 : if (BothInputsAre(node, Type::NumberOrOddball())) {
2051 : VisitBinop(node, UseInfo::TruncatingWord32(),
2052 : UseInfo::TruncatingWord32(),
2053 5480 : MachineRepresentation::kWord32);
2054 5480 : if (lower()) {
2055 1590 : lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
2056 : }
2057 : return;
2058 : }
2059 : VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
2060 1302 : MachineRepresentation::kWord32, Type::Unsigned32());
2061 1302 : if (lower()) {
2062 387 : lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
2063 : }
2064 : return;
2065 : }
2066 : case IrOpcode::kNumberAbs: {
2067 240 : if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32())) {
2068 : VisitUnop(node, UseInfo::TruncatingWord32(),
2069 0 : MachineRepresentation::kWord32);
2070 0 : if (lower()) DeferReplacement(node, node->InputAt(0));
2071 240 : } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32())) {
2072 : VisitUnop(node, UseInfo::TruncatingWord32(),
2073 99 : MachineRepresentation::kWord32);
2074 99 : if (lower()) DeferReplacement(node, lowering->Int32Abs(node));
2075 141 : } else if (TypeOf(node->InputAt(0))
2076 141 : ->Is(type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) {
2077 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2078 0 : MachineRepresentation::kFloat64);
2079 0 : if (lower()) DeferReplacement(node, node->InputAt(0));
2080 : } else {
2081 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2082 141 : MachineRepresentation::kFloat64);
2083 184 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2084 : }
2085 : return;
2086 : }
2087 : case IrOpcode::kNumberClz32: {
2088 : VisitUnop(node, UseInfo::TruncatingWord32(),
2089 81 : MachineRepresentation::kWord32);
2090 108 : if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
2091 : return;
2092 : }
2093 : case IrOpcode::kNumberImul: {
2094 : VisitBinop(node, UseInfo::TruncatingWord32(),
2095 187 : UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
2096 241 : if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
2097 : return;
2098 : }
2099 : case IrOpcode::kNumberFround: {
2100 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2101 2004 : MachineRepresentation::kFloat32);
2102 2666 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2103 : return;
2104 : }
2105 : case IrOpcode::kNumberMax: {
2106 : // It is safe to use the feedback types for left and right hand side
2107 : // here, since we can only narrow those types and thus we can only
2108 : // promise a more specific truncation.
2109 : Type* const lhs_type = TypeOf(node->InputAt(0));
2110 : Type* const rhs_type = TypeOf(node->InputAt(1));
2111 570 : if (lhs_type->Is(Type::Unsigned32()) &&
2112 : rhs_type->Is(Type::Unsigned32())) {
2113 21 : VisitWord32TruncatingBinop(node);
2114 21 : if (lower()) {
2115 : lowering->DoMax(node, lowering->machine()->Uint32LessThan(),
2116 7 : MachineRepresentation::kWord32);
2117 : }
2118 672 : } else if (lhs_type->Is(Type::Signed32()) &&
2119 : rhs_type->Is(Type::Signed32())) {
2120 184 : VisitWord32TruncatingBinop(node);
2121 184 : if (lower()) {
2122 : lowering->DoMax(node, lowering->machine()->Int32LessThan(),
2123 64 : MachineRepresentation::kWord32);
2124 : }
2125 406 : } else if (lhs_type->Is(Type::PlainNumber()) &&
2126 : rhs_type->Is(Type::PlainNumber())) {
2127 150 : VisitFloat64Binop(node);
2128 150 : if (lower()) {
2129 : lowering->DoMax(node, lowering->machine()->Float64LessThan(),
2130 50 : MachineRepresentation::kFloat64);
2131 : }
2132 : } else {
2133 65 : VisitFloat64Binop(node);
2134 84 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2135 : }
2136 : return;
2137 : }
2138 : case IrOpcode::kNumberMin: {
2139 : // It is safe to use the feedback types for left and right hand side
2140 : // here, since we can only narrow those types and thus we can only
2141 : // promise a more specific truncation.
2142 : Type* const lhs_type = TypeOf(node->InputAt(0));
2143 : Type* const rhs_type = TypeOf(node->InputAt(1));
2144 665 : if (lhs_type->Is(Type::Unsigned32()) &&
2145 : rhs_type->Is(Type::Unsigned32())) {
2146 21 : VisitWord32TruncatingBinop(node);
2147 21 : if (lower()) {
2148 : lowering->DoMin(node, lowering->machine()->Uint32LessThan(),
2149 7 : MachineRepresentation::kWord32);
2150 : }
2151 806 : } else if (lhs_type->Is(Type::Signed32()) &&
2152 : rhs_type->Is(Type::Signed32())) {
2153 197 : VisitWord32TruncatingBinop(node);
2154 197 : if (lower()) {
2155 : lowering->DoMin(node, lowering->machine()->Int32LessThan(),
2156 68 : MachineRepresentation::kWord32);
2157 : }
2158 472 : } else if (lhs_type->Is(Type::PlainNumber()) &&
2159 : rhs_type->Is(Type::PlainNumber())) {
2160 126 : VisitFloat64Binop(node);
2161 126 : if (lower()) {
2162 : lowering->DoMin(node, lowering->machine()->Float64LessThan(),
2163 42 : MachineRepresentation::kFloat64);
2164 : }
2165 : } else {
2166 187 : VisitFloat64Binop(node);
2167 247 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2168 : }
2169 : return;
2170 : }
2171 : case IrOpcode::kNumberAtan2:
2172 : case IrOpcode::kNumberPow: {
2173 : VisitBinop(node, UseInfo::TruncatingFloat64(),
2174 : MachineRepresentation::kFloat64);
2175 3724 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2176 : return;
2177 : }
2178 : case IrOpcode::kNumberAcos:
2179 : case IrOpcode::kNumberAcosh:
2180 : case IrOpcode::kNumberAsin:
2181 : case IrOpcode::kNumberAsinh:
2182 : case IrOpcode::kNumberAtan:
2183 : case IrOpcode::kNumberAtanh:
2184 : case IrOpcode::kNumberCeil:
2185 : case IrOpcode::kNumberCos:
2186 : case IrOpcode::kNumberCosh:
2187 : case IrOpcode::kNumberExp:
2188 : case IrOpcode::kNumberExpm1:
2189 : case IrOpcode::kNumberFloor:
2190 : case IrOpcode::kNumberLog:
2191 : case IrOpcode::kNumberLog1p:
2192 : case IrOpcode::kNumberLog2:
2193 : case IrOpcode::kNumberLog10:
2194 : case IrOpcode::kNumberCbrt:
2195 : case IrOpcode::kNumberSin:
2196 : case IrOpcode::kNumberSinh:
2197 : case IrOpcode::kNumberTan:
2198 : case IrOpcode::kNumberTanh:
2199 : case IrOpcode::kNumberTrunc: {
2200 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2201 50237 : MachineRepresentation::kFloat64);
2202 66627 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2203 : return;
2204 : }
2205 : case IrOpcode::kNumberRound: {
2206 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2207 201 : MachineRepresentation::kFloat64);
2208 201 : if (lower()) DeferReplacement(node, lowering->Float64Round(node));
2209 : return;
2210 : }
2211 : case IrOpcode::kNumberSign: {
2212 63 : if (InputIs(node, Type::Signed32())) {
2213 : VisitUnop(node, UseInfo::TruncatingWord32(),
2214 21 : MachineRepresentation::kWord32);
2215 21 : if (lower()) DeferReplacement(node, lowering->Int32Sign(node));
2216 : } else {
2217 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2218 42 : MachineRepresentation::kFloat64);
2219 42 : if (lower()) DeferReplacement(node, lowering->Float64Sign(node));
2220 : }
2221 : return;
2222 : }
2223 : case IrOpcode::kNumberSqrt: {
2224 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2225 180 : MachineRepresentation::kFloat64);
2226 239 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2227 : return;
2228 : }
2229 : case IrOpcode::kNumberToBoolean: {
2230 : Type* const input_type = TypeOf(node->InputAt(0));
2231 1086 : if (input_type->Is(Type::Integral32())) {
2232 : VisitUnop(node, UseInfo::TruncatingWord32(),
2233 327 : MachineRepresentation::kBit);
2234 327 : if (lower()) lowering->DoIntegral32ToBit(node);
2235 759 : } else if (input_type->Is(Type::OrderedNumber())) {
2236 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2237 0 : MachineRepresentation::kBit);
2238 0 : if (lower()) lowering->DoOrderedNumberToBit(node);
2239 : } else {
2240 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2241 759 : MachineRepresentation::kBit);
2242 759 : if (lower()) lowering->DoNumberToBit(node);
2243 : }
2244 : return;
2245 : }
2246 : case IrOpcode::kNumberToInt32: {
2247 : // Just change representation if necessary.
2248 : VisitUnop(node, UseInfo::TruncatingWord32(),
2249 108467 : MachineRepresentation::kWord32);
2250 141328 : if (lower()) DeferReplacement(node, node->InputAt(0));
2251 : return;
2252 : }
2253 : case IrOpcode::kNumberToUint32: {
2254 : // Just change representation if necessary.
2255 : VisitUnop(node, UseInfo::TruncatingWord32(),
2256 32238 : MachineRepresentation::kWord32);
2257 42529 : if (lower()) DeferReplacement(node, node->InputAt(0));
2258 : return;
2259 : }
2260 : case IrOpcode::kNumberToUint8Clamped: {
2261 : Type* const input_type = TypeOf(node->InputAt(0));
2262 2976 : if (input_type->Is(type_cache_.kUint8OrMinusZeroOrNaN)) {
2263 : VisitUnop(node, UseInfo::TruncatingWord32(),
2264 54 : MachineRepresentation::kWord32);
2265 72 : if (lower()) DeferReplacement(node, node->InputAt(0));
2266 1434 : } else if (input_type->Is(Type::Unsigned32OrMinusZeroOrNaN())) {
2267 : VisitUnop(node, UseInfo::TruncatingWord32(),
2268 236 : MachineRepresentation::kWord32);
2269 236 : if (lower()) lowering->DoUnsigned32ToUint8Clamped(node);
2270 1198 : } else if (input_type->Is(Type::Signed32OrMinusZeroOrNaN())) {
2271 : VisitUnop(node, UseInfo::TruncatingWord32(),
2272 211 : MachineRepresentation::kWord32);
2273 211 : if (lower()) lowering->DoSigned32ToUint8Clamped(node);
2274 1974 : } else if (input_type->Is(type_cache_.kIntegerOrMinusZeroOrNaN)) {
2275 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2276 87 : MachineRepresentation::kFloat64);
2277 87 : if (lower()) lowering->DoIntegerToUint8Clamped(node);
2278 : } else {
2279 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2280 900 : MachineRepresentation::kFloat64);
2281 900 : if (lower()) lowering->DoNumberToUint8Clamped(node);
2282 : }
2283 : return;
2284 : }
2285 : case IrOpcode::kReferenceEqual: {
2286 : VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
2287 670460 : if (lower()) {
2288 220083 : NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
2289 : }
2290 : return;
2291 : }
2292 : case IrOpcode::kStringEqual:
2293 : case IrOpcode::kStringLessThan:
2294 : case IrOpcode::kStringLessThanOrEqual: {
2295 : return VisitBinop(node, UseInfo::AnyTagged(),
2296 : MachineRepresentation::kTaggedPointer);
2297 : }
2298 : case IrOpcode::kStringCharAt: {
2299 : VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
2300 1022 : MachineRepresentation::kTaggedPointer);
2301 1022 : return;
2302 : }
2303 : case IrOpcode::kStringCharCodeAt: {
2304 : // TODO(turbofan): Allow builtins to return untagged values.
2305 : VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
2306 1236 : MachineRepresentation::kTaggedSigned);
2307 1236 : return;
2308 : }
2309 : case IrOpcode::kStringFromCharCode: {
2310 : VisitUnop(node, UseInfo::TruncatingWord32(),
2311 2372 : MachineRepresentation::kTaggedPointer);
2312 2372 : return;
2313 : }
2314 : case IrOpcode::kStringFromCodePoint: {
2315 : VisitUnop(node, UseInfo::TruncatingWord32(),
2316 185 : MachineRepresentation::kTaggedPointer);
2317 185 : return;
2318 : }
2319 : case IrOpcode::kStringIndexOf: {
2320 511 : ProcessInput(node, 0, UseInfo::AnyTagged());
2321 511 : ProcessInput(node, 1, UseInfo::AnyTagged());
2322 511 : ProcessInput(node, 2, UseInfo::TaggedSigned());
2323 : SetOutput(node, MachineRepresentation::kTaggedSigned);
2324 : return;
2325 : }
2326 :
2327 : case IrOpcode::kCheckBounds: {
2328 : Type* index_type = TypeOf(node->InputAt(0));
2329 : Type* length_type = TypeOf(node->InputAt(1));
2330 114388 : if (index_type->Is(Type::Integral32OrMinusZero())) {
2331 : // Map -0 to 0, and the values in the [-2^31,-1] range to the
2332 : // [2^31,2^32-1] range, which will be considered out-of-bounds
2333 : // as well, because the {length_type} is limited to Unsigned31.
2334 : VisitBinop(node, UseInfo::TruncatingWord32(),
2335 : MachineRepresentation::kWord32);
2336 92392 : if (lower()) {
2337 47666 : if (index_type->Min() >= 0.0 &&
2338 21728 : index_type->Max() < length_type->Min()) {
2339 : // The bounds check is redundant if we already know that
2340 : // the index is within the bounds of [0.0, length[.
2341 3293 : DeferReplacement(node, node->InputAt(0));
2342 : }
2343 : }
2344 : } else {
2345 : VisitBinop(node, UseInfo::CheckedSigned32AsWord32(kIdentifyZeros),
2346 : UseInfo::TruncatingWord32(),
2347 21996 : MachineRepresentation::kWord32);
2348 : }
2349 : return;
2350 : }
2351 : case IrOpcode::kCheckHeapObject: {
2352 57990 : if (InputCannotBe(node, Type::SignedSmall())) {
2353 : VisitUnop(node, UseInfo::AnyTagged(),
2354 510 : MachineRepresentation::kTaggedPointer);
2355 : } else {
2356 : VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
2357 57480 : MachineRepresentation::kTaggedPointer);
2358 : }
2359 75954 : if (lower()) DeferReplacement(node, node->InputAt(0));
2360 : return;
2361 : }
2362 : case IrOpcode::kCheckIf: {
2363 91837 : ProcessInput(node, 0, UseInfo::Bool());
2364 91837 : ProcessRemainingInputs(node, 1);
2365 : SetOutput(node, MachineRepresentation::kNone);
2366 : return;
2367 : }
2368 : case IrOpcode::kCheckInternalizedString: {
2369 7273 : if (InputIs(node, Type::InternalizedString())) {
2370 : VisitUnop(node, UseInfo::AnyTagged(),
2371 332 : MachineRepresentation::kTaggedPointer);
2372 417 : if (lower()) DeferReplacement(node, node->InputAt(0));
2373 : } else {
2374 : VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
2375 6941 : MachineRepresentation::kTaggedPointer);
2376 : }
2377 : return;
2378 : }
2379 : case IrOpcode::kCheckNumber: {
2380 : Type* const input_type = TypeOf(node->InputAt(0));
2381 1473 : if (input_type->Is(Type::Number())) {
2382 42 : VisitNoop(node, truncation);
2383 : } else {
2384 1431 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2385 : }
2386 : return;
2387 : }
2388 : case IrOpcode::kCheckReceiver: {
2389 1630 : if (InputIs(node, Type::Receiver())) {
2390 : VisitUnop(node, UseInfo::AnyTagged(),
2391 12 : MachineRepresentation::kTaggedPointer);
2392 16 : if (lower()) DeferReplacement(node, node->InputAt(0));
2393 : } else {
2394 : VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
2395 1618 : MachineRepresentation::kTaggedPointer);
2396 : }
2397 : return;
2398 : }
2399 : case IrOpcode::kCheckSmi: {
2400 89122 : if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) {
2401 : VisitUnop(node,
2402 : UseInfo::CheckedSignedSmallAsWord32(kDistinguishZeros),
2403 1320 : MachineRepresentation::kWord32);
2404 : } else {
2405 : VisitUnop(node, UseInfo::CheckedSignedSmallAsTaggedSigned(),
2406 43241 : MachineRepresentation::kTaggedSigned);
2407 : }
2408 58308 : if (lower()) DeferReplacement(node, node->InputAt(0));
2409 : return;
2410 : }
2411 : case IrOpcode::kCheckString: {
2412 4082 : if (InputIs(node, Type::String())) {
2413 : VisitUnop(node, UseInfo::AnyTagged(),
2414 0 : MachineRepresentation::kTaggedPointer);
2415 0 : if (lower()) DeferReplacement(node, node->InputAt(0));
2416 : } else {
2417 : VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(),
2418 4082 : MachineRepresentation::kTaggedPointer);
2419 : }
2420 : return;
2421 : }
2422 :
2423 : case IrOpcode::kAllocate: {
2424 272071 : ProcessInput(node, 0, UseInfo::TruncatingWord32());
2425 272071 : ProcessRemainingInputs(node, 1);
2426 : SetOutput(node, MachineRepresentation::kTaggedPointer);
2427 : return;
2428 : }
2429 : case IrOpcode::kLoadField: {
2430 3140293 : if (truncation.IsUnused()) return VisitUnused(node);
2431 2831329 : FieldAccess access = FieldAccessOf(node->op());
2432 : MachineRepresentation const representation =
2433 : access.machine_type.representation();
2434 2831330 : VisitUnop(node, UseInfoForBasePointer(access), representation);
2435 : return;
2436 : }
2437 : case IrOpcode::kStoreField: {
2438 2739711 : FieldAccess access = FieldAccessOf(node->op());
2439 2739730 : NodeInfo* input_info = GetInfo(node->InputAt(1));
2440 : WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
2441 : access.base_is_tagged, access.machine_type.representation(),
2442 : access.offset, access.type, input_info->representation(),
2443 2739730 : node->InputAt(1));
2444 2739697 : ProcessInput(node, 0, UseInfoForBasePointer(access));
2445 : ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
2446 2739683 : access.machine_type.representation()));
2447 2739625 : ProcessRemainingInputs(node, 2);
2448 : SetOutput(node, MachineRepresentation::kNone);
2449 2739608 : if (lower()) {
2450 907509 : if (write_barrier_kind < access.write_barrier_kind) {
2451 437366 : access.write_barrier_kind = write_barrier_kind;
2452 : NodeProperties::ChangeOp(
2453 874732 : node, jsgraph_->simplified()->StoreField(access));
2454 : }
2455 : }
2456 : return;
2457 : }
2458 : case IrOpcode::kLoadBuffer: {
2459 24542 : if (truncation.IsUnused()) return VisitUnused(node);
2460 20316 : BufferAccess access = BufferAccessOf(node->op());
2461 20316 : ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
2462 20316 : ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
2463 20316 : ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
2464 20318 : ProcessRemainingInputs(node, 3);
2465 :
2466 : MachineRepresentation output;
2467 20318 : if (truncation.IdentifiesUndefinedAndNaNAndZero()) {
2468 19523 : if (truncation.IdentifiesNaNAndZero()) {
2469 : // If undefined is truncated to a non-NaN number, we can use
2470 : // the load's representation.
2471 14412 : output = access.machine_type().representation();
2472 : } else {
2473 : // If undefined is truncated to a number, but the use can
2474 : // observe NaN, we need to output at least the float32
2475 : // representation.
2476 5111 : if (access.machine_type().representation() ==
2477 : MachineRepresentation::kFloat32) {
2478 4678 : output = access.machine_type().representation();
2479 : } else {
2480 : output = MachineRepresentation::kFloat64;
2481 : }
2482 : }
2483 : } else {
2484 : // If undefined is not truncated away, we need to have the tagged
2485 : // representation.
2486 : output = MachineRepresentation::kTagged;
2487 : }
2488 : SetOutput(node, output);
2489 20318 : if (lower()) lowering->DoLoadBuffer(node, output, changer_);
2490 : return;
2491 : }
2492 : case IrOpcode::kStoreBuffer: {
2493 14219 : BufferAccess access = BufferAccessOf(node->op());
2494 14219 : ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
2495 14219 : ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
2496 14219 : ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
2497 : ProcessInput(node, 3,
2498 : TruncatingUseInfoFromRepresentation(
2499 14219 : access.machine_type().representation())); // value
2500 14219 : ProcessRemainingInputs(node, 4);
2501 : SetOutput(node, MachineRepresentation::kNone);
2502 14219 : if (lower()) lowering->DoStoreBuffer(node);
2503 : return;
2504 : }
2505 : case IrOpcode::kLoadElement: {
2506 116995 : if (truncation.IsUnused()) return VisitUnused(node);
2507 111781 : ElementAccess access = ElementAccessOf(node->op());
2508 : VisitBinop(node, UseInfoForBasePointer(access),
2509 : UseInfo::TruncatingWord32(),
2510 111781 : access.machine_type.representation());
2511 111781 : return;
2512 : }
2513 : case IrOpcode::kStoreElement: {
2514 494881 : ElementAccess access = ElementAccessOf(node->op());
2515 494881 : NodeInfo* input_info = GetInfo(node->InputAt(2));
2516 : WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
2517 : access.base_is_tagged, access.machine_type.representation(),
2518 494881 : access.type, input_info->representation(), node->InputAt(2));
2519 494881 : ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
2520 494881 : ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
2521 : ProcessInput(node, 2,
2522 : TruncatingUseInfoFromRepresentation(
2523 494881 : access.machine_type.representation())); // value
2524 494881 : ProcessRemainingInputs(node, 3);
2525 : SetOutput(node, MachineRepresentation::kNone);
2526 494881 : if (lower()) {
2527 162650 : if (write_barrier_kind < access.write_barrier_kind) {
2528 147080 : access.write_barrier_kind = write_barrier_kind;
2529 : NodeProperties::ChangeOp(
2530 294160 : node, jsgraph_->simplified()->StoreElement(access));
2531 : }
2532 : }
2533 : return;
2534 : }
2535 : case IrOpcode::kLoadTypedElement: {
2536 : MachineRepresentation const rep =
2537 12166 : MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
2538 12166 : ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer
2539 12166 : ProcessInput(node, 1, UseInfo::AnyTagged()); // base pointer
2540 12166 : ProcessInput(node, 2, UseInfo::PointerInt()); // external pointer
2541 12166 : ProcessInput(node, 3, UseInfo::TruncatingWord32()); // index
2542 12166 : ProcessRemainingInputs(node, 4);
2543 : SetOutput(node, rep);
2544 : return;
2545 : }
2546 : case IrOpcode::kStoreTypedElement: {
2547 : MachineRepresentation const rep =
2548 11033 : MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op()));
2549 11033 : ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer
2550 11033 : ProcessInput(node, 1, UseInfo::AnyTagged()); // base pointer
2551 11033 : ProcessInput(node, 2, UseInfo::PointerInt()); // external pointer
2552 11033 : ProcessInput(node, 3, UseInfo::TruncatingWord32()); // index
2553 : ProcessInput(node, 4,
2554 11033 : TruncatingUseInfoFromRepresentation(rep)); // value
2555 11033 : ProcessRemainingInputs(node, 5);
2556 : SetOutput(node, MachineRepresentation::kNone);
2557 : return;
2558 : }
2559 : case IrOpcode::kPlainPrimitiveToNumber: {
2560 51994 : if (InputIs(node, Type::Boolean())) {
2561 1224 : VisitUnop(node, UseInfo::Bool(), MachineRepresentation::kWord32);
2562 1604 : if (lower()) DeferReplacement(node, node->InputAt(0));
2563 50771 : } else if (InputIs(node, Type::String())) {
2564 1746 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2565 1746 : if (lower()) lowering->DoStringToNumber(node);
2566 98046 : } else if (truncation.IsUsedAsWord32()) {
2567 35500 : if (InputIs(node, Type::NumberOrOddball())) {
2568 : VisitUnop(node, UseInfo::TruncatingWord32(),
2569 14722 : MachineRepresentation::kWord32);
2570 19187 : if (lower()) DeferReplacement(node, node->InputAt(0));
2571 : } else {
2572 : VisitUnop(node, UseInfo::AnyTagged(),
2573 20777 : MachineRepresentation::kWord32);
2574 20777 : if (lower()) {
2575 : NodeProperties::ChangeOp(node,
2576 6380 : simplified()->PlainPrimitiveToWord32());
2577 : }
2578 : }
2579 27046 : } else if (truncation.IsUsedAsFloat64()) {
2580 13415 : if (InputIs(node, Type::NumberOrOddball())) {
2581 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2582 6188 : MachineRepresentation::kFloat64);
2583 8109 : if (lower()) DeferReplacement(node, node->InputAt(0));
2584 : } else {
2585 : VisitUnop(node, UseInfo::AnyTagged(),
2586 7227 : MachineRepresentation::kFloat64);
2587 7227 : if (lower()) {
2588 : NodeProperties::ChangeOp(node,
2589 1896 : simplified()->PlainPrimitiveToFloat64());
2590 : }
2591 : }
2592 : } else {
2593 108 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2594 : }
2595 : return;
2596 : }
2597 : case IrOpcode::kSpeculativeToNumber: {
2598 5303 : NumberOperationHint const hint = NumberOperationHintOf(node->op());
2599 5303 : switch (hint) {
2600 : case NumberOperationHint::kSigned32:
2601 : case NumberOperationHint::kSignedSmall:
2602 : VisitUnop(node, CheckedUseInfoAsWord32FromHint(hint),
2603 5303 : MachineRepresentation::kWord32, Type::Signed32());
2604 5303 : break;
2605 : case NumberOperationHint::kNumber:
2606 : case NumberOperationHint::kNumberOrOddball:
2607 : VisitUnop(node, CheckedUseInfoAsFloat64FromHint(hint),
2608 0 : MachineRepresentation::kFloat64);
2609 0 : break;
2610 : }
2611 6735 : if (lower()) DeferReplacement(node, node->InputAt(0));
2612 : return;
2613 : }
2614 : case IrOpcode::kObjectIsDetectableCallable: {
2615 52968 : VisitObjectIs(node, Type::DetectableCallable(), lowering);
2616 52968 : return;
2617 : }
2618 : case IrOpcode::kObjectIsNaN: {
2619 : Type* const input_type = GetUpperBound(node->InputAt(0));
2620 9028 : if (input_type->Is(Type::NaN())) {
2621 0 : VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
2622 0 : if (lower()) {
2623 0 : DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
2624 : }
2625 9028 : } else if (!input_type->Maybe(Type::NaN())) {
2626 24 : VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit);
2627 24 : if (lower()) {
2628 8 : DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
2629 : }
2630 9004 : } else if (input_type->Is(Type::Number())) {
2631 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2632 51 : MachineRepresentation::kBit);
2633 51 : if (lower()) {
2634 : // ObjectIsNaN(x:kRepFloat64) => Word32Equal(Float64Equal(x,x),#0)
2635 : Node* const input = node->InputAt(0);
2636 : node->ReplaceInput(
2637 : 0, jsgraph_->graph()->NewNode(
2638 34 : lowering->machine()->Float64Equal(), input, input));
2639 34 : node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
2640 17 : NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
2641 : }
2642 : } else {
2643 8953 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
2644 : }
2645 : return;
2646 : }
2647 : case IrOpcode::kObjectIsNonCallable: {
2648 25811 : VisitObjectIs(node, Type::NonCallable(), lowering);
2649 25811 : return;
2650 : }
2651 : case IrOpcode::kObjectIsNumber: {
2652 34827 : VisitObjectIs(node, Type::Number(), lowering);
2653 34827 : return;
2654 : }
2655 : case IrOpcode::kObjectIsReceiver: {
2656 69269 : VisitObjectIs(node, Type::Receiver(), lowering);
2657 69269 : return;
2658 : }
2659 : case IrOpcode::kObjectIsSmi: {
2660 : // TODO(turbofan): Optimize based on input representation.
2661 10683 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
2662 10683 : return;
2663 : }
2664 : case IrOpcode::kObjectIsString: {
2665 14653 : VisitObjectIs(node, Type::String(), lowering);
2666 14653 : return;
2667 : }
2668 : case IrOpcode::kObjectIsSymbol: {
2669 1995 : VisitObjectIs(node, Type::Symbol(), lowering);
2670 1995 : return;
2671 : }
2672 : case IrOpcode::kObjectIsUndetectable: {
2673 27546 : VisitObjectIs(node, Type::Undetectable(), lowering);
2674 27546 : return;
2675 : }
2676 : case IrOpcode::kArgumentsFrame: {
2677 : SetOutput(node, MachineType::PointerRepresentation());
2678 : return;
2679 : }
2680 : case IrOpcode::kArgumentsLength: {
2681 : VisitUnop(node, UseInfo::PointerInt(),
2682 12084 : MachineRepresentation::kTaggedSigned);
2683 12084 : return;
2684 : }
2685 : case IrOpcode::kNewUnmappedArgumentsElements: {
2686 : VisitBinop(node, UseInfo::PointerInt(), UseInfo::TaggedSigned(),
2687 12299 : MachineRepresentation::kTaggedPointer);
2688 12299 : return;
2689 : }
2690 : case IrOpcode::kArrayBufferWasNeutered: {
2691 1035 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
2692 1035 : return;
2693 : }
2694 : case IrOpcode::kCheckFloat64Hole: {
2695 : Type* const input_type = TypeOf(node->InputAt(0));
2696 2442 : if (input_type->Is(Type::Number())) {
2697 144 : VisitNoop(node, truncation);
2698 : } else {
2699 2298 : CheckFloat64HoleMode mode = CheckFloat64HoleModeOf(node->op());
2700 2298 : switch (mode) {
2701 : case CheckFloat64HoleMode::kAllowReturnHole:
2702 2083 : if (truncation.IsUnused()) return VisitUnused(node);
2703 1970 : if (truncation.IsUsedAsFloat64()) {
2704 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2705 195 : MachineRepresentation::kFloat64);
2706 260 : if (lower()) DeferReplacement(node, node->InputAt(0));
2707 : } else {
2708 : VisitUnop(
2709 : node,
2710 : UseInfo(MachineRepresentation::kFloat64, Truncation::Any()),
2711 1775 : MachineRepresentation::kFloat64, Type::Number());
2712 : }
2713 : break;
2714 : case CheckFloat64HoleMode::kNeverReturnHole:
2715 : VisitUnop(
2716 : node,
2717 : UseInfo(MachineRepresentation::kFloat64, Truncation::Any()),
2718 215 : MachineRepresentation::kFloat64, Type::Number());
2719 215 : break;
2720 : }
2721 : }
2722 : return;
2723 : }
2724 : case IrOpcode::kCheckTaggedHole: {
2725 3612 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2726 3612 : return;
2727 : }
2728 : case IrOpcode::kConvertTaggedHoleToUndefined: {
2729 8560 : if (InputIs(node, Type::NumberOrOddball()) &&
2730 2080 : truncation.IsUsedAsWord32()) {
2731 : // Propagate the Word32 truncation.
2732 : VisitUnop(node, UseInfo::TruncatingWord32(),
2733 680 : MachineRepresentation::kWord32);
2734 852 : if (lower()) DeferReplacement(node, node->InputAt(0));
2735 7200 : } else if (InputIs(node, Type::NumberOrOddball()) &&
2736 1400 : truncation.IsUsedAsFloat64()) {
2737 : // Propagate the Float64 truncation.
2738 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2739 75 : MachineRepresentation::kFloat64);
2740 100 : if (lower()) DeferReplacement(node, node->InputAt(0));
2741 5725 : } else if (InputIs(node, Type::NonInternal())) {
2742 75 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2743 100 : if (lower()) DeferReplacement(node, node->InputAt(0));
2744 : } else {
2745 : // TODO(turbofan): Add a (Tagged) truncation that identifies hole
2746 : // and undefined, i.e. for a[i] === obj cases.
2747 5650 : VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
2748 : }
2749 : return;
2750 : }
2751 : case IrOpcode::kCheckMaps:
2752 : case IrOpcode::kTransitionElementsKind: {
2753 153856 : VisitInputs(node);
2754 : return SetOutput(node, MachineRepresentation::kNone);
2755 : }
2756 : case IrOpcode::kEnsureWritableFastElements:
2757 : return VisitBinop(node, UseInfo::AnyTagged(),
2758 : MachineRepresentation::kTaggedPointer);
2759 : case IrOpcode::kMaybeGrowFastElements: {
2760 6415 : ProcessInput(node, 0, UseInfo::AnyTagged()); // object
2761 6415 : ProcessInput(node, 1, UseInfo::AnyTagged()); // elements
2762 6415 : ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index
2763 6415 : ProcessInput(node, 3, UseInfo::TruncatingWord32()); // length
2764 6415 : ProcessRemainingInputs(node, 4);
2765 : SetOutput(node, MachineRepresentation::kTaggedPointer);
2766 : return;
2767 : }
2768 :
2769 : case IrOpcode::kNumberSilenceNaN:
2770 : VisitUnop(node, UseInfo::TruncatingFloat64(),
2771 2260 : MachineRepresentation::kFloat64);
2772 2986 : if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2773 : return;
2774 : case IrOpcode::kStateValues:
2775 15899439 : return VisitStateValues(node);
2776 : case IrOpcode::kObjectState:
2777 27923 : return VisitObjectState(node);
2778 : case IrOpcode::kTypeGuard: {
2779 : // We just get rid of the sigma here. In principle, it should be
2780 : // possible to refine the truncation and representation based on
2781 : // the sigma's type.
2782 : MachineRepresentation output =
2783 67185 : GetOutputInfoForPhi(node, TypeOf(node->InputAt(0)), truncation);
2784 67185 : VisitUnop(node, UseInfo(output, truncation), output);
2785 82911 : if (lower()) DeferReplacement(node, node->InputAt(0));
2786 : return;
2787 : }
2788 :
2789 : case IrOpcode::kOsrGuard:
2790 167066 : return VisitOsrGuard(node);
2791 :
2792 : case IrOpcode::kFinishRegion:
2793 302215 : VisitInputs(node);
2794 : // Assume the output is tagged pointer.
2795 : return SetOutput(node, MachineRepresentation::kTaggedPointer);
2796 :
2797 : case IrOpcode::kReturn:
2798 1594381 : VisitReturn(node);
2799 : // Assume the output is tagged.
2800 : return SetOutput(node, MachineRepresentation::kTagged);
2801 :
2802 : // Operators with all inputs tagged and no or tagged output have uniform
2803 : // handling.
2804 : case IrOpcode::kEnd:
2805 : case IrOpcode::kIfSuccess:
2806 : case IrOpcode::kIfException:
2807 : case IrOpcode::kIfTrue:
2808 : case IrOpcode::kIfFalse:
2809 : case IrOpcode::kDeoptimize:
2810 : case IrOpcode::kEffectPhi:
2811 : case IrOpcode::kTerminate:
2812 : case IrOpcode::kFrameState:
2813 : case IrOpcode::kCheckpoint:
2814 : case IrOpcode::kLoop:
2815 : case IrOpcode::kMerge:
2816 : case IrOpcode::kThrow:
2817 : case IrOpcode::kBeginRegion:
2818 : case IrOpcode::kProjection:
2819 : case IrOpcode::kOsrValue:
2820 : case IrOpcode::kArgumentsElementsState:
2821 : case IrOpcode::kArgumentsLengthState:
2822 : // All JavaScript operators except JSToNumber have uniform handling.
2823 : #define OPCODE_CASE(name) case IrOpcode::k##name:
2824 : JS_SIMPLE_BINOP_LIST(OPCODE_CASE)
2825 : JS_OTHER_UNOP_LIST(OPCODE_CASE)
2826 : JS_OBJECT_OP_LIST(OPCODE_CASE)
2827 : JS_CONTEXT_OP_LIST(OPCODE_CASE)
2828 : JS_OTHER_OP_LIST(OPCODE_CASE)
2829 : #undef OPCODE_CASE
2830 : case IrOpcode::kJSToInteger:
2831 : case IrOpcode::kJSToLength:
2832 : case IrOpcode::kJSToName:
2833 : case IrOpcode::kJSToObject:
2834 : case IrOpcode::kJSToString:
2835 38675795 : VisitInputs(node);
2836 : // Assume the output is tagged.
2837 : return SetOutput(node, MachineRepresentation::kTagged);
2838 :
2839 : default:
2840 : V8_Fatal(
2841 : __FILE__, __LINE__,
2842 : "Representation inference: unsupported opcode %i (%s), node #%i\n.",
2843 0 : node->opcode(), node->op()->mnemonic(), node->id());
2844 : break;
2845 : }
2846 : UNREACHABLE();
2847 : }
2848 :
2849 250582 : void DeferReplacement(Node* node, Node* replacement) {
2850 596652 : TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(),
2851 : node->op()->mnemonic(), replacement->id(),
2852 : replacement->op()->mnemonic());
2853 :
2854 : // Disconnect the node from effect and control chains, if necessary.
2855 751752 : if (node->op()->EffectInputCount() > 0) {
2856 : DCHECK_LT(0, node->op()->ControlInputCount());
2857 : // Disconnect the node from effect and control chains.
2858 95486 : Node* control = NodeProperties::GetControlInput(node);
2859 95486 : Node* effect = NodeProperties::GetEffectInput(node);
2860 190972 : ReplaceEffectControlUses(node, effect, control);
2861 : }
2862 :
2863 250584 : replacements_.push_back(node);
2864 250583 : replacements_.push_back(replacement);
2865 :
2866 250580 : node->NullAllInputs(); // Node is now dead.
2867 250581 : }
2868 :
2869 149482 : void Kill(Node* node) {
2870 49835 : TRACE("killing #%d:%s\n", node->id(), node->op()->mnemonic());
2871 :
2872 49835 : if (node->op()->EffectInputCount() == 1) {
2873 : DCHECK_LT(0, node->op()->ControlInputCount());
2874 : // Disconnect the node from effect and control chains.
2875 49812 : Node* control = NodeProperties::GetControlInput(node);
2876 49812 : Node* effect = NodeProperties::GetEffectInput(node);
2877 49812 : ReplaceEffectControlUses(node, effect, control);
2878 : } else {
2879 : DCHECK_EQ(0, node->op()->EffectInputCount());
2880 : DCHECK_EQ(0, node->op()->ControlOutputCount());
2881 : DCHECK_EQ(0, node->op()->EffectOutputCount());
2882 : }
2883 :
2884 49835 : node->ReplaceUses(jsgraph_->Dead());
2885 :
2886 49835 : node->NullAllInputs(); // The {node} is now dead.
2887 49835 : }
2888 :
2889 47806905 : void PrintOutputInfo(NodeInfo* info) {
2890 47806905 : if (FLAG_trace_representation) {
2891 0 : OFStream os(stdout);
2892 0 : os << info->representation();
2893 : }
2894 47806905 : }
2895 :
2896 : void PrintRepresentation(MachineRepresentation rep) {
2897 : if (FLAG_trace_representation) {
2898 : OFStream os(stdout);
2899 : os << rep;
2900 : }
2901 : }
2902 :
2903 89619387 : void PrintTruncation(Truncation truncation) {
2904 89619387 : if (FLAG_trace_representation) {
2905 0 : OFStream os(stdout);
2906 0 : os << truncation.description() << std::endl;
2907 : }
2908 89619387 : }
2909 :
2910 13215964 : void PrintUseInfo(UseInfo info) {
2911 13215964 : if (FLAG_trace_representation) {
2912 0 : OFStream os(stdout);
2913 0 : os << info.representation() << ":" << info.truncation().description();
2914 : }
2915 13215964 : }
2916 :
2917 : private:
2918 : JSGraph* jsgraph_;
2919 : Zone* zone_; // Temporary zone.
2920 : size_t const count_; // number of nodes in the graph
2921 : ZoneVector<NodeInfo> info_; // node id -> usage information
2922 : #ifdef DEBUG
2923 : ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about
2924 : // requirements on inputs.
2925 : #endif // DEBUG
2926 : NodeVector nodes_; // collected nodes
2927 : NodeVector replacements_; // replacements to be done after lowering
2928 : Phase phase_; // current phase of algorithm
2929 : RepresentationChanger* changer_; // for inserting representation changes
2930 : ZoneQueue<Node*> queue_; // queue for traversing the graph
2931 :
2932 : struct NodeState {
2933 : Node* node;
2934 : int input_index;
2935 : };
2936 : ZoneStack<NodeState> typing_stack_; // stack for graph typing.
2937 : // TODO(danno): RepresentationSelector shouldn't know anything about the
2938 : // source positions table, but must for now since there currently is no other
2939 : // way to pass down source position information to nodes created during
2940 : // lowering. Once this phase becomes a vanilla reducer, it should get source
2941 : // position information via the SourcePositionWrapper like all other reducers.
2942 : SourcePositionTable* source_positions_;
2943 : TypeCache const& type_cache_;
2944 : OperationTyper op_typer_; // helper for the feedback typer
2945 :
2946 593864934 : NodeInfo* GetInfo(Node* node) {
2947 : DCHECK(node->id() < count_);
2948 597585113 : return &info_[node->id()];
2949 : }
2950 : Zone* zone() { return zone_; }
2951 : Zone* graph_zone() { return jsgraph_->zone(); }
2952 : };
2953 :
2954 395303 : SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
2955 : SourcePositionTable* source_positions)
2956 : : jsgraph_(jsgraph),
2957 : zone_(zone),
2958 395303 : type_cache_(TypeCache::Get()),
2959 1185909 : source_positions_(source_positions) {}
2960 :
2961 395303 : void SimplifiedLowering::LowerAllNodes() {
2962 395303 : RepresentationChanger changer(jsgraph(), jsgraph()->isolate());
2963 : RepresentationSelector selector(jsgraph(), zone_, &changer,
2964 395303 : source_positions_);
2965 395303 : selector.Run(this);
2966 395302 : }
2967 :
2968 162 : void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
2969 : Node* node, RepresentationSelector* selector) {
2970 : DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
2971 : Node* value = node->InputAt(0);
2972 : Node* context = node->InputAt(1);
2973 : Node* frame_state = node->InputAt(2);
2974 : Node* effect = node->InputAt(3);
2975 : Node* control = node->InputAt(4);
2976 :
2977 162 : Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
2978 : Node* branch0 =
2979 162 : graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
2980 :
2981 162 : Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2982 : Node* etrue0 = effect;
2983 : Node* vtrue0;
2984 : {
2985 162 : vtrue0 = graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
2986 162 : vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
2987 : }
2988 :
2989 162 : Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2990 : Node* efalse0 = effect;
2991 : Node* vfalse0;
2992 : {
2993 : vfalse0 = efalse0 = if_false0 =
2994 : graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
2995 162 : frame_state, efalse0, if_false0);
2996 :
2997 : // Update potential {IfException} uses of {node} to point to the above
2998 : // {ToNumber} stub call node instead.
2999 162 : Node* on_exception = nullptr;
3000 162 : if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
3001 0 : NodeProperties::ReplaceControlInput(on_exception, vfalse0);
3002 0 : NodeProperties::ReplaceEffectInput(on_exception, efalse0);
3003 0 : if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
3004 : }
3005 :
3006 162 : Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
3007 162 : Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
3008 :
3009 162 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3010 : Node* etrue1 = efalse0;
3011 : Node* vtrue1;
3012 : {
3013 : vtrue1 =
3014 162 : graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
3015 162 : vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
3016 : }
3017 :
3018 162 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3019 : Node* efalse1 = efalse0;
3020 : Node* vfalse1;
3021 : {
3022 : vfalse1 = efalse1 = graph()->NewNode(
3023 : simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
3024 486 : efalse1, if_false1);
3025 : }
3026 :
3027 162 : if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3028 : efalse0 =
3029 162 : graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
3030 : vfalse0 =
3031 : graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3032 162 : vtrue1, vfalse1, if_false0);
3033 : }
3034 :
3035 162 : control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
3036 162 : effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
3037 : value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
3038 162 : vtrue0, vfalse0, control);
3039 :
3040 : // Replace effect and control uses appropriately.
3041 1740 : for (Edge edge : node->use_edges()) {
3042 789 : if (NodeProperties::IsControlEdge(edge)) {
3043 1077 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
3044 0 : edge.from()->ReplaceUses(control);
3045 0 : edge.from()->Kill();
3046 : } else {
3047 : DCHECK(edge.from()->opcode() != IrOpcode::kIfException);
3048 359 : edge.UpdateTo(control);
3049 : }
3050 430 : } else if (NodeProperties::IsEffectEdge(edge)) {
3051 238 : edge.UpdateTo(effect);
3052 : }
3053 : }
3054 :
3055 162 : selector->DeferReplacement(node, value);
3056 162 : }
3057 :
3058 2350 : void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
3059 : Node* node, RepresentationSelector* selector) {
3060 : DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
3061 : Node* value = node->InputAt(0);
3062 : Node* context = node->InputAt(1);
3063 : Node* frame_state = node->InputAt(2);
3064 : Node* effect = node->InputAt(3);
3065 : Node* control = node->InputAt(4);
3066 :
3067 2350 : Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
3068 : Node* branch0 =
3069 2350 : graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
3070 :
3071 2350 : Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3072 : Node* etrue0 = effect;
3073 : Node* vtrue0 =
3074 2350 : graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
3075 :
3076 2350 : Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3077 : Node* efalse0 = effect;
3078 : Node* vfalse0;
3079 : {
3080 : vfalse0 = efalse0 = if_false0 =
3081 : graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
3082 2350 : frame_state, efalse0, if_false0);
3083 :
3084 : // Update potential {IfException} uses of {node} to point to the above
3085 : // {ToNumber} stub call node instead.
3086 2350 : Node* on_exception = nullptr;
3087 2350 : if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
3088 0 : NodeProperties::ReplaceControlInput(on_exception, vfalse0);
3089 0 : NodeProperties::ReplaceEffectInput(on_exception, efalse0);
3090 0 : if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
3091 : }
3092 :
3093 2350 : Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
3094 2350 : Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
3095 :
3096 2350 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3097 : Node* etrue1 = efalse0;
3098 : Node* vtrue1 =
3099 2350 : graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
3100 :
3101 2350 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3102 : Node* efalse1 = efalse0;
3103 : Node* vfalse1;
3104 : {
3105 : vfalse1 = efalse1 = graph()->NewNode(
3106 : simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
3107 7050 : efalse1, if_false1);
3108 2350 : vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
3109 : }
3110 :
3111 2350 : if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
3112 : efalse0 =
3113 2350 : graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
3114 : vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
3115 2350 : vtrue1, vfalse1, if_false0);
3116 : }
3117 :
3118 2350 : control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
3119 2350 : effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
3120 : value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
3121 2350 : vtrue0, vfalse0, control);
3122 :
3123 : // Replace effect and control uses appropriately.
3124 25832 : for (Edge edge : node->use_edges()) {
3125 11741 : if (NodeProperties::IsControlEdge(edge)) {
3126 17391 : if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
3127 0 : edge.from()->ReplaceUses(control);
3128 0 : edge.from()->Kill();
3129 : } else {
3130 : DCHECK(edge.from()->opcode() != IrOpcode::kIfException);
3131 5797 : edge.UpdateTo(control);
3132 : }
3133 5944 : } else if (NodeProperties::IsEffectEdge(edge)) {
3134 3717 : edge.UpdateTo(effect);
3135 : }
3136 : }
3137 :
3138 2350 : selector->DeferReplacement(node, value);
3139 2350 : }
3140 :
3141 5912 : void SimplifiedLowering::DoLoadBuffer(Node* node,
3142 : MachineRepresentation output_rep,
3143 616 : RepresentationChanger* changer) {
3144 : DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode());
3145 : DCHECK_NE(MachineRepresentation::kNone, output_rep);
3146 5912 : MachineType const access_type = BufferAccessOf(node->op()).machine_type();
3147 5912 : if (output_rep != access_type.representation()) {
3148 : Node* const buffer = node->InputAt(0);
3149 : Node* const offset = node->InputAt(1);
3150 : Node* const length = node->InputAt(2);
3151 : Node* const effect = node->InputAt(3);
3152 : Node* const control = node->InputAt(4);
3153 : Node* const index =
3154 : machine()->Is64()
3155 308 : ? graph()->NewNode(machine()->ChangeUint32ToUint64(), offset)
3156 308 : : offset;
3157 :
3158 308 : Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length);
3159 : Node* branch =
3160 308 : graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
3161 :
3162 308 : Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
3163 : Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
3164 308 : effect, if_true);
3165 : Type* element_type =
3166 308 : Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone());
3167 : Node* vtrue = changer->GetRepresentationFor(
3168 : etrue, access_type.representation(), element_type, node,
3169 308 : UseInfo(output_rep, Truncation::None()));
3170 :
3171 308 : Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
3172 : Node* efalse = effect;
3173 : Node* vfalse;
3174 308 : if (output_rep == MachineRepresentation::kTagged) {
3175 206 : vfalse = jsgraph()->UndefinedConstant();
3176 102 : } else if (output_rep == MachineRepresentation::kFloat64) {
3177 : vfalse =
3178 102 : jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
3179 0 : } else if (output_rep == MachineRepresentation::kFloat32) {
3180 : vfalse =
3181 0 : jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN());
3182 : } else {
3183 0 : vfalse = jsgraph()->Int32Constant(0);
3184 : }
3185 :
3186 308 : Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
3187 308 : Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
3188 :
3189 : // Replace effect uses of {node} with the {ephi}.
3190 308 : NodeProperties::ReplaceUses(node, node, ephi);
3191 :
3192 : // Turn the {node} into a Phi.
3193 308 : node->ReplaceInput(0, vtrue);
3194 308 : node->ReplaceInput(1, vfalse);
3195 308 : node->ReplaceInput(2, merge);
3196 308 : node->TrimInputCount(3);
3197 308 : NodeProperties::ChangeOp(node, common()->Phi(output_rep, 2));
3198 : } else {
3199 5604 : NodeProperties::ChangeOp(node, machine()->CheckedLoad(access_type));
3200 : }
3201 5912 : }
3202 :
3203 :
3204 4111 : void SimplifiedLowering::DoStoreBuffer(Node* node) {
3205 : DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode());
3206 : MachineRepresentation const rep =
3207 4111 : BufferAccessOf(node->op()).machine_type().representation();
3208 4111 : NodeProperties::ChangeOp(node, machine()->CheckedStore(rep));
3209 4111 : }
3210 :
3211 124 : Node* SimplifiedLowering::Float64Round(Node* const node) {
3212 62 : Node* const one = jsgraph()->Float64Constant(1.0);
3213 62 : Node* const one_half = jsgraph()->Float64Constant(0.5);
3214 : Node* const input = node->InputAt(0);
3215 :
3216 : // Round up towards Infinity, and adjust if the difference exceeds 0.5.
3217 : Node* result = graph()->NewNode(machine()->Float64RoundUp().placeholder(),
3218 124 : node->InputAt(0));
3219 : return graph()->NewNode(
3220 : common()->Select(MachineRepresentation::kFloat64),
3221 : graph()->NewNode(
3222 : machine()->Float64LessThanOrEqual(),
3223 : graph()->NewNode(machine()->Float64Sub(), result, one_half), input),
3224 310 : result, graph()->NewNode(machine()->Float64Sub(), result, one));
3225 : }
3226 :
3227 42 : Node* SimplifiedLowering::Float64Sign(Node* const node) {
3228 14 : Node* const minus_one = jsgraph()->Float64Constant(-1.0);
3229 14 : Node* const zero = jsgraph()->Float64Constant(0.0);
3230 14 : Node* const one = jsgraph()->Float64Constant(1.0);
3231 :
3232 : Node* const input = node->InputAt(0);
3233 :
3234 : return graph()->NewNode(
3235 : common()->Select(MachineRepresentation::kFloat64),
3236 : graph()->NewNode(machine()->Float64LessThan(), input, zero), minus_one,
3237 : graph()->NewNode(
3238 : common()->Select(MachineRepresentation::kFloat64),
3239 : graph()->NewNode(machine()->Float64LessThan(), zero, input), one,
3240 70 : input));
3241 : }
3242 :
3243 66 : Node* SimplifiedLowering::Int32Abs(Node* const node) {
3244 : Node* const input = node->InputAt(0);
3245 :
3246 : // Generate case for absolute integer value.
3247 : //
3248 : // let sign = input >> 31 in
3249 : // (input ^ sign) - sign
3250 :
3251 : Node* sign = graph()->NewNode(machine()->Word32Sar(), input,
3252 66 : jsgraph()->Int32Constant(31));
3253 : return graph()->NewNode(machine()->Int32Sub(),
3254 : graph()->NewNode(machine()->Word32Xor(), input, sign),
3255 99 : sign);
3256 : }
3257 :
3258 8901 : Node* SimplifiedLowering::Int32Div(Node* const node) {
3259 2967 : Int32BinopMatcher m(node);
3260 2967 : Node* const zero = jsgraph()->Int32Constant(0);
3261 2967 : Node* const minus_one = jsgraph()->Int32Constant(-1);
3262 : Node* const lhs = m.left().node();
3263 : Node* const rhs = m.right().node();
3264 :
3265 2967 : if (m.right().Is(-1)) {
3266 42 : return graph()->NewNode(machine()->Int32Sub(), zero, lhs);
3267 2946 : } else if (m.right().Is(0)) {
3268 : return rhs;
3269 2933 : } else if (machine()->Int32DivIsSafe() || m.right().HasValue()) {
3270 5676 : return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
3271 : }
3272 :
3273 : // General case for signed integer division.
3274 : //
3275 : // if 0 < rhs then
3276 : // lhs / rhs
3277 : // else
3278 : // if rhs < -1 then
3279 : // lhs / rhs
3280 : // else if rhs == 0 then
3281 : // 0
3282 : // else
3283 : // 0 - lhs
3284 : //
3285 : // Note: We do not use the Diamond helper class here, because it really hurts
3286 : // readability with nested diamonds.
3287 95 : const Operator* const merge_op = common()->Merge(2);
3288 : const Operator* const phi_op =
3289 95 : common()->Phi(MachineRepresentation::kWord32, 2);
3290 :
3291 95 : Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
3292 : Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
3293 190 : graph()->start());
3294 :
3295 95 : Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3296 95 : Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0);
3297 :
3298 95 : Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3299 : Node* false0;
3300 : {
3301 95 : Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
3302 95 : Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
3303 :
3304 95 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3305 95 : Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1);
3306 :
3307 95 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3308 : Node* false1;
3309 : {
3310 95 : Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
3311 95 : Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
3312 :
3313 95 : Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
3314 : Node* true2 = zero;
3315 :
3316 95 : Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
3317 95 : Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
3318 :
3319 : if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
3320 : false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
3321 : }
3322 :
3323 : if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
3324 : false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
3325 : }
3326 :
3327 : Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
3328 95 : return graph()->NewNode(phi_op, true0, false0, merge0);
3329 : }
3330 :
3331 :
3332 9006 : Node* SimplifiedLowering::Int32Mod(Node* const node) {
3333 3002 : Int32BinopMatcher m(node);
3334 3002 : Node* const zero = jsgraph()->Int32Constant(0);
3335 3002 : Node* const minus_one = jsgraph()->Int32Constant(-1);
3336 : Node* const lhs = m.left().node();
3337 : Node* const rhs = m.right().node();
3338 :
3339 5989 : if (m.right().Is(-1) || m.right().Is(0)) {
3340 : return zero;
3341 2987 : } else if (m.right().HasValue()) {
3342 8574 : return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
3343 : }
3344 :
3345 : // General case for signed integer modulus, with optimization for (unknown)
3346 : // power of 2 right hand side.
3347 : //
3348 : // if 0 < rhs then
3349 : // msk = rhs - 1
3350 : // if rhs & msk != 0 then
3351 : // lhs % rhs
3352 : // else
3353 : // if lhs < 0 then
3354 : // -(-lhs & msk)
3355 : // else
3356 : // lhs & msk
3357 : // else
3358 : // if rhs < -1 then
3359 : // lhs % rhs
3360 : // else
3361 : // zero
3362 : //
3363 : // Note: We do not use the Diamond helper class here, because it really hurts
3364 : // readability with nested diamonds.
3365 129 : const Operator* const merge_op = common()->Merge(2);
3366 : const Operator* const phi_op =
3367 129 : common()->Phi(MachineRepresentation::kWord32, 2);
3368 :
3369 129 : Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
3370 : Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
3371 258 : graph()->start());
3372 :
3373 129 : Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3374 : Node* true0;
3375 : {
3376 129 : Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
3377 :
3378 129 : Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
3379 129 : Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
3380 :
3381 129 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3382 129 : Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
3383 :
3384 129 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3385 : Node* false1;
3386 : {
3387 129 : Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
3388 : Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
3389 129 : check2, if_false1);
3390 :
3391 129 : Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
3392 : Node* true2 = graph()->NewNode(
3393 : machine()->Int32Sub(), zero,
3394 : graph()->NewNode(machine()->Word32And(),
3395 : graph()->NewNode(machine()->Int32Sub(), zero, lhs),
3396 387 : msk));
3397 :
3398 129 : Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
3399 129 : Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
3400 :
3401 : if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
3402 : false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
3403 : }
3404 :
3405 : if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
3406 : true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
3407 : }
3408 :
3409 129 : Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3410 : Node* false0;
3411 : {
3412 129 : Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
3413 : Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
3414 129 : check1, if_false0);
3415 :
3416 129 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3417 129 : Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
3418 :
3419 129 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3420 : Node* false1 = zero;
3421 :
3422 : if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
3423 : false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
3424 : }
3425 :
3426 : Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
3427 129 : return graph()->NewNode(phi_op, true0, false0, merge0);
3428 : }
3429 :
3430 21 : Node* SimplifiedLowering::Int32Sign(Node* const node) {
3431 7 : Node* const minus_one = jsgraph()->Int32Constant(-1);
3432 7 : Node* const zero = jsgraph()->Int32Constant(0);
3433 7 : Node* const one = jsgraph()->Int32Constant(1);
3434 :
3435 : Node* const input = node->InputAt(0);
3436 :
3437 : return graph()->NewNode(
3438 : common()->Select(MachineRepresentation::kWord32),
3439 : graph()->NewNode(machine()->Int32LessThan(), input, zero), minus_one,
3440 : graph()->NewNode(
3441 : common()->Select(MachineRepresentation::kWord32),
3442 : graph()->NewNode(machine()->Int32LessThan(), zero, input), one,
3443 35 : zero));
3444 : }
3445 :
3446 562 : Node* SimplifiedLowering::Uint32Div(Node* const node) {
3447 281 : Uint32BinopMatcher m(node);
3448 : Node* const zero = jsgraph()->Uint32Constant(0);
3449 : Node* const lhs = m.left().node();
3450 : Node* const rhs = m.right().node();
3451 :
3452 281 : if (m.right().Is(0)) {
3453 : return zero;
3454 261 : } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) {
3455 420 : return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
3456 : }
3457 :
3458 51 : Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
3459 51 : Diamond d(graph(), common(), check, BranchHint::kFalse);
3460 102 : Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
3461 51 : return d.Phi(MachineRepresentation::kWord32, zero, div);
3462 : }
3463 :
3464 :
3465 1518 : Node* SimplifiedLowering::Uint32Mod(Node* const node) {
3466 506 : Uint32BinopMatcher m(node);
3467 506 : Node* const minus_one = jsgraph()->Int32Constant(-1);
3468 : Node* const zero = jsgraph()->Uint32Constant(0);
3469 : Node* const lhs = m.left().node();
3470 : Node* const rhs = m.right().node();
3471 :
3472 506 : if (m.right().Is(0)) {
3473 : return zero;
3474 506 : } else if (m.right().HasValue()) {
3475 1374 : return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
3476 : }
3477 :
3478 : // General case for unsigned integer modulus, with optimization for (unknown)
3479 : // power of 2 right hand side.
3480 : //
3481 : // if rhs then
3482 : // msk = rhs - 1
3483 : // if rhs & msk != 0 then
3484 : // lhs % rhs
3485 : // else
3486 : // lhs & msk
3487 : // else
3488 : // zero
3489 : //
3490 : // Note: We do not use the Diamond helper class here, because it really hurts
3491 : // readability with nested diamonds.
3492 48 : const Operator* const merge_op = common()->Merge(2);
3493 : const Operator* const phi_op =
3494 48 : common()->Phi(MachineRepresentation::kWord32, 2);
3495 :
3496 : Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), rhs,
3497 96 : graph()->start());
3498 :
3499 48 : Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3500 : Node* true0;
3501 : {
3502 48 : Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
3503 :
3504 48 : Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
3505 48 : Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
3506 :
3507 48 : Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3508 48 : Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1);
3509 :
3510 48 : Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3511 48 : Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk);
3512 :
3513 : if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
3514 : true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
3515 : }
3516 :
3517 48 : Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3518 : Node* false0 = zero;
3519 :
3520 : Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
3521 48 : return graph()->NewNode(phi_op, true0, false0, merge0);
3522 : }
3523 :
3524 121 : void SimplifiedLowering::DoMax(Node* node, Operator const* op,
3525 : MachineRepresentation rep) {
3526 : Node* const lhs = node->InputAt(0);
3527 : Node* const rhs = node->InputAt(1);
3528 :
3529 121 : node->ReplaceInput(0, graph()->NewNode(op, lhs, rhs));
3530 : DCHECK_EQ(rhs, node->InputAt(1));
3531 121 : node->AppendInput(graph()->zone(), lhs);
3532 121 : NodeProperties::ChangeOp(node, common()->Select(rep));
3533 121 : }
3534 :
3535 117 : void SimplifiedLowering::DoMin(Node* node, Operator const* op,
3536 : MachineRepresentation rep) {
3537 : Node* const lhs = node->InputAt(0);
3538 : Node* const rhs = node->InputAt(1);
3539 :
3540 117 : node->InsertInput(graph()->zone(), 0, graph()->NewNode(op, lhs, rhs));
3541 : DCHECK_EQ(lhs, node->InputAt(1));
3542 : DCHECK_EQ(rhs, node->InputAt(2));
3543 117 : NodeProperties::ChangeOp(node, common()->Select(rep));
3544 117 : }
3545 :
3546 40180 : void SimplifiedLowering::DoShift(Node* node, Operator const* op,
3547 5076 : Type* rhs_type) {
3548 80360 : if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) {
3549 5076 : Node* const rhs = NodeProperties::GetValueInput(node, 1);
3550 : node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs,
3551 15228 : jsgraph()->Int32Constant(0x1f)));
3552 : }
3553 40180 : ChangeToPureOp(node, op);
3554 40180 : }
3555 :
3556 2284 : void SimplifiedLowering::DoStringToNumber(Node* node) {
3557 : Operator::Properties properties = Operator::kEliminatable;
3558 571 : Callable callable = CodeFactory::StringToNumber(isolate());
3559 : CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
3560 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
3561 1713 : isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
3562 : node->InsertInput(graph()->zone(), 0,
3563 1142 : jsgraph()->HeapConstant(callable.code()));
3564 571 : node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant());
3565 571 : node->AppendInput(graph()->zone(), graph()->start());
3566 571 : NodeProperties::ChangeOp(node, common()->Call(desc));
3567 571 : }
3568 :
3569 326 : void SimplifiedLowering::DoIntegral32ToBit(Node* node) {
3570 : Node* const input = node->InputAt(0);
3571 163 : Node* const zero = jsgraph()->Int32Constant(0);
3572 163 : Operator const* const op = machine()->Word32Equal();
3573 :
3574 163 : node->ReplaceInput(0, graph()->NewNode(op, input, zero));
3575 163 : node->AppendInput(graph()->zone(), zero);
3576 163 : NodeProperties::ChangeOp(node, op);
3577 163 : }
3578 :
3579 0 : void SimplifiedLowering::DoOrderedNumberToBit(Node* node) {
3580 : Node* const input = node->InputAt(0);
3581 :
3582 : node->ReplaceInput(0, graph()->NewNode(machine()->Float64Equal(), input,
3583 0 : jsgraph()->Float64Constant(0.0)));
3584 0 : node->AppendInput(graph()->zone(), jsgraph()->Int32Constant(0));
3585 0 : NodeProperties::ChangeOp(node, machine()->Word32Equal());
3586 0 : }
3587 :
3588 394 : void SimplifiedLowering::DoNumberToBit(Node* node) {
3589 : Node* const input = node->InputAt(0);
3590 :
3591 197 : node->ReplaceInput(0, jsgraph()->Float64Constant(0.0));
3592 : node->AppendInput(graph()->zone(),
3593 394 : graph()->NewNode(machine()->Float64Abs(), input));
3594 197 : NodeProperties::ChangeOp(node, machine()->Float64LessThan());
3595 197 : }
3596 :
3597 72 : void SimplifiedLowering::DoIntegerToUint8Clamped(Node* node) {
3598 : Node* const input = node->InputAt(0);
3599 24 : Node* const min = jsgraph()->Float64Constant(0.0);
3600 24 : Node* const max = jsgraph()->Float64Constant(255.0);
3601 :
3602 : node->ReplaceInput(
3603 48 : 0, graph()->NewNode(machine()->Float64LessThan(), min, input));
3604 : node->AppendInput(
3605 : graph()->zone(),
3606 : graph()->NewNode(
3607 : common()->Select(MachineRepresentation::kFloat64),
3608 : graph()->NewNode(machine()->Float64LessThan(), input, max), input,
3609 72 : max));
3610 24 : node->AppendInput(graph()->zone(), min);
3611 : NodeProperties::ChangeOp(node,
3612 24 : common()->Select(MachineRepresentation::kFloat64));
3613 24 : }
3614 :
3615 900 : void SimplifiedLowering::DoNumberToUint8Clamped(Node* node) {
3616 : Node* const input = node->InputAt(0);
3617 300 : Node* const min = jsgraph()->Float64Constant(0.0);
3618 300 : Node* const max = jsgraph()->Float64Constant(255.0);
3619 :
3620 : node->ReplaceInput(
3621 : 0, graph()->NewNode(
3622 : common()->Select(MachineRepresentation::kFloat64),
3623 : graph()->NewNode(machine()->Float64LessThan(), min, input),
3624 : graph()->NewNode(
3625 : common()->Select(MachineRepresentation::kFloat64),
3626 : graph()->NewNode(machine()->Float64LessThan(), input, max),
3627 : input, max),
3628 1500 : min));
3629 : NodeProperties::ChangeOp(node,
3630 300 : machine()->Float64RoundTiesEven().placeholder());
3631 300 : }
3632 :
3633 186 : void SimplifiedLowering::DoSigned32ToUint8Clamped(Node* node) {
3634 : Node* const input = node->InputAt(0);
3635 62 : Node* const min = jsgraph()->Int32Constant(0);
3636 62 : Node* const max = jsgraph()->Int32Constant(255);
3637 :
3638 : node->ReplaceInput(
3639 124 : 0, graph()->NewNode(machine()->Int32LessThanOrEqual(), input, max));
3640 : node->AppendInput(
3641 : graph()->zone(),
3642 : graph()->NewNode(common()->Select(MachineRepresentation::kWord32),
3643 : graph()->NewNode(machine()->Int32LessThan(), input, min),
3644 186 : min, input));
3645 62 : node->AppendInput(graph()->zone(), max);
3646 : NodeProperties::ChangeOp(node,
3647 62 : common()->Select(MachineRepresentation::kWord32));
3648 62 : }
3649 :
3650 144 : void SimplifiedLowering::DoUnsigned32ToUint8Clamped(Node* node) {
3651 : Node* const input = node->InputAt(0);
3652 : Node* const max = jsgraph()->Uint32Constant(255u);
3653 :
3654 : node->ReplaceInput(
3655 144 : 0, graph()->NewNode(machine()->Uint32LessThanOrEqual(), input, max));
3656 72 : node->AppendInput(graph()->zone(), input);
3657 72 : node->AppendInput(graph()->zone(), max);
3658 : NodeProperties::ChangeOp(node,
3659 72 : common()->Select(MachineRepresentation::kWord32));
3660 72 : }
3661 :
3662 5872 : Node* SimplifiedLowering::ToNumberCode() {
3663 2512 : if (!to_number_code_.is_set()) {
3664 1680 : Callable callable = CodeFactory::ToNumber(isolate());
3665 3360 : to_number_code_.set(jsgraph()->HeapConstant(callable.code()));
3666 : }
3667 2512 : return to_number_code_.get();
3668 : }
3669 :
3670 4192 : Operator const* SimplifiedLowering::ToNumberOperator() {
3671 2512 : if (!to_number_operator_.is_set()) {
3672 1680 : Callable callable = CodeFactory::ToNumber(isolate());
3673 : CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
3674 : CallDescriptor* desc = Linkage::GetStubCallDescriptor(
3675 : isolate(), graph()->zone(), callable.descriptor(), 0, flags,
3676 5040 : Operator::kNoProperties);
3677 1680 : to_number_operator_.set(common()->Call(desc));
3678 : }
3679 2512 : return to_number_operator_.get();
3680 : }
3681 :
3682 : } // namespace compiler
3683 : } // namespace internal
3684 : } // namespace v8
|