| Index: src/compiler/instruction-selector.cc
|
| diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc
|
| index e8a52a61e12213577b48711ba768ad36ac117252..c170a01d4a2bebbfe51e246254c2d86600c96ce2 100644
|
| --- a/src/compiler/instruction-selector.cc
|
| +++ b/src/compiler/instruction-selector.cc
|
| @@ -4,6 +4,8 @@
|
|
|
| #include "src/compiler/instruction-selector.h"
|
|
|
| +#include <limits>
|
| +
|
| #include "src/compiler/instruction-selector-impl.h"
|
| #include "src/compiler/node-matchers.h"
|
| #include "src/compiler/node-properties.h"
|
| @@ -519,15 +521,33 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
|
| }
|
| case BasicBlock::kSwitch: {
|
| DCHECK_EQ(IrOpcode::kSwitch, input->opcode());
|
| - BasicBlock** const branches = &block->successors().front();
|
| - size_t const branch_count = block->SuccessorCount();
|
| - DCHECK_LE(2u, branch_count);
|
| + // Last successor must be Default.
|
| + BasicBlock* default_branch = block->successors().back();
|
| + DCHECK_EQ(IrOpcode::kIfDefault, default_branch->front()->opcode());
|
| // SSA deconstruction requires targets of branches not to have phis.
|
| // Edge split form guarantees this property, but is more strict.
|
| - for (size_t index = 0; index < branch_count; ++index) {
|
| - CheckNoPhis(branches[index]);
|
| + CheckNoPhis(default_branch);
|
| + // All other successors must be cases.
|
| + size_t case_count = block->SuccessorCount() - 1;
|
| + DCHECK_LE(1u, case_count);
|
| + BasicBlock** case_branches = &block->successors().front();
|
| + // Determine case values and their min/max.
|
| + int32_t* case_values = zone()->NewArray<int32_t>(case_count);
|
| + int32_t min_value = std::numeric_limits<int32_t>::max();
|
| + int32_t max_value = std::numeric_limits<int32_t>::min();
|
| + for (size_t index = 0; index < case_count; ++index) {
|
| + BasicBlock* branch = case_branches[index];
|
| + int32_t value = OpParameter<int32_t>(branch->front()->op());
|
| + case_values[index] = value;
|
| + if (min_value > value) min_value = value;
|
| + if (max_value < value) max_value = value;
|
| + // SSA deconstruction requires targets of branches not to have phis.
|
| + // Edge split form guarantees this property, but is more strict.
|
| + CheckNoPhis(branch);
|
| }
|
| - return VisitSwitch(input, branches, branch_count);
|
| + DCHECK_LE(min_value, max_value);
|
| + return VisitSwitch(input, default_branch, case_branches, case_values,
|
| + case_count, min_value, max_value);
|
| }
|
| case BasicBlock::kReturn: {
|
| // If the result itself is a return, return its input.
|
| @@ -561,7 +581,8 @@ MachineType InstructionSelector::GetMachineType(Node* node) {
|
| case IrOpcode::kIfTrue:
|
| case IrOpcode::kIfFalse:
|
| case IrOpcode::kSwitch:
|
| - case IrOpcode::kCase:
|
| + case IrOpcode::kIfValue:
|
| + case IrOpcode::kIfDefault:
|
| case IrOpcode::kEffectPhi:
|
| case IrOpcode::kEffectSet:
|
| case IrOpcode::kMerge:
|
| @@ -701,7 +722,8 @@ void InstructionSelector::VisitNode(Node* node) {
|
| case IrOpcode::kIfTrue:
|
| case IrOpcode::kIfFalse:
|
| case IrOpcode::kSwitch:
|
| - case IrOpcode::kCase:
|
| + case IrOpcode::kIfValue:
|
| + case IrOpcode::kIfDefault:
|
| case IrOpcode::kEffectPhi:
|
| case IrOpcode::kMerge:
|
| // No code needed for these graph artifacts.
|
| @@ -1058,22 +1080,6 @@ void InstructionSelector::VisitGoto(BasicBlock* target) {
|
| }
|
|
|
|
|
| -void InstructionSelector::VisitSwitch(Node* node, BasicBlock** branches,
|
| - size_t branch_count) {
|
| - OperandGenerator g(this);
|
| - Node* const value = node->InputAt(0);
|
| - size_t const input_count = branch_count + 1;
|
| - InstructionOperand* const inputs =
|
| - zone()->NewArray<InstructionOperand>(input_count);
|
| - inputs[0] = g.UseRegister(value);
|
| - for (size_t index = 0; index < branch_count; ++index) {
|
| - inputs[index + 1] = g.Label(branches[index]);
|
| - }
|
| - Emit(kArchSwitch, 0, nullptr, input_count, inputs, 0, nullptr)
|
| - ->MarkAsControl();
|
| -}
|
| -
|
| -
|
| void InstructionSelector::VisitReturn(Node* value) {
|
| OperandGenerator g(this);
|
| if (value != NULL) {
|
|
|