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 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 outputs[output_count++] = g.DefineAsRegister(node); | 242 outputs[output_count++] = g.DefineAsRegister(node); |
243 if (cont->IsSet()) { | 243 if (cont->IsSet()) { |
244 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 244 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
245 } | 245 } |
246 | 246 |
247 DCHECK_NE(0u, input_count); | 247 DCHECK_NE(0u, input_count); |
248 DCHECK_NE(0u, output_count); | 248 DCHECK_NE(0u, output_count); |
249 DCHECK_GE(arraysize(inputs), input_count); | 249 DCHECK_GE(arraysize(inputs), input_count); |
250 DCHECK_GE(arraysize(outputs), output_count); | 250 DCHECK_GE(arraysize(outputs), output_count); |
251 | 251 |
252 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 252 selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, |
253 outputs, input_count, inputs); | 253 inputs); |
254 if (cont->IsBranch()) instr->MarkAsControl(); | |
255 } | 254 } |
256 | 255 |
257 | 256 |
258 // Shared routine for multiple binary operations. | 257 // Shared routine for multiple binary operations. |
259 template <typename Matcher> | 258 template <typename Matcher> |
260 static void VisitBinop(InstructionSelector* selector, Node* node, | 259 static void VisitBinop(InstructionSelector* selector, Node* node, |
261 ArchOpcode opcode, ImmediateMode operand_mode) { | 260 ArchOpcode opcode, ImmediateMode operand_mode) { |
262 FlagsContinuation cont; | 261 FlagsContinuation cont; |
263 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); | 262 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); |
264 } | 263 } |
(...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1223 | 1222 |
1224 | 1223 |
1225 // Shared routine for multiple compare operations. | 1224 // Shared routine for multiple compare operations. |
1226 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1225 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1227 InstructionOperand left, InstructionOperand right, | 1226 InstructionOperand left, InstructionOperand right, |
1228 FlagsContinuation* cont) { | 1227 FlagsContinuation* cont) { |
1229 Arm64OperandGenerator g(selector); | 1228 Arm64OperandGenerator g(selector); |
1230 opcode = cont->Encode(opcode); | 1229 opcode = cont->Encode(opcode); |
1231 if (cont->IsBranch()) { | 1230 if (cont->IsBranch()) { |
1232 selector->Emit(opcode, g.NoOutput(), left, right, | 1231 selector->Emit(opcode, g.NoOutput(), left, right, |
1233 g.Label(cont->true_block()), | 1232 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1234 g.Label(cont->false_block()))->MarkAsControl(); | |
1235 } else { | 1233 } else { |
1236 DCHECK(cont->IsSet()); | 1234 DCHECK(cont->IsSet()); |
1237 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 1235 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
1238 } | 1236 } |
1239 } | 1237 } |
1240 | 1238 |
1241 | 1239 |
1242 // Shared routine for multiple word compare operations. | 1240 // Shared routine for multiple word compare operations. |
1243 static void VisitWordCompare(InstructionSelector* selector, Node* node, | 1241 static void VisitWordCompare(InstructionSelector* selector, Node* node, |
1244 InstructionCode opcode, FlagsContinuation* cont, | 1242 InstructionCode opcode, FlagsContinuation* cont, |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1403 Int32BinopMatcher m(value); | 1401 Int32BinopMatcher m(value); |
1404 if (m.right().HasValue() && | 1402 if (m.right().HasValue() && |
1405 (base::bits::CountPopulation32(m.right().Value()) == 1)) { | 1403 (base::bits::CountPopulation32(m.right().Value()) == 1)) { |
1406 // If the mask has only one bit set, we can use tbz/tbnz. | 1404 // If the mask has only one bit set, we can use tbz/tbnz. |
1407 DCHECK((cont.condition() == kEqual) || | 1405 DCHECK((cont.condition() == kEqual) || |
1408 (cont.condition() == kNotEqual)); | 1406 (cont.condition() == kNotEqual)); |
1409 Emit(cont.Encode(kArm64TestAndBranch32), g.NoOutput(), | 1407 Emit(cont.Encode(kArm64TestAndBranch32), g.NoOutput(), |
1410 g.UseRegister(m.left().node()), | 1408 g.UseRegister(m.left().node()), |
1411 g.TempImmediate( | 1409 g.TempImmediate( |
1412 base::bits::CountTrailingZeros32(m.right().Value())), | 1410 base::bits::CountTrailingZeros32(m.right().Value())), |
1413 g.Label(cont.true_block()), | 1411 g.Label(cont.true_block()), g.Label(cont.false_block())); |
1414 g.Label(cont.false_block()))->MarkAsControl(); | |
1415 return; | 1412 return; |
1416 } | 1413 } |
1417 return VisitWordCompare(this, value, kArm64Tst32, &cont, true, | 1414 return VisitWordCompare(this, value, kArm64Tst32, &cont, true, |
1418 kLogical32Imm); | 1415 kLogical32Imm); |
1419 } | 1416 } |
1420 case IrOpcode::kWord64And: { | 1417 case IrOpcode::kWord64And: { |
1421 Int64BinopMatcher m(value); | 1418 Int64BinopMatcher m(value); |
1422 if (m.right().HasValue() && | 1419 if (m.right().HasValue() && |
1423 (base::bits::CountPopulation64(m.right().Value()) == 1)) { | 1420 (base::bits::CountPopulation64(m.right().Value()) == 1)) { |
1424 // If the mask has only one bit set, we can use tbz/tbnz. | 1421 // If the mask has only one bit set, we can use tbz/tbnz. |
1425 DCHECK((cont.condition() == kEqual) || | 1422 DCHECK((cont.condition() == kEqual) || |
1426 (cont.condition() == kNotEqual)); | 1423 (cont.condition() == kNotEqual)); |
1427 Emit(cont.Encode(kArm64TestAndBranch), g.NoOutput(), | 1424 Emit(cont.Encode(kArm64TestAndBranch), g.NoOutput(), |
1428 g.UseRegister(m.left().node()), | 1425 g.UseRegister(m.left().node()), |
1429 g.TempImmediate( | 1426 g.TempImmediate( |
1430 base::bits::CountTrailingZeros64(m.right().Value())), | 1427 base::bits::CountTrailingZeros64(m.right().Value())), |
1431 g.Label(cont.true_block()), | 1428 g.Label(cont.true_block()), g.Label(cont.false_block())); |
1432 g.Label(cont.false_block()))->MarkAsControl(); | |
1433 return; | 1429 return; |
1434 } | 1430 } |
1435 return VisitWordCompare(this, value, kArm64Tst, &cont, true, | 1431 return VisitWordCompare(this, value, kArm64Tst, &cont, true, |
1436 kLogical64Imm); | 1432 kLogical64Imm); |
1437 } | 1433 } |
1438 default: | 1434 default: |
1439 break; | 1435 break; |
1440 } | 1436 } |
1441 } | 1437 } |
1442 | 1438 |
1443 // Branch could not be combined with a compare, compare against 0 and branch. | 1439 // Branch could not be combined with a compare, compare against 0 and branch. |
1444 Emit(cont.Encode(kArm64CompareAndBranch32), g.NoOutput(), | 1440 Emit(cont.Encode(kArm64CompareAndBranch32), g.NoOutput(), |
1445 g.UseRegister(value), g.Label(cont.true_block()), | 1441 g.UseRegister(value), g.Label(cont.true_block()), |
1446 g.Label(cont.false_block()))->MarkAsControl(); | 1442 g.Label(cont.false_block())); |
1447 } | 1443 } |
1448 | 1444 |
1449 | 1445 |
1450 void InstructionSelector::VisitSwitch(Node* node, BasicBlock* default_branch, | 1446 void InstructionSelector::VisitSwitch(Node* node, BasicBlock* default_branch, |
1451 BasicBlock** case_branches, | 1447 BasicBlock** case_branches, |
1452 int32_t* case_values, size_t case_count, | 1448 int32_t* case_values, size_t case_count, |
1453 int32_t min_value, int32_t max_value) { | 1449 int32_t min_value, int32_t max_value) { |
1454 Arm64OperandGenerator g(this); | 1450 Arm64OperandGenerator g(this); |
1455 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); | 1451 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); |
1456 InstructionOperand default_operand = g.Label(default_branch); | 1452 InstructionOperand default_operand = g.Label(default_branch); |
(...skipping 23 matching lines...) Expand all Loading... |
1480 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); | 1476 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
1481 inputs[0] = index_operand; | 1477 inputs[0] = index_operand; |
1482 std::fill(&inputs[1], &inputs[input_count], default_operand); | 1478 std::fill(&inputs[1], &inputs[input_count], default_operand); |
1483 for (size_t index = 0; index < case_count; ++index) { | 1479 for (size_t index = 0; index < case_count; ++index) { |
1484 size_t value = case_values[index] - min_value; | 1480 size_t value = case_values[index] - min_value; |
1485 BasicBlock* branch = case_branches[index]; | 1481 BasicBlock* branch = case_branches[index]; |
1486 DCHECK_LE(0u, value); | 1482 DCHECK_LE(0u, value); |
1487 DCHECK_LT(value + 2, input_count); | 1483 DCHECK_LT(value + 2, input_count); |
1488 inputs[value + 2] = g.Label(branch); | 1484 inputs[value + 2] = g.Label(branch); |
1489 } | 1485 } |
1490 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr) | 1486 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr); |
1491 ->MarkAsControl(); | |
1492 return; | 1487 return; |
1493 } | 1488 } |
1494 | 1489 |
1495 // Generate a sequence of conditional jumps. | 1490 // Generate a sequence of conditional jumps. |
1496 size_t input_count = 2 + case_count * 2; | 1491 size_t input_count = 2 + case_count * 2; |
1497 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); | 1492 auto* inputs = zone()->NewArray<InstructionOperand>(input_count); |
1498 inputs[0] = value_operand; | 1493 inputs[0] = value_operand; |
1499 inputs[1] = default_operand; | 1494 inputs[1] = default_operand; |
1500 for (size_t index = 0; index < case_count; ++index) { | 1495 for (size_t index = 0; index < case_count; ++index) { |
1501 int32_t value = case_values[index]; | 1496 int32_t value = case_values[index]; |
1502 BasicBlock* branch = case_branches[index]; | 1497 BasicBlock* branch = case_branches[index]; |
1503 inputs[index * 2 + 2 + 0] = g.TempImmediate(value); | 1498 inputs[index * 2 + 2 + 0] = g.TempImmediate(value); |
1504 inputs[index * 2 + 2 + 1] = g.Label(branch); | 1499 inputs[index * 2 + 2 + 1] = g.Label(branch); |
1505 } | 1500 } |
1506 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr) | 1501 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr); |
1507 ->MarkAsControl(); | |
1508 } | 1502 } |
1509 | 1503 |
1510 | 1504 |
1511 void InstructionSelector::VisitWord32Equal(Node* const node) { | 1505 void InstructionSelector::VisitWord32Equal(Node* const node) { |
1512 Node* const user = node; | 1506 Node* const user = node; |
1513 FlagsContinuation cont(kEqual, node); | 1507 FlagsContinuation cont(kEqual, node); |
1514 Int32BinopMatcher m(user); | 1508 Int32BinopMatcher m(user); |
1515 if (m.right().Is(0)) { | 1509 if (m.right().Is(0)) { |
1516 Node* const value = m.left().node(); | 1510 Node* const value = m.left().node(); |
1517 if (CanCover(user, value)) { | 1511 if (CanCover(user, value)) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1696 MachineOperatorBuilder::kFloat64Max | | 1690 MachineOperatorBuilder::kFloat64Max | |
1697 MachineOperatorBuilder::kFloat64Min | | 1691 MachineOperatorBuilder::kFloat64Min | |
1698 MachineOperatorBuilder::kWord32ShiftIsSafe | | 1692 MachineOperatorBuilder::kWord32ShiftIsSafe | |
1699 MachineOperatorBuilder::kInt32DivIsSafe | | 1693 MachineOperatorBuilder::kInt32DivIsSafe | |
1700 MachineOperatorBuilder::kUint32DivIsSafe; | 1694 MachineOperatorBuilder::kUint32DivIsSafe; |
1701 } | 1695 } |
1702 | 1696 |
1703 } // namespace compiler | 1697 } // namespace compiler |
1704 } // namespace internal | 1698 } // namespace internal |
1705 } // namespace v8 | 1699 } // namespace v8 |
OLD | NEW |