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 |