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/compiler/linkage.h" | 6 #include "src/compiler/linkage.h" |
7 #include "src/compiler/register-allocator.h" | 7 #include "src/compiler/register-allocator.h" |
8 #include "src/string-stream.h" | 8 #include "src/string-stream.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 1687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1698 void ConstraintBuilder::MeetConstraintsAfter(int instr_index) { | 1698 void ConstraintBuilder::MeetConstraintsAfter(int instr_index) { |
1699 Instruction* first = code()->InstructionAt(instr_index); | 1699 Instruction* first = code()->InstructionAt(instr_index); |
1700 // Handle fixed temporaries. | 1700 // Handle fixed temporaries. |
1701 for (size_t i = 0; i < first->TempCount(); i++) { | 1701 for (size_t i = 0; i < first->TempCount(); i++) { |
1702 UnallocatedOperand* temp = UnallocatedOperand::cast(first->TempAt(i)); | 1702 UnallocatedOperand* temp = UnallocatedOperand::cast(first->TempAt(i)); |
1703 if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false); | 1703 if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false); |
1704 } | 1704 } |
1705 // Handle constant/fixed output operands. | 1705 // Handle constant/fixed output operands. |
1706 for (size_t i = 0; i < first->OutputCount(); i++) { | 1706 for (size_t i = 0; i < first->OutputCount(); i++) { |
1707 InstructionOperand* output = first->OutputAt(i); | 1707 InstructionOperand* output = first->OutputAt(i); |
| 1708 if (output->IsAllocated()) continue; |
1708 if (output->IsConstant()) { | 1709 if (output->IsConstant()) { |
1709 int output_vreg = ConstantOperand::cast(output)->virtual_register(); | 1710 int output_vreg = ConstantOperand::cast(output)->virtual_register(); |
1710 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(output_vreg); | 1711 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(output_vreg); |
1711 range->SetSpillStartIndex(instr_index + 1); | 1712 range->SetSpillStartIndex(instr_index + 1); |
1712 range->SetSpillOperand(output); | 1713 range->SetSpillOperand(output); |
1713 continue; | 1714 continue; |
1714 } | 1715 } |
1715 UnallocatedOperand* first_output = UnallocatedOperand::cast(output); | 1716 UnallocatedOperand* first_output = UnallocatedOperand::cast(output); |
1716 TopLevelLiveRange* range = | 1717 TopLevelLiveRange* range = |
1717 data()->GetOrCreateLiveRangeFor(first_output->virtual_register()); | 1718 data()->GetOrCreateLiveRangeFor(first_output->virtual_register()); |
(...skipping 26 matching lines...) Expand all Loading... |
1744 range->RecordSpillLocation(allocation_zone(), instr_index + 1, | 1745 range->RecordSpillLocation(allocation_zone(), instr_index + 1, |
1745 first_output); | 1746 first_output); |
1746 range->SetSpillStartIndex(instr_index + 1); | 1747 range->SetSpillStartIndex(instr_index + 1); |
1747 } | 1748 } |
1748 } | 1749 } |
1749 } | 1750 } |
1750 | 1751 |
1751 | 1752 |
1752 void ConstraintBuilder::MeetConstraintsBefore(int instr_index) { | 1753 void ConstraintBuilder::MeetConstraintsBefore(int instr_index) { |
1753 Instruction* second = code()->InstructionAt(instr_index); | 1754 Instruction* second = code()->InstructionAt(instr_index); |
| 1755 ZoneMap<int, InstructionOperand> constraints(allocation_zone()); |
| 1756 |
1754 // Handle fixed input operands of second instruction. | 1757 // Handle fixed input operands of second instruction. |
1755 for (size_t i = 0; i < second->InputCount(); i++) { | 1758 for (size_t i = 0; i < second->InputCount(); ++i) { |
1756 InstructionOperand* input = second->InputAt(i); | 1759 InstructionOperand* input = second->InputAt(i); |
1757 if (input->IsImmediate() || input->IsExplicit()) { | 1760 if (input->IsImmediate() || input->IsExplicit()) { |
1758 continue; // Ignore immediates and explicitly reserved registers. | 1761 continue; // Ignore immediates and explicitly reserved registers. |
1759 } | 1762 } |
1760 UnallocatedOperand* cur_input = UnallocatedOperand::cast(input); | 1763 UnallocatedOperand* cur_input = UnallocatedOperand::cast(input); |
1761 if (cur_input->HasFixedPolicy()) { | 1764 if (cur_input->HasFixedPolicy()) { |
1762 int input_vreg = cur_input->virtual_register(); | 1765 int input_vreg = cur_input->virtual_register(); |
1763 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg); | 1766 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg); |
1764 bool is_tagged = code()->IsReference(input_vreg); | 1767 bool is_tagged = code()->IsReference(input_vreg); |
1765 AllocateFixed(cur_input, instr_index, is_tagged); | 1768 AllocateFixed(cur_input, instr_index, is_tagged); |
| 1769 // TODO(mtrofin): refactor AllocateFixed, its behavior is |
| 1770 // not the most maintainable: cur_input is mutated. |
| 1771 if (cur_input->IsAnyRegister()) { |
| 1772 // It may be that the vreg is constrained to be in different registers. |
| 1773 // We just want one of them for the other potential non-fixed register |
| 1774 // uses. |
| 1775 constraints.insert(std::make_pair(input_vreg, *cur_input)); |
| 1776 } |
1766 data()->AddGapMove(instr_index, Instruction::END, input_copy, *cur_input); | 1777 data()->AddGapMove(instr_index, Instruction::END, input_copy, *cur_input); |
1767 } | 1778 } |
1768 } | 1779 } |
1769 // Handle "output same as input" for second instruction. | 1780 // Handle "output same as input" for second instruction. |
1770 for (size_t i = 0; i < second->OutputCount(); i++) { | 1781 for (size_t i = 0; i < second->OutputCount(); ++i) { |
1771 InstructionOperand* output = second->OutputAt(i); | 1782 InstructionOperand* output = second->OutputAt(i); |
1772 if (!output->IsUnallocated()) continue; | 1783 if (!output->IsUnallocated()) continue; |
1773 UnallocatedOperand* second_output = UnallocatedOperand::cast(output); | 1784 UnallocatedOperand* second_output = UnallocatedOperand::cast(output); |
1774 if (!second_output->HasSameAsInputPolicy()) continue; | 1785 if (!second_output->HasSameAsInputPolicy()) continue; |
1775 DCHECK(i == 0); // Only valid for first output. | 1786 DCHECK(i == 0); // Only valid for first output. |
1776 UnallocatedOperand* cur_input = | 1787 UnallocatedOperand* cur_input = |
1777 UnallocatedOperand::cast(second->InputAt(0)); | 1788 UnallocatedOperand::cast(second->InputAt(0)); |
1778 int output_vreg = second_output->virtual_register(); | 1789 int output_vreg = second_output->virtual_register(); |
1779 int input_vreg = cur_input->virtual_register(); | 1790 int input_vreg = cur_input->virtual_register(); |
1780 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg); | 1791 if (constraints.count(input_vreg) > 0) { |
1781 cur_input->set_virtual_register(second_output->virtual_register()); | 1792 InstructionOperand reg_operand = constraints[input_vreg]; |
1782 MoveOperands* gap_move = data()->AddGapMove(instr_index, Instruction::END, | 1793 InstructionOperand::ReplaceWith(second_output, ®_operand); |
1783 input_copy, *cur_input); | 1794 if (data()->code()->instructions().size() > |
1784 if (code()->IsReference(input_vreg) && !code()->IsReference(output_vreg)) { | 1795 static_cast<size_t>(instr_index) + 1) { |
1785 if (second->HasReferenceMap()) { | 1796 UnallocatedOperand new_output_op(UnallocatedOperand::ANY, output_vreg); |
1786 RegisterAllocationData::DelayedReference delayed_reference = { | 1797 data()->AddGapMove(instr_index + 1, Instruction::START, reg_operand, |
1787 second->reference_map(), &gap_move->source()}; | 1798 new_output_op); |
1788 data()->delayed_references().push_back(delayed_reference); | 1799 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(output_vreg); |
| 1800 range->RecordSpillLocation(allocation_zone(), instr_index + 1, |
| 1801 second_output); |
| 1802 range->SetSpillStartIndex(instr_index + 1); |
1789 } | 1803 } |
1790 } else if (!code()->IsReference(input_vreg) && | 1804 } else { |
1791 code()->IsReference(output_vreg)) { | 1805 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg); |
1792 // The input is assumed to immediately have a tagged representation, | 1806 cur_input->set_virtual_register(second_output->virtual_register()); |
1793 // before the pointer map can be used. I.e. the pointer map at the | 1807 MoveOperands* gap_move = data()->AddGapMove(instr_index, Instruction::END, |
1794 // instruction will include the output operand (whose value at the | 1808 input_copy, *cur_input); |
1795 // beginning of the instruction is equal to the input operand). If | 1809 if (code()->IsReference(input_vreg) && |
1796 // this is not desired, then the pointer map at this instruction needs | 1810 !code()->IsReference(output_vreg)) { |
1797 // to be adjusted manually. | 1811 if (second->HasReferenceMap()) { |
| 1812 RegisterAllocationData::DelayedReference delayed_reference = { |
| 1813 second->reference_map(), &gap_move->source()}; |
| 1814 data()->delayed_references().push_back(delayed_reference); |
| 1815 } |
| 1816 } else if (!code()->IsReference(input_vreg) && |
| 1817 code()->IsReference(output_vreg)) { |
| 1818 // The input is assumed to immediately have a tagged representation, |
| 1819 // before the pointer map can be used. I.e. the pointer map at the |
| 1820 // instruction will include the output operand (whose value at the |
| 1821 // beginning of the instruction is equal to the input operand). If |
| 1822 // this is not desired, then the pointer map at this instruction needs |
| 1823 // to be adjusted manually. |
| 1824 } |
| 1825 } |
| 1826 } |
| 1827 |
| 1828 for (size_t i = 0; i < second->InputCount(); ++i) { |
| 1829 InstructionOperand* input = second->InputAt(i); |
| 1830 if (!input->IsUnallocated()) continue; |
| 1831 UnallocatedOperand* cur_input = UnallocatedOperand::cast(input); |
| 1832 if (cur_input->HasFixedPolicy() || cur_input->HasSlotPolicy()) { |
| 1833 continue; |
| 1834 } |
| 1835 int vreg = cur_input->virtual_register(); |
| 1836 if (constraints.count(vreg) > 0) { |
| 1837 InstructionOperand::ReplaceWith(input, &constraints.at(vreg)); |
1798 } | 1838 } |
1799 } | 1839 } |
1800 } | 1840 } |
1801 | 1841 |
1802 | 1842 |
1803 void ConstraintBuilder::ResolvePhis() { | 1843 void ConstraintBuilder::ResolvePhis() { |
1804 // Process the blocks in reverse order. | 1844 // Process the blocks in reverse order. |
1805 for (InstructionBlock* block : base::Reversed(code()->instruction_blocks())) { | 1845 for (InstructionBlock* block : base::Reversed(code()->instruction_blocks())) { |
1806 ResolvePhis(block); | 1846 ResolvePhis(block); |
1807 } | 1847 } |
(...skipping 2202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4010 } | 4050 } |
4011 } | 4051 } |
4012 } | 4052 } |
4013 } | 4053 } |
4014 } | 4054 } |
4015 | 4055 |
4016 | 4056 |
4017 } // namespace compiler | 4057 } // namespace compiler |
4018 } // namespace internal | 4058 } // namespace internal |
4019 } // namespace v8 | 4059 } // namespace v8 |
OLD | NEW |