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/instruction-selector.h" | 5 #include "src/compiler/instruction-selector.h" |
6 | 6 |
7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
10 #include "src/compiler/pipeline.h" | 10 #include "src/compiler/pipeline.h" |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 // We're done with the block. | 476 // We're done with the block. |
477 InstructionBlock* instruction_block = | 477 InstructionBlock* instruction_block = |
478 sequence()->InstructionBlockAt(block->GetRpoNumber()); | 478 sequence()->InstructionBlockAt(block->GetRpoNumber()); |
479 instruction_block->set_code_start(static_cast<int>(instructions_.size())); | 479 instruction_block->set_code_start(static_cast<int>(instructions_.size())); |
480 instruction_block->set_code_end(current_block_end); | 480 instruction_block->set_code_end(current_block_end); |
481 | 481 |
482 current_block_ = NULL; | 482 current_block_ = NULL; |
483 } | 483 } |
484 | 484 |
485 | 485 |
486 static inline void CheckNoPhis(const BasicBlock* block) { | 486 namespace { |
| 487 |
| 488 V8_INLINE void CheckNoPhis(const BasicBlock* block) { |
487 #ifdef DEBUG | 489 #ifdef DEBUG |
488 // Branch targets should not have phis. | 490 // Branch targets should not have phis. |
489 for (BasicBlock::const_iterator i = block->begin(); i != block->end(); ++i) { | 491 for (BasicBlock::const_iterator i = block->begin(); i != block->end(); ++i) { |
490 const Node* node = *i; | 492 const Node* node = *i; |
491 CHECK_NE(IrOpcode::kPhi, node->opcode()); | 493 CHECK_NE(IrOpcode::kPhi, node->opcode()); |
492 } | 494 } |
493 #endif | 495 #endif |
494 } | 496 } |
495 | 497 |
| 498 } // namespace |
| 499 |
496 | 500 |
497 void InstructionSelector::VisitControl(BasicBlock* block) { | 501 void InstructionSelector::VisitControl(BasicBlock* block) { |
498 Node* input = block->control_input(); | 502 Node* input = block->control_input(); |
499 switch (block->control()) { | 503 switch (block->control()) { |
500 case BasicBlock::kGoto: | 504 case BasicBlock::kGoto: |
501 return VisitGoto(block->SuccessorAt(0)); | 505 return VisitGoto(block->SuccessorAt(0)); |
502 case BasicBlock::kBranch: { | 506 case BasicBlock::kBranch: { |
503 DCHECK_EQ(IrOpcode::kBranch, input->opcode()); | 507 DCHECK_EQ(IrOpcode::kBranch, input->opcode()); |
504 BasicBlock* tbranch = block->SuccessorAt(0); | 508 BasicBlock* tbranch = block->SuccessorAt(0); |
505 BasicBlock* fbranch = block->SuccessorAt(1); | 509 BasicBlock* fbranch = block->SuccessorAt(1); |
506 // SSA deconstruction requires targets of branches not to have phis. | 510 // SSA deconstruction requires targets of branches not to have phis. |
507 // Edge split form guarantees this property, but is more strict. | 511 // Edge split form guarantees this property, but is more strict. |
508 CheckNoPhis(tbranch); | 512 CheckNoPhis(tbranch); |
509 CheckNoPhis(fbranch); | 513 CheckNoPhis(fbranch); |
510 if (tbranch == fbranch) return VisitGoto(tbranch); | 514 if (tbranch == fbranch) return VisitGoto(tbranch); |
511 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue). | 515 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue). |
512 Node* const condition = input->InputAt(0); | 516 Node* const condition = input->InputAt(0); |
513 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); | 517 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); |
514 return VisitBranch(input, tbranch, fbranch); | 518 return VisitBranch(input, tbranch, fbranch); |
515 } | 519 } |
| 520 case BasicBlock::kSwitch: { |
| 521 DCHECK_EQ(IrOpcode::kSwitch, input->opcode()); |
| 522 BasicBlock** const branches = &block->successors().front(); |
| 523 size_t const branch_count = block->SuccessorCount(); |
| 524 DCHECK_LE(2u, branch_count); |
| 525 // SSA deconstruction requires targets of branches not to have phis. |
| 526 // Edge split form guarantees this property, but is more strict. |
| 527 for (size_t index = 0; index < branch_count; ++index) { |
| 528 CheckNoPhis(branches[index]); |
| 529 } |
| 530 return VisitSwitch(input, branches, branch_count); |
| 531 } |
516 case BasicBlock::kReturn: { | 532 case BasicBlock::kReturn: { |
517 // If the result itself is a return, return its input. | 533 // If the result itself is a return, return its input. |
518 Node* value = (input != NULL && input->opcode() == IrOpcode::kReturn) | 534 Node* value = (input != NULL && input->opcode() == IrOpcode::kReturn) |
519 ? input->InputAt(0) | 535 ? input->InputAt(0) |
520 : input; | 536 : input; |
521 return VisitReturn(value); | 537 return VisitReturn(value); |
522 } | 538 } |
523 case BasicBlock::kThrow: | 539 case BasicBlock::kThrow: |
524 DCHECK_EQ(IrOpcode::kThrow, input->opcode()); | 540 DCHECK_EQ(IrOpcode::kThrow, input->opcode()); |
525 return VisitThrow(input->InputAt(0)); | 541 return VisitThrow(input->InputAt(0)); |
526 case BasicBlock::kNone: { | 542 case BasicBlock::kNone: { |
527 // TODO(titzer): exit block doesn't have control. | 543 // TODO(titzer): exit block doesn't have control. |
528 DCHECK(input == NULL); | 544 DCHECK_NULL(input); |
529 break; | 545 break; |
530 } | 546 } |
531 default: | 547 default: |
532 UNREACHABLE(); | 548 UNREACHABLE(); |
533 break; | 549 break; |
534 } | 550 } |
535 } | 551 } |
536 | 552 |
537 | 553 |
538 MachineType InstructionSelector::GetMachineType(Node* node) { | 554 MachineType InstructionSelector::GetMachineType(Node* node) { |
539 DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes. | 555 DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes. |
540 switch (node->opcode()) { | 556 switch (node->opcode()) { |
541 case IrOpcode::kStart: | 557 case IrOpcode::kStart: |
542 case IrOpcode::kLoop: | 558 case IrOpcode::kLoop: |
543 case IrOpcode::kEnd: | 559 case IrOpcode::kEnd: |
544 case IrOpcode::kBranch: | 560 case IrOpcode::kBranch: |
545 case IrOpcode::kIfTrue: | 561 case IrOpcode::kIfTrue: |
546 case IrOpcode::kIfFalse: | 562 case IrOpcode::kIfFalse: |
| 563 case IrOpcode::kSwitch: |
| 564 case IrOpcode::kCase: |
547 case IrOpcode::kEffectPhi: | 565 case IrOpcode::kEffectPhi: |
548 case IrOpcode::kEffectSet: | 566 case IrOpcode::kEffectSet: |
549 case IrOpcode::kMerge: | 567 case IrOpcode::kMerge: |
550 // No code needed for these graph artifacts. | 568 // No code needed for these graph artifacts. |
551 return kMachNone; | 569 return kMachNone; |
552 case IrOpcode::kFinish: | 570 case IrOpcode::kFinish: |
553 return kMachAnyTagged; | 571 return kMachAnyTagged; |
554 case IrOpcode::kParameter: | 572 case IrOpcode::kParameter: |
555 return linkage()->GetParameterType(OpParameter<int>(node)); | 573 return linkage()->GetParameterType(OpParameter<int>(node)); |
556 case IrOpcode::kOsrValue: | 574 case IrOpcode::kOsrValue: |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 Emit(SourcePositionInstruction::New(instruction_zone(), source_position)); | 693 Emit(SourcePositionInstruction::New(instruction_zone(), source_position)); |
676 } | 694 } |
677 } | 695 } |
678 switch (node->opcode()) { | 696 switch (node->opcode()) { |
679 case IrOpcode::kStart: | 697 case IrOpcode::kStart: |
680 case IrOpcode::kLoop: | 698 case IrOpcode::kLoop: |
681 case IrOpcode::kEnd: | 699 case IrOpcode::kEnd: |
682 case IrOpcode::kBranch: | 700 case IrOpcode::kBranch: |
683 case IrOpcode::kIfTrue: | 701 case IrOpcode::kIfTrue: |
684 case IrOpcode::kIfFalse: | 702 case IrOpcode::kIfFalse: |
| 703 case IrOpcode::kSwitch: |
| 704 case IrOpcode::kCase: |
685 case IrOpcode::kEffectPhi: | 705 case IrOpcode::kEffectPhi: |
686 case IrOpcode::kMerge: | 706 case IrOpcode::kMerge: |
687 // No code needed for these graph artifacts. | 707 // No code needed for these graph artifacts. |
688 return; | 708 return; |
689 case IrOpcode::kFinish: | 709 case IrOpcode::kFinish: |
690 return MarkAsReference(node), VisitFinish(node); | 710 return MarkAsReference(node), VisitFinish(node); |
691 case IrOpcode::kParameter: { | 711 case IrOpcode::kParameter: { |
692 MachineType type = linkage()->GetParameterType(OpParameter<int>(node)); | 712 MachineType type = linkage()->GetParameterType(OpParameter<int>(node)); |
693 MarkAsRepresentation(type, node); | 713 MarkAsRepresentation(type, node); |
694 return VisitParameter(node); | 714 return VisitParameter(node); |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1031 } | 1051 } |
1032 | 1052 |
1033 | 1053 |
1034 void InstructionSelector::VisitGoto(BasicBlock* target) { | 1054 void InstructionSelector::VisitGoto(BasicBlock* target) { |
1035 // jump to the next block. | 1055 // jump to the next block. |
1036 OperandGenerator g(this); | 1056 OperandGenerator g(this); |
1037 Emit(kArchJmp, g.NoOutput(), g.Label(target))->MarkAsControl(); | 1057 Emit(kArchJmp, g.NoOutput(), g.Label(target))->MarkAsControl(); |
1038 } | 1058 } |
1039 | 1059 |
1040 | 1060 |
| 1061 void InstructionSelector::VisitSwitch(Node* node, BasicBlock** branches, |
| 1062 size_t branch_count) { |
| 1063 OperandGenerator g(this); |
| 1064 Node* const value = node->InputAt(0); |
| 1065 size_t const input_count = branch_count + 1; |
| 1066 InstructionOperand* const inputs = |
| 1067 zone()->NewArray<InstructionOperand>(static_cast<int>(input_count)); |
| 1068 inputs[0] = g.UseRegister(value); |
| 1069 for (size_t index = 0; index < branch_count; ++index) { |
| 1070 inputs[index + 1] = g.Label(branches[index]); |
| 1071 } |
| 1072 Emit(kArchSwitch, 0, nullptr, input_count, inputs, 0, nullptr) |
| 1073 ->MarkAsControl(); |
| 1074 } |
| 1075 |
| 1076 |
1041 void InstructionSelector::VisitReturn(Node* value) { | 1077 void InstructionSelector::VisitReturn(Node* value) { |
1042 OperandGenerator g(this); | 1078 OperandGenerator g(this); |
1043 if (value != NULL) { | 1079 if (value != NULL) { |
1044 Emit(kArchRet, g.NoOutput(), | 1080 Emit(kArchRet, g.NoOutput(), |
1045 g.UseLocation(value, linkage()->GetReturnLocation(), | 1081 g.UseLocation(value, linkage()->GetReturnLocation(), |
1046 linkage()->GetReturnType())); | 1082 linkage()->GetReturnType())); |
1047 } else { | 1083 } else { |
1048 Emit(kArchRet, g.NoOutput()); | 1084 Emit(kArchRet, g.NoOutput()); |
1049 } | 1085 } |
1050 } | 1086 } |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 MachineOperatorBuilder::Flags | 1212 MachineOperatorBuilder::Flags |
1177 InstructionSelector::SupportedMachineOperatorFlags() { | 1213 InstructionSelector::SupportedMachineOperatorFlags() { |
1178 return MachineOperatorBuilder::Flag::kNoFlags; | 1214 return MachineOperatorBuilder::Flag::kNoFlags; |
1179 } | 1215 } |
1180 | 1216 |
1181 #endif // !V8_TURBOFAN_BACKEND | 1217 #endif // !V8_TURBOFAN_BACKEND |
1182 | 1218 |
1183 } // namespace compiler | 1219 } // namespace compiler |
1184 } // namespace internal | 1220 } // namespace internal |
1185 } // namespace v8 | 1221 } // namespace v8 |
OLD | NEW |