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