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/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/base/bits.h" | 6 #include "src/base/bits.h" |
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 | 10 |
(...skipping 13 matching lines...) Expand all Loading... |
24 explicit Mips64OperandGenerator(InstructionSelector* selector) | 24 explicit Mips64OperandGenerator(InstructionSelector* selector) |
25 : OperandGenerator(selector) {} | 25 : OperandGenerator(selector) {} |
26 | 26 |
27 InstructionOperand UseOperand(Node* node, InstructionCode opcode) { | 27 InstructionOperand UseOperand(Node* node, InstructionCode opcode) { |
28 if (CanBeImmediate(node, opcode)) { | 28 if (CanBeImmediate(node, opcode)) { |
29 return UseImmediate(node); | 29 return UseImmediate(node); |
30 } | 30 } |
31 return UseRegister(node); | 31 return UseRegister(node); |
32 } | 32 } |
33 | 33 |
| 34 // Use the zero register if the node has the immediate value zero, otherwise |
| 35 // assign a register. |
| 36 InstructionOperand UseRegisterOrImmediateZero(Node* node) { |
| 37 if ((IsIntegerConstant(node) && (GetIntegerConstantValue(node) == 0)) || |
| 38 (IsFloatConstant(node) && |
| 39 (bit_cast<int64_t>(GetFloatConstantValue(node)) == V8_INT64_C(0)))) { |
| 40 return UseImmediate(node); |
| 41 } |
| 42 return UseRegister(node); |
| 43 } |
| 44 |
34 bool IsIntegerConstant(Node* node) { | 45 bool IsIntegerConstant(Node* node) { |
35 return (node->opcode() == IrOpcode::kInt32Constant) || | 46 return (node->opcode() == IrOpcode::kInt32Constant) || |
36 (node->opcode() == IrOpcode::kInt64Constant); | 47 (node->opcode() == IrOpcode::kInt64Constant); |
37 } | 48 } |
38 | 49 |
39 int64_t GetIntegerConstantValue(Node* node) { | 50 int64_t GetIntegerConstantValue(Node* node) { |
40 if (node->opcode() == IrOpcode::kInt32Constant) { | 51 if (node->opcode() == IrOpcode::kInt32Constant) { |
41 return OpParameter<int32_t>(node); | 52 return OpParameter<int32_t>(node); |
42 } | 53 } |
43 DCHECK(node->opcode() == IrOpcode::kInt64Constant); | 54 DCHECK(node->opcode() == IrOpcode::kInt64Constant); |
44 return OpParameter<int64_t>(node); | 55 return OpParameter<int64_t>(node); |
45 } | 56 } |
46 | 57 |
| 58 bool IsFloatConstant(Node* node) { |
| 59 return (node->opcode() == IrOpcode::kFloat32Constant) || |
| 60 (node->opcode() == IrOpcode::kFloat64Constant); |
| 61 } |
| 62 |
| 63 double GetFloatConstantValue(Node* node) { |
| 64 if (node->opcode() == IrOpcode::kFloat32Constant) { |
| 65 return OpParameter<float>(node); |
| 66 } |
| 67 DCHECK_EQ(IrOpcode::kFloat64Constant, node->opcode()); |
| 68 return OpParameter<double>(node); |
| 69 } |
| 70 |
47 bool CanBeImmediate(Node* node, InstructionCode mode) { | 71 bool CanBeImmediate(Node* node, InstructionCode mode) { |
48 return IsIntegerConstant(node) && | 72 return IsIntegerConstant(node) && |
49 CanBeImmediate(GetIntegerConstantValue(node), mode); | 73 CanBeImmediate(GetIntegerConstantValue(node), mode); |
50 } | 74 } |
51 | 75 |
52 bool CanBeImmediate(int64_t value, InstructionCode opcode) { | 76 bool CanBeImmediate(int64_t value, InstructionCode opcode) { |
53 switch (ArchOpcodeField::decode(opcode)) { | 77 switch (ArchOpcodeField::decode(opcode)) { |
54 case kMips64Shl: | 78 case kMips64Shl: |
55 case kMips64Sar: | 79 case kMips64Sar: |
56 case kMips64Shr: | 80 case kMips64Shr: |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 opcode = kMips64Sd; | 417 opcode = kMips64Sd; |
394 break; | 418 break; |
395 case MachineRepresentation::kSimd128: // Fall through. | 419 case MachineRepresentation::kSimd128: // Fall through. |
396 case MachineRepresentation::kNone: | 420 case MachineRepresentation::kNone: |
397 UNREACHABLE(); | 421 UNREACHABLE(); |
398 return; | 422 return; |
399 } | 423 } |
400 | 424 |
401 if (g.CanBeImmediate(index, opcode)) { | 425 if (g.CanBeImmediate(index, opcode)) { |
402 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 426 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
403 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 427 g.UseRegister(base), g.UseImmediate(index), |
| 428 g.UseRegisterOrImmediateZero(value)); |
404 } else { | 429 } else { |
405 InstructionOperand addr_reg = g.TempRegister(); | 430 InstructionOperand addr_reg = g.TempRegister(); |
406 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, | 431 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, |
407 g.UseRegister(index), g.UseRegister(base)); | 432 g.UseRegister(index), g.UseRegister(base)); |
408 // Emit desired store opcode, using temp addr_reg. | 433 // Emit desired store opcode, using temp addr_reg. |
409 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 434 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
410 addr_reg, g.TempImmediate(0), g.UseRegister(value)); | 435 addr_reg, g.TempImmediate(0), g.UseRegisterOrImmediateZero(value)); |
411 } | 436 } |
412 } | 437 } |
413 } | 438 } |
414 | 439 |
415 | 440 |
416 void InstructionSelector::VisitWord32And(Node* node) { | 441 void InstructionSelector::VisitWord32And(Node* node) { |
417 Mips64OperandGenerator g(this); | 442 Mips64OperandGenerator g(this); |
418 Int32BinopMatcher m(node); | 443 Int32BinopMatcher m(node); |
419 if (m.left().IsWord32Shr() && CanCover(node, m.left().node()) && | 444 if (m.left().IsWord32Shr() && CanCover(node, m.left().node()) && |
420 m.right().HasValue()) { | 445 m.right().HasValue()) { |
(...skipping 1311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1732 opcode = kMips64Usd; | 1757 opcode = kMips64Usd; |
1733 break; | 1758 break; |
1734 case MachineRepresentation::kSimd128: // Fall through. | 1759 case MachineRepresentation::kSimd128: // Fall through. |
1735 case MachineRepresentation::kNone: | 1760 case MachineRepresentation::kNone: |
1736 UNREACHABLE(); | 1761 UNREACHABLE(); |
1737 return; | 1762 return; |
1738 } | 1763 } |
1739 | 1764 |
1740 if (g.CanBeImmediate(index, opcode)) { | 1765 if (g.CanBeImmediate(index, opcode)) { |
1741 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 1766 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
1742 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 1767 g.UseRegister(base), g.UseImmediate(index), |
| 1768 g.UseRegisterOrImmediateZero(value)); |
1743 } else { | 1769 } else { |
1744 InstructionOperand addr_reg = g.TempRegister(); | 1770 InstructionOperand addr_reg = g.TempRegister(); |
1745 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, | 1771 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, |
1746 g.UseRegister(index), g.UseRegister(base)); | 1772 g.UseRegister(index), g.UseRegister(base)); |
1747 // Emit desired store opcode, using temp addr_reg. | 1773 // Emit desired store opcode, using temp addr_reg. |
1748 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 1774 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
1749 addr_reg, g.TempImmediate(0), g.UseRegister(value)); | 1775 addr_reg, g.TempImmediate(0), g.UseRegisterOrImmediateZero(value)); |
1750 } | 1776 } |
1751 } | 1777 } |
1752 | 1778 |
1753 void InstructionSelector::VisitCheckedLoad(Node* node) { | 1779 void InstructionSelector::VisitCheckedLoad(Node* node) { |
1754 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); | 1780 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); |
1755 Mips64OperandGenerator g(this); | 1781 Mips64OperandGenerator g(this); |
1756 Node* const buffer = node->InputAt(0); | 1782 Node* const buffer = node->InputAt(0); |
1757 Node* const offset = node->InputAt(1); | 1783 Node* const offset = node->InputAt(1); |
1758 Node* const length = node->InputAt(2); | 1784 Node* const length = node->InputAt(2); |
1759 ArchOpcode opcode = kArchNop; | 1785 ArchOpcode opcode = kArchNop; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1841 ? g.UseImmediate(offset) | 1867 ? g.UseImmediate(offset) |
1842 : g.UseRegister(offset); | 1868 : g.UseRegister(offset); |
1843 | 1869 |
1844 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) | 1870 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) |
1845 ? g.CanBeImmediate(length, opcode) | 1871 ? g.CanBeImmediate(length, opcode) |
1846 ? g.UseImmediate(length) | 1872 ? g.UseImmediate(length) |
1847 : g.UseRegister(length) | 1873 : g.UseRegister(length) |
1848 : g.UseRegister(length); | 1874 : g.UseRegister(length); |
1849 | 1875 |
1850 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 1876 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
1851 offset_operand, length_operand, g.UseRegister(value), | 1877 offset_operand, length_operand, g.UseRegisterOrImmediateZero(value), |
1852 g.UseRegister(buffer)); | 1878 g.UseRegister(buffer)); |
1853 } | 1879 } |
1854 | 1880 |
1855 | 1881 |
1856 namespace { | 1882 namespace { |
1857 | 1883 |
1858 // Shared routine for multiple compare operations. | 1884 // Shared routine for multiple compare operations. |
1859 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1885 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1860 InstructionOperand left, InstructionOperand right, | 1886 InstructionOperand left, InstructionOperand right, |
1861 FlagsContinuation* cont) { | 1887 FlagsContinuation* cont) { |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2484 case MachineRepresentation::kWord32: | 2510 case MachineRepresentation::kWord32: |
2485 opcode = kAtomicStoreWord32; | 2511 opcode = kAtomicStoreWord32; |
2486 break; | 2512 break; |
2487 default: | 2513 default: |
2488 UNREACHABLE(); | 2514 UNREACHABLE(); |
2489 return; | 2515 return; |
2490 } | 2516 } |
2491 | 2517 |
2492 if (g.CanBeImmediate(index, opcode)) { | 2518 if (g.CanBeImmediate(index, opcode)) { |
2493 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 2519 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
2494 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 2520 g.UseRegister(base), g.UseImmediate(index), |
| 2521 g.UseRegisterOrImmediateZero(value)); |
2495 } else { | 2522 } else { |
2496 InstructionOperand addr_reg = g.TempRegister(); | 2523 InstructionOperand addr_reg = g.TempRegister(); |
2497 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, | 2524 Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg, |
2498 g.UseRegister(index), g.UseRegister(base)); | 2525 g.UseRegister(index), g.UseRegister(base)); |
2499 // Emit desired store opcode, using temp addr_reg. | 2526 // Emit desired store opcode, using temp addr_reg. |
2500 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), | 2527 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
2501 addr_reg, g.TempImmediate(0), g.UseRegister(value)); | 2528 addr_reg, g.TempImmediate(0), g.UseRegisterOrImmediateZero(value)); |
2502 } | 2529 } |
2503 } | 2530 } |
2504 | 2531 |
2505 // static | 2532 // static |
2506 MachineOperatorBuilder::Flags | 2533 MachineOperatorBuilder::Flags |
2507 InstructionSelector::SupportedMachineOperatorFlags() { | 2534 InstructionSelector::SupportedMachineOperatorFlags() { |
2508 MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags; | 2535 MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::kNoFlags; |
2509 return flags | MachineOperatorBuilder::kWord32Ctz | | 2536 return flags | MachineOperatorBuilder::kWord32Ctz | |
2510 MachineOperatorBuilder::kWord64Ctz | | 2537 MachineOperatorBuilder::kWord64Ctz | |
2511 MachineOperatorBuilder::kWord32Popcnt | | 2538 MachineOperatorBuilder::kWord32Popcnt | |
(...skipping 22 matching lines...) Expand all Loading... |
2534 } else { | 2561 } else { |
2535 DCHECK(kArchVariant == kMips64r2); | 2562 DCHECK(kArchVariant == kMips64r2); |
2536 return MachineOperatorBuilder::AlignmentRequirements:: | 2563 return MachineOperatorBuilder::AlignmentRequirements:: |
2537 NoUnalignedAccessSupport(); | 2564 NoUnalignedAccessSupport(); |
2538 } | 2565 } |
2539 } | 2566 } |
2540 | 2567 |
2541 } // namespace compiler | 2568 } // namespace compiler |
2542 } // namespace internal | 2569 } // namespace internal |
2543 } // namespace v8 | 2570 } // namespace v8 |
OLD | NEW |