Chromium Code Reviews| Index: src/compiler/mips/instruction-selector-mips.cc |
| diff --git a/src/compiler/mips/instruction-selector-mips.cc b/src/compiler/mips/instruction-selector-mips.cc |
| index ae6ba3f524d06cf16fa763cea4aa3686b4a1e78e..30fcb80e6af2df78bbe63650cfe74340335a680e 100644 |
| --- a/src/compiler/mips/instruction-selector-mips.cc |
| +++ b/src/compiler/mips/instruction-selector-mips.cc |
| @@ -746,6 +746,66 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
| } |
| +void InstructionSelector::VisitSwitch(Node* node, BasicBlock* default_branch, |
| + BasicBlock** case_branches, |
| + int32_t* case_values, size_t case_count, |
| + int32_t min_value, int32_t max_value) { |
| + MipsOperandGenerator g(this); |
| + InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); |
| + InstructionOperand default_operand = g.Label(default_branch); |
| + |
| + // Note that {value_range} can be 0 if {min_value} is -2^31 and {max_value} |
| + // is 2^31-1, so don't assume that it's non-zero below. |
| + size_t value_range = |
| + 1u + bit_cast<uint32_t>(max_value) - bit_cast<uint32_t>(min_value); |
| + |
| + // Determine whether to issue an ArchTableSwitch or an ArchLookupSwitch |
| + // instruction. |
| + size_t table_space_cost = 4 + value_range; |
|
paul.l...
2015/02/17 19:33:59
The cost numbers here are incorrect for MIPS, sinc
|
| + size_t table_time_cost = 3; |
| + size_t lookup_space_cost = 3 + 2 * case_count; |
| + size_t lookup_time_cost = case_count; |
| + if (case_count > 0 && |
| + table_space_cost + 3 * table_time_cost <= |
| + lookup_space_cost + 3 * lookup_time_cost && |
| + min_value > std::numeric_limits<int32_t>::min()) { |
| + InstructionOperand index_operand = value_operand; |
| + if (min_value) { |
| + index_operand = g.TempRegister(); |
| + Emit(kMipsSub, index_operand, value_operand, g.TempImmediate(min_value)); |
| + } |
| + size_t input_count = 2 + value_range; |
| + auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
| + inputs[0] = index_operand; |
| + std::fill(&inputs[1], &inputs[input_count], default_operand); |
| + for (size_t index = 0; index < case_count; ++index) { |
| + size_t value = case_values[index] - min_value; |
| + BasicBlock* branch = case_branches[index]; |
| + DCHECK_LE(0u, value); |
| + DCHECK_LT(value + 2, input_count); |
| + inputs[value + 2] = g.Label(branch); |
| + } |
| + Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr) |
| + ->MarkAsControl(); |
| + return; |
| + } |
| + |
| + // Generate a sequence of conditional jumps. |
| + size_t input_count = 2 + case_count * 2; |
| + auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
| + inputs[0] = value_operand; |
| + inputs[1] = default_operand; |
| + for (size_t index = 0; index < case_count; ++index) { |
| + int32_t value = case_values[index]; |
| + BasicBlock* branch = case_branches[index]; |
| + inputs[index * 2 + 2 + 0] = g.TempImmediate(value); |
| + inputs[index * 2 + 2 + 1] = g.Label(branch); |
| + } |
| + Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr) |
| + ->MarkAsControl(); |
| +} |
| + |
| + |
| void InstructionSelector::VisitWord32Equal(Node* const node) { |
| FlagsContinuation cont(kEqual, node); |
| Int32BinopMatcher m(node); |