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

Unified Diff: src/compiler/instruction-selector.cc

Issue 1019803005: [turbofan] Factor out common switch-related code in instruction selectors. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/instruction-selector.h ('k') | src/compiler/instruction-selector-impl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/instruction-selector.cc
diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc
index 3eb46db828ee5773a7ea688ddfb8135c319d6ef1..7604cf8d3b78af518a60a94677613bc521c5b62e 100644
--- a/src/compiler/instruction-selector.cc
+++ b/src/compiler/instruction-selector.cc
@@ -522,27 +522,32 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
}
case BasicBlock::kSwitch: {
DCHECK_EQ(IrOpcode::kSwitch, input->opcode());
+ SwitchInfo sw;
// Last successor must be Default.
- BasicBlock* default_branch = block->successors().back();
- DCHECK_EQ(IrOpcode::kIfDefault, default_branch->front()->opcode());
+ sw.default_branch = block->successors().back();
+ DCHECK_EQ(IrOpcode::kIfDefault, sw.default_branch->front()->opcode());
// All other successors must be cases.
- size_t case_count = block->SuccessorCount() - 1;
- DCHECK_LE(1u, case_count);
- BasicBlock** case_branches = &block->successors().front();
+ sw.case_count = block->SuccessorCount() - 1;
+ DCHECK_LE(1u, sw.case_count);
+ sw.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];
+ sw.case_values = zone()->NewArray<int32_t>(sw.case_count);
+ sw.min_value = std::numeric_limits<int32_t>::max();
+ sw.max_value = std::numeric_limits<int32_t>::min();
+ for (size_t index = 0; index < sw.case_count; ++index) {
+ BasicBlock* branch = sw.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;
+ sw.case_values[index] = value;
+ if (sw.min_value > value) sw.min_value = value;
+ if (sw.max_value < value) sw.max_value = value;
}
- DCHECK_LE(min_value, max_value);
- return VisitSwitch(input, default_branch, case_branches, case_values,
- case_count, min_value, max_value);
+ DCHECK_LE(sw.min_value, sw.max_value);
+ // 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.
+ sw.value_range = 1u + bit_cast<uint32_t>(sw.max_value) -
+ bit_cast<uint32_t>(sw.min_value);
+ return VisitSwitch(input, sw);
}
case BasicBlock::kReturn: {
// If the result itself is a return, return its input.
@@ -813,6 +818,43 @@ void InstructionSelector::VisitLoadStackPointer(Node* node) {
Emit(kArchStackPointer, g.DefineAsRegister(node));
}
+
+void InstructionSelector::EmitTableSwitch(const SwitchInfo& sw,
+ InstructionOperand& index_operand) {
+ OperandGenerator g(this);
+ size_t input_count = 2 + sw.value_range;
+ auto* inputs = zone()->NewArray<InstructionOperand>(input_count);
+ inputs[0] = index_operand;
+ InstructionOperand default_operand = g.Label(sw.default_branch);
+ std::fill(&inputs[1], &inputs[input_count], default_operand);
+ for (size_t index = 0; index < sw.case_count; ++index) {
+ size_t value = sw.case_values[index] - sw.min_value;
+ BasicBlock* branch = sw.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);
+}
+
+
+void InstructionSelector::EmitLookupSwitch(const SwitchInfo& sw,
+ InstructionOperand& value_operand) {
+ OperandGenerator g(this);
+ size_t input_count = 2 + sw.case_count * 2;
+ auto* inputs = zone()->NewArray<InstructionOperand>(input_count);
+ inputs[0] = value_operand;
+ inputs[1] = g.Label(sw.default_branch);
+ for (size_t index = 0; index < sw.case_count; ++index) {
+ int32_t value = sw.case_values[index];
+ BasicBlock* branch = sw.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);
+}
+
+
#endif // V8_TURBOFAN_BACKEND
// 32 bit targets do not implement the following instructions.
« no previous file with comments | « src/compiler/instruction-selector.h ('k') | src/compiler/instruction-selector-impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698