| Index: src/compiler/instruction-selector.cc
|
| diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc
|
| index 11f455cfbb4c74b1d18114d651b8c2edb55d0983..75fc35560a18fa80e6a37b549d63ccde0ea19260 100644
|
| --- a/src/compiler/instruction-selector.cc
|
| +++ b/src/compiler/instruction-selector.cc
|
| @@ -483,7 +483,9 @@ void InstructionSelector::VisitBlock(BasicBlock* block) {
|
| }
|
|
|
|
|
| -static inline void CheckNoPhis(const BasicBlock* block) {
|
| +namespace {
|
| +
|
| +V8_INLINE void CheckNoPhis(const BasicBlock* block) {
|
| #ifdef DEBUG
|
| // Branch targets should not have phis.
|
| for (BasicBlock::const_iterator i = block->begin(); i != block->end(); ++i) {
|
| @@ -493,6 +495,8 @@ static inline void CheckNoPhis(const BasicBlock* block) {
|
| #endif
|
| }
|
|
|
| +} // namespace
|
| +
|
|
|
| void InstructionSelector::VisitControl(BasicBlock* block) {
|
| Node* input = block->control_input();
|
| @@ -513,6 +517,18 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
|
| if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch);
|
| return VisitBranch(input, tbranch, fbranch);
|
| }
|
| + 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);
|
| + // 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]);
|
| + }
|
| + return VisitSwitch(input, branches, branch_count);
|
| + }
|
| case BasicBlock::kReturn: {
|
| // If the result itself is a return, return its input.
|
| Node* value = (input != NULL && input->opcode() == IrOpcode::kReturn)
|
| @@ -525,7 +541,7 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
|
| return VisitThrow(input->InputAt(0));
|
| case BasicBlock::kNone: {
|
| // TODO(titzer): exit block doesn't have control.
|
| - DCHECK(input == NULL);
|
| + DCHECK_NULL(input);
|
| break;
|
| }
|
| default:
|
| @@ -544,6 +560,8 @@ MachineType InstructionSelector::GetMachineType(Node* node) {
|
| case IrOpcode::kBranch:
|
| case IrOpcode::kIfTrue:
|
| case IrOpcode::kIfFalse:
|
| + case IrOpcode::kSwitch:
|
| + case IrOpcode::kCase:
|
| case IrOpcode::kEffectPhi:
|
| case IrOpcode::kEffectSet:
|
| case IrOpcode::kMerge:
|
| @@ -682,6 +700,8 @@ void InstructionSelector::VisitNode(Node* node) {
|
| case IrOpcode::kBranch:
|
| case IrOpcode::kIfTrue:
|
| case IrOpcode::kIfFalse:
|
| + case IrOpcode::kSwitch:
|
| + case IrOpcode::kCase:
|
| case IrOpcode::kEffectPhi:
|
| case IrOpcode::kMerge:
|
| // No code needed for these graph artifacts.
|
| @@ -1038,6 +1058,22 @@ 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>(static_cast<int>(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) {
|
|
|