Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: src/compiler/instruction-selector.cc

Issue 892513003: [turbofan] Initial support for Switch. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix Wuschelstudio build. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/instruction-selector.h ('k') | src/compiler/opcodes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "src/compiler/instruction-selector-impl.h" 7 #include "src/compiler/instruction-selector-impl.h"
8 #include "src/compiler/node-matchers.h" 8 #include "src/compiler/node-matchers.h"
9 #include "src/compiler/node-properties.h" 9 #include "src/compiler/node-properties.h"
10 #include "src/compiler/pipeline.h" 10 #include "src/compiler/pipeline.h"
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 // We're done with the block. 476 // We're done with the block.
477 InstructionBlock* instruction_block = 477 InstructionBlock* instruction_block =
478 sequence()->InstructionBlockAt(block->GetRpoNumber()); 478 sequence()->InstructionBlockAt(block->GetRpoNumber());
479 instruction_block->set_code_start(static_cast<int>(instructions_.size())); 479 instruction_block->set_code_start(static_cast<int>(instructions_.size()));
480 instruction_block->set_code_end(current_block_end); 480 instruction_block->set_code_end(current_block_end);
481 481
482 current_block_ = NULL; 482 current_block_ = NULL;
483 } 483 }
484 484
485 485
486 static inline void CheckNoPhis(const BasicBlock* block) { 486 namespace {
487
488 V8_INLINE void CheckNoPhis(const BasicBlock* block) {
487 #ifdef DEBUG 489 #ifdef DEBUG
488 // Branch targets should not have phis. 490 // Branch targets should not have phis.
489 for (BasicBlock::const_iterator i = block->begin(); i != block->end(); ++i) { 491 for (BasicBlock::const_iterator i = block->begin(); i != block->end(); ++i) {
490 const Node* node = *i; 492 const Node* node = *i;
491 CHECK_NE(IrOpcode::kPhi, node->opcode()); 493 CHECK_NE(IrOpcode::kPhi, node->opcode());
492 } 494 }
493 #endif 495 #endif
494 } 496 }
495 497
498 } // namespace
499
496 500
497 void InstructionSelector::VisitControl(BasicBlock* block) { 501 void InstructionSelector::VisitControl(BasicBlock* block) {
498 Node* input = block->control_input(); 502 Node* input = block->control_input();
499 switch (block->control()) { 503 switch (block->control()) {
500 case BasicBlock::kGoto: 504 case BasicBlock::kGoto:
501 return VisitGoto(block->SuccessorAt(0)); 505 return VisitGoto(block->SuccessorAt(0));
502 case BasicBlock::kBranch: { 506 case BasicBlock::kBranch: {
503 DCHECK_EQ(IrOpcode::kBranch, input->opcode()); 507 DCHECK_EQ(IrOpcode::kBranch, input->opcode());
504 BasicBlock* tbranch = block->SuccessorAt(0); 508 BasicBlock* tbranch = block->SuccessorAt(0);
505 BasicBlock* fbranch = block->SuccessorAt(1); 509 BasicBlock* fbranch = block->SuccessorAt(1);
506 // SSA deconstruction requires targets of branches not to have phis. 510 // SSA deconstruction requires targets of branches not to have phis.
507 // Edge split form guarantees this property, but is more strict. 511 // Edge split form guarantees this property, but is more strict.
508 CheckNoPhis(tbranch); 512 CheckNoPhis(tbranch);
509 CheckNoPhis(fbranch); 513 CheckNoPhis(fbranch);
510 if (tbranch == fbranch) return VisitGoto(tbranch); 514 if (tbranch == fbranch) return VisitGoto(tbranch);
511 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue). 515 // Treat special Branch(Always, IfTrue, IfFalse) as Goto(IfTrue).
512 Node* const condition = input->InputAt(0); 516 Node* const condition = input->InputAt(0);
513 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); 517 if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch);
514 return VisitBranch(input, tbranch, fbranch); 518 return VisitBranch(input, tbranch, fbranch);
515 } 519 }
520 case BasicBlock::kSwitch: {
521 DCHECK_EQ(IrOpcode::kSwitch, input->opcode());
522 BasicBlock** const branches = &block->successors().front();
523 size_t const branch_count = block->SuccessorCount();
524 DCHECK_LE(2u, branch_count);
525 // SSA deconstruction requires targets of branches not to have phis.
526 // Edge split form guarantees this property, but is more strict.
527 for (size_t index = 0; index < branch_count; ++index) {
528 CheckNoPhis(branches[index]);
529 }
530 return VisitSwitch(input, branches, branch_count);
531 }
516 case BasicBlock::kReturn: { 532 case BasicBlock::kReturn: {
517 // If the result itself is a return, return its input. 533 // If the result itself is a return, return its input.
518 Node* value = (input != NULL && input->opcode() == IrOpcode::kReturn) 534 Node* value = (input != NULL && input->opcode() == IrOpcode::kReturn)
519 ? input->InputAt(0) 535 ? input->InputAt(0)
520 : input; 536 : input;
521 return VisitReturn(value); 537 return VisitReturn(value);
522 } 538 }
523 case BasicBlock::kThrow: 539 case BasicBlock::kThrow:
524 DCHECK_EQ(IrOpcode::kThrow, input->opcode()); 540 DCHECK_EQ(IrOpcode::kThrow, input->opcode());
525 return VisitThrow(input->InputAt(0)); 541 return VisitThrow(input->InputAt(0));
526 case BasicBlock::kNone: { 542 case BasicBlock::kNone: {
527 // TODO(titzer): exit block doesn't have control. 543 // TODO(titzer): exit block doesn't have control.
528 DCHECK(input == NULL); 544 DCHECK_NULL(input);
529 break; 545 break;
530 } 546 }
531 default: 547 default:
532 UNREACHABLE(); 548 UNREACHABLE();
533 break; 549 break;
534 } 550 }
535 } 551 }
536 552
537 553
538 MachineType InstructionSelector::GetMachineType(Node* node) { 554 MachineType InstructionSelector::GetMachineType(Node* node) {
539 DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes. 555 DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes.
540 switch (node->opcode()) { 556 switch (node->opcode()) {
541 case IrOpcode::kStart: 557 case IrOpcode::kStart:
542 case IrOpcode::kLoop: 558 case IrOpcode::kLoop:
543 case IrOpcode::kEnd: 559 case IrOpcode::kEnd:
544 case IrOpcode::kBranch: 560 case IrOpcode::kBranch:
545 case IrOpcode::kIfTrue: 561 case IrOpcode::kIfTrue:
546 case IrOpcode::kIfFalse: 562 case IrOpcode::kIfFalse:
563 case IrOpcode::kSwitch:
564 case IrOpcode::kCase:
547 case IrOpcode::kEffectPhi: 565 case IrOpcode::kEffectPhi:
548 case IrOpcode::kEffectSet: 566 case IrOpcode::kEffectSet:
549 case IrOpcode::kMerge: 567 case IrOpcode::kMerge:
550 // No code needed for these graph artifacts. 568 // No code needed for these graph artifacts.
551 return kMachNone; 569 return kMachNone;
552 case IrOpcode::kFinish: 570 case IrOpcode::kFinish:
553 return kMachAnyTagged; 571 return kMachAnyTagged;
554 case IrOpcode::kParameter: 572 case IrOpcode::kParameter:
555 return linkage()->GetParameterType(OpParameter<int>(node)); 573 return linkage()->GetParameterType(OpParameter<int>(node));
556 case IrOpcode::kOsrValue: 574 case IrOpcode::kOsrValue:
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 Emit(SourcePositionInstruction::New(instruction_zone(), source_position)); 693 Emit(SourcePositionInstruction::New(instruction_zone(), source_position));
676 } 694 }
677 } 695 }
678 switch (node->opcode()) { 696 switch (node->opcode()) {
679 case IrOpcode::kStart: 697 case IrOpcode::kStart:
680 case IrOpcode::kLoop: 698 case IrOpcode::kLoop:
681 case IrOpcode::kEnd: 699 case IrOpcode::kEnd:
682 case IrOpcode::kBranch: 700 case IrOpcode::kBranch:
683 case IrOpcode::kIfTrue: 701 case IrOpcode::kIfTrue:
684 case IrOpcode::kIfFalse: 702 case IrOpcode::kIfFalse:
703 case IrOpcode::kSwitch:
704 case IrOpcode::kCase:
685 case IrOpcode::kEffectPhi: 705 case IrOpcode::kEffectPhi:
686 case IrOpcode::kMerge: 706 case IrOpcode::kMerge:
687 // No code needed for these graph artifacts. 707 // No code needed for these graph artifacts.
688 return; 708 return;
689 case IrOpcode::kFinish: 709 case IrOpcode::kFinish:
690 return MarkAsReference(node), VisitFinish(node); 710 return MarkAsReference(node), VisitFinish(node);
691 case IrOpcode::kParameter: { 711 case IrOpcode::kParameter: {
692 MachineType type = linkage()->GetParameterType(OpParameter<int>(node)); 712 MachineType type = linkage()->GetParameterType(OpParameter<int>(node));
693 MarkAsRepresentation(type, node); 713 MarkAsRepresentation(type, node);
694 return VisitParameter(node); 714 return VisitParameter(node);
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
1031 } 1051 }
1032 1052
1033 1053
1034 void InstructionSelector::VisitGoto(BasicBlock* target) { 1054 void InstructionSelector::VisitGoto(BasicBlock* target) {
1035 // jump to the next block. 1055 // jump to the next block.
1036 OperandGenerator g(this); 1056 OperandGenerator g(this);
1037 Emit(kArchJmp, g.NoOutput(), g.Label(target))->MarkAsControl(); 1057 Emit(kArchJmp, g.NoOutput(), g.Label(target))->MarkAsControl();
1038 } 1058 }
1039 1059
1040 1060
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>(static_cast<int>(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
1041 void InstructionSelector::VisitReturn(Node* value) { 1077 void InstructionSelector::VisitReturn(Node* value) {
1042 OperandGenerator g(this); 1078 OperandGenerator g(this);
1043 if (value != NULL) { 1079 if (value != NULL) {
1044 Emit(kArchRet, g.NoOutput(), 1080 Emit(kArchRet, g.NoOutput(),
1045 g.UseLocation(value, linkage()->GetReturnLocation(), 1081 g.UseLocation(value, linkage()->GetReturnLocation(),
1046 linkage()->GetReturnType())); 1082 linkage()->GetReturnType()));
1047 } else { 1083 } else {
1048 Emit(kArchRet, g.NoOutput()); 1084 Emit(kArchRet, g.NoOutput());
1049 } 1085 }
1050 } 1086 }
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1176 MachineOperatorBuilder::Flags 1212 MachineOperatorBuilder::Flags
1177 InstructionSelector::SupportedMachineOperatorFlags() { 1213 InstructionSelector::SupportedMachineOperatorFlags() {
1178 return MachineOperatorBuilder::Flag::kNoFlags; 1214 return MachineOperatorBuilder::Flag::kNoFlags;
1179 } 1215 }
1180 1216
1181 #endif // !V8_TURBOFAN_BACKEND 1217 #endif // !V8_TURBOFAN_BACKEND
1182 1218
1183 } // namespace compiler 1219 } // namespace compiler
1184 } // namespace internal 1220 } // namespace internal
1185 } // namespace v8 1221 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/instruction-selector.h ('k') | src/compiler/opcodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698