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> | 7 #include <limits> |
8 | 8 |
9 #include "src/compiler/instruction-selector-impl.h" | 9 #include "src/compiler/instruction-selector-impl.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 BasicBlock* tbranch = block->SuccessorAt(0); | 515 BasicBlock* tbranch = block->SuccessorAt(0); |
516 BasicBlock* fbranch = block->SuccessorAt(1); | 516 BasicBlock* fbranch = block->SuccessorAt(1); |
517 if (tbranch == fbranch) return VisitGoto(tbranch); | 517 if (tbranch == fbranch) return VisitGoto(tbranch); |
518 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue). | 518 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue). |
519 Node* const condition = input->InputAt(0); | 519 Node* const condition = input->InputAt(0); |
520 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); | 520 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); |
521 return VisitBranch(input, tbranch, fbranch); | 521 return VisitBranch(input, tbranch, fbranch); |
522 } | 522 } |
523 case BasicBlock::kSwitch: { | 523 case BasicBlock::kSwitch: { |
524 DCHECK_EQ(IrOpcode::kSwitch, input->opcode()); | 524 DCHECK_EQ(IrOpcode::kSwitch, input->opcode()); |
| 525 SwitchInfo sw; |
525 // Last successor must be Default. | 526 // Last successor must be Default. |
526 BasicBlock* default_branch = block->successors().back(); | 527 sw.default_branch = block->successors().back(); |
527 DCHECK_EQ(IrOpcode::kIfDefault, default_branch->front()->opcode()); | 528 DCHECK_EQ(IrOpcode::kIfDefault, sw.default_branch->front()->opcode()); |
528 // All other successors must be cases. | 529 // All other successors must be cases. |
529 size_t case_count = block->SuccessorCount() - 1; | 530 sw.case_count = block->SuccessorCount() - 1; |
530 DCHECK_LE(1u, case_count); | 531 DCHECK_LE(1u, sw.case_count); |
531 BasicBlock** case_branches = &block->successors().front(); | 532 sw.case_branches = &block->successors().front(); |
532 // Determine case values and their min/max. | 533 // Determine case values and their min/max. |
533 int32_t* case_values = zone()->NewArray<int32_t>(case_count); | 534 sw.case_values = zone()->NewArray<int32_t>(sw.case_count); |
534 int32_t min_value = std::numeric_limits<int32_t>::max(); | 535 sw.min_value = std::numeric_limits<int32_t>::max(); |
535 int32_t max_value = std::numeric_limits<int32_t>::min(); | 536 sw.max_value = std::numeric_limits<int32_t>::min(); |
536 for (size_t index = 0; index < case_count; ++index) { | 537 for (size_t index = 0; index < sw.case_count; ++index) { |
537 BasicBlock* branch = case_branches[index]; | 538 BasicBlock* branch = sw.case_branches[index]; |
538 int32_t value = OpParameter<int32_t>(branch->front()->op()); | 539 int32_t value = OpParameter<int32_t>(branch->front()->op()); |
539 case_values[index] = value; | 540 sw.case_values[index] = value; |
540 if (min_value > value) min_value = value; | 541 if (sw.min_value > value) sw.min_value = value; |
541 if (max_value < value) max_value = value; | 542 if (sw.max_value < value) sw.max_value = value; |
542 } | 543 } |
543 DCHECK_LE(min_value, max_value); | 544 DCHECK_LE(sw.min_value, sw.max_value); |
544 return VisitSwitch(input, default_branch, case_branches, case_values, | 545 // Note that {value_range} can be 0 if {min_value} is -2^31 and |
545 case_count, min_value, max_value); | 546 // {max_value} |
| 547 // is 2^31-1, so don't assume that it's non-zero below. |
| 548 sw.value_range = 1u + bit_cast<uint32_t>(sw.max_value) - |
| 549 bit_cast<uint32_t>(sw.min_value); |
| 550 return VisitSwitch(input, sw); |
546 } | 551 } |
547 case BasicBlock::kReturn: { | 552 case BasicBlock::kReturn: { |
548 // If the result itself is a return, return its input. | 553 // If the result itself is a return, return its input. |
549 Node* value = (input != nullptr && input->opcode() == IrOpcode::kReturn) | 554 Node* value = (input != nullptr && input->opcode() == IrOpcode::kReturn) |
550 ? input->InputAt(0) | 555 ? input->InputAt(0) |
551 : input; | 556 : input; |
552 return VisitReturn(value); | 557 return VisitReturn(value); |
553 } | 558 } |
554 case BasicBlock::kDeoptimize: { | 559 case BasicBlock::kDeoptimize: { |
555 // If the result itself is a return, return its input. | 560 // If the result itself is a return, return its input. |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
806 Emit(kArchTruncateDoubleToI, g.DefineAsRegister(node), | 811 Emit(kArchTruncateDoubleToI, g.DefineAsRegister(node), |
807 g.UseRegister(node->InputAt(0))); | 812 g.UseRegister(node->InputAt(0))); |
808 } | 813 } |
809 | 814 |
810 | 815 |
811 void InstructionSelector::VisitLoadStackPointer(Node* node) { | 816 void InstructionSelector::VisitLoadStackPointer(Node* node) { |
812 OperandGenerator g(this); | 817 OperandGenerator g(this); |
813 Emit(kArchStackPointer, g.DefineAsRegister(node)); | 818 Emit(kArchStackPointer, g.DefineAsRegister(node)); |
814 } | 819 } |
815 | 820 |
| 821 |
| 822 void InstructionSelector::EmitTableSwitch(const SwitchInfo& sw, |
| 823 InstructionOperand& index_operand) { |
| 824 OperandGenerator g(this); |
| 825 size_t input_count = 2 + sw.value_range; |
| 826 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
| 827 inputs[0] = index_operand; |
| 828 InstructionOperand default_operand = g.Label(sw.default_branch); |
| 829 std::fill(&inputs[1], &inputs[input_count], default_operand); |
| 830 for (size_t index = 0; index < sw.case_count; ++index) { |
| 831 size_t value = sw.case_values[index] - sw.min_value; |
| 832 BasicBlock* branch = sw.case_branches[index]; |
| 833 DCHECK_LE(0u, value); |
| 834 DCHECK_LT(value + 2, input_count); |
| 835 inputs[value + 2] = g.Label(branch); |
| 836 } |
| 837 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr); |
| 838 } |
| 839 |
| 840 |
| 841 void InstructionSelector::EmitLookupSwitch(const SwitchInfo& sw, |
| 842 InstructionOperand& value_operand) { |
| 843 OperandGenerator g(this); |
| 844 size_t input_count = 2 + sw.case_count * 2; |
| 845 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
| 846 inputs[0] = value_operand; |
| 847 inputs[1] = g.Label(sw.default_branch); |
| 848 for (size_t index = 0; index < sw.case_count; ++index) { |
| 849 int32_t value = sw.case_values[index]; |
| 850 BasicBlock* branch = sw.case_branches[index]; |
| 851 inputs[index * 2 + 2 + 0] = g.TempImmediate(value); |
| 852 inputs[index * 2 + 2 + 1] = g.Label(branch); |
| 853 } |
| 854 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr); |
| 855 } |
| 856 |
| 857 |
816 #endif // V8_TURBOFAN_BACKEND | 858 #endif // V8_TURBOFAN_BACKEND |
817 | 859 |
818 // 32 bit targets do not implement the following instructions. | 860 // 32 bit targets do not implement the following instructions. |
819 #if V8_TARGET_ARCH_32_BIT && !V8_TARGET_ARCH_X64 && V8_TURBOFAN_BACKEND | 861 #if V8_TARGET_ARCH_32_BIT && !V8_TARGET_ARCH_X64 && V8_TURBOFAN_BACKEND |
820 | 862 |
821 void InstructionSelector::VisitWord64And(Node* node) { UNIMPLEMENTED(); } | 863 void InstructionSelector::VisitWord64And(Node* node) { UNIMPLEMENTED(); } |
822 | 864 |
823 | 865 |
824 void InstructionSelector::VisitWord64Or(Node* node) { UNIMPLEMENTED(); } | 866 void InstructionSelector::VisitWord64Or(Node* node) { UNIMPLEMENTED(); } |
825 | 867 |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1124 MachineOperatorBuilder::Flags | 1166 MachineOperatorBuilder::Flags |
1125 InstructionSelector::SupportedMachineOperatorFlags() { | 1167 InstructionSelector::SupportedMachineOperatorFlags() { |
1126 return MachineOperatorBuilder::Flag::kNoFlags; | 1168 return MachineOperatorBuilder::Flag::kNoFlags; |
1127 } | 1169 } |
1128 | 1170 |
1129 #endif // !V8_TURBOFAN_BACKEND | 1171 #endif // !V8_TURBOFAN_BACKEND |
1130 | 1172 |
1131 } // namespace compiler | 1173 } // namespace compiler |
1132 } // namespace internal | 1174 } // namespace internal |
1133 } // namespace v8 | 1175 } // namespace v8 |
OLD | NEW |