| 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 <limits> |
| 8 |
| 7 #include "src/compiler/instruction-selector-impl.h" | 9 #include "src/compiler/instruction-selector-impl.h" |
| 8 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/node-properties.h" | 11 #include "src/compiler/node-properties.h" |
| 10 #include "src/compiler/pipeline.h" | 12 #include "src/compiler/pipeline.h" |
| 11 | 13 |
| 12 namespace v8 { | 14 namespace v8 { |
| 13 namespace internal { | 15 namespace internal { |
| 14 namespace compiler { | 16 namespace compiler { |
| 15 | 17 |
| 16 InstructionSelector::InstructionSelector(Zone* zone, size_t node_count, | 18 InstructionSelector::InstructionSelector(Zone* zone, size_t node_count, |
| (...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 CheckNoPhis(tbranch); | 514 CheckNoPhis(tbranch); |
| 513 CheckNoPhis(fbranch); | 515 CheckNoPhis(fbranch); |
| 514 if (tbranch == fbranch) return VisitGoto(tbranch); | 516 if (tbranch == fbranch) return VisitGoto(tbranch); |
| 515 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue). | 517 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue). |
| 516 Node* const condition = input->InputAt(0); | 518 Node* const condition = input->InputAt(0); |
| 517 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); | 519 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); |
| 518 return VisitBranch(input, tbranch, fbranch); | 520 return VisitBranch(input, tbranch, fbranch); |
| 519 } | 521 } |
| 520 case BasicBlock::kSwitch: { | 522 case BasicBlock::kSwitch: { |
| 521 DCHECK_EQ(IrOpcode::kSwitch, input->opcode()); | 523 DCHECK_EQ(IrOpcode::kSwitch, input->opcode()); |
| 522 BasicBlock** const branches = &block->successors().front(); | 524 // Last successor must be Default. |
| 523 size_t const branch_count = block->SuccessorCount(); | 525 BasicBlock* default_branch = block->successors().back(); |
| 524 DCHECK_LE(2u, branch_count); | 526 DCHECK_EQ(IrOpcode::kIfDefault, default_branch->front()->opcode()); |
| 525 // SSA deconstruction requires targets of branches not to have phis. | 527 // SSA deconstruction requires targets of branches not to have phis. |
| 526 // Edge split form guarantees this property, but is more strict. | 528 // Edge split form guarantees this property, but is more strict. |
| 527 for (size_t index = 0; index < branch_count; ++index) { | 529 CheckNoPhis(default_branch); |
| 528 CheckNoPhis(branches[index]); | 530 // All other successors must be cases. |
| 531 size_t case_count = block->SuccessorCount() - 1; |
| 532 DCHECK_LE(1u, case_count); |
| 533 BasicBlock** case_branches = &block->successors().front(); |
| 534 // Determine case values and their min/max. |
| 535 int32_t* case_values = zone()->NewArray<int32_t>(case_count); |
| 536 int32_t min_value = std::numeric_limits<int32_t>::max(); |
| 537 int32_t max_value = std::numeric_limits<int32_t>::min(); |
| 538 for (size_t index = 0; index < case_count; ++index) { |
| 539 BasicBlock* branch = case_branches[index]; |
| 540 int32_t value = OpParameter<int32_t>(branch->front()->op()); |
| 541 case_values[index] = value; |
| 542 if (min_value > value) min_value = value; |
| 543 if (max_value < value) max_value = value; |
| 544 // SSA deconstruction requires targets of branches not to have phis. |
| 545 // Edge split form guarantees this property, but is more strict. |
| 546 CheckNoPhis(branch); |
| 529 } | 547 } |
| 530 return VisitSwitch(input, branches, branch_count); | 548 DCHECK_LE(min_value, max_value); |
| 549 return VisitSwitch(input, default_branch, case_branches, case_values, |
| 550 case_count, min_value, max_value); |
| 531 } | 551 } |
| 532 case BasicBlock::kReturn: { | 552 case BasicBlock::kReturn: { |
| 533 // If the result itself is a return, return its input. | 553 // If the result itself is a return, return its input. |
| 534 Node* value = (input != NULL && input->opcode() == IrOpcode::kReturn) | 554 Node* value = (input != NULL && input->opcode() == IrOpcode::kReturn) |
| 535 ? input->InputAt(0) | 555 ? input->InputAt(0) |
| 536 : input; | 556 : input; |
| 537 return VisitReturn(value); | 557 return VisitReturn(value); |
| 538 } | 558 } |
| 539 case BasicBlock::kThrow: | 559 case BasicBlock::kThrow: |
| 540 DCHECK_EQ(IrOpcode::kThrow, input->opcode()); | 560 DCHECK_EQ(IrOpcode::kThrow, input->opcode()); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 554 MachineType InstructionSelector::GetMachineType(Node* node) { | 574 MachineType InstructionSelector::GetMachineType(Node* node) { |
| 555 DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes. | 575 DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes. |
| 556 switch (node->opcode()) { | 576 switch (node->opcode()) { |
| 557 case IrOpcode::kStart: | 577 case IrOpcode::kStart: |
| 558 case IrOpcode::kLoop: | 578 case IrOpcode::kLoop: |
| 559 case IrOpcode::kEnd: | 579 case IrOpcode::kEnd: |
| 560 case IrOpcode::kBranch: | 580 case IrOpcode::kBranch: |
| 561 case IrOpcode::kIfTrue: | 581 case IrOpcode::kIfTrue: |
| 562 case IrOpcode::kIfFalse: | 582 case IrOpcode::kIfFalse: |
| 563 case IrOpcode::kSwitch: | 583 case IrOpcode::kSwitch: |
| 564 case IrOpcode::kCase: | 584 case IrOpcode::kIfValue: |
| 585 case IrOpcode::kIfDefault: |
| 565 case IrOpcode::kEffectPhi: | 586 case IrOpcode::kEffectPhi: |
| 566 case IrOpcode::kEffectSet: | 587 case IrOpcode::kEffectSet: |
| 567 case IrOpcode::kMerge: | 588 case IrOpcode::kMerge: |
| 568 // No code needed for these graph artifacts. | 589 // No code needed for these graph artifacts. |
| 569 return kMachNone; | 590 return kMachNone; |
| 570 case IrOpcode::kFinish: | 591 case IrOpcode::kFinish: |
| 571 return kMachAnyTagged; | 592 return kMachAnyTagged; |
| 572 case IrOpcode::kParameter: | 593 case IrOpcode::kParameter: |
| 573 return linkage()->GetParameterType(OpParameter<int>(node)); | 594 return linkage()->GetParameterType(OpParameter<int>(node)); |
| 574 case IrOpcode::kOsrValue: | 595 case IrOpcode::kOsrValue: |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 } | 715 } |
| 695 } | 716 } |
| 696 switch (node->opcode()) { | 717 switch (node->opcode()) { |
| 697 case IrOpcode::kStart: | 718 case IrOpcode::kStart: |
| 698 case IrOpcode::kLoop: | 719 case IrOpcode::kLoop: |
| 699 case IrOpcode::kEnd: | 720 case IrOpcode::kEnd: |
| 700 case IrOpcode::kBranch: | 721 case IrOpcode::kBranch: |
| 701 case IrOpcode::kIfTrue: | 722 case IrOpcode::kIfTrue: |
| 702 case IrOpcode::kIfFalse: | 723 case IrOpcode::kIfFalse: |
| 703 case IrOpcode::kSwitch: | 724 case IrOpcode::kSwitch: |
| 704 case IrOpcode::kCase: | 725 case IrOpcode::kIfValue: |
| 726 case IrOpcode::kIfDefault: |
| 705 case IrOpcode::kEffectPhi: | 727 case IrOpcode::kEffectPhi: |
| 706 case IrOpcode::kMerge: | 728 case IrOpcode::kMerge: |
| 707 // No code needed for these graph artifacts. | 729 // No code needed for these graph artifacts. |
| 708 return; | 730 return; |
| 709 case IrOpcode::kFinish: | 731 case IrOpcode::kFinish: |
| 710 return MarkAsReference(node), VisitFinish(node); | 732 return MarkAsReference(node), VisitFinish(node); |
| 711 case IrOpcode::kParameter: { | 733 case IrOpcode::kParameter: { |
| 712 MachineType type = linkage()->GetParameterType(OpParameter<int>(node)); | 734 MachineType type = linkage()->GetParameterType(OpParameter<int>(node)); |
| 713 MarkAsRepresentation(type, node); | 735 MarkAsRepresentation(type, node); |
| 714 return VisitParameter(node); | 736 return VisitParameter(node); |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 } | 1073 } |
| 1052 | 1074 |
| 1053 | 1075 |
| 1054 void InstructionSelector::VisitGoto(BasicBlock* target) { | 1076 void InstructionSelector::VisitGoto(BasicBlock* target) { |
| 1055 // jump to the next block. | 1077 // jump to the next block. |
| 1056 OperandGenerator g(this); | 1078 OperandGenerator g(this); |
| 1057 Emit(kArchJmp, g.NoOutput(), g.Label(target))->MarkAsControl(); | 1079 Emit(kArchJmp, g.NoOutput(), g.Label(target))->MarkAsControl(); |
| 1058 } | 1080 } |
| 1059 | 1081 |
| 1060 | 1082 |
| 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>(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 | |
| 1077 void InstructionSelector::VisitReturn(Node* value) { | 1083 void InstructionSelector::VisitReturn(Node* value) { |
| 1078 OperandGenerator g(this); | 1084 OperandGenerator g(this); |
| 1079 if (value != NULL) { | 1085 if (value != NULL) { |
| 1080 Emit(kArchRet, g.NoOutput(), | 1086 Emit(kArchRet, g.NoOutput(), |
| 1081 g.UseLocation(value, linkage()->GetReturnLocation(), | 1087 g.UseLocation(value, linkage()->GetReturnLocation(), |
| 1082 linkage()->GetReturnType())); | 1088 linkage()->GetReturnType())); |
| 1083 } else { | 1089 } else { |
| 1084 Emit(kArchRet, g.NoOutput()); | 1090 Emit(kArchRet, g.NoOutput()); |
| 1085 } | 1091 } |
| 1086 } | 1092 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1212 MachineOperatorBuilder::Flags | 1218 MachineOperatorBuilder::Flags |
| 1213 InstructionSelector::SupportedMachineOperatorFlags() { | 1219 InstructionSelector::SupportedMachineOperatorFlags() { |
| 1214 return MachineOperatorBuilder::Flag::kNoFlags; | 1220 return MachineOperatorBuilder::Flag::kNoFlags; |
| 1215 } | 1221 } |
| 1216 | 1222 |
| 1217 #endif // !V8_TURBOFAN_BACKEND | 1223 #endif // !V8_TURBOFAN_BACKEND |
| 1218 | 1224 |
| 1219 } // namespace compiler | 1225 } // namespace compiler |
| 1220 } // namespace internal | 1226 } // namespace internal |
| 1221 } // namespace v8 | 1227 } // namespace v8 |
| OLD | NEW |