Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(609)

Side by Side Diff: src/compiler/simplified-lowering.cc

Issue 1921563002: [turbofan] Initial version of number type feedback. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add tests for the checks and fix check insertion Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/simplified-lowering.h" 5 #include "src/compiler/simplified-lowering.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "src/address-map.h" 9 #include "src/address-map.h"
10 #include "src/base/bits.h" 10 #include "src/base/bits.h"
11 #include "src/code-factory.h" 11 #include "src/code-factory.h"
12 #include "src/compiler/access-builder.h" 12 #include "src/compiler/access-builder.h"
13 #include "src/compiler/common-operator.h" 13 #include "src/compiler/common-operator.h"
14 #include "src/compiler/diamond.h" 14 #include "src/compiler/diamond.h"
15 #include "src/compiler/linkage.h" 15 #include "src/compiler/linkage.h"
16 #include "src/compiler/node-matchers.h" 16 #include "src/compiler/node-matchers.h"
17 #include "src/compiler/node-properties.h" 17 #include "src/compiler/node-properties.h"
18 #include "src/compiler/operation-typer.h"
18 #include "src/compiler/operator-properties.h" 19 #include "src/compiler/operator-properties.h"
19 #include "src/compiler/representation-change.h" 20 #include "src/compiler/representation-change.h"
20 #include "src/compiler/simplified-operator.h" 21 #include "src/compiler/simplified-operator.h"
21 #include "src/compiler/source-position.h" 22 #include "src/compiler/source-position.h"
22 #include "src/conversions-inl.h" 23 #include "src/conversions-inl.h"
23 #include "src/objects.h" 24 #include "src/objects.h"
24 #include "src/type-cache.h" 25 #include "src/type-cache.h"
25 26
26 namespace v8 { 27 namespace v8 {
27 namespace internal { 28 namespace internal {
(...skipping 27 matching lines...) Expand all
55 // removing some (redundant) nodes. 56 // removing some (redundant) nodes.
56 // During this phase, use the {RepresentationChanger} to insert 57 // During this phase, use the {RepresentationChanger} to insert
57 // representation changes between uses that demand a particular 58 // representation changes between uses that demand a particular
58 // representation and nodes that produce a different representation. 59 // representation and nodes that produce a different representation.
59 LOWER 60 LOWER
60 }; 61 };
61 62
62 63
63 namespace { 64 namespace {
64 65
65 // The {UseInfo} class is used to describe a use of an input of a node.
66 //
67 // This information is used in two different ways, based on the phase:
68 //
69 // 1. During propagation, the use info is used to inform the input node
70 // about what part of the input is used (we call this truncation) and what
71 // is the preferred representation.
72 //
73 // 2. During lowering, the use info is used to properly convert the input
74 // to the preferred representation. The preferred representation might be
75 // insufficient to do the conversion (e.g. word32->float64 conv), so we also
76 // need the signedness information to produce the correct value.
77 class UseInfo {
78 public:
79 UseInfo(MachineRepresentation preferred, Truncation truncation)
80 : preferred_(preferred), truncation_(truncation) {}
81 static UseInfo TruncatingWord32() {
82 return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
83 }
84 static UseInfo TruncatingWord64() {
85 return UseInfo(MachineRepresentation::kWord64, Truncation::Word64());
86 }
87 static UseInfo Bool() {
88 return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
89 }
90 static UseInfo TruncatingFloat32() {
91 return UseInfo(MachineRepresentation::kFloat32, Truncation::Float32());
92 }
93 static UseInfo TruncatingFloat64() {
94 return UseInfo(MachineRepresentation::kFloat64, Truncation::Float64());
95 }
96 static UseInfo PointerInt() {
97 return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64();
98 }
99 static UseInfo AnyTagged() {
100 return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
101 }
102
103 // Undetermined representation.
104 static UseInfo Any() {
105 return UseInfo(MachineRepresentation::kNone, Truncation::Any());
106 }
107 static UseInfo None() {
108 return UseInfo(MachineRepresentation::kNone, Truncation::None());
109 }
110 static UseInfo AnyTruncatingToBool() {
111 return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
112 }
113
114 MachineRepresentation preferred() const { return preferred_; }
115 Truncation truncation() const { return truncation_; }
116
117 private:
118 MachineRepresentation preferred_;
119 Truncation truncation_;
120 };
121
122 66
123 UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { 67 UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) {
124 switch (rep) { 68 switch (rep) {
125 case MachineRepresentation::kTagged: 69 case MachineRepresentation::kTagged:
126 return UseInfo::AnyTagged(); 70 return UseInfo::AnyTagged();
127 case MachineRepresentation::kFloat64: 71 case MachineRepresentation::kFloat64:
128 return UseInfo::TruncatingFloat64(); 72 return UseInfo::TruncatingFloat64();
129 case MachineRepresentation::kFloat32: 73 case MachineRepresentation::kFloat32:
130 return UseInfo::TruncatingFloat32(); 74 return UseInfo::TruncatingFloat32();
131 case MachineRepresentation::kWord64: 75 case MachineRepresentation::kWord64:
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 // Check that the new use informatin is a super-type of the old 160 // Check that the new use informatin is a super-type of the old
217 // one. 161 // one.
218 CHECK(IsUseLessGeneral(input_use_infos_[index], use_info)); 162 CHECK(IsUseLessGeneral(input_use_infos_[index], use_info));
219 input_use_infos_[index] = use_info; 163 input_use_infos_[index] = use_info;
220 } 164 }
221 165
222 private: 166 private:
223 ZoneVector<UseInfo> input_use_infos_; 167 ZoneVector<UseInfo> input_use_infos_;
224 168
225 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) { 169 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
226 return MachineRepresentationIsSubtype(use1.preferred(), use2.preferred()) && 170 return MachineRepresentationIsSubtype(use1.representation(),
171 use2.representation()) &&
227 use1.truncation().IsLessGeneralThan(use2.truncation()); 172 use1.truncation().IsLessGeneralThan(use2.truncation());
228 } 173 }
229 }; 174 };
230 175
231 #endif // DEBUG 176 #endif // DEBUG
232 177
233 } // namespace 178 } // namespace
234 179
235 180
236 class RepresentationSelector { 181 class RepresentationSelector {
237 public: 182 public:
238 // Information for each node tracked during the fixpoint. 183 // Information for each node tracked during the fixpoint.
239 class NodeInfo { 184 class NodeInfo {
240 public: 185 public:
241 // Adds new use to the node. Returns true if something has changed 186 // Adds new use to the node. Returns true if something has changed
242 // and the node has to be requeued. 187 // and the node has to be requeued.
243 bool AddUse(UseInfo info) { 188 bool AddUse(UseInfo info) {
244 Truncation old_truncation = truncation_; 189 Truncation old_truncation = truncation_;
245 truncation_ = Truncation::Generalize(truncation_, info.truncation()); 190 truncation_ = Truncation::Generalize(truncation_, info.truncation());
246 return truncation_ != old_truncation; 191 return truncation_ != old_truncation;
247 } 192 }
248 193
249 void set_queued(bool value) { queued_ = value; } 194 void set_queued() { state_ = kQueued; }
250 bool queued() const { return queued_; } 195 void set_visited() { state_ = kVisited; }
251 void set_visited() { visited_ = true; } 196 void set_pushed() { state_ = kPushed; }
252 bool visited() const { return visited_; } 197 void reset_state() { state_ = kUnvisited; }
198 bool visited() const { return state_ == kVisited; }
199 bool queued() const { return state_ == kQueued; }
200 bool unvisited() const { return state_ == kUnvisited; }
253 Truncation truncation() const { return truncation_; } 201 Truncation truncation() const { return truncation_; }
254 void set_output(MachineRepresentation output) { representation_ = output; } 202 void set_output(MachineRepresentation output) { representation_ = output; }
255 203
256 MachineRepresentation representation() const { return representation_; } 204 MachineRepresentation representation() const { return representation_; }
257 205
206 // Helpers for feedback typing.
207 void set_feedback_type(Type* type) { feedback_type_ = type; }
208 Type* feedback_type() { return feedback_type_; }
209 void set_weakened() { weakened_ = true; }
210 bool weakened() { return weakened_; }
211 TypeCheckKind type_check() { return type_check_; }
212 void set_type_check(TypeCheckKind type_check) { type_check_ = type_check; }
213
258 private: 214 private:
259 bool queued_ = false; // Bookkeeping for the traversal. 215 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued };
260 bool visited_ = false; // Bookkeeping for the traversal. 216 State state_ = kUnvisited;
261 MachineRepresentation representation_ = 217 MachineRepresentation representation_ =
262 MachineRepresentation::kNone; // Output representation. 218 MachineRepresentation::kNone; // Output representation.
263 Truncation truncation_ = Truncation::None(); // Information about uses. 219 Truncation truncation_ = Truncation::None(); // Information about uses.
220 TypeCheckKind type_check_ = TypeCheckKind::kNone; // Runtime check kind.
221
222 Type* feedback_type_ = nullptr;
223 bool weakened_ = false;
264 }; 224 };
265 225
266 RepresentationSelector(JSGraph* jsgraph, Zone* zone, 226 RepresentationSelector(JSGraph* jsgraph, Zone* zone,
267 RepresentationChanger* changer, 227 RepresentationChanger* changer,
268 SourcePositionTable* source_positions) 228 SourcePositionTable* source_positions)
269 : jsgraph_(jsgraph), 229 : jsgraph_(jsgraph),
230 zone_(zone),
270 count_(jsgraph->graph()->NodeCount()), 231 count_(jsgraph->graph()->NodeCount()),
271 info_(count_, zone), 232 info_(count_, zone),
272 #ifdef DEBUG 233 #ifdef DEBUG
273 node_input_use_infos_(count_, InputUseInfos(zone), zone), 234 node_input_use_infos_(count_, InputUseInfos(zone), zone),
274 #endif 235 #endif
275 nodes_(zone), 236 nodes_(zone),
276 replacements_(zone), 237 replacements_(zone),
277 phase_(PROPAGATE), 238 phase_(PROPAGATE),
278 changer_(changer), 239 changer_(changer),
279 queue_(zone), 240 queue_(zone),
241 typing_stack_(zone),
280 source_positions_(source_positions), 242 source_positions_(source_positions),
281 type_cache_(TypeCache::Get()) { 243 type_cache_(TypeCache::Get()),
282 } 244 op_typer_(jsgraph->isolate(), graph_zone()) {
283 245 }
284 void Run(SimplifiedLowering* lowering) { 246
247 // Forward propagation of types from type feedback.
248 void RunTypePropagationPhase() {
249 DCHECK(typing_stack_.empty());
250
251 typing_stack_.push({graph()->end(), 0});
252 GetInfo(graph()->end())->set_pushed();
253 while (!typing_stack_.empty()) {
254 NodeState& current = typing_stack_.top();
255
256 // If there is an unvisited input, push it and continue.
257 bool pushed_unvisited = false;
258 while (current.input_index < current.node->InputCount()) {
259 Node* input = current.node->InputAt(current.input_index);
260 NodeInfo* input_info = GetInfo(input);
261 current.input_index++;
262 if (input_info->unvisited()) {
263 input_info->set_pushed();
264 typing_stack_.push({input, 0});
265 pushed_unvisited = true;
266 break;
267 }
268 }
269 if (pushed_unvisited) continue;
270
271 // Process the top of the stack.
272 Node* node = current.node;
273 typing_stack_.pop();
274 NodeInfo* info = GetInfo(node);
275 info->set_visited();
276 bool updated = UpdateFeedbackType(node);
277 if (updated) {
278 for (Node* const user : node->uses()) {
279 if (GetInfo(user)->visited()) {
280 GetInfo(user)->set_queued();
281 queue_.push(user);
282 }
283 }
284 }
285 }
286
287 // Process the revisit queue.
288 while (!queue_.empty()) {
289 Node* node = queue_.front();
290 queue_.pop();
291 NodeInfo* info = GetInfo(node);
292 info->set_visited();
293 bool updated = UpdateFeedbackType(node);
294 if (updated) {
295 for (Node* const user : node->uses()) {
296 if (GetInfo(user)->visited()) {
297 GetInfo(user)->set_queued();
298 queue_.push(user);
299 }
300 }
301 }
302 }
303 }
304
305 void ResetNodeInfoState() {
306 // Clean up for the next phase.
307 for (NodeInfo& info : info_) {
308 info.reset_state();
309 }
310 }
311
312 Type* TypeOf(Node* node) {
313 Type* type = GetInfo(node)->feedback_type();
314 return type == nullptr ? NodeProperties::GetType(node) : type;
315 }
316
317 Type* FeedbackTypeOf(Node* node) {
318 Type* type = GetInfo(node)->feedback_type();
319 return type == nullptr ? Type::None() : type;
320 }
321
322 Type* TypePhi(Node* node) {
323 int arity = node->op()->ValueInputCount();
324 Type* type = FeedbackTypeOf(node->InputAt(0));
325 for (int i = 1; i < arity; ++i) {
326 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i)));
327 }
328 return type;
329 }
330
331 Type* TypeSelect(Node* node) {
332 return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)),
333 FeedbackTypeOf(node->InputAt(2)));
334 }
335
336 static Type* TypeOfSpeculativeOp(TypeCheckKind type_check) {
337 switch (type_check) {
338 case TypeCheckKind::kNone:
339 return Type::Any();
340 case TypeCheckKind::kSigned32:
341 return Type::Signed32();
342 case TypeCheckKind::kNumber:
343 return Type::Number();
344 // Unexpected cases.
345 case TypeCheckKind::kNumberOrUndefined:
346 FATAL("Unexpected checked type.");
347 break;
348 }
349 UNREACHABLE();
350 return nullptr;
351 }
352
353 bool UpdateFeedbackType(Node* node) {
354 if (node->op()->ValueOutputCount() == 0) return false;
355
356 NodeInfo* info = GetInfo(node);
357 Type* type = info->feedback_type();
358 Type* new_type = type;
359
360 switch (node->opcode()) {
361 case IrOpcode::kSpeculativeNumberAdd: {
362 Type* lhs = FeedbackTypeOf(node->InputAt(0));
363 Type* rhs = FeedbackTypeOf(node->InputAt(1));
364 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
365 // TODO(jarin) The ToNumber conversion is too conservative here,
366 // e.g. it will treat true as 1 even though the number check will
367 // fail on a boolean. OperationTyper should have a function that
368 // computes a more precise type.
369 lhs = op_typer_.ToNumber(lhs);
370 rhs = op_typer_.ToNumber(rhs);
371 Type* static_type = op_typer_.NumericAdd(lhs, rhs);
372 if (info->type_check() == TypeCheckKind::kNone) {
373 new_type = static_type;
374 } else {
375 Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
376 new_type = Type::Intersect(static_type, feedback_type, graph_zone());
377 }
378 break;
379 }
380
381 case IrOpcode::kSpeculativeNumberSubtract: {
382 Type* lhs = FeedbackTypeOf(node->InputAt(0));
383 Type* rhs = FeedbackTypeOf(node->InputAt(1));
384 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
385 // TODO(jarin) The ToNumber conversion is too conservative here,
386 // e.g. it will treat true as 1 even though the number check will
387 // fail on a boolean. OperationTyper should have a function that
388 // computes a more precise type.
389 lhs = op_typer_.ToNumber(lhs);
390 rhs = op_typer_.ToNumber(rhs);
391 Type* static_type = op_typer_.NumericSubtract(lhs, rhs);
392 if (info->type_check() == TypeCheckKind::kNone) {
393 new_type = static_type;
394 } else {
395 Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
396 new_type = Type::Intersect(static_type, feedback_type, graph_zone());
397 }
398 break;
399 }
400
401 case IrOpcode::kPhi: {
402 new_type = TypePhi(node);
403 if (type != nullptr) {
404 new_type = Weaken(node, type, new_type);
405 }
406 // Recompute the phi representation based on the new type.
407 MachineRepresentation output =
408 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type);
409 ResetOutput(node, output);
410 break;
411 }
412
413 case IrOpcode::kSelect: {
414 new_type = TypeSelect(node);
415 // Recompute representation based on the new type.
416 MachineRepresentation output =
417 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type);
418 ResetOutput(node, output);
419 break;
420 }
421
422 default:
423 // Shortcut for operations that we do not handle.
424 if (type == nullptr) {
425 GetInfo(node)->set_feedback_type(NodeProperties::GetType(node));
426 return true;
427 }
428 return false;
429 }
430 if (type != nullptr && new_type->Is(type)) return false;
431 GetInfo(node)->set_feedback_type(new_type);
432 if (FLAG_trace_representation) {
433 PrintNodeFeedbackType(node);
434 }
435 return true;
436 }
437
438 void PrintNodeFeedbackType(Node* n) {
439 OFStream os(stdout);
440 os << "#" << n->id() << ":" << *n->op() << "(";
441 int j = 0;
442 for (Node* const i : n->inputs()) {
443 if (j++ > 0) os << ", ";
444 os << "#" << i->id() << ":" << i->op()->mnemonic();
445 }
446 os << ")";
447 if (NodeProperties::IsTyped(n)) {
448 os << " [Static type: ";
449 Type* static_type = NodeProperties::GetType(n);
450 static_type->PrintTo(os);
451 Type* feedback_type = GetInfo(n)->feedback_type();
452 if (feedback_type != nullptr && feedback_type != static_type) {
453 os << ", Feedback type: ";
454 feedback_type->PrintTo(os);
455 }
456 os << "]";
457 }
458 os << std::endl;
459 }
460
461 Type* Weaken(Node* node, Type* previous_type, Type* current_type) {
462 // If the types have nothing to do with integers, return the types.
463 Type* const integer = type_cache_.kInteger;
464 if (!previous_type->Maybe(integer)) {
465 return current_type;
466 }
467 DCHECK(current_type->Maybe(integer));
468
469 Type* current_integer =
470 Type::Intersect(current_type, integer, graph_zone());
471 Type* previous_integer =
472 Type::Intersect(previous_type, integer, graph_zone());
473
474 // Once we start weakening a node, we should always weaken.
475 if (!GetInfo(node)->weakened()) {
476 // Only weaken if there is range involved; we should converge quickly
477 // for all other types (the exception is a union of many constants,
478 // but we currently do not increase the number of constants in unions).
479 Type* previous = previous_integer->GetRange();
480 Type* current = current_integer->GetRange();
481 if (current == nullptr || previous == nullptr) {
482 return current_type;
483 }
484 // Range is involved => we are weakening.
485 GetInfo(node)->set_weakened();
486 }
487
488 return Type::Union(current_type,
489 op_typer_.WeakenRange(previous_integer, current_integer),
490 graph_zone());
491 }
492
493 // Backward propagation of truncations.
494 void RunTruncationPropagationPhase() {
285 // Run propagation phase to a fixpoint. 495 // Run propagation phase to a fixpoint.
286 TRACE("--{Propagation phase}--\n"); 496 TRACE("--{Propagation phase}--\n");
287 phase_ = PROPAGATE; 497 phase_ = PROPAGATE;
288 EnqueueInitial(jsgraph_->graph()->end()); 498 EnqueueInitial(jsgraph_->graph()->end());
289 // Process nodes from the queue until it is empty. 499 // Process nodes from the queue until it is empty.
290 while (!queue_.empty()) { 500 while (!queue_.empty()) {
291 Node* node = queue_.front(); 501 Node* node = queue_.front();
292 NodeInfo* info = GetInfo(node); 502 NodeInfo* info = GetInfo(node);
293 queue_.pop(); 503 queue_.pop();
294 info->set_queued(false); 504 info->set_visited();
295 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); 505 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
296 VisitNode(node, info->truncation(), nullptr); 506 VisitNode(node, info->truncation(), nullptr);
297 TRACE(" ==> output "); 507 TRACE(" ==> output ");
298 PrintOutputInfo(info); 508 PrintOutputInfo(info);
299 TRACE("\n"); 509 TRACE("\n");
300 } 510 }
511 }
512
513 void Run(SimplifiedLowering* lowering) {
514 RunTruncationPropagationPhase();
515
516 if (lowering->flags() & SimplifiedLowering::kTypeFeedbackEnabled) {
517 ResetNodeInfoState();
518 RunTypePropagationPhase();
519 }
301 520
302 // Run lowering and change insertion phase. 521 // Run lowering and change insertion phase.
303 TRACE("--{Simplified lowering phase}--\n"); 522 TRACE("--{Simplified lowering phase}--\n");
304 phase_ = LOWER; 523 phase_ = LOWER;
305 // Process nodes from the collected {nodes_} vector. 524 // Process nodes from the collected {nodes_} vector.
306 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { 525 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
307 Node* node = *i; 526 Node* node = *i;
308 NodeInfo* info = GetInfo(node); 527 NodeInfo* info = GetInfo(node);
309 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); 528 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
310 // Reuse {VisitNode()} so the representation rules are in one place. 529 // Reuse {VisitNode()} so the representation rules are in one place.
311 SourcePositionTable::Scope scope( 530 SourcePositionTable::Scope scope(
312 source_positions_, source_positions_->GetSourcePosition(node)); 531 source_positions_, source_positions_->GetSourcePosition(node));
313 VisitNode(node, info->truncation(), lowering); 532 VisitNode(node, info->truncation(), lowering);
314 } 533 }
315 534
316 // Perform the final replacements. 535 // Perform the final replacements.
317 for (NodeVector::iterator i = replacements_.begin(); 536 for (NodeVector::iterator i = replacements_.begin();
318 i != replacements_.end(); ++i) { 537 i != replacements_.end(); ++i) {
319 Node* node = *i; 538 Node* node = *i;
320 Node* replacement = *(++i); 539 Node* replacement = *(++i);
321 node->ReplaceUses(replacement); 540 node->ReplaceUses(replacement);
541 node->Kill();
322 // We also need to replace the node in the rest of the vector. 542 // We also need to replace the node in the rest of the vector.
323 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) { 543 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
324 ++j; 544 ++j;
325 if (*j == node) *j = replacement; 545 if (*j == node) *j = replacement;
326 } 546 }
327 } 547 }
328 } 548 }
329 549
330 void EnqueueInitial(Node* node) { 550 void EnqueueInitial(Node* node) {
331 NodeInfo* info = GetInfo(node); 551 NodeInfo* info = GetInfo(node);
332 info->set_visited(); 552 info->set_queued();
333 info->set_queued(true);
334 nodes_.push_back(node); 553 nodes_.push_back(node);
335 queue_.push(node); 554 queue_.push(node);
336 } 555 }
337 556
338 // Enqueue {use_node}'s {index} input if the {use} contains new information 557 // Enqueue {use_node}'s {index} input if the {use} contains new information
339 // for that input node. Add the input to {nodes_} if this is the first time 558 // for that input node. Add the input to {nodes_} if this is the first time
340 // it's been visited. 559 // it's been visited.
341 void EnqueueInput(Node* use_node, int index, 560 void EnqueueInput(Node* use_node, int index,
342 UseInfo use_info = UseInfo::None()) { 561 UseInfo use_info = UseInfo::None()) {
343 Node* node = use_node->InputAt(index); 562 Node* node = use_node->InputAt(index);
344 if (phase_ != PROPAGATE) return; 563 if (phase_ != PROPAGATE) return;
345 NodeInfo* info = GetInfo(node); 564 NodeInfo* info = GetInfo(node);
346 #ifdef DEBUG 565 #ifdef DEBUG
347 // Check monotonicity of input requirements. 566 // Check monotonicity of input requirements.
348 node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index, 567 node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
349 use_info); 568 use_info);
350 #endif // DEBUG 569 #endif // DEBUG
351 if (!info->visited()) { 570 if (info->unvisited()) {
352 // First visit of this node. 571 // First visit of this node.
353 info->set_visited(); 572 info->set_queued();
354 info->set_queued(true);
355 nodes_.push_back(node); 573 nodes_.push_back(node);
356 queue_.push(node); 574 queue_.push(node);
357 TRACE(" initial: "); 575 TRACE(" initial: ");
358 info->AddUse(use_info); 576 info->AddUse(use_info);
359 PrintTruncation(info->truncation()); 577 PrintTruncation(info->truncation());
360 return; 578 return;
361 } 579 }
362 TRACE(" queue?: "); 580 TRACE(" queue?: ");
363 PrintTruncation(info->truncation()); 581 PrintTruncation(info->truncation());
364 if (info->AddUse(use_info)) { 582 if (info->AddUse(use_info)) {
365 // New usage information for the node is available. 583 // New usage information for the node is available.
366 if (!info->queued()) { 584 if (!info->queued()) {
367 queue_.push(node); 585 queue_.push(node);
368 info->set_queued(true); 586 info->set_queued();
369 TRACE(" added: "); 587 TRACE(" added: ");
370 } else { 588 } else {
371 TRACE(" inqueue: "); 589 TRACE(" inqueue: ");
372 } 590 }
373 PrintTruncation(info->truncation()); 591 PrintTruncation(info->truncation());
374 } 592 }
375 } 593 }
376 594
377 bool lower() { return phase_ == LOWER; } 595 bool lower() { return phase_ == LOWER; }
596 bool propagate() { return phase_ == PROPAGATE; }
378 597
379 void EnqueueUses(Node* node) { 598 void SetOutput(Node* node, MachineRepresentation representation,
380 for (Edge edge : node->use_edges()) { 599 TypeCheckKind type_check = TypeCheckKind::kNone) {
381 if (NodeProperties::IsValueEdge(edge)) { 600 DCHECK(MachineRepresentationIsSubtype(GetInfo(node)->representation(),
382 Node* const user = edge.from(); 601 representation));
383 if (user->id() < count_) { 602 ResetOutput(node, representation, type_check);
384 // New type information for the node is available.
385 NodeInfo* info = GetInfo(user);
386 // Enqueue the node only if we are sure it is reachable from
387 // the end and it has not been queued yet.
388 if (info->visited() && !info->queued()) {
389 queue_.push(user);
390 info->set_queued(true);
391 }
392 }
393 }
394 }
395 } 603 }
396 604
397 void SetOutput(Node* node, MachineRepresentation representation) { 605 void ResetOutput(Node* node, MachineRepresentation representation,
606 TypeCheckKind type_check = TypeCheckKind::kNone) {
398 NodeInfo* info = GetInfo(node); 607 NodeInfo* info = GetInfo(node);
399 DCHECK(
400 MachineRepresentationIsSubtype(info->representation(), representation));
401 info->set_output(representation); 608 info->set_output(representation);
609 info->set_type_check(type_check);
402 } 610 }
403 611
404 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } 612 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
405 613
406 bool BothInputsAreSigned32(Node* node) { 614 bool BothInputsAreSigned32(Node* node) {
407 DCHECK_EQ(2, node->InputCount()); 615 DCHECK_EQ(2, node->InputCount());
408 return GetUpperBound(node->InputAt(0))->Is(Type::Signed32()) && 616 return GetUpperBound(node->InputAt(0))->Is(Type::Signed32()) &&
409 GetUpperBound(node->InputAt(1))->Is(Type::Signed32()); 617 GetUpperBound(node->InputAt(1))->Is(Type::Signed32());
410 } 618 }
411 619
412 bool BothInputsAreUnsigned32(Node* node) { 620 bool BothInputsAreUnsigned32(Node* node) {
413 DCHECK_EQ(2, node->InputCount()); 621 DCHECK_EQ(2, node->InputCount());
414 return GetUpperBound(node->InputAt(0))->Is(Type::Unsigned32()) && 622 return GetUpperBound(node->InputAt(0))->Is(Type::Unsigned32()) &&
415 GetUpperBound(node->InputAt(1))->Is(Type::Unsigned32()); 623 GetUpperBound(node->InputAt(1))->Is(Type::Unsigned32());
416 } 624 }
417 625
418 bool BothInputsAre(Node* node, Type* type) { 626 bool BothInputsAre(Node* node, Type* type) {
419 DCHECK_EQ(2, node->InputCount()); 627 DCHECK_EQ(2, node->op()->ValueInputCount());
420 return GetUpperBound(node->InputAt(0))->Is(type) && 628 return GetUpperBound(node->InputAt(0))->Is(type) &&
421 GetUpperBound(node->InputAt(1))->Is(type); 629 GetUpperBound(node->InputAt(1))->Is(type);
422 } 630 }
423 631
424 void ConvertInput(Node* node, int index, UseInfo use) { 632 void ConvertInput(Node* node, int index, UseInfo use) {
425 Node* input = node->InputAt(index); 633 Node* input = node->InputAt(index);
426 // In the change phase, insert a change before the use if necessary. 634 // In the change phase, insert a change before the use if necessary.
427 if (use.preferred() == MachineRepresentation::kNone) 635 if (use.representation() == MachineRepresentation::kNone)
428 return; // No input requirement on the use. 636 return; // No input requirement on the use.
429 NodeInfo* input_info = GetInfo(input); 637 NodeInfo* input_info = GetInfo(input);
430 MachineRepresentation input_rep = input_info->representation(); 638 MachineRepresentation input_rep = input_info->representation();
431 if (input_rep != use.preferred()) { 639 if (input_rep != use.representation() ||
640 use.type_check() != TypeCheckKind::kNone) {
432 // Output representation doesn't match usage. 641 // Output representation doesn't match usage.
433 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(), 642 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
434 index, input->id(), input->op()->mnemonic()); 643 index, input->id(), input->op()->mnemonic());
435 TRACE(" from "); 644 TRACE(" from ");
436 PrintOutputInfo(input_info); 645 PrintOutputInfo(input_info);
437 TRACE(" to "); 646 TRACE(" to ");
438 PrintUseInfo(use); 647 PrintUseInfo(use);
439 TRACE("\n"); 648 TRACE("\n");
440 Node* n = changer_->GetRepresentationFor( 649 Node* n = changer_->GetRepresentationFor(
441 input, input_info->representation(), GetUpperBound(input), 650 input, input_info->representation(), TypeOf(input), node, use);
442 use.preferred(), use.truncation());
443 node->ReplaceInput(index, n); 651 node->ReplaceInput(index, n);
444 } 652 }
445 } 653 }
446 654
447 void ProcessInput(Node* node, int index, UseInfo use) { 655 void ProcessInput(Node* node, int index, UseInfo use) {
448 if (phase_ == PROPAGATE) { 656 if (phase_ == PROPAGATE) {
449 EnqueueInput(node, index, use); 657 EnqueueInput(node, index, use);
450 } else { 658 } else {
451 ConvertInput(node, index, use); 659 ConvertInput(node, index, use);
452 } 660 }
(...skipping 24 matching lines...) Expand all
477 ProcessInput(node, i, UseInfo::AnyTagged()); 685 ProcessInput(node, i, UseInfo::AnyTagged());
478 } 686 }
479 // Only enqueue other inputs (framestates, effects, control). 687 // Only enqueue other inputs (framestates, effects, control).
480 for (int i = tagged_count; i < node->InputCount(); i++) { 688 for (int i = tagged_count; i < node->InputCount(); i++) {
481 EnqueueInput(node, i); 689 EnqueueInput(node, i);
482 } 690 }
483 } 691 }
484 692
485 // Helper for binops of the R x L -> O variety. 693 // Helper for binops of the R x L -> O variety.
486 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use, 694 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
487 MachineRepresentation output) { 695 MachineRepresentation output,
696 TypeCheckKind type_check = TypeCheckKind::kNone) {
488 DCHECK_EQ(2, node->op()->ValueInputCount()); 697 DCHECK_EQ(2, node->op()->ValueInputCount());
489 ProcessInput(node, 0, left_use); 698 ProcessInput(node, 0, left_use);
490 ProcessInput(node, 1, right_use); 699 ProcessInput(node, 1, right_use);
491 for (int i = 2; i < node->InputCount(); i++) { 700 for (int i = 2; i < node->InputCount(); i++) {
492 EnqueueInput(node, i); 701 EnqueueInput(node, i);
493 } 702 }
494 SetOutput(node, output); 703 SetOutput(node, output, type_check);
495 } 704 }
496 705
497 // Helper for binops of the I x I -> O variety. 706 // Helper for binops of the I x I -> O variety.
498 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output) { 707 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output,
499 VisitBinop(node, input_use, input_use, output); 708 TypeCheckKind type_check = TypeCheckKind::kNone) {
709 VisitBinop(node, input_use, input_use, output, type_check);
500 } 710 }
501 711
502 // Helper for unops of the I -> O variety. 712 // Helper for unops of the I -> O variety.
503 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) { 713 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) {
504 DCHECK_EQ(1, node->InputCount()); 714 DCHECK_EQ(1, node->InputCount());
505 ProcessInput(node, 0, input_use); 715 ProcessInput(node, 0, input_use);
506 SetOutput(node, output); 716 SetOutput(node, output);
507 } 717 }
508 718
509 // Helper for leaf nodes. 719 // Helper for leaf nodes.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); 757 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit);
548 } 758 }
549 void VisitInt64Cmp(Node* node) { 759 void VisitInt64Cmp(Node* node) {
550 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); 760 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit);
551 } 761 }
552 void VisitUint64Cmp(Node* node) { 762 void VisitUint64Cmp(Node* node) {
553 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); 763 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit);
554 } 764 }
555 765
556 // Infer representation for phi-like nodes. 766 // Infer representation for phi-like nodes.
557 MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use) { 767 MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use,
768 Type* type = nullptr) {
558 // Compute the representation. 769 // Compute the representation.
559 Type* type = GetUpperBound(node); 770 if (type == nullptr) {
771 type = TypeOf(node);
772 }
560 if (type->Is(Type::None())) { 773 if (type->Is(Type::None())) {
561 return MachineRepresentation::kNone; 774 return MachineRepresentation::kNone;
562 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) { 775 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
563 return MachineRepresentation::kWord32; 776 return MachineRepresentation::kWord32;
564 } else if (use.TruncatesToWord32()) { 777 } else if (use.TruncatesToWord32()) {
565 return MachineRepresentation::kWord32; 778 return MachineRepresentation::kWord32;
566 } else if (type->Is(Type::Boolean())) { 779 } else if (type->Is(Type::Boolean())) {
567 return MachineRepresentation::kBit; 780 return MachineRepresentation::kBit;
568 } else if (type->Is(Type::Number())) { 781 } else if (type->Is(Type::Number())) {
569 return MachineRepresentation::kFloat64; 782 return MachineRepresentation::kFloat64;
570 } else if (use.TruncatesToFloat64()) { 783 } else if (use.TruncatesToFloat64()) {
571 return MachineRepresentation::kFloat64; 784 return MachineRepresentation::kFloat64;
572 } else if (type->Is(Type::Internal())) { 785 } else if (type->Is(Type::Internal())) {
573 // We mark (u)int64 as Type::Internal. 786 // We mark (u)int64 as Type::Internal.
574 // TODO(jarin) This is a workaround for our lack of (u)int64 787 // TODO(jarin) This is a workaround for our lack of (u)int64
575 // types. This can be removed once we can represent (u)int64 788 // types. This can be removed once we can represent (u)int64
576 // unambiguously. (At the moment internal objects, such as the hole, 789 // unambiguously. (At the moment internal objects, such as the hole,
577 // are also Type::Internal()). 790 // are also Type::Internal()).
578 bool is_word64 = GetInfo(node->InputAt(0))->representation() == 791 bool is_word64 = GetInfo(node->InputAt(0))->representation() ==
579 MachineRepresentation::kWord64; 792 MachineRepresentation::kWord64;
580 #ifdef DEBUG 793 #ifdef DEBUG
581 // Check that all the inputs agree on being Word64. 794 // Check that all the inputs agree on being Word64.
795 DCHECK_EQ(IrOpcode::kPhi, node->opcode()); // This only works for phis.
582 for (int i = 1; i < node->op()->ValueInputCount(); i++) { 796 for (int i = 1; i < node->op()->ValueInputCount(); i++) {
583 DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() == 797 DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() ==
584 MachineRepresentation::kWord64); 798 MachineRepresentation::kWord64);
585 } 799 }
586 #endif 800 #endif
587 return is_word64 ? MachineRepresentation::kWord64 801 return is_word64 ? MachineRepresentation::kWord64
588 : MachineRepresentation::kTagged; 802 : MachineRepresentation::kTagged;
589 } 803 }
590 return MachineRepresentation::kTagged; 804 return MachineRepresentation::kTagged;
591 } 805 }
(...skipping 18 matching lines...) Expand all
610 // truncation truncation along. 824 // truncation truncation along.
611 UseInfo input_use(output, truncation); 825 UseInfo input_use(output, truncation);
612 ProcessInput(node, 1, input_use); 826 ProcessInput(node, 1, input_use);
613 ProcessInput(node, 2, input_use); 827 ProcessInput(node, 2, input_use);
614 } 828 }
615 829
616 // Helper for handling phis. 830 // Helper for handling phis.
617 void VisitPhi(Node* node, Truncation truncation, 831 void VisitPhi(Node* node, Truncation truncation,
618 SimplifiedLowering* lowering) { 832 SimplifiedLowering* lowering) {
619 MachineRepresentation output = GetOutputInfoForPhi(node, truncation); 833 MachineRepresentation output = GetOutputInfoForPhi(node, truncation);
834 // Only set the output representation if not running with type
835 // feedback. (Feedback typing will set the representation.)
620 SetOutput(node, output); 836 SetOutput(node, output);
621 837
622 int values = node->op()->ValueInputCount(); 838 int values = node->op()->ValueInputCount();
623 if (lower()) { 839 if (lower()) {
624 // Update the phi operator. 840 // Update the phi operator.
625 if (output != PhiRepresentationOf(node->op())) { 841 if (output != PhiRepresentationOf(node->op())) {
626 NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values)); 842 NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values));
627 } 843 }
628 } 844 }
629 845
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 } 895 }
680 } else { 896 } else {
681 Zone* zone = jsgraph_->zone(); 897 Zone* zone = jsgraph_->zone();
682 ZoneVector<MachineType>* types = 898 ZoneVector<MachineType>* types =
683 new (zone->New(sizeof(ZoneVector<MachineType>))) 899 new (zone->New(sizeof(ZoneVector<MachineType>)))
684 ZoneVector<MachineType>(node->InputCount(), zone); 900 ZoneVector<MachineType>(node->InputCount(), zone);
685 for (int i = 0; i < node->InputCount(); i++) { 901 for (int i = 0; i < node->InputCount(); i++) {
686 Node* input = node->InputAt(i); 902 Node* input = node->InputAt(i);
687 NodeInfo* input_info = GetInfo(input); 903 NodeInfo* input_info = GetInfo(input);
688 MachineType machine_type(input_info->representation(), 904 MachineType machine_type(input_info->representation(),
689 DeoptValueSemanticOf(GetUpperBound(input))); 905 DeoptValueSemanticOf(TypeOf(input)));
690 DCHECK(machine_type.representation() != 906 DCHECK(machine_type.representation() !=
691 MachineRepresentation::kWord32 || 907 MachineRepresentation::kWord32 ||
692 machine_type.semantic() == MachineSemantic::kInt32 || 908 machine_type.semantic() == MachineSemantic::kInt32 ||
693 machine_type.semantic() == MachineSemantic::kUint32); 909 machine_type.semantic() == MachineSemantic::kUint32);
694 (*types)[i] = machine_type; 910 (*types)[i] = machine_type;
695 } 911 }
696 NodeProperties::ChangeOp(node, 912 NodeProperties::ChangeOp(node,
697 jsgraph_->common()->TypedStateValues(types)); 913 jsgraph_->common()->TypedStateValues(types));
698 } 914 }
699 SetOutput(node, MachineRepresentation::kTagged); 915 SetOutput(node, MachineRepresentation::kTagged);
700 } 916 }
701 917
702 const Operator* Int32Op(Node* node) { 918 const Operator* Int32Op(Node* node) {
703 return changer_->Int32OperatorFor(node->opcode()); 919 return changer_->Int32OperatorFor(node->opcode());
704 } 920 }
705 921
922 const Operator* Int32OverflowOp(Node* node) {
923 return changer_->Int32OverflowOperatorFor(node->opcode());
924 }
925
706 const Operator* Uint32Op(Node* node) { 926 const Operator* Uint32Op(Node* node) {
707 return changer_->Uint32OperatorFor(node->opcode()); 927 return changer_->Uint32OperatorFor(node->opcode());
708 } 928 }
709 929
710 const Operator* Float64Op(Node* node) { 930 const Operator* Float64Op(Node* node) {
711 return changer_->Float64OperatorFor(node->opcode()); 931 return changer_->Float64OperatorFor(node->opcode());
712 } 932 }
713 933
714 WriteBarrierKind WriteBarrierKindFor( 934 WriteBarrierKind WriteBarrierKindFor(
715 BaseTaggedness base_taggedness, 935 BaseTaggedness base_taggedness,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 MachineRepresentation field_representation, int field_offset, 989 MachineRepresentation field_representation, int field_offset,
770 Type* field_type, Node* value) { 990 Type* field_type, Node* value) {
771 if (base_taggedness == kTaggedBase && 991 if (base_taggedness == kTaggedBase &&
772 field_offset == HeapObject::kMapOffset) { 992 field_offset == HeapObject::kMapOffset) {
773 return kMapWriteBarrier; 993 return kMapWriteBarrier;
774 } 994 }
775 return WriteBarrierKindFor(base_taggedness, field_representation, 995 return WriteBarrierKindFor(base_taggedness, field_representation,
776 field_type, value); 996 field_type, value);
777 } 997 }
778 998
999 Graph* graph() const { return jsgraph_->graph(); }
1000 CommonOperatorBuilder* common() const { return jsgraph_->common(); }
1001 SimplifiedOperatorBuilder* simplified() const {
1002 return jsgraph_->simplified();
1003 }
1004
1005 void ChangeToPureOp(Node* node, const Operator* new_op) {
1006 // Disconnect the node from effect and control chains.
1007 Node* control = NodeProperties::GetControlInput(node);
1008 Node* effect = NodeProperties::GetEffectInput(node);
1009 for (Edge edge : node->use_edges()) {
1010 if (NodeProperties::IsControlEdge(edge)) {
1011 edge.UpdateTo(control);
1012 } else if (NodeProperties::IsEffectEdge(edge)) {
1013 edge.UpdateTo(effect);
1014 } else {
1015 DCHECK(NodeProperties::IsValueEdge(edge));
1016 }
1017 }
1018
1019 node->TrimInputCount(new_op->ValueInputCount());
1020 NodeProperties::ChangeOp(node, new_op);
1021 }
1022
1023 void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) {
1024 for (Edge edge : node->use_edges()) {
1025 if (NodeProperties::IsControlEdge(edge)) {
1026 edge.UpdateTo(control);
1027 } else if (NodeProperties::IsEffectEdge(edge)) {
1028 edge.UpdateTo(effect);
1029 } else {
1030 DCHECK(NodeProperties::IsValueEdge(edge));
1031 }
1032 }
1033 }
1034
1035 void ChangeToInt32OverflowOp(Node* node, const Operator* op) {
1036 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
1037 Node* effect = NodeProperties::GetEffectInput(node);
1038 Node* control = NodeProperties::GetControlInput(node);
1039 Node* arith = graph()->NewNode(op, node->InputAt(0), node->InputAt(1));
1040 Node* overflow = graph()->NewNode(common()->Projection(1), arith);
1041 control = effect = graph()->NewNode(common()->DeoptimizeIf(), overflow,
1042 frame_state, effect, control);
1043
1044 Node* value = graph()->NewNode(common()->Projection(0), arith);
1045 ReplaceEffectControlUses(node, effect, control);
1046 DeferReplacement(node, value);
1047 }
1048
1049 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
1050 SimplifiedLowering* lowering) {
1051 if (BothInputsAre(node, Type::Signed32()) &&
1052 NodeProperties::GetType(node)->Is(Type::Signed32())) {
1053 // int32 + int32 = int32 ==> signed Int32Add/Sub
1054 VisitInt32Binop(node);
1055 if (lower()) ChangeToPureOp(node, Int32Op(node));
1056 return;
1057 }
1058
1059 // Use truncation if available.
1060 if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) &&
1061 truncation.TruncatesToWord32()) {
1062 // safe-int + safe-int = x (truncated to int32)
1063 // => signed Int32Add/Sub (truncated)
1064 VisitWord32TruncatingBinop(node);
1065 if (lower()) ChangeToPureOp(node, Int32Op(node));
1066 return;
1067 }
1068
1069 // Try to use type feedback.
1070 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op());
1071
1072 // TODO(jarin) This might not be necessary (covered by the next case).
1073 // The only real difference is that this one actually treats the
1074 // inputs as truncated to word32.
1075 if (BothInputsAre(node, Type::Signed32())) {
1076 // If both the inputs the feedback are int32, use the overflow op.
1077 if (hint == BinaryOperationHints::kSignedSmall ||
1078 hint == BinaryOperationHints::kSigned32) {
1079 VisitBinop(node, UseInfo::TruncatingWord32(),
1080 MachineRepresentation::kWord32, TypeCheckKind::kSigned32);
1081 if (lower()) {
1082 ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
1083 }
1084 return;
1085 }
1086 }
1087
1088 if (hint == BinaryOperationHints::kSignedSmall ||
1089 hint == BinaryOperationHints::kSigned32) {
1090 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
1091 MachineRepresentation::kWord32, TypeCheckKind::kSigned32);
1092 if (lower()) {
1093 ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
1094 }
1095 return;
1096 }
1097
1098 // default case => Float64Add/Sub
1099 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
1100 MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
1101 if (lower()) {
1102 ChangeToPureOp(node, Float64Op(node));
1103 }
1104 return;
1105 }
1106
779 // Dispatching routine for visiting the node {node} with the usage {use}. 1107 // Dispatching routine for visiting the node {node} with the usage {use}.
780 // Depending on the operator, propagate new usage info to the inputs. 1108 // Depending on the operator, propagate new usage info to the inputs.
781 void VisitNode(Node* node, Truncation truncation, 1109 void VisitNode(Node* node, Truncation truncation,
782 SimplifiedLowering* lowering) { 1110 SimplifiedLowering* lowering) {
783 switch (node->opcode()) { 1111 switch (node->opcode()) {
784 //------------------------------------------------------------------ 1112 //------------------------------------------------------------------
785 // Common operators. 1113 // Common operators.
786 //------------------------------------------------------------------ 1114 //------------------------------------------------------------------
787 case IrOpcode::kStart: 1115 case IrOpcode::kStart:
788 case IrOpcode::kDead: 1116 case IrOpcode::kDead:
(...skipping 17 matching lines...) Expand all
806 case IrOpcode::kNumberConstant: 1134 case IrOpcode::kNumberConstant:
807 return VisitLeaf(node, MachineRepresentation::kTagged); 1135 return VisitLeaf(node, MachineRepresentation::kTagged);
808 case IrOpcode::kHeapConstant: 1136 case IrOpcode::kHeapConstant:
809 return VisitLeaf(node, MachineRepresentation::kTagged); 1137 return VisitLeaf(node, MachineRepresentation::kTagged);
810 1138
811 case IrOpcode::kDeoptimizeIf: 1139 case IrOpcode::kDeoptimizeIf:
812 case IrOpcode::kDeoptimizeUnless: 1140 case IrOpcode::kDeoptimizeUnless:
813 ProcessInput(node, 0, UseInfo::Bool()); 1141 ProcessInput(node, 0, UseInfo::Bool());
814 ProcessInput(node, 1, UseInfo::AnyTagged()); 1142 ProcessInput(node, 1, UseInfo::AnyTagged());
815 ProcessRemainingInputs(node, 2); 1143 ProcessRemainingInputs(node, 2);
816 break; 1144 return;
817 case IrOpcode::kBranch: 1145 case IrOpcode::kBranch:
818 ProcessInput(node, 0, UseInfo::Bool()); 1146 ProcessInput(node, 0, UseInfo::Bool());
819 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); 1147 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
820 break; 1148 return;
821 case IrOpcode::kSwitch: 1149 case IrOpcode::kSwitch:
822 ProcessInput(node, 0, UseInfo::TruncatingWord32()); 1150 ProcessInput(node, 0, UseInfo::TruncatingWord32());
823 EnqueueInput(node, NodeProperties::FirstControlIndex(node)); 1151 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
824 break; 1152 return;
825 case IrOpcode::kSelect: 1153 case IrOpcode::kSelect:
826 return VisitSelect(node, truncation, lowering); 1154 return VisitSelect(node, truncation, lowering);
827 case IrOpcode::kPhi: 1155 case IrOpcode::kPhi:
828 return VisitPhi(node, truncation, lowering); 1156 return VisitPhi(node, truncation, lowering);
829 case IrOpcode::kCall: 1157 case IrOpcode::kCall:
830 return VisitCall(node, lowering); 1158 return VisitCall(node, lowering);
831 1159
832 //------------------------------------------------------------------ 1160 //------------------------------------------------------------------
833 // JavaScript operators. 1161 // JavaScript operators.
834 //------------------------------------------------------------------ 1162 //------------------------------------------------------------------
835 case IrOpcode::kJSToNumber: { 1163 case IrOpcode::kJSToNumber: {
836 VisitInputs(node); 1164 VisitInputs(node);
837 // TODO(bmeurer): Optimize somewhat based on input type? 1165 // TODO(bmeurer): Optimize somewhat based on input type?
838 if (truncation.TruncatesToWord32()) { 1166 if (truncation.TruncatesToWord32()) {
839 SetOutput(node, MachineRepresentation::kWord32); 1167 SetOutput(node, MachineRepresentation::kWord32);
840 if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this); 1168 if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this);
841 } else if (truncation.TruncatesToFloat64()) { 1169 } else if (truncation.TruncatesToFloat64()) {
842 SetOutput(node, MachineRepresentation::kFloat64); 1170 SetOutput(node, MachineRepresentation::kFloat64);
843 if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this); 1171 if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this);
844 } else { 1172 } else {
845 SetOutput(node, MachineRepresentation::kTagged); 1173 SetOutput(node, MachineRepresentation::kTagged);
846 } 1174 }
847 break; 1175 return;
848 } 1176 }
849 1177
850 //------------------------------------------------------------------ 1178 //------------------------------------------------------------------
851 // Simplified operators. 1179 // Simplified operators.
852 //------------------------------------------------------------------ 1180 //------------------------------------------------------------------
853 case IrOpcode::kBooleanNot: { 1181 case IrOpcode::kBooleanNot: {
854 if (lower()) { 1182 if (lower()) {
855 NodeInfo* input_info = GetInfo(node->InputAt(0)); 1183 NodeInfo* input_info = GetInfo(node->InputAt(0));
856 if (input_info->representation() == MachineRepresentation::kBit) { 1184 if (input_info->representation() == MachineRepresentation::kBit) {
857 // BooleanNot(x: kRepBit) => Word32Equal(x, #0) 1185 // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
858 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0)); 1186 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
859 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal()); 1187 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
860 } else { 1188 } else {
861 // BooleanNot(x: kRepTagged) => WordEqual(x, #false) 1189 // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
862 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant()); 1190 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
863 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); 1191 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
864 } 1192 }
865 } else { 1193 } else {
866 // No input representation requirement; adapt during lowering. 1194 // No input representation requirement; adapt during lowering.
867 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); 1195 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
868 SetOutput(node, MachineRepresentation::kBit); 1196 SetOutput(node, MachineRepresentation::kBit);
869 } 1197 }
870 break; 1198 return;
871 } 1199 }
872 case IrOpcode::kBooleanToNumber: { 1200 case IrOpcode::kBooleanToNumber: {
873 if (lower()) { 1201 if (lower()) {
874 NodeInfo* input_info = GetInfo(node->InputAt(0)); 1202 NodeInfo* input_info = GetInfo(node->InputAt(0));
875 if (input_info->representation() == MachineRepresentation::kBit) { 1203 if (input_info->representation() == MachineRepresentation::kBit) {
876 // BooleanToNumber(x: kRepBit) => x 1204 // BooleanToNumber(x: kRepBit) => x
877 DeferReplacement(node, node->InputAt(0)); 1205 DeferReplacement(node, node->InputAt(0));
878 } else { 1206 } else {
879 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true) 1207 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true)
880 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant()); 1208 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant());
881 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); 1209 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
882 } 1210 }
883 } else { 1211 } else {
884 // No input representation requirement; adapt during lowering. 1212 // No input representation requirement; adapt during lowering.
885 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool()); 1213 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
886 SetOutput(node, MachineRepresentation::kWord32); 1214 SetOutput(node, MachineRepresentation::kWord32);
887 } 1215 }
888 break; 1216 return;
889 } 1217 }
890 case IrOpcode::kNumberEqual: 1218 case IrOpcode::kNumberEqual:
891 case IrOpcode::kNumberLessThan: 1219 case IrOpcode::kNumberLessThan:
892 case IrOpcode::kNumberLessThanOrEqual: { 1220 case IrOpcode::kNumberLessThanOrEqual: {
893 // Number comparisons reduce to integer comparisons for integer inputs. 1221 // Number comparisons reduce to integer comparisons for integer inputs.
894 if (BothInputsAreSigned32(node)) { 1222 if (BothInputsAreSigned32(node)) {
895 // => signed Int32Cmp 1223 // => signed Int32Cmp
896 VisitInt32Cmp(node); 1224 VisitInt32Cmp(node);
897 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); 1225 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
898 } else if (BothInputsAreUnsigned32(node)) { 1226 } else if (BothInputsAreUnsigned32(node)) {
899 // => unsigned Int32Cmp 1227 // => unsigned Int32Cmp
900 VisitUint32Cmp(node); 1228 VisitUint32Cmp(node);
901 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); 1229 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
902 } else { 1230 } else {
903 // => Float64Cmp 1231 // => Float64Cmp
904 VisitFloat64Cmp(node); 1232 VisitFloat64Cmp(node);
905 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 1233 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
906 } 1234 }
907 break; 1235 return;
908 } 1236 }
1237
1238 case IrOpcode::kSpeculativeNumberAdd:
1239 case IrOpcode::kSpeculativeNumberSubtract:
1240 return VisitSpeculativeAdditiveOp(node, truncation, lowering);
1241
909 case IrOpcode::kNumberAdd: 1242 case IrOpcode::kNumberAdd:
910 case IrOpcode::kNumberSubtract: { 1243 case IrOpcode::kNumberSubtract: {
911 if (BothInputsAre(node, Type::Signed32()) && 1244 if (BothInputsAre(node, Type::Signed32()) &&
912 NodeProperties::GetType(node)->Is(Type::Signed32())) { 1245 NodeProperties::GetType(node)->Is(Type::Signed32())) {
913 // int32 + int32 = int32 1246 // int32 + int32 = int32
914 // => signed Int32Add/Sub 1247 // => signed Int32Add/Sub
915 VisitInt32Binop(node); 1248 VisitInt32Binop(node);
916 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); 1249 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
917 } else if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) && 1250 } else if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) &&
918 truncation.TruncatesToWord32()) { 1251 truncation.TruncatesToWord32()) {
919 // safe-int + safe-int = x (truncated to int32) 1252 // safe-int + safe-int = x (truncated to int32)
920 // => signed Int32Add/Sub (truncated) 1253 // => signed Int32Add/Sub (truncated)
921 VisitWord32TruncatingBinop(node); 1254 VisitWord32TruncatingBinop(node);
922 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); 1255 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
923 } else { 1256 } else {
924 // => Float64Add/Sub 1257 // => Float64Add/Sub
925 VisitFloat64Binop(node); 1258 VisitFloat64Binop(node);
926 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 1259 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
927 } 1260 }
928 break; 1261 return;
929 } 1262 }
930 case IrOpcode::kNumberMultiply: { 1263 case IrOpcode::kNumberMultiply: {
931 if (BothInputsAreSigned32(node)) { 1264 if (BothInputsAreSigned32(node)) {
932 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { 1265 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
933 // Multiply reduces to Int32Mul if the inputs and the output 1266 // Multiply reduces to Int32Mul if the inputs and the output
934 // are integers. 1267 // are integers.
935 VisitInt32Binop(node); 1268 VisitInt32Binop(node);
936 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); 1269 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
937 break; 1270 return;
938 } 1271 }
939 if (truncation.TruncatesToWord32() && 1272 if (truncation.TruncatesToWord32() &&
940 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) { 1273 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) {
941 // Multiply reduces to Int32Mul if the inputs are integers, 1274 // Multiply reduces to Int32Mul if the inputs are integers,
942 // the uses are truncating and the result is in the safe 1275 // the uses are truncating and the result is in the safe
943 // integer range. 1276 // integer range.
944 VisitWord32TruncatingBinop(node); 1277 VisitWord32TruncatingBinop(node);
945 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); 1278 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
946 break; 1279 return;
947 } 1280 }
948 } 1281 }
949 // => Float64Mul 1282 // => Float64Mul
950 VisitFloat64Binop(node); 1283 VisitFloat64Binop(node);
951 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 1284 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
952 break; 1285 return;
953 } 1286 }
954 case IrOpcode::kNumberDivide: { 1287 case IrOpcode::kNumberDivide: {
955 if (BothInputsAreSigned32(node)) { 1288 if (BothInputsAreSigned32(node)) {
956 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { 1289 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
957 // => signed Int32Div 1290 // => signed Int32Div
958 VisitInt32Binop(node); 1291 VisitInt32Binop(node);
959 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); 1292 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
960 break; 1293 return;
961 } 1294 }
962 if (truncation.TruncatesToWord32()) { 1295 if (truncation.TruncatesToWord32()) {
963 // => signed Int32Div 1296 // => signed Int32Div
964 VisitWord32TruncatingBinop(node); 1297 VisitWord32TruncatingBinop(node);
965 if (lower()) DeferReplacement(node, lowering->Int32Div(node)); 1298 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
966 break; 1299 return;
967 } 1300 }
968 } 1301 }
969 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { 1302 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
970 // => unsigned Uint32Div 1303 // => unsigned Uint32Div
971 VisitWord32TruncatingBinop(node); 1304 VisitWord32TruncatingBinop(node);
972 if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); 1305 if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
973 break; 1306 return;
974 } 1307 }
975 // => Float64Div 1308 // => Float64Div
976 VisitFloat64Binop(node); 1309 VisitFloat64Binop(node);
977 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 1310 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
978 break; 1311 return;
979 } 1312 }
980 case IrOpcode::kNumberModulus: { 1313 case IrOpcode::kNumberModulus: {
981 if (BothInputsAreSigned32(node)) { 1314 if (BothInputsAreSigned32(node)) {
982 if (NodeProperties::GetType(node)->Is(Type::Signed32())) { 1315 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
983 // => signed Int32Mod 1316 // => signed Int32Mod
984 VisitInt32Binop(node); 1317 VisitInt32Binop(node);
985 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); 1318 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
986 break; 1319 return;
987 } 1320 }
988 if (truncation.TruncatesToWord32()) { 1321 if (truncation.TruncatesToWord32()) {
989 // => signed Int32Mod 1322 // => signed Int32Mod
990 VisitWord32TruncatingBinop(node); 1323 VisitWord32TruncatingBinop(node);
991 if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); 1324 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
992 break; 1325 return;
993 } 1326 }
994 } 1327 }
995 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) { 1328 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
996 // => unsigned Uint32Mod 1329 // => unsigned Uint32Mod
997 VisitWord32TruncatingBinop(node); 1330 VisitWord32TruncatingBinop(node);
998 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); 1331 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
999 break; 1332 return;
1000 } 1333 }
1001 // => Float64Mod 1334 // => Float64Mod
1002 VisitFloat64Binop(node); 1335 VisitFloat64Binop(node);
1003 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); 1336 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
1004 break; 1337 return;
1005 } 1338 }
1006 case IrOpcode::kNumberBitwiseOr: 1339 case IrOpcode::kNumberBitwiseOr:
1007 case IrOpcode::kNumberBitwiseXor: 1340 case IrOpcode::kNumberBitwiseXor:
1008 case IrOpcode::kNumberBitwiseAnd: { 1341 case IrOpcode::kNumberBitwiseAnd: {
1009 VisitInt32Binop(node); 1342 VisitInt32Binop(node);
1010 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); 1343 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
1011 break; 1344 return;
1012 } 1345 }
1013 case IrOpcode::kNumberShiftLeft: { 1346 case IrOpcode::kNumberShiftLeft: {
1014 Type* rhs_type = GetUpperBound(node->InputAt(1)); 1347 Type* rhs_type = GetUpperBound(node->InputAt(1));
1015 VisitBinop(node, UseInfo::TruncatingWord32(), 1348 VisitBinop(node, UseInfo::TruncatingWord32(),
1016 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); 1349 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1017 if (lower()) { 1350 if (lower()) {
1018 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type); 1351 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
1019 } 1352 }
1020 break; 1353 return;
1021 } 1354 }
1022 case IrOpcode::kNumberShiftRight: { 1355 case IrOpcode::kNumberShiftRight: {
1023 Type* rhs_type = GetUpperBound(node->InputAt(1)); 1356 Type* rhs_type = GetUpperBound(node->InputAt(1));
1024 VisitBinop(node, UseInfo::TruncatingWord32(), 1357 VisitBinop(node, UseInfo::TruncatingWord32(),
1025 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); 1358 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1026 if (lower()) { 1359 if (lower()) {
1027 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type); 1360 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
1028 } 1361 }
1029 break; 1362 return;
1030 } 1363 }
1031 case IrOpcode::kNumberShiftRightLogical: { 1364 case IrOpcode::kNumberShiftRightLogical: {
1032 Type* rhs_type = GetUpperBound(node->InputAt(1)); 1365 Type* rhs_type = GetUpperBound(node->InputAt(1));
1033 VisitBinop(node, UseInfo::TruncatingWord32(), 1366 VisitBinop(node, UseInfo::TruncatingWord32(),
1034 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); 1367 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1035 if (lower()) { 1368 if (lower()) {
1036 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); 1369 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
1037 } 1370 }
1038 break; 1371 return;
1039 } 1372 }
1040 case IrOpcode::kNumberClz32: { 1373 case IrOpcode::kNumberClz32: {
1041 VisitUnop(node, UseInfo::TruncatingWord32(), 1374 VisitUnop(node, UseInfo::TruncatingWord32(),
1042 MachineRepresentation::kWord32); 1375 MachineRepresentation::kWord32);
1043 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); 1376 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
1044 break; 1377 return;
1045 } 1378 }
1046 case IrOpcode::kNumberImul: { 1379 case IrOpcode::kNumberImul: {
1047 VisitBinop(node, UseInfo::TruncatingWord32(), 1380 VisitBinop(node, UseInfo::TruncatingWord32(),
1048 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); 1381 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1049 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); 1382 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
1050 break; 1383 return;
1051 } 1384 }
1052 case IrOpcode::kNumberCeil: { 1385 case IrOpcode::kNumberCeil: {
1053 VisitUnop(node, UseInfo::TruncatingFloat64(), 1386 VisitUnop(node, UseInfo::TruncatingFloat64(),
1054 MachineRepresentation::kFloat64); 1387 MachineRepresentation::kFloat64);
1055 if (lower()) DeferReplacement(node, lowering->Float64Ceil(node)); 1388 if (lower()) DeferReplacement(node, lowering->Float64Ceil(node));
1056 break; 1389 return;
1057 } 1390 }
1058 case IrOpcode::kNumberFloor: { 1391 case IrOpcode::kNumberFloor: {
1059 VisitUnop(node, UseInfo::TruncatingFloat64(), 1392 VisitUnop(node, UseInfo::TruncatingFloat64(),
1060 MachineRepresentation::kFloat64); 1393 MachineRepresentation::kFloat64);
1061 if (lower()) DeferReplacement(node, lowering->Float64Floor(node)); 1394 if (lower()) DeferReplacement(node, lowering->Float64Floor(node));
1062 break; 1395 return;
1063 } 1396 }
1064 case IrOpcode::kNumberRound: { 1397 case IrOpcode::kNumberRound: {
1065 VisitUnop(node, UseInfo::TruncatingFloat64(), 1398 VisitUnop(node, UseInfo::TruncatingFloat64(),
1066 MachineRepresentation::kFloat64); 1399 MachineRepresentation::kFloat64);
1067 if (lower()) DeferReplacement(node, lowering->Float64Round(node)); 1400 if (lower()) DeferReplacement(node, lowering->Float64Round(node));
1068 break; 1401 return;
1069 } 1402 }
1070 case IrOpcode::kNumberTrunc: { 1403 case IrOpcode::kNumberTrunc: {
1071 VisitUnop(node, UseInfo::TruncatingFloat64(), 1404 VisitUnop(node, UseInfo::TruncatingFloat64(),
1072 MachineRepresentation::kFloat64); 1405 MachineRepresentation::kFloat64);
1073 if (lower()) DeferReplacement(node, lowering->Float64Trunc(node)); 1406 if (lower()) DeferReplacement(node, lowering->Float64Trunc(node));
1074 break; 1407 return;
1075 } 1408 }
1076 case IrOpcode::kNumberToInt32: { 1409 case IrOpcode::kNumberToInt32: {
1077 // Just change representation if necessary. 1410 // Just change representation if necessary.
1078 VisitUnop(node, UseInfo::TruncatingWord32(), 1411 VisitUnop(node, UseInfo::TruncatingWord32(),
1079 MachineRepresentation::kWord32); 1412 MachineRepresentation::kWord32);
1080 if (lower()) DeferReplacement(node, node->InputAt(0)); 1413 if (lower()) DeferReplacement(node, node->InputAt(0));
1081 break; 1414 return;
1082 } 1415 }
1083 case IrOpcode::kNumberToUint32: { 1416 case IrOpcode::kNumberToUint32: {
1084 // Just change representation if necessary. 1417 // Just change representation if necessary.
1085 VisitUnop(node, UseInfo::TruncatingWord32(), 1418 VisitUnop(node, UseInfo::TruncatingWord32(),
1086 MachineRepresentation::kWord32); 1419 MachineRepresentation::kWord32);
1087 if (lower()) DeferReplacement(node, node->InputAt(0)); 1420 if (lower()) DeferReplacement(node, node->InputAt(0));
1088 break; 1421 return;
1089 } 1422 }
1090 case IrOpcode::kNumberIsHoleNaN: { 1423 case IrOpcode::kNumberIsHoleNaN: {
1091 VisitUnop(node, UseInfo::TruncatingFloat64(), 1424 VisitUnop(node, UseInfo::TruncatingFloat64(),
1092 MachineRepresentation::kBit); 1425 MachineRepresentation::kBit);
1093 if (lower()) { 1426 if (lower()) {
1094 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x), 1427 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x),
1095 // #HoleNaNLower32) 1428 // #HoleNaNLower32)
1096 node->ReplaceInput(0, 1429 node->ReplaceInput(0,
1097 jsgraph_->graph()->NewNode( 1430 jsgraph_->graph()->NewNode(
1098 lowering->machine()->Float64ExtractLowWord32(), 1431 lowering->machine()->Float64ExtractLowWord32(),
1099 node->InputAt(0))); 1432 node->InputAt(0)));
1100 node->AppendInput(jsgraph_->zone(), 1433 node->AppendInput(jsgraph_->zone(),
1101 jsgraph_->Int32Constant(kHoleNanLower32)); 1434 jsgraph_->Int32Constant(kHoleNanLower32));
1102 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal()); 1435 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal());
1103 } 1436 }
1104 break; 1437 return;
1105 } 1438 }
1106 case IrOpcode::kReferenceEqual: { 1439 case IrOpcode::kReferenceEqual: {
1107 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); 1440 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
1108 if (lower()) { 1441 if (lower()) {
1109 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual()); 1442 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
1110 } 1443 }
1111 break; 1444 return;
1112 } 1445 }
1113 case IrOpcode::kStringEqual: { 1446 case IrOpcode::kStringEqual: {
1114 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); 1447 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1115 if (lower()) { 1448 if (lower()) {
1116 // StringEqual(x, y) => Call(StringEqualStub, x, y, no-context) 1449 // StringEqual(x, y) => Call(StringEqualStub, x, y, no-context)
1117 Operator::Properties properties = 1450 Operator::Properties properties =
1118 Operator::kCommutative | Operator::kNoThrow; 1451 Operator::kCommutative | Operator::kNoThrow;
1119 Callable callable = CodeFactory::StringEqual(jsgraph_->isolate()); 1452 Callable callable = CodeFactory::StringEqual(jsgraph_->isolate());
1120 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 1453 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1121 CallDescriptor* desc = Linkage::GetStubCallDescriptor( 1454 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1122 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, 1455 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1123 flags, properties); 1456 flags, properties);
1124 node->InsertInput(jsgraph_->zone(), 0, 1457 node->InsertInput(jsgraph_->zone(), 0,
1125 jsgraph_->HeapConstant(callable.code())); 1458 jsgraph_->HeapConstant(callable.code()));
1126 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); 1459 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1127 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); 1460 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1128 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); 1461 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1129 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); 1462 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1130 } 1463 }
1131 break; 1464 return;
1132 } 1465 }
1133 case IrOpcode::kStringLessThan: { 1466 case IrOpcode::kStringLessThan: {
1134 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); 1467 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1135 if (lower()) { 1468 if (lower()) {
1136 // StringLessThan(x, y) => Call(StringLessThanStub, x, y, no-context) 1469 // StringLessThan(x, y) => Call(StringLessThanStub, x, y, no-context)
1137 Operator::Properties properties = Operator::kNoThrow; 1470 Operator::Properties properties = Operator::kNoThrow;
1138 Callable callable = CodeFactory::StringLessThan(jsgraph_->isolate()); 1471 Callable callable = CodeFactory::StringLessThan(jsgraph_->isolate());
1139 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 1472 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1140 CallDescriptor* desc = Linkage::GetStubCallDescriptor( 1473 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1141 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, 1474 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1142 flags, properties); 1475 flags, properties);
1143 node->InsertInput(jsgraph_->zone(), 0, 1476 node->InsertInput(jsgraph_->zone(), 0,
1144 jsgraph_->HeapConstant(callable.code())); 1477 jsgraph_->HeapConstant(callable.code()));
1145 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); 1478 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1146 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); 1479 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1147 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); 1480 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1148 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); 1481 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1149 } 1482 }
1150 break; 1483 return;
1151 } 1484 }
1152 case IrOpcode::kStringLessThanOrEqual: { 1485 case IrOpcode::kStringLessThanOrEqual: {
1153 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); 1486 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1154 if (lower()) { 1487 if (lower()) {
1155 // StringLessThanOrEqual(x, y) 1488 // StringLessThanOrEqual(x, y)
1156 // => Call(StringLessThanOrEqualStub, x, y, no-context) 1489 // => Call(StringLessThanOrEqualStub, x, y, no-context)
1157 Operator::Properties properties = Operator::kNoThrow; 1490 Operator::Properties properties = Operator::kNoThrow;
1158 Callable callable = 1491 Callable callable =
1159 CodeFactory::StringLessThanOrEqual(jsgraph_->isolate()); 1492 CodeFactory::StringLessThanOrEqual(jsgraph_->isolate());
1160 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 1493 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1161 CallDescriptor* desc = Linkage::GetStubCallDescriptor( 1494 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1162 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, 1495 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1163 flags, properties); 1496 flags, properties);
1164 node->InsertInput(jsgraph_->zone(), 0, 1497 node->InsertInput(jsgraph_->zone(), 0,
1165 jsgraph_->HeapConstant(callable.code())); 1498 jsgraph_->HeapConstant(callable.code()));
1166 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); 1499 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1167 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); 1500 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1168 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); 1501 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1169 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); 1502 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1170 } 1503 }
1171 break; 1504 return;
1172 } 1505 }
1173 case IrOpcode::kStringToNumber: { 1506 case IrOpcode::kStringToNumber: {
1174 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); 1507 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1175 if (lower()) { 1508 if (lower()) {
1176 // StringToNumber(x) => Call(StringToNumberStub, x, no-context) 1509 // StringToNumber(x) => Call(StringToNumberStub, x, no-context)
1177 Operator::Properties properties = Operator::kNoThrow; 1510 Operator::Properties properties = Operator::kNoThrow;
1178 Callable callable = CodeFactory::StringToNumber(jsgraph_->isolate()); 1511 Callable callable = CodeFactory::StringToNumber(jsgraph_->isolate());
1179 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 1512 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1180 CallDescriptor* desc = Linkage::GetStubCallDescriptor( 1513 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1181 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0, 1514 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1182 flags, properties); 1515 flags, properties);
1183 node->InsertInput(jsgraph_->zone(), 0, 1516 node->InsertInput(jsgraph_->zone(), 0,
1184 jsgraph_->HeapConstant(callable.code())); 1517 jsgraph_->HeapConstant(callable.code()));
1185 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); 1518 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1186 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); 1519 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1187 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start()); 1520 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
1188 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc)); 1521 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1189 } 1522 }
1190 break; 1523 return;
1191 } 1524 }
1192 case IrOpcode::kAllocate: { 1525 case IrOpcode::kAllocate: {
1193 ProcessInput(node, 0, UseInfo::TruncatingWord32()); 1526 ProcessInput(node, 0, UseInfo::TruncatingWord32());
1194 ProcessRemainingInputs(node, 1); 1527 ProcessRemainingInputs(node, 1);
1195 SetOutput(node, MachineRepresentation::kTagged); 1528 SetOutput(node, MachineRepresentation::kTagged);
1196 break; 1529 return;
1197 } 1530 }
1198 case IrOpcode::kLoadField: { 1531 case IrOpcode::kLoadField: {
1199 FieldAccess access = FieldAccessOf(node->op()); 1532 FieldAccess access = FieldAccessOf(node->op());
1200 ProcessInput(node, 0, UseInfoForBasePointer(access)); 1533 ProcessInput(node, 0, UseInfoForBasePointer(access));
1201 ProcessRemainingInputs(node, 1); 1534 ProcessRemainingInputs(node, 1);
1202 SetOutput(node, access.machine_type.representation()); 1535 SetOutput(node, access.machine_type.representation());
1203 break; 1536 return;
1204 } 1537 }
1205 case IrOpcode::kStoreField: { 1538 case IrOpcode::kStoreField: {
1206 FieldAccess access = FieldAccessOf(node->op()); 1539 FieldAccess access = FieldAccessOf(node->op());
1207 ProcessInput(node, 0, UseInfoForBasePointer(access)); 1540 ProcessInput(node, 0, UseInfoForBasePointer(access));
1208 ProcessInput(node, 1, TruncatingUseInfoFromRepresentation( 1541 ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
1209 access.machine_type.representation())); 1542 access.machine_type.representation()));
1210 ProcessRemainingInputs(node, 2); 1543 ProcessRemainingInputs(node, 2);
1211 SetOutput(node, MachineRepresentation::kNone); 1544 SetOutput(node, MachineRepresentation::kNone);
1212 if (lower()) { 1545 if (lower()) {
1213 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( 1546 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
1214 access.base_is_tagged, access.machine_type.representation(), 1547 access.base_is_tagged, access.machine_type.representation(),
1215 access.offset, access.type, node->InputAt(1)); 1548 access.offset, access.type, node->InputAt(1));
1216 if (write_barrier_kind < access.write_barrier_kind) { 1549 if (write_barrier_kind < access.write_barrier_kind) {
1217 access.write_barrier_kind = write_barrier_kind; 1550 access.write_barrier_kind = write_barrier_kind;
1218 NodeProperties::ChangeOp( 1551 NodeProperties::ChangeOp(
1219 node, jsgraph_->simplified()->StoreField(access)); 1552 node, jsgraph_->simplified()->StoreField(access));
1220 } 1553 }
1221 } 1554 }
1222 break; 1555 return;
1223 } 1556 }
1224 case IrOpcode::kLoadBuffer: { 1557 case IrOpcode::kLoadBuffer: {
1225 BufferAccess access = BufferAccessOf(node->op()); 1558 BufferAccess access = BufferAccessOf(node->op());
1226 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer 1559 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1227 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset 1560 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1228 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length 1561 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
1229 ProcessRemainingInputs(node, 3); 1562 ProcessRemainingInputs(node, 3);
1230 1563
1231 MachineRepresentation output; 1564 MachineRepresentation output;
1232 if (truncation.TruncatesUndefinedToZeroOrNaN()) { 1565 if (truncation.TruncatesUndefinedToZeroOrNaN()) {
(...skipping 12 matching lines...) Expand all
1245 output = MachineRepresentation::kFloat64; 1578 output = MachineRepresentation::kFloat64;
1246 } 1579 }
1247 } 1580 }
1248 } else { 1581 } else {
1249 // If undefined is not truncated away, we need to have the tagged 1582 // If undefined is not truncated away, we need to have the tagged
1250 // representation. 1583 // representation.
1251 output = MachineRepresentation::kTagged; 1584 output = MachineRepresentation::kTagged;
1252 } 1585 }
1253 SetOutput(node, output); 1586 SetOutput(node, output);
1254 if (lower()) lowering->DoLoadBuffer(node, output, changer_); 1587 if (lower()) lowering->DoLoadBuffer(node, output, changer_);
1255 break; 1588 return;
1256 } 1589 }
1257 case IrOpcode::kStoreBuffer: { 1590 case IrOpcode::kStoreBuffer: {
1258 BufferAccess access = BufferAccessOf(node->op()); 1591 BufferAccess access = BufferAccessOf(node->op());
1259 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer 1592 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1260 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset 1593 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1261 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length 1594 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
1262 ProcessInput(node, 3, 1595 ProcessInput(node, 3,
1263 TruncatingUseInfoFromRepresentation( 1596 TruncatingUseInfoFromRepresentation(
1264 access.machine_type().representation())); // value 1597 access.machine_type().representation())); // value
1265 ProcessRemainingInputs(node, 4); 1598 ProcessRemainingInputs(node, 4);
1266 SetOutput(node, MachineRepresentation::kNone); 1599 SetOutput(node, MachineRepresentation::kNone);
1267 if (lower()) lowering->DoStoreBuffer(node); 1600 if (lower()) lowering->DoStoreBuffer(node);
1268 break; 1601 return;
1269 } 1602 }
1270 case IrOpcode::kLoadElement: { 1603 case IrOpcode::kLoadElement: {
1271 ElementAccess access = ElementAccessOf(node->op()); 1604 ElementAccess access = ElementAccessOf(node->op());
1272 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base 1605 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1273 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index 1606 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
1274 ProcessRemainingInputs(node, 2); 1607 ProcessRemainingInputs(node, 2);
1275 SetOutput(node, access.machine_type.representation()); 1608 SetOutput(node, access.machine_type.representation());
1276 break; 1609 return;
1277 } 1610 }
1278 case IrOpcode::kStoreElement: { 1611 case IrOpcode::kStoreElement: {
1279 ElementAccess access = ElementAccessOf(node->op()); 1612 ElementAccess access = ElementAccessOf(node->op());
1280 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base 1613 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1281 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index 1614 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
1282 ProcessInput(node, 2, 1615 ProcessInput(node, 2,
1283 TruncatingUseInfoFromRepresentation( 1616 TruncatingUseInfoFromRepresentation(
1284 access.machine_type.representation())); // value 1617 access.machine_type.representation())); // value
1285 ProcessRemainingInputs(node, 3); 1618 ProcessRemainingInputs(node, 3);
1286 SetOutput(node, MachineRepresentation::kNone); 1619 SetOutput(node, MachineRepresentation::kNone);
1287 if (lower()) { 1620 if (lower()) {
1288 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor( 1621 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
1289 access.base_is_tagged, access.machine_type.representation(), 1622 access.base_is_tagged, access.machine_type.representation(),
1290 access.type, node->InputAt(2)); 1623 access.type, node->InputAt(2));
1291 if (write_barrier_kind < access.write_barrier_kind) { 1624 if (write_barrier_kind < access.write_barrier_kind) {
1292 access.write_barrier_kind = write_barrier_kind; 1625 access.write_barrier_kind = write_barrier_kind;
1293 NodeProperties::ChangeOp( 1626 NodeProperties::ChangeOp(
1294 node, jsgraph_->simplified()->StoreElement(access)); 1627 node, jsgraph_->simplified()->StoreElement(access));
1295 } 1628 }
1296 } 1629 }
1297 break; 1630 return;
1298 } 1631 }
1299 case IrOpcode::kObjectIsCallable: 1632 case IrOpcode::kObjectIsCallable:
1300 case IrOpcode::kObjectIsNumber: 1633 case IrOpcode::kObjectIsNumber:
1301 case IrOpcode::kObjectIsReceiver: 1634 case IrOpcode::kObjectIsReceiver:
1302 case IrOpcode::kObjectIsSmi: 1635 case IrOpcode::kObjectIsSmi:
1303 case IrOpcode::kObjectIsString: 1636 case IrOpcode::kObjectIsString:
1304 case IrOpcode::kObjectIsUndetectable: { 1637 case IrOpcode::kObjectIsUndetectable: {
1305 ProcessInput(node, 0, UseInfo::AnyTagged()); 1638 ProcessInput(node, 0, UseInfo::AnyTagged());
1306 SetOutput(node, MachineRepresentation::kBit); 1639 SetOutput(node, MachineRepresentation::kBit);
1307 break; 1640 return;
1308 } 1641 }
1309 1642
1310 //------------------------------------------------------------------ 1643 //------------------------------------------------------------------
1311 // Machine-level operators. 1644 // Machine-level operators.
1312 //------------------------------------------------------------------ 1645 //------------------------------------------------------------------
1313 case IrOpcode::kLoad: { 1646 case IrOpcode::kLoad: {
1314 // TODO(jarin) Eventually, we should get rid of all machine stores 1647 // TODO(jarin) Eventually, we should get rid of all machine stores
1315 // from the high-level phases, then this becomes UNREACHABLE. 1648 // from the high-level phases, then this becomes UNREACHABLE.
1316 LoadRepresentation rep = LoadRepresentationOf(node->op()); 1649 LoadRepresentation rep = LoadRepresentationOf(node->op());
1317 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer 1650 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1318 ProcessInput(node, 1, UseInfo::PointerInt()); // index 1651 ProcessInput(node, 1, UseInfo::PointerInt()); // index
1319 ProcessRemainingInputs(node, 2); 1652 ProcessRemainingInputs(node, 2);
1320 SetOutput(node, rep.representation()); 1653 return SetOutput(node, rep.representation());
1321 break;
1322 } 1654 }
1323 case IrOpcode::kStore: { 1655 case IrOpcode::kStore: {
1324 // TODO(jarin) Eventually, we should get rid of all machine stores 1656 // TODO(jarin) Eventually, we should get rid of all machine stores
1325 // from the high-level phases, then this becomes UNREACHABLE. 1657 // from the high-level phases, then this becomes UNREACHABLE.
1326 StoreRepresentation rep = StoreRepresentationOf(node->op()); 1658 StoreRepresentation rep = StoreRepresentationOf(node->op());
1327 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer 1659 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1328 ProcessInput(node, 1, UseInfo::PointerInt()); // index 1660 ProcessInput(node, 1, UseInfo::PointerInt()); // index
1329 ProcessInput(node, 2, 1661 ProcessInput(node, 2,
1330 TruncatingUseInfoFromRepresentation(rep.representation())); 1662 TruncatingUseInfoFromRepresentation(rep.representation()));
1331 ProcessRemainingInputs(node, 3); 1663 ProcessRemainingInputs(node, 3);
1332 SetOutput(node, MachineRepresentation::kNone); 1664 return SetOutput(node, MachineRepresentation::kNone);
1333 break;
1334 } 1665 }
1335 case IrOpcode::kWord32Shr: 1666 case IrOpcode::kWord32Shr:
1336 // We output unsigned int32 for shift right because JavaScript. 1667 // We output unsigned int32 for shift right because JavaScript.
1337 return VisitBinop(node, UseInfo::TruncatingWord32(), 1668 return VisitBinop(node, UseInfo::TruncatingWord32(),
1338 MachineRepresentation::kWord32); 1669 MachineRepresentation::kWord32);
1339 case IrOpcode::kWord32And: 1670 case IrOpcode::kWord32And:
1340 case IrOpcode::kWord32Or: 1671 case IrOpcode::kWord32Or:
1341 case IrOpcode::kWord32Xor: 1672 case IrOpcode::kWord32Xor:
1342 case IrOpcode::kWord32Shl: 1673 case IrOpcode::kWord32Shl:
1343 case IrOpcode::kWord32Sar: 1674 case IrOpcode::kWord32Sar:
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1408 case IrOpcode::kChangeUint32ToUint64: 1739 case IrOpcode::kChangeUint32ToUint64:
1409 return VisitUnop(node, UseInfo::TruncatingWord32(), 1740 return VisitUnop(node, UseInfo::TruncatingWord32(),
1410 MachineRepresentation::kWord64); 1741 MachineRepresentation::kWord64);
1411 case IrOpcode::kTruncateFloat64ToFloat32: 1742 case IrOpcode::kTruncateFloat64ToFloat32:
1412 return VisitUnop(node, UseInfo::TruncatingFloat64(), 1743 return VisitUnop(node, UseInfo::TruncatingFloat64(),
1413 MachineRepresentation::kFloat32); 1744 MachineRepresentation::kFloat32);
1414 case IrOpcode::kTruncateFloat64ToWord32: 1745 case IrOpcode::kTruncateFloat64ToWord32:
1415 return VisitUnop(node, UseInfo::TruncatingFloat64(), 1746 return VisitUnop(node, UseInfo::TruncatingFloat64(),
1416 MachineRepresentation::kWord32); 1747 MachineRepresentation::kWord32);
1417 1748
1418 case IrOpcode::kChangeFloat32ToFloat64:
1419 UNREACHABLE();
1420 return VisitUnop(node, UseInfo::TruncatingFloat32(),
1421 MachineRepresentation::kFloat64);
1422 case IrOpcode::kChangeInt32ToFloat64: 1749 case IrOpcode::kChangeInt32ToFloat64:
1423 return VisitUnop(node, UseInfo::TruncatingWord32(), 1750 return VisitUnop(node, UseInfo::TruncatingWord32(),
1424 MachineRepresentation::kFloat64); 1751 MachineRepresentation::kFloat64);
1425 case IrOpcode::kChangeUint32ToFloat64: 1752 case IrOpcode::kChangeUint32ToFloat64:
1426 return VisitUnop(node, UseInfo::TruncatingWord32(), 1753 return VisitUnop(node, UseInfo::TruncatingWord32(),
1427 MachineRepresentation::kFloat64); 1754 MachineRepresentation::kFloat64);
1428 case IrOpcode::kFloat64Add: 1755 case IrOpcode::kFloat64Add:
1429 case IrOpcode::kFloat64Sub: 1756 case IrOpcode::kFloat64Sub:
1430 case IrOpcode::kFloat64Mul: 1757 case IrOpcode::kFloat64Mul:
1431 case IrOpcode::kFloat64Div: 1758 case IrOpcode::kFloat64Div:
(...skipping 19 matching lines...) Expand all
1451 case IrOpcode::kFloat64InsertLowWord32: 1778 case IrOpcode::kFloat64InsertLowWord32:
1452 case IrOpcode::kFloat64InsertHighWord32: 1779 case IrOpcode::kFloat64InsertHighWord32:
1453 return VisitBinop(node, UseInfo::TruncatingFloat64(), 1780 return VisitBinop(node, UseInfo::TruncatingFloat64(),
1454 UseInfo::TruncatingWord32(), 1781 UseInfo::TruncatingWord32(),
1455 MachineRepresentation::kFloat64); 1782 MachineRepresentation::kFloat64);
1456 case IrOpcode::kLoadStackPointer: 1783 case IrOpcode::kLoadStackPointer:
1457 case IrOpcode::kLoadFramePointer: 1784 case IrOpcode::kLoadFramePointer:
1458 case IrOpcode::kLoadParentFramePointer: 1785 case IrOpcode::kLoadParentFramePointer:
1459 return VisitLeaf(node, MachineType::PointerRepresentation()); 1786 return VisitLeaf(node, MachineType::PointerRepresentation());
1460 case IrOpcode::kStateValues: 1787 case IrOpcode::kStateValues:
1461 VisitStateValues(node); 1788 return VisitStateValues(node);
1462 break;
1463 1789
1464 // The following opcodes are not produced before representation 1790 // The following opcodes are not produced before representation
1465 // inference runs, so we do not have any real test coverage. 1791 // inference runs, so we do not have any real test coverage.
1466 // Simply fail here. 1792 // Simply fail here.
1467 case IrOpcode::kChangeFloat64ToInt32: 1793 case IrOpcode::kChangeFloat64ToInt32:
1468 case IrOpcode::kChangeFloat64ToUint32: 1794 case IrOpcode::kChangeFloat64ToUint32:
1469 case IrOpcode::kTruncateInt64ToInt32: 1795 case IrOpcode::kTruncateInt64ToInt32:
1796 case IrOpcode::kChangeFloat32ToFloat64:
1797 case IrOpcode::kCheckedUint32ToInt32:
1798 case IrOpcode::kCheckedFloat64ToInt32:
1799 case IrOpcode::kCheckedTaggedToInt32:
1800 case IrOpcode::kCheckedTaggedToFloat64:
1470 FATAL("Representation inference: unsupported opcodes."); 1801 FATAL("Representation inference: unsupported opcodes.");
1802 break;
1471 1803
1472 default: 1804 default:
1473 VisitInputs(node); 1805 VisitInputs(node);
1474 // Assume the output is tagged. 1806 // Assume the output is tagged.
1475 SetOutput(node, MachineRepresentation::kTagged); 1807 return SetOutput(node, MachineRepresentation::kTagged);
1476 break;
1477 } 1808 }
1809 UNREACHABLE();
1478 } 1810 }
1479 1811
1480 void DeferReplacement(Node* node, Node* replacement) { 1812 void DeferReplacement(Node* node, Node* replacement) {
1481 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(), 1813 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(),
1482 node->op()->mnemonic(), replacement->id(), 1814 node->op()->mnemonic(), replacement->id(),
1483 replacement->op()->mnemonic()); 1815 replacement->op()->mnemonic());
1484 1816
1485 if (replacement->id() < count_ && 1817 if (replacement->id() < count_ &&
1486 GetUpperBound(node)->Is(GetUpperBound(replacement))) { 1818 GetUpperBound(node)->Is(GetUpperBound(replacement)) &&
1819 TypeOf(node)->Is(TypeOf(replacement))) {
1487 // Replace with a previously existing node eagerly only if the type is the 1820 // Replace with a previously existing node eagerly only if the type is the
1488 // same. 1821 // same.
1489 node->ReplaceUses(replacement); 1822 node->ReplaceUses(replacement);
1490 } else { 1823 } else {
1491 // Otherwise, we are replacing a node with a representation change. 1824 // Otherwise, we are replacing a node with a representation change.
1492 // Such a substitution must be done after all lowering is done, because 1825 // Such a substitution must be done after all lowering is done, because
1493 // changing the type could confuse the representation change 1826 // changing the type could confuse the representation change
1494 // insertion for uses of the node. 1827 // insertion for uses of the node.
1495 replacements_.push_back(node); 1828 replacements_.push_back(node);
1496 replacements_.push_back(replacement); 1829 replacements_.push_back(replacement);
(...skipping 11 matching lines...) Expand all
1508 void PrintRepresentation(MachineRepresentation rep) { 1841 void PrintRepresentation(MachineRepresentation rep) {
1509 if (FLAG_trace_representation) { 1842 if (FLAG_trace_representation) {
1510 OFStream os(stdout); 1843 OFStream os(stdout);
1511 os << rep; 1844 os << rep;
1512 } 1845 }
1513 } 1846 }
1514 1847
1515 void PrintTruncation(Truncation truncation) { 1848 void PrintTruncation(Truncation truncation) {
1516 if (FLAG_trace_representation) { 1849 if (FLAG_trace_representation) {
1517 OFStream os(stdout); 1850 OFStream os(stdout);
1518 os << truncation.description(); 1851 os << truncation.description() << std::endl;
1519 } 1852 }
1520 } 1853 }
1521 1854
1522 void PrintUseInfo(UseInfo info) { 1855 void PrintUseInfo(UseInfo info) {
1523 if (FLAG_trace_representation) { 1856 if (FLAG_trace_representation) {
1524 OFStream os(stdout); 1857 OFStream os(stdout);
1525 os << info.preferred() << ":" << info.truncation().description(); 1858 os << info.representation() << ":" << info.truncation().description();
1526 } 1859 }
1527 } 1860 }
1528 1861
1529 private: 1862 private:
1530 JSGraph* jsgraph_; 1863 JSGraph* jsgraph_;
1864 Zone* zone_; // Temporary zone.
1531 size_t const count_; // number of nodes in the graph 1865 size_t const count_; // number of nodes in the graph
1532 ZoneVector<NodeInfo> info_; // node id -> usage information 1866 ZoneVector<NodeInfo> info_; // node id -> usage information
1533 #ifdef DEBUG 1867 #ifdef DEBUG
1534 ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about 1868 ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about
1535 // requirements on inputs. 1869 // requirements on inputs.
1536 #endif // DEBUG 1870 #endif // DEBUG
1537 NodeVector nodes_; // collected nodes 1871 NodeVector nodes_; // collected nodes
1538 NodeVector replacements_; // replacements to be done after lowering 1872 NodeVector replacements_; // replacements to be done after lowering
1539 Phase phase_; // current phase of algorithm 1873 Phase phase_; // current phase of algorithm
1540 RepresentationChanger* changer_; // for inserting representation changes 1874 RepresentationChanger* changer_; // for inserting representation changes
1541 ZoneQueue<Node*> queue_; // queue for traversing the graph 1875 ZoneQueue<Node*> queue_; // queue for traversing the graph
1876
1877 struct NodeState {
1878 Node* node;
1879 int input_index;
1880 };
1881 ZoneStack<NodeState> typing_stack_; // stack for graph typing.
1542 // TODO(danno): RepresentationSelector shouldn't know anything about the 1882 // TODO(danno): RepresentationSelector shouldn't know anything about the
1543 // source positions table, but must for now since there currently is no other 1883 // source positions table, but must for now since there currently is no other
1544 // way to pass down source position information to nodes created during 1884 // way to pass down source position information to nodes created during
1545 // lowering. Once this phase becomes a vanilla reducer, it should get source 1885 // lowering. Once this phase becomes a vanilla reducer, it should get source
1546 // position information via the SourcePositionWrapper like all other reducers. 1886 // position information via the SourcePositionWrapper like all other reducers.
1547 SourcePositionTable* source_positions_; 1887 SourcePositionTable* source_positions_;
1548 TypeCache const& type_cache_; 1888 TypeCache const& type_cache_;
1889 OperationTyper op_typer_; // helper for the feedback typer
1549 1890
1550 NodeInfo* GetInfo(Node* node) { 1891 NodeInfo* GetInfo(Node* node) {
1551 DCHECK(node->id() >= 0); 1892 DCHECK(node->id() >= 0);
1552 DCHECK(node->id() < count_); 1893 DCHECK(node->id() < count_);
1553 return &info_[node->id()]; 1894 return &info_[node->id()];
1554 } 1895 }
1896 Zone* zone() { return zone_; }
1897 Zone* graph_zone() { return jsgraph_->zone(); }
1555 }; 1898 };
1556 1899
1557
1558 SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone, 1900 SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
1559 SourcePositionTable* source_positions) 1901 SourcePositionTable* source_positions,
1902 Flags flags)
1560 : jsgraph_(jsgraph), 1903 : jsgraph_(jsgraph),
1561 zone_(zone), 1904 zone_(zone),
1562 type_cache_(TypeCache::Get()), 1905 type_cache_(TypeCache::Get()),
1906 flags_(flags),
1563 source_positions_(source_positions) {} 1907 source_positions_(source_positions) {}
1564 1908
1565
1566 void SimplifiedLowering::LowerAllNodes() { 1909 void SimplifiedLowering::LowerAllNodes() {
1567 RepresentationChanger changer(jsgraph(), jsgraph()->isolate()); 1910 RepresentationChanger changer(jsgraph(), jsgraph()->isolate());
1568 RepresentationSelector selector(jsgraph(), zone_, &changer, 1911 RepresentationSelector selector(jsgraph(), zone_, &changer,
1569 source_positions_); 1912 source_positions_);
1570 selector.Run(this); 1913 selector.Run(this);
1571 } 1914 }
1572 1915
1573 void SimplifiedLowering::DoJSToNumberTruncatesToFloat64( 1916 void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
1574 Node* node, RepresentationSelector* selector) { 1917 Node* node, RepresentationSelector* selector) {
1575 DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode()); 1918 DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
1751 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length); 2094 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length);
1752 Node* branch = 2095 Node* branch =
1753 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); 2096 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1754 2097
1755 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 2098 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1756 Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index, 2099 Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
1757 effect, if_true); 2100 effect, if_true);
1758 Type* element_type = 2101 Type* element_type =
1759 Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone()); 2102 Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone());
1760 Node* vtrue = changer->GetRepresentationFor( 2103 Node* vtrue = changer->GetRepresentationFor(
1761 etrue, access_type.representation(), element_type, output_rep, 2104 etrue, access_type.representation(), element_type, node,
1762 Truncation::None()); 2105 UseInfo(output_rep, Truncation::None()));
1763 2106
1764 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); 2107 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1765 Node* efalse = effect; 2108 Node* efalse = effect;
1766 Node* vfalse; 2109 Node* vfalse;
1767 if (output_rep == MachineRepresentation::kTagged) { 2110 if (output_rep == MachineRepresentation::kTagged) {
1768 vfalse = jsgraph()->UndefinedConstant(); 2111 vfalse = jsgraph()->UndefinedConstant();
1769 } else if (output_rep == MachineRepresentation::kFloat64) { 2112 } else if (output_rep == MachineRepresentation::kFloat64) {
1770 vfalse = 2113 vfalse =
1771 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN()); 2114 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
1772 } else if (output_rep == MachineRepresentation::kFloat32) { 2115 } else if (output_rep == MachineRepresentation::kFloat32) {
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after
2466 isolate(), graph()->zone(), callable.descriptor(), 0, flags, 2809 isolate(), graph()->zone(), callable.descriptor(), 0, flags,
2467 Operator::kNoProperties); 2810 Operator::kNoProperties);
2468 to_number_operator_.set(common()->Call(desc)); 2811 to_number_operator_.set(common()->Call(desc));
2469 } 2812 }
2470 return to_number_operator_.get(); 2813 return to_number_operator_.get();
2471 } 2814 }
2472 2815
2473 } // namespace compiler 2816 } // namespace compiler
2474 } // namespace internal 2817 } // namespace internal
2475 } // namespace v8 2818 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698