| 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 |