OLD | NEW |
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-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 1373 matching lines...) Loading... |
1384 } | 1384 } |
1385 } | 1385 } |
1386 | 1386 |
1387 // Branch could not be combined with a compare, compare against 0 and branch. | 1387 // Branch could not be combined with a compare, compare against 0 and branch. |
1388 Emit(cont.Encode(kArm64CompareAndBranch32), g.NoOutput(), | 1388 Emit(cont.Encode(kArm64CompareAndBranch32), g.NoOutput(), |
1389 g.UseRegister(value), g.Label(cont.true_block()), | 1389 g.UseRegister(value), g.Label(cont.true_block()), |
1390 g.Label(cont.false_block()))->MarkAsControl(); | 1390 g.Label(cont.false_block()))->MarkAsControl(); |
1391 } | 1391 } |
1392 | 1392 |
1393 | 1393 |
| 1394 void InstructionSelector::VisitSwitch(Node* node, BasicBlock* default_branch, |
| 1395 BasicBlock** case_branches, |
| 1396 int32_t* case_values, size_t case_count, |
| 1397 int32_t min_value, int32_t max_value) { |
| 1398 Arm64OperandGenerator g(this); |
| 1399 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); |
| 1400 InstructionOperand default_operand = g.Label(default_branch); |
| 1401 |
| 1402 // Note that {value_range} can be 0 if {min_value} is -2^31 and {max_value} |
| 1403 // is 2^31-1, so don't assume that it's non-zero below. |
| 1404 size_t value_range = |
| 1405 1u + bit_cast<uint32_t>(max_value) - bit_cast<uint32_t>(min_value); |
| 1406 |
| 1407 // Determine whether to issue an ArchTableSwitch or an ArchLookupSwitch |
| 1408 // instruction. |
| 1409 size_t table_space_cost = 4 + value_range; |
| 1410 size_t table_time_cost = 3; |
| 1411 size_t lookup_space_cost = 3 + 2 * case_count; |
| 1412 size_t lookup_time_cost = case_count; |
| 1413 if (case_count > 0 && |
| 1414 table_space_cost + 3 * table_time_cost <= |
| 1415 lookup_space_cost + 3 * lookup_time_cost && |
| 1416 min_value > std::numeric_limits<int32_t>::min()) { |
| 1417 InstructionOperand index_operand = value_operand; |
| 1418 if (min_value) { |
| 1419 index_operand = g.TempRegister(); |
| 1420 Emit(kArm64Sub32, index_operand, value_operand, |
| 1421 g.TempImmediate(min_value)); |
| 1422 } |
| 1423 size_t input_count = 2 + value_range; |
| 1424 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
| 1425 inputs[0] = index_operand; |
| 1426 std::fill(&inputs[1], &inputs[input_count], default_operand); |
| 1427 for (size_t index = 0; index < case_count; ++index) { |
| 1428 size_t value = case_values[index] - min_value; |
| 1429 BasicBlock* branch = case_branches[index]; |
| 1430 DCHECK_LE(0u, value); |
| 1431 DCHECK_LT(value + 2, input_count); |
| 1432 inputs[value + 2] = g.Label(branch); |
| 1433 } |
| 1434 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr) |
| 1435 ->MarkAsControl(); |
| 1436 return; |
| 1437 } |
| 1438 |
| 1439 // Generate a sequence of conditional jumps. |
| 1440 size_t input_count = 2 + case_count * 2; |
| 1441 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
| 1442 inputs[0] = value_operand; |
| 1443 inputs[1] = default_operand; |
| 1444 for (size_t index = 0; index < case_count; ++index) { |
| 1445 int32_t value = case_values[index]; |
| 1446 BasicBlock* branch = case_branches[index]; |
| 1447 inputs[index * 2 + 2 + 0] = g.TempImmediate(value); |
| 1448 inputs[index * 2 + 2 + 1] = g.Label(branch); |
| 1449 } |
| 1450 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr) |
| 1451 ->MarkAsControl(); |
| 1452 } |
| 1453 |
| 1454 |
1394 void InstructionSelector::VisitWord32Equal(Node* const node) { | 1455 void InstructionSelector::VisitWord32Equal(Node* const node) { |
1395 Node* const user = node; | 1456 Node* const user = node; |
1396 FlagsContinuation cont(kEqual, node); | 1457 FlagsContinuation cont(kEqual, node); |
1397 Int32BinopMatcher m(user); | 1458 Int32BinopMatcher m(user); |
1398 if (m.right().Is(0)) { | 1459 if (m.right().Is(0)) { |
1399 Node* const value = m.left().node(); | 1460 Node* const value = m.left().node(); |
1400 if (CanCover(user, value)) { | 1461 if (CanCover(user, value)) { |
1401 switch (value->opcode()) { | 1462 switch (value->opcode()) { |
1402 case IrOpcode::kInt32Add: | 1463 case IrOpcode::kInt32Add: |
1403 return VisitWordCompare(this, value, kArm64Cmn32, &cont, true, | 1464 return VisitWordCompare(this, value, kArm64Cmn32, &cont, true, |
(...skipping 125 matching lines...) Loading... |
1529 MachineOperatorBuilder::kFloat64RoundTruncate | | 1590 MachineOperatorBuilder::kFloat64RoundTruncate | |
1530 MachineOperatorBuilder::kFloat64RoundTiesAway | | 1591 MachineOperatorBuilder::kFloat64RoundTiesAway | |
1531 MachineOperatorBuilder::kWord32ShiftIsSafe | | 1592 MachineOperatorBuilder::kWord32ShiftIsSafe | |
1532 MachineOperatorBuilder::kInt32DivIsSafe | | 1593 MachineOperatorBuilder::kInt32DivIsSafe | |
1533 MachineOperatorBuilder::kUint32DivIsSafe; | 1594 MachineOperatorBuilder::kUint32DivIsSafe; |
1534 } | 1595 } |
1535 | 1596 |
1536 } // namespace compiler | 1597 } // namespace compiler |
1537 } // namespace internal | 1598 } // namespace internal |
1538 } // namespace v8 | 1599 } // namespace v8 |
OLD | NEW |