Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(482)

Side by Side Diff: src/compiler/register-allocator.cc

Issue 1426943010: [turbofan] Spill rsi and rdi in their existing locations. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/register-allocator.h ('k') | src/compiler/register-allocator-verifier.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 653 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 for (auto interval = first_interval(); interval != nullptr; 664 for (auto interval = first_interval(); interval != nullptr;
665 interval = interval->next()) { 665 interval = interval->next()) {
666 size_ += (interval->end().value() - interval->start().value()); 666 size_ += (interval->end().value() - interval->start().value());
667 } 667 }
668 } 668 }
669 669
670 return static_cast<unsigned>(size_); 670 return static_cast<unsigned>(size_);
671 } 671 }
672 672
673 673
674 struct TopLevelLiveRange::SpillAtDefinitionList : ZoneObject { 674 struct TopLevelLiveRange::SpillMoveInsertionList : ZoneObject {
675 SpillAtDefinitionList(int gap_index, InstructionOperand* operand, 675 SpillMoveInsertionList(int gap_index, InstructionOperand* operand,
676 SpillAtDefinitionList* next) 676 SpillMoveInsertionList* next)
677 : gap_index(gap_index), operand(operand), next(next) {} 677 : gap_index(gap_index), operand(operand), next(next) {}
678 const int gap_index; 678 const int gap_index;
679 InstructionOperand* const operand; 679 InstructionOperand* const operand;
680 SpillAtDefinitionList* const next; 680 SpillMoveInsertionList* const next;
681 }; 681 };
682 682
683 683
684 TopLevelLiveRange::TopLevelLiveRange(int vreg, MachineType machine_type) 684 TopLevelLiveRange::TopLevelLiveRange(int vreg, MachineType machine_type)
685 : LiveRange(0, machine_type, this), 685 : LiveRange(0, machine_type, this),
686 vreg_(vreg), 686 vreg_(vreg),
687 last_child_id_(0), 687 last_child_id_(0),
688 splintered_from_(nullptr), 688 splintered_from_(nullptr),
689 spill_operand_(nullptr), 689 spill_operand_(nullptr),
690 spills_at_definition_(nullptr), 690 spill_move_insertion_locations_(nullptr),
691 spilled_in_deferred_blocks_(false), 691 spilled_in_deferred_blocks_(false),
692 spill_start_index_(kMaxInt), 692 spill_start_index_(kMaxInt),
693 last_child_(this), 693 last_child_(this),
694 last_pos_(nullptr), 694 last_pos_(nullptr),
695 splinter_(nullptr) { 695 splinter_(nullptr),
696 has_preassigned_slot_(false) {
696 bits_ |= SpillTypeField::encode(SpillType::kNoSpillType); 697 bits_ |= SpillTypeField::encode(SpillType::kNoSpillType);
697 } 698 }
698 699
699 700
700 #if DEBUG 701 #if DEBUG
701 int TopLevelLiveRange::debug_virt_reg() const { 702 int TopLevelLiveRange::debug_virt_reg() const {
702 return IsSplinter() ? splintered_from()->vreg() : vreg(); 703 return IsSplinter() ? splintered_from()->vreg() : vreg();
703 } 704 }
704 #endif 705 #endif
705 706
706 707
707 void TopLevelLiveRange::SpillAtDefinition(Zone* zone, int gap_index, 708 void TopLevelLiveRange::RecordSpillLocation(Zone* zone, int gap_index,
708 InstructionOperand* operand) { 709 InstructionOperand* operand) {
709 DCHECK(HasNoSpillType()); 710 DCHECK(HasNoSpillType());
710 spills_at_definition_ = new (zone) 711 spill_move_insertion_locations_ = new (zone) SpillMoveInsertionList(
711 SpillAtDefinitionList(gap_index, operand, spills_at_definition_); 712 gap_index, operand, spill_move_insertion_locations_);
712 } 713 }
713 714
714 715
715 void TopLevelLiveRange::MarkSpilledInDeferredBlock( 716 void TopLevelLiveRange::MarkSpilledInDeferredBlock(
716 const InstructionSequence* code) { 717 const InstructionSequence* code) {
717 if (!FLAG_turbo_preprocess_ranges || IsEmpty() || HasNoSpillType() || 718 if (!FLAG_turbo_preprocess_ranges || IsEmpty() || HasNoSpillType() ||
718 !HasSpillRange()) { 719 !HasSpillRange()) {
719 return; 720 return;
720 } 721 }
721 722
(...skipping 25 matching lines...) Expand all
747 return; 748 return;
748 } 749 }
749 } else { 750 } else {
750 if (child->spilled() || has_slot_use) ++count; 751 if (child->spilled() || has_slot_use) ++count;
751 } 752 }
752 } 753 }
753 if (count == 0) return; 754 if (count == 0) return;
754 755
755 spill_start_index_ = -1; 756 spill_start_index_ = -1;
756 spilled_in_deferred_blocks_ = true; 757 spilled_in_deferred_blocks_ = true;
757 spills_at_definition_ = nullptr; 758 spill_move_insertion_locations_ = nullptr;
758 } 759 }
759 760
760 761
761 bool TopLevelLiveRange::TryCommitSpillInDeferredBlock( 762 bool TopLevelLiveRange::TryCommitSpillInDeferredBlock(
762 InstructionSequence* code, const InstructionOperand& spill_operand) { 763 InstructionSequence* code, const InstructionOperand& spill_operand) {
763 if (!IsSpilledOnlyInDeferredBlocks()) return false; 764 if (!IsSpilledOnlyInDeferredBlocks()) return false;
764 765
765 TRACE("Live Range %d will be spilled only in deferred blocks.\n", vreg()); 766 TRACE("Live Range %d will be spilled only in deferred blocks.\n", vreg());
766 // If we have ranges that aren't spilled but require the operand on the stack, 767 // If we have ranges that aren't spilled but require the operand on the stack,
767 // make sure we insert the spill. 768 // make sure we insert the spill.
(...skipping 19 matching lines...) Expand all
787 } 788 }
788 789
789 move->AddMove(assigned, spill_operand); 790 move->AddMove(assigned, spill_operand);
790 } 791 }
791 } 792 }
792 793
793 return true; 794 return true;
794 } 795 }
795 796
796 797
797 void TopLevelLiveRange::CommitSpillsAtDefinition(InstructionSequence* sequence, 798 void TopLevelLiveRange::CommitSpillMoves(InstructionSequence* sequence,
798 const InstructionOperand& op, 799 const InstructionOperand& op,
799 bool might_be_duplicated) { 800 bool might_be_duplicated) {
800 DCHECK_IMPLIES(op.IsConstant(), spills_at_definition_ == nullptr); 801 DCHECK_IMPLIES(op.IsConstant(), spill_move_insertion_locations() == nullptr);
801 auto zone = sequence->zone(); 802 auto zone = sequence->zone();
802 803
803 for (auto to_spill = spills_at_definition_; to_spill != nullptr; 804 for (auto to_spill = spill_move_insertion_locations(); to_spill != nullptr;
804 to_spill = to_spill->next) { 805 to_spill = to_spill->next) {
805 auto instr = sequence->InstructionAt(to_spill->gap_index); 806 auto instr = sequence->InstructionAt(to_spill->gap_index);
806 auto move = instr->GetOrCreateParallelMove(Instruction::START, zone); 807 auto move = instr->GetOrCreateParallelMove(Instruction::START, zone);
807 // Skip insertion if it's possible that the move exists already as a 808 // Skip insertion if it's possible that the move exists already as a
808 // constraint move from a fixed output register to a slot. 809 // constraint move from a fixed output register to a slot.
809 if (might_be_duplicated) { 810 if (might_be_duplicated || has_preassigned_slot()) {
810 bool found = false; 811 bool found = false;
811 for (auto move_op : *move) { 812 for (auto move_op : *move) {
812 if (move_op->IsEliminated()) continue; 813 if (move_op->IsEliminated()) continue;
813 if (move_op->source().Equals(*to_spill->operand) && 814 if (move_op->source().Equals(*to_spill->operand) &&
814 move_op->destination().Equals(op)) { 815 move_op->destination().Equals(op)) {
815 found = true; 816 found = true;
817 if (has_preassigned_slot()) move_op->Eliminate();
816 break; 818 break;
817 } 819 }
818 } 820 }
819 if (found) continue; 821 if (found) continue;
820 } 822 }
821 move->AddMove(*to_spill->operand, op); 823 move->AddMove(*to_spill->operand, op);
822 } 824 }
823 } 825 }
824 826
825 827
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg); 1604 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg);
1603 data()->AddGapMove(gap_index, Instruction::START, *output, output_copy); 1605 data()->AddGapMove(gap_index, Instruction::START, *output, output_copy);
1604 } 1606 }
1605 } 1607 }
1606 1608
1607 if (!assigned) { 1609 if (!assigned) {
1608 for (auto succ : block->successors()) { 1610 for (auto succ : block->successors()) {
1609 const InstructionBlock* successor = code()->InstructionBlockAt(succ); 1611 const InstructionBlock* successor = code()->InstructionBlockAt(succ);
1610 DCHECK(successor->PredecessorCount() == 1); 1612 DCHECK(successor->PredecessorCount() == 1);
1611 int gap_index = successor->first_instruction_index(); 1613 int gap_index = successor->first_instruction_index();
1612 range->SpillAtDefinition(allocation_zone(), gap_index, output); 1614 range->RecordSpillLocation(allocation_zone(), gap_index, output);
1613 range->SetSpillStartIndex(gap_index); 1615 range->SetSpillStartIndex(gap_index);
1614 } 1616 }
1615 } 1617 }
1616 } 1618 }
1617 } 1619 }
1618 1620
1619 1621
1620 void ConstraintBuilder::MeetConstraintsAfter(int instr_index) { 1622 void ConstraintBuilder::MeetConstraintsAfter(int instr_index) {
1621 auto first = code()->InstructionAt(instr_index); 1623 auto first = code()->InstructionAt(instr_index);
1622 // Handle fixed temporaries. 1624 // Handle fixed temporaries.
(...skipping 12 matching lines...) Expand all
1635 continue; 1637 continue;
1636 } 1638 }
1637 auto first_output = UnallocatedOperand::cast(output); 1639 auto first_output = UnallocatedOperand::cast(output);
1638 auto range = 1640 auto range =
1639 data()->GetOrCreateLiveRangeFor(first_output->virtual_register()); 1641 data()->GetOrCreateLiveRangeFor(first_output->virtual_register());
1640 bool assigned = false; 1642 bool assigned = false;
1641 if (first_output->HasFixedPolicy()) { 1643 if (first_output->HasFixedPolicy()) {
1642 int output_vreg = first_output->virtual_register(); 1644 int output_vreg = first_output->virtual_register();
1643 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg); 1645 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg);
1644 bool is_tagged = code()->IsReference(output_vreg); 1646 bool is_tagged = code()->IsReference(output_vreg);
1647 if (first_output->HasSecondaryStorage()) {
1648 range->MarkHasPreassignedSlot();
1649 InstructionOperand* spill_op = AllocatedOperand::New(
1650 data()->code_zone(), LocationOperand::LocationKind::STACK_SLOT,
1651 range->machine_type(), first_output->GetSecondaryStorage());
1652 range->RecordSpillLocation(allocation_zone(), instr_index + 1,
1653 first_output);
1654 range->SetSpillOperand(spill_op);
1655 range->SetSpillStartIndex(instr_index + 1);
1656 assigned = true;
1657 }
1645 AllocateFixed(first_output, instr_index, is_tagged); 1658 AllocateFixed(first_output, instr_index, is_tagged);
1646 1659
1647 // This value is produced on the stack, we never need to spill it. 1660 // This value is produced on the stack, we never need to spill it.
1648 if (first_output->IsStackSlot()) { 1661 if (first_output->IsStackSlot()) {
1649 DCHECK(LocationOperand::cast(first_output)->index() < 1662 DCHECK(LocationOperand::cast(first_output)->index() <
1650 data()->frame()->GetTotalFrameSlotCount()); 1663 data()->frame()->GetTotalFrameSlotCount());
1651 range->SetSpillOperand(LocationOperand::cast(first_output)); 1664 range->SetSpillOperand(LocationOperand::cast(first_output));
1652 range->SetSpillStartIndex(instr_index + 1); 1665 range->SetSpillStartIndex(instr_index + 1);
1653 assigned = true; 1666 assigned = true;
1654 } 1667 }
1655 data()->AddGapMove(instr_index + 1, Instruction::START, *first_output, 1668 data()->AddGapMove(instr_index + 1, Instruction::START, *first_output,
1656 output_copy); 1669 output_copy);
1657 } 1670 }
1658 // Make sure we add a gap move for spilling (if we have not done 1671 // Make sure we add a gap move for spilling (if we have not done
1659 // so already). 1672 // so already).
1660 if (!assigned) { 1673 if (!assigned) {
1661 range->SpillAtDefinition(allocation_zone(), instr_index + 1, 1674 range->RecordSpillLocation(allocation_zone(), instr_index + 1,
1662 first_output); 1675 first_output);
1663 range->SetSpillStartIndex(instr_index + 1); 1676 range->SetSpillStartIndex(instr_index + 1);
1664 } 1677 }
1665 } 1678 }
1666 } 1679 }
1667 1680
1668 1681
1669 void ConstraintBuilder::MeetConstraintsBefore(int instr_index) { 1682 void ConstraintBuilder::MeetConstraintsBefore(int instr_index) {
1670 auto second = code()->InstructionAt(instr_index); 1683 auto second = code()->InstructionAt(instr_index);
1671 // Handle fixed input operands of second instruction. 1684 // Handle fixed input operands of second instruction.
1672 for (size_t i = 0; i < second->InputCount(); i++) { 1685 for (size_t i = 0; i < second->InputCount(); i++) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1737 UnallocatedOperand input(UnallocatedOperand::ANY, phi->operands()[i]); 1750 UnallocatedOperand input(UnallocatedOperand::ANY, phi->operands()[i]);
1738 auto move = data()->AddGapMove(cur_block->last_instruction_index(), 1751 auto move = data()->AddGapMove(cur_block->last_instruction_index(),
1739 Instruction::END, input, output); 1752 Instruction::END, input, output);
1740 map_value->AddOperand(&move->destination()); 1753 map_value->AddOperand(&move->destination());
1741 DCHECK(!code() 1754 DCHECK(!code()
1742 ->InstructionAt(cur_block->last_instruction_index()) 1755 ->InstructionAt(cur_block->last_instruction_index())
1743 ->HasReferenceMap()); 1756 ->HasReferenceMap());
1744 } 1757 }
1745 auto live_range = data()->GetOrCreateLiveRangeFor(phi_vreg); 1758 auto live_range = data()->GetOrCreateLiveRangeFor(phi_vreg);
1746 int gap_index = block->first_instruction_index(); 1759 int gap_index = block->first_instruction_index();
1747 live_range->SpillAtDefinition(allocation_zone(), gap_index, &output); 1760 live_range->RecordSpillLocation(allocation_zone(), gap_index, &output);
1748 live_range->SetSpillStartIndex(gap_index); 1761 live_range->SetSpillStartIndex(gap_index);
1749 // We use the phi-ness of some nodes in some later heuristics. 1762 // We use the phi-ness of some nodes in some later heuristics.
1750 live_range->set_is_phi(true); 1763 live_range->set_is_phi(true);
1751 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); 1764 live_range->set_is_non_loop_phi(!block->IsLoopHeader());
1752 } 1765 }
1753 } 1766 }
1754 1767
1755 1768
1756 LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data, 1769 LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data,
1757 Zone* local_zone) 1770 Zone* local_zone)
(...skipping 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after
2952 if (!range->HasSpillRange()) continue; 2965 if (!range->HasSpillRange()) continue;
2953 range->MarkSpilledInDeferredBlock(data()->code()); 2966 range->MarkSpilledInDeferredBlock(data()->code());
2954 if (range->IsSpilledOnlyInDeferredBlocks()) { 2967 if (range->IsSpilledOnlyInDeferredBlocks()) {
2955 for (LiveRange* child = range; child != nullptr; child = child->next()) { 2968 for (LiveRange* child = range; child != nullptr; child = child->next()) {
2956 if (child->spilled()) { 2969 if (child->spilled()) {
2957 code->GetInstructionBlock(child->Start().ToInstructionIndex()) 2970 code->GetInstructionBlock(child->Start().ToInstructionIndex())
2958 ->mark_needs_frame(); 2971 ->mark_needs_frame();
2959 } 2972 }
2960 } 2973 }
2961 } else { 2974 } else {
2962 auto spills = range->spills_at_definition(); 2975 auto spills = range->spill_move_insertion_locations();
2963 DCHECK_NOT_NULL(spills); 2976 DCHECK_NOT_NULL(spills);
2964 for (; spills != nullptr; spills = spills->next) { 2977 for (; spills != nullptr; spills = spills->next) {
2965 code->GetInstructionBlock(spills->gap_index)->mark_needs_frame(); 2978 code->GetInstructionBlock(spills->gap_index)->mark_needs_frame();
2966 } 2979 }
2967 } 2980 }
2968 } 2981 }
2969 } 2982 }
2970 2983
2971 2984
2972 OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {} 2985 OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {}
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3025 // spilled range picks up its value from the slot which was assigned at 3038 // spilled range picks up its value from the slot which was assigned at
3026 // definition. For ranges that are determined to spill only in deferred 3039 // definition. For ranges that are determined to spill only in deferred
3027 // blocks, we let ConnectLiveRanges and ResolveControlFlow insert such 3040 // blocks, we let ConnectLiveRanges and ResolveControlFlow insert such
3028 // moves between ranges. Because of how the ranges are split around 3041 // moves between ranges. Because of how the ranges are split around
3029 // deferred blocks, this amounts to spilling and filling inside such 3042 // deferred blocks, this amounts to spilling and filling inside such
3030 // blocks. 3043 // blocks.
3031 if (!top_range->TryCommitSpillInDeferredBlock(data()->code(), 3044 if (!top_range->TryCommitSpillInDeferredBlock(data()->code(),
3032 spill_operand)) { 3045 spill_operand)) {
3033 // Spill at definition if the range isn't spilled only in deferred 3046 // Spill at definition if the range isn't spilled only in deferred
3034 // blocks. 3047 // blocks.
3035 top_range->CommitSpillsAtDefinition( 3048 top_range->CommitSpillMoves(
3036 data()->code(), spill_operand, 3049 data()->code(), spill_operand,
3037 top_range->has_slot_use() || top_range->spilled()); 3050 top_range->has_slot_use() || top_range->spilled());
3038 } 3051 }
3039 } 3052 }
3040 } 3053 }
3041 } 3054 }
3042 3055
3043 3056
3044 ReferenceMapPopulator::ReferenceMapPopulator(RegisterAllocationData* data) 3057 ReferenceMapPopulator::ReferenceMapPopulator(RegisterAllocationData* data)
3045 : data_(data) {} 3058 : data_(data) {}
(...skipping 20 matching lines...) Expand all
3066 // for all spilled live ranges at this point. 3079 // for all spilled live ranges at this point.
3067 int last_range_start = 0; 3080 int last_range_start = 0;
3068 auto reference_maps = data()->code()->reference_maps(); 3081 auto reference_maps = data()->code()->reference_maps();
3069 ReferenceMapDeque::const_iterator first_it = reference_maps->begin(); 3082 ReferenceMapDeque::const_iterator first_it = reference_maps->begin();
3070 for (TopLevelLiveRange* range : data()->live_ranges()) { 3083 for (TopLevelLiveRange* range : data()->live_ranges()) {
3071 if (range == nullptr) continue; 3084 if (range == nullptr) continue;
3072 // Skip non-reference values. 3085 // Skip non-reference values.
3073 if (!data()->IsReference(range)) continue; 3086 if (!data()->IsReference(range)) continue;
3074 // Skip empty live ranges. 3087 // Skip empty live ranges.
3075 if (range->IsEmpty()) continue; 3088 if (range->IsEmpty()) continue;
3089 if (range->has_preassigned_slot()) continue;
3076 3090
3077 // Find the extent of the range and its children. 3091 // Find the extent of the range and its children.
3078 int start = range->Start().ToInstructionIndex(); 3092 int start = range->Start().ToInstructionIndex();
3079 int end = 0; 3093 int end = 0;
3080 for (LiveRange* cur = range; cur != nullptr; cur = cur->next()) { 3094 for (LiveRange* cur = range; cur != nullptr; cur = cur->next()) {
3081 auto this_end = cur->End(); 3095 auto this_end = cur->End();
3082 if (this_end.ToInstructionIndex() > end) 3096 if (this_end.ToInstructionIndex() > end)
3083 end = this_end.ToInstructionIndex(); 3097 end = this_end.ToInstructionIndex();
3084 DCHECK(cur->Start().ToInstructionIndex() >= start); 3098 DCHECK(cur->Start().ToInstructionIndex() >= start);
3085 } 3099 }
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
3441 auto eliminate = moves->PrepareInsertAfter(move); 3455 auto eliminate = moves->PrepareInsertAfter(move);
3442 to_insert.push_back(move); 3456 to_insert.push_back(move);
3443 if (eliminate != nullptr) to_eliminate.push_back(eliminate); 3457 if (eliminate != nullptr) to_eliminate.push_back(eliminate);
3444 } 3458 }
3445 } 3459 }
3446 3460
3447 3461
3448 } // namespace compiler 3462 } // namespace compiler
3449 } // namespace internal 3463 } // namespace internal
3450 } // namespace v8 3464 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.h ('k') | src/compiler/register-allocator-verifier.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698