OLD | NEW |
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" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information | 44 // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information |
45 // backwards from uses to definitions, around cycles in phis, according | 45 // backwards from uses to definitions, around cycles in phis, according |
46 // to local rules for each operator. | 46 // to local rules for each operator. |
47 // During this phase, the usage information for a node determines the best | 47 // During this phase, the usage information for a node determines the best |
48 // possible lowering for each operator so far, and that in turn determines | 48 // possible lowering for each operator so far, and that in turn determines |
49 // the output representation. | 49 // the output representation. |
50 // Therefore, to be correct, this phase must iterate to a fixpoint before | 50 // Therefore, to be correct, this phase must iterate to a fixpoint before |
51 // the next phase can begin. | 51 // the next phase can begin. |
52 PROPAGATE, | 52 PROPAGATE, |
53 | 53 |
54 // 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some | 54 // 2.) RETYPE: Propagate types from type feedback forwards. |
| 55 RETYPE, |
| 56 |
| 57 // 3.) LOWER: perform lowering for all {Simplified} nodes by replacing some |
55 // operators for some nodes, expanding some nodes to multiple nodes, or | 58 // operators for some nodes, expanding some nodes to multiple nodes, or |
56 // removing some (redundant) nodes. | 59 // removing some (redundant) nodes. |
57 // During this phase, use the {RepresentationChanger} to insert | 60 // During this phase, use the {RepresentationChanger} to insert |
58 // representation changes between uses that demand a particular | 61 // representation changes between uses that demand a particular |
59 // representation and nodes that produce a different representation. | 62 // representation and nodes that produce a different representation. |
60 LOWER | 63 LOWER |
61 }; | 64 }; |
62 | 65 |
63 | |
64 namespace { | 66 namespace { |
65 | 67 |
66 | 68 |
67 UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { | 69 UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { |
68 switch (rep) { | 70 switch (rep) { |
69 case MachineRepresentation::kTagged: | 71 case MachineRepresentation::kTagged: |
70 return UseInfo::AnyTagged(); | 72 return UseInfo::AnyTagged(); |
71 case MachineRepresentation::kFloat64: | 73 case MachineRepresentation::kFloat64: |
72 return UseInfo::TruncatingFloat64(); | 74 return UseInfo::TruncatingFloat64(); |
73 case MachineRepresentation::kFloat32: | 75 case MachineRepresentation::kFloat32: |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 changer_(changer), | 241 changer_(changer), |
240 queue_(zone), | 242 queue_(zone), |
241 typing_stack_(zone), | 243 typing_stack_(zone), |
242 source_positions_(source_positions), | 244 source_positions_(source_positions), |
243 type_cache_(TypeCache::Get()), | 245 type_cache_(TypeCache::Get()), |
244 op_typer_(jsgraph->isolate(), graph_zone()) { | 246 op_typer_(jsgraph->isolate(), graph_zone()) { |
245 } | 247 } |
246 | 248 |
247 // Forward propagation of types from type feedback. | 249 // Forward propagation of types from type feedback. |
248 void RunTypePropagationPhase() { | 250 void RunTypePropagationPhase() { |
| 251 // Run type propagation. |
| 252 TRACE("--{Type propagation phase}--\n"); |
| 253 phase_ = RETYPE; |
| 254 ResetNodeInfoState(); |
| 255 |
249 DCHECK(typing_stack_.empty()); | 256 DCHECK(typing_stack_.empty()); |
250 | |
251 typing_stack_.push({graph()->end(), 0}); | 257 typing_stack_.push({graph()->end(), 0}); |
252 GetInfo(graph()->end())->set_pushed(); | 258 GetInfo(graph()->end())->set_pushed(); |
253 while (!typing_stack_.empty()) { | 259 while (!typing_stack_.empty()) { |
254 NodeState& current = typing_stack_.top(); | 260 NodeState& current = typing_stack_.top(); |
255 | 261 |
256 // If there is an unvisited input, push it and continue. | 262 // If there is an unvisited input, push it and continue. |
257 bool pushed_unvisited = false; | 263 bool pushed_unvisited = false; |
258 while (current.input_index < current.node->InputCount()) { | 264 while (current.input_index < current.node->InputCount()) { |
259 Node* input = current.node->InputAt(current.input_index); | 265 Node* input = current.node->InputAt(current.input_index); |
260 NodeInfo* input_info = GetInfo(input); | 266 NodeInfo* input_info = GetInfo(input); |
261 current.input_index++; | 267 current.input_index++; |
262 if (input_info->unvisited()) { | 268 if (input_info->unvisited()) { |
263 input_info->set_pushed(); | 269 input_info->set_pushed(); |
264 typing_stack_.push({input, 0}); | 270 typing_stack_.push({input, 0}); |
265 pushed_unvisited = true; | 271 pushed_unvisited = true; |
266 break; | 272 break; |
267 } | 273 } |
268 } | 274 } |
269 if (pushed_unvisited) continue; | 275 if (pushed_unvisited) continue; |
270 | 276 |
271 // Process the top of the stack. | 277 // Process the top of the stack. |
272 Node* node = current.node; | 278 Node* node = current.node; |
273 typing_stack_.pop(); | 279 typing_stack_.pop(); |
274 NodeInfo* info = GetInfo(node); | 280 NodeInfo* info = GetInfo(node); |
275 info->set_visited(); | 281 info->set_visited(); |
276 bool updated = UpdateFeedbackType(node); | 282 bool updated = UpdateFeedbackType(node); |
| 283 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
| 284 VisitNode(node, info->truncation(), nullptr); |
277 if (updated) { | 285 if (updated) { |
278 for (Node* const user : node->uses()) { | 286 for (Node* const user : node->uses()) { |
279 if (GetInfo(user)->visited()) { | 287 if (GetInfo(user)->visited()) { |
280 GetInfo(user)->set_queued(); | 288 GetInfo(user)->set_queued(); |
281 queue_.push(user); | 289 queue_.push(user); |
282 } | 290 } |
283 } | 291 } |
284 } | 292 } |
285 } | 293 } |
286 | 294 |
287 // Process the revisit queue. | 295 // Process the revisit queue. |
288 while (!queue_.empty()) { | 296 while (!queue_.empty()) { |
289 Node* node = queue_.front(); | 297 Node* node = queue_.front(); |
290 queue_.pop(); | 298 queue_.pop(); |
291 NodeInfo* info = GetInfo(node); | 299 NodeInfo* info = GetInfo(node); |
292 info->set_visited(); | 300 info->set_visited(); |
293 bool updated = UpdateFeedbackType(node); | 301 bool updated = UpdateFeedbackType(node); |
| 302 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
| 303 VisitNode(node, info->truncation(), nullptr); |
294 if (updated) { | 304 if (updated) { |
295 for (Node* const user : node->uses()) { | 305 for (Node* const user : node->uses()) { |
296 if (GetInfo(user)->visited()) { | 306 if (GetInfo(user)->visited()) { |
297 GetInfo(user)->set_queued(); | 307 GetInfo(user)->set_queued(); |
298 queue_.push(user); | 308 queue_.push(user); |
299 } | 309 } |
300 } | 310 } |
301 } | 311 } |
302 } | 312 } |
303 } | 313 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 } | 379 } |
370 | 380 |
371 switch (node->opcode()) { | 381 switch (node->opcode()) { |
372 case IrOpcode::kSpeculativeNumberAdd: { | 382 case IrOpcode::kSpeculativeNumberAdd: { |
373 // TODO(jarin) The ToNumber conversion is too conservative here, | 383 // TODO(jarin) The ToNumber conversion is too conservative here, |
374 // e.g. it will treat true as 1 even though the number check will | 384 // e.g. it will treat true as 1 even though the number check will |
375 // fail on a boolean. OperationTyper should have a function that | 385 // fail on a boolean. OperationTyper should have a function that |
376 // computes a more precise type. | 386 // computes a more precise type. |
377 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 387 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
378 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 388 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
379 Type* static_type = op_typer_.NumericAdd(lhs, rhs); | 389 Type* static_type = op_typer_.NumberAdd(lhs, rhs); |
380 if (info->type_check() == TypeCheckKind::kNone) { | 390 if (info->type_check() == TypeCheckKind::kNone) { |
381 new_type = static_type; | 391 new_type = static_type; |
382 } else { | 392 } else { |
383 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | 393 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
384 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | 394 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
385 } | 395 } |
386 break; | 396 break; |
387 } | 397 } |
388 | 398 |
389 case IrOpcode::kSpeculativeNumberSubtract: { | 399 case IrOpcode::kSpeculativeNumberSubtract: { |
390 // TODO(jarin) The ToNumber conversion is too conservative here, | 400 // TODO(jarin) The ToNumber conversion is too conservative here, |
391 // e.g. it will treat true as 1 even though the number check will | 401 // e.g. it will treat true as 1 even though the number check will |
392 // fail on a boolean. OperationTyper should have a function that | 402 // fail on a boolean. OperationTyper should have a function that |
393 // computes a more precise type. | 403 // computes a more precise type. |
394 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 404 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
395 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 405 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
396 Type* static_type = op_typer_.NumericSubtract(lhs, rhs); | 406 Type* static_type = op_typer_.NumberSubtract(lhs, rhs); |
397 if (info->type_check() == TypeCheckKind::kNone) { | 407 if (info->type_check() == TypeCheckKind::kNone) { |
398 new_type = static_type; | 408 new_type = static_type; |
399 } else { | 409 } else { |
400 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | 410 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
401 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | 411 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
402 } | 412 } |
403 break; | 413 break; |
404 } | 414 } |
405 | 415 |
406 case IrOpcode::kSpeculativeNumberMultiply: { | 416 case IrOpcode::kSpeculativeNumberMultiply: { |
407 // TODO(jarin) The ToNumber conversion is too conservative here, | 417 // TODO(jarin) The ToNumber conversion is too conservative here, |
408 // e.g. it will treat true as 1 even though the number check will | 418 // e.g. it will treat true as 1 even though the number check will |
409 // fail on a boolean. OperationTyper should have a function that | 419 // fail on a boolean. OperationTyper should have a function that |
410 // computes a more precise type. | 420 // computes a more precise type. |
411 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 421 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
412 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 422 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
413 Type* static_type = op_typer_.NumericMultiply(lhs, rhs); | 423 Type* static_type = op_typer_.NumberMultiply(lhs, rhs); |
414 if (info->type_check() == TypeCheckKind::kNone) { | 424 if (info->type_check() == TypeCheckKind::kNone) { |
415 new_type = static_type; | 425 new_type = static_type; |
416 } else { | 426 } else { |
417 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | 427 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
418 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | 428 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
419 } | 429 } |
420 break; | 430 break; |
421 } | 431 } |
422 | 432 |
423 case IrOpcode::kSpeculativeNumberDivide: { | 433 case IrOpcode::kSpeculativeNumberDivide: { |
424 // TODO(jarin) The ToNumber conversion is too conservative here, | 434 // TODO(jarin) The ToNumber conversion is too conservative here, |
425 // e.g. it will treat true as 1 even though the number check will | 435 // e.g. it will treat true as 1 even though the number check will |
426 // fail on a boolean. OperationTyper should have a function that | 436 // fail on a boolean. OperationTyper should have a function that |
427 // computes a more precise type. | 437 // computes a more precise type. |
428 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 438 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
429 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 439 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
430 Type* static_type = op_typer_.NumericDivide(lhs, rhs); | 440 Type* static_type = op_typer_.NumberDivide(lhs, rhs); |
431 if (info->type_check() == TypeCheckKind::kNone) { | 441 if (info->type_check() == TypeCheckKind::kNone) { |
432 new_type = static_type; | 442 new_type = static_type; |
433 } else { | 443 } else { |
434 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | 444 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
435 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | 445 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
436 } | 446 } |
437 break; | 447 break; |
438 } | 448 } |
439 | 449 |
440 case IrOpcode::kSpeculativeNumberModulus: { | 450 case IrOpcode::kSpeculativeNumberModulus: { |
441 // TODO(jarin) The ToNumber conversion is too conservative here, | 451 // TODO(jarin) The ToNumber conversion is too conservative here, |
442 // e.g. it will treat true as 1 even though the number check will | 452 // e.g. it will treat true as 1 even though the number check will |
443 // fail on a boolean. OperationTyper should have a function that | 453 // fail on a boolean. OperationTyper should have a function that |
444 // computes a more precise type. | 454 // computes a more precise type. |
445 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); | 455 Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); |
446 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); | 456 Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1))); |
447 Type* static_type = op_typer_.NumericModulus(lhs, rhs); | 457 Type* static_type = op_typer_.NumberModulus(lhs, rhs); |
448 if (info->type_check() == TypeCheckKind::kNone) { | 458 if (info->type_check() == TypeCheckKind::kNone) { |
449 new_type = static_type; | 459 new_type = static_type; |
450 } else { | 460 } else { |
451 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); | 461 Type* feedback_type = TypeOfSpeculativeOp(info->type_check()); |
452 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); | 462 new_type = Type::Intersect(static_type, feedback_type, graph_zone()); |
453 } | 463 } |
454 break; | 464 break; |
455 } | 465 } |
456 | 466 |
| 467 case IrOpcode::kNumberAbs: { |
| 468 new_type = op_typer_.NumberAbs(FeedbackTypeOf(node->InputAt(0))); |
| 469 break; |
| 470 } |
| 471 |
457 case IrOpcode::kPhi: { | 472 case IrOpcode::kPhi: { |
458 new_type = TypePhi(node); | 473 new_type = TypePhi(node); |
459 if (type != nullptr) { | 474 if (type != nullptr) { |
460 new_type = Weaken(node, type, new_type); | 475 new_type = Weaken(node, type, new_type); |
461 } | 476 } |
462 // Recompute the phi representation based on the new type. | |
463 MachineRepresentation output = | |
464 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type); | |
465 ResetOutput(node, output); | |
466 break; | 477 break; |
467 } | 478 } |
468 | 479 |
469 case IrOpcode::kSelect: { | 480 case IrOpcode::kSelect: { |
470 new_type = TypeSelect(node); | 481 new_type = TypeSelect(node); |
471 // Recompute representation based on the new type. | |
472 MachineRepresentation output = | |
473 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type); | |
474 ResetOutput(node, output); | |
475 break; | 482 break; |
476 } | 483 } |
477 | 484 |
478 default: | 485 default: |
479 // Shortcut for operations that we do not handle. | 486 // Shortcut for operations that we do not handle. |
480 if (type == nullptr) { | 487 if (type == nullptr) { |
481 GetInfo(node)->set_feedback_type(NodeProperties::GetType(node)); | 488 GetInfo(node)->set_feedback_type(NodeProperties::GetType(node)); |
482 return true; | 489 return true; |
483 } | 490 } |
484 return false; | 491 return false; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 VisitNode(node, info->truncation(), nullptr); | 569 VisitNode(node, info->truncation(), nullptr); |
563 TRACE(" ==> output "); | 570 TRACE(" ==> output "); |
564 PrintOutputInfo(info); | 571 PrintOutputInfo(info); |
565 TRACE("\n"); | 572 TRACE("\n"); |
566 } | 573 } |
567 } | 574 } |
568 | 575 |
569 void Run(SimplifiedLowering* lowering) { | 576 void Run(SimplifiedLowering* lowering) { |
570 RunTruncationPropagationPhase(); | 577 RunTruncationPropagationPhase(); |
571 | 578 |
572 // Run type propagation. | |
573 ResetNodeInfoState(); | |
574 RunTypePropagationPhase(); | 579 RunTypePropagationPhase(); |
575 | 580 |
576 // Run lowering and change insertion phase. | 581 // Run lowering and change insertion phase. |
577 TRACE("--{Simplified lowering phase}--\n"); | 582 TRACE("--{Simplified lowering phase}--\n"); |
578 phase_ = LOWER; | 583 phase_ = LOWER; |
579 // Process nodes from the collected {nodes_} vector. | 584 // Process nodes from the collected {nodes_} vector. |
580 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { | 585 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) { |
581 Node* node = *i; | 586 Node* node = *i; |
582 NodeInfo* info = GetInfo(node); | 587 NodeInfo* info = GetInfo(node); |
583 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); | 588 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic()); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 queue_.push(node); | 645 queue_.push(node); |
641 info->set_queued(); | 646 info->set_queued(); |
642 TRACE(" added: "); | 647 TRACE(" added: "); |
643 } else { | 648 } else { |
644 TRACE(" inqueue: "); | 649 TRACE(" inqueue: "); |
645 } | 650 } |
646 PrintTruncation(info->truncation()); | 651 PrintTruncation(info->truncation()); |
647 } | 652 } |
648 } | 653 } |
649 | 654 |
650 bool lower() { return phase_ == LOWER; } | 655 bool lower() const { return phase_ == LOWER; } |
651 bool propagate() { return phase_ == PROPAGATE; } | 656 bool retype() const { return phase_ == RETYPE; } |
| 657 bool propagate() const { return phase_ == PROPAGATE; } |
652 | 658 |
653 void SetOutput(Node* node, MachineRepresentation representation, | 659 void SetOutput(Node* node, MachineRepresentation representation, |
654 TypeCheckKind type_check = TypeCheckKind::kNone) { | 660 TypeCheckKind type_check = TypeCheckKind::kNone) { |
655 DCHECK(MachineRepresentationIsSubtype(GetInfo(node)->representation(), | 661 NodeInfo* const info = GetInfo(node); |
656 representation)); | 662 switch (phase_) { |
657 ResetOutput(node, representation, type_check); | 663 case PROPAGATE: |
| 664 info->set_type_check(type_check); |
| 665 break; |
| 666 case RETYPE: |
| 667 DCHECK_EQ(info->type_check(), type_check); |
| 668 info->set_output(representation); |
| 669 break; |
| 670 case LOWER: |
| 671 DCHECK_EQ(info->type_check(), type_check); |
| 672 DCHECK_EQ(info->representation(), representation); |
| 673 break; |
| 674 } |
658 } | 675 } |
659 | 676 |
660 void ResetOutput(Node* node, MachineRepresentation representation, | 677 void ResetOutput(Node* node, MachineRepresentation representation, |
661 TypeCheckKind type_check = TypeCheckKind::kNone) { | 678 TypeCheckKind type_check = TypeCheckKind::kNone) { |
662 NodeInfo* info = GetInfo(node); | 679 NodeInfo* info = GetInfo(node); |
663 info->set_output(representation); | 680 info->set_output(representation); |
664 info->set_type_check(type_check); | 681 info->set_type_check(type_check); |
665 } | 682 } |
666 | 683 |
667 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } | 684 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 TRACE(" to "); | 725 TRACE(" to "); |
709 PrintUseInfo(use); | 726 PrintUseInfo(use); |
710 TRACE("\n"); | 727 TRACE("\n"); |
711 Node* n = changer_->GetRepresentationFor( | 728 Node* n = changer_->GetRepresentationFor( |
712 input, input_info->representation(), TypeOf(input), node, use); | 729 input, input_info->representation(), TypeOf(input), node, use); |
713 node->ReplaceInput(index, n); | 730 node->ReplaceInput(index, n); |
714 } | 731 } |
715 } | 732 } |
716 | 733 |
717 void ProcessInput(Node* node, int index, UseInfo use) { | 734 void ProcessInput(Node* node, int index, UseInfo use) { |
718 if (phase_ == PROPAGATE) { | 735 switch (phase_) { |
719 EnqueueInput(node, index, use); | 736 case PROPAGATE: |
720 } else { | 737 EnqueueInput(node, index, use); |
721 ConvertInput(node, index, use); | 738 break; |
| 739 case RETYPE: |
| 740 break; |
| 741 case LOWER: |
| 742 ConvertInput(node, index, use); |
| 743 break; |
722 } | 744 } |
723 } | 745 } |
724 | 746 |
725 void ProcessRemainingInputs(Node* node, int index) { | 747 void ProcessRemainingInputs(Node* node, int index) { |
726 DCHECK_GE(index, NodeProperties::PastValueIndex(node)); | 748 DCHECK_GE(index, NodeProperties::PastValueIndex(node)); |
727 DCHECK_GE(index, NodeProperties::PastContextIndex(node)); | 749 DCHECK_GE(index, NodeProperties::PastContextIndex(node)); |
728 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); | 750 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node)); |
729 i < NodeProperties::PastEffectIndex(node); ++i) { | 751 i < NodeProperties::PastEffectIndex(node); ++i) { |
730 EnqueueInput(node, i); // Effect inputs: just visit | 752 EnqueueInput(node, i); // Effect inputs: just visit |
731 } | 753 } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); | 842 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); |
821 } | 843 } |
822 void VisitInt64Cmp(Node* node) { | 844 void VisitInt64Cmp(Node* node) { |
823 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); | 845 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); |
824 } | 846 } |
825 void VisitUint64Cmp(Node* node) { | 847 void VisitUint64Cmp(Node* node) { |
826 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); | 848 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit); |
827 } | 849 } |
828 | 850 |
829 // Infer representation for phi-like nodes. | 851 // Infer representation for phi-like nodes. |
830 MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use, | 852 MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use) { |
831 Type* type = nullptr) { | |
832 // Compute the representation. | 853 // Compute the representation. |
833 if (type == nullptr) { | 854 Type* type = TypeOf(node); |
834 type = TypeOf(node); | |
835 } | |
836 if (type->Is(Type::None())) { | 855 if (type->Is(Type::None())) { |
837 return MachineRepresentation::kNone; | 856 return MachineRepresentation::kNone; |
838 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) { | 857 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) { |
839 return MachineRepresentation::kWord32; | 858 return MachineRepresentation::kWord32; |
840 } else if (use.TruncatesToWord32()) { | 859 } else if (use.TruncatesToWord32()) { |
841 return MachineRepresentation::kWord32; | 860 return MachineRepresentation::kWord32; |
842 } else if (type->Is(Type::Boolean())) { | 861 } else if (type->Is(Type::Boolean())) { |
843 return MachineRepresentation::kBit; | 862 return MachineRepresentation::kBit; |
844 } else if (type->Is(Type::Number())) { | 863 } else if (type->Is(Type::Number())) { |
845 return MachineRepresentation::kFloat64; | 864 return MachineRepresentation::kFloat64; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
942 if (type->Is(Type::Signed32())) { | 961 if (type->Is(Type::Signed32())) { |
943 return MachineSemantic::kInt32; | 962 return MachineSemantic::kInt32; |
944 } else if (type->Is(Type::Unsigned32())) { | 963 } else if (type->Is(Type::Unsigned32())) { |
945 return MachineSemantic::kUint32; | 964 return MachineSemantic::kUint32; |
946 } else { | 965 } else { |
947 return MachineSemantic::kAny; | 966 return MachineSemantic::kAny; |
948 } | 967 } |
949 } | 968 } |
950 | 969 |
951 void VisitStateValues(Node* node) { | 970 void VisitStateValues(Node* node) { |
952 if (phase_ == PROPAGATE) { | 971 if (propagate()) { |
953 for (int i = 0; i < node->InputCount(); i++) { | 972 for (int i = 0; i < node->InputCount(); i++) { |
954 EnqueueInput(node, i, UseInfo::Any()); | 973 EnqueueInput(node, i, UseInfo::Any()); |
955 } | 974 } |
956 } else { | 975 } else if (lower()) { |
957 Zone* zone = jsgraph_->zone(); | 976 Zone* zone = jsgraph_->zone(); |
958 ZoneVector<MachineType>* types = | 977 ZoneVector<MachineType>* types = |
959 new (zone->New(sizeof(ZoneVector<MachineType>))) | 978 new (zone->New(sizeof(ZoneVector<MachineType>))) |
960 ZoneVector<MachineType>(node->InputCount(), zone); | 979 ZoneVector<MachineType>(node->InputCount(), zone); |
961 for (int i = 0; i < node->InputCount(); i++) { | 980 for (int i = 0; i < node->InputCount(); i++) { |
962 Node* input = node->InputAt(i); | 981 Node* input = node->InputAt(i); |
963 NodeInfo* input_info = GetInfo(input); | 982 NodeInfo* input_info = GetInfo(input); |
964 MachineType machine_type(input_info->representation(), | 983 MachineType machine_type(input_info->representation(), |
965 DeoptValueSemanticOf(TypeOf(input))); | 984 DeoptValueSemanticOf(TypeOf(input))); |
966 DCHECK(machine_type.representation() != | 985 DCHECK(machine_type.representation() != |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1589 case IrOpcode::kNumberShiftRightLogical: { | 1608 case IrOpcode::kNumberShiftRightLogical: { |
1590 Type* rhs_type = GetUpperBound(node->InputAt(1)); | 1609 Type* rhs_type = GetUpperBound(node->InputAt(1)); |
1591 VisitBinop(node, UseInfo::TruncatingWord32(), | 1610 VisitBinop(node, UseInfo::TruncatingWord32(), |
1592 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); | 1611 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); |
1593 if (lower()) { | 1612 if (lower()) { |
1594 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); | 1613 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type); |
1595 } | 1614 } |
1596 return; | 1615 return; |
1597 } | 1616 } |
1598 case IrOpcode::kNumberAbs: { | 1617 case IrOpcode::kNumberAbs: { |
1599 if (InputIs(node, Type::Unsigned32())) { | 1618 if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32())) { |
1600 VisitUnop(node, UseInfo::TruncatingWord32(), | 1619 VisitUnop(node, UseInfo::TruncatingWord32(), |
1601 MachineRepresentation::kWord32); | 1620 MachineRepresentation::kWord32); |
1602 if (lower()) DeferReplacement(node, node->InputAt(0)); | 1621 if (lower()) DeferReplacement(node, node->InputAt(0)); |
1603 } else if (InputIs(node, Type::Signed32())) { | 1622 } else if (TypeOf(node->InputAt(0))->Is(Type::Signed32())) { |
1604 VisitUnop(node, UseInfo::TruncatingWord32(), | 1623 VisitUnop(node, UseInfo::TruncatingWord32(), |
1605 MachineRepresentation::kWord32); | 1624 MachineRepresentation::kWord32); |
1606 if (lower()) DeferReplacement(node, lowering->Int32Abs(node)); | 1625 if (lower()) DeferReplacement(node, lowering->Int32Abs(node)); |
1607 } else if (InputIs(node, | 1626 } else if (TypeOf(node->InputAt(0)) |
1608 type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) { | 1627 ->Is(type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) { |
1609 VisitUnop(node, UseInfo::TruncatingFloat64(), | 1628 VisitUnop(node, UseInfo::TruncatingFloat64(), |
1610 MachineRepresentation::kFloat64); | 1629 MachineRepresentation::kFloat64); |
1611 if (lower()) DeferReplacement(node, node->InputAt(0)); | 1630 if (lower()) DeferReplacement(node, node->InputAt(0)); |
1612 } else { | 1631 } else { |
1613 VisitUnop(node, UseInfo::TruncatingFloat64(), | 1632 VisitUnop(node, UseInfo::TruncatingFloat64(), |
1614 MachineRepresentation::kFloat64); | 1633 MachineRepresentation::kFloat64); |
1615 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); | 1634 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); |
1616 } | 1635 } |
1617 return; | 1636 return; |
1618 } | 1637 } |
(...skipping 1667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3286 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3305 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
3287 Operator::kNoProperties); | 3306 Operator::kNoProperties); |
3288 to_number_operator_.set(common()->Call(desc)); | 3307 to_number_operator_.set(common()->Call(desc)); |
3289 } | 3308 } |
3290 return to_number_operator_.get(); | 3309 return to_number_operator_.get(); |
3291 } | 3310 } |
3292 | 3311 |
3293 } // namespace compiler | 3312 } // namespace compiler |
3294 } // namespace internal | 3313 } // namespace internal |
3295 } // namespace v8 | 3314 } // namespace v8 |
OLD | NEW |