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

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
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 674 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 spills_at_definition_(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 elidable_def_(nullptr) {
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
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after
1618 1619
1619 1620
1620 void ConstraintBuilder::MeetConstraintsAfter(int instr_index) { 1621 void ConstraintBuilder::MeetConstraintsAfter(int instr_index) {
1621 auto first = code()->InstructionAt(instr_index); 1622 auto first = code()->InstructionAt(instr_index);
1622 // Handle fixed temporaries. 1623 // Handle fixed temporaries.
1623 for (size_t i = 0; i < first->TempCount(); i++) { 1624 for (size_t i = 0; i < first->TempCount(); i++) {
1624 auto temp = UnallocatedOperand::cast(first->TempAt(i)); 1625 auto temp = UnallocatedOperand::cast(first->TempAt(i));
1625 if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false); 1626 if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false);
1626 } 1627 }
1627 // Handle constant/fixed output operands. 1628 // Handle constant/fixed output operands.
1629 bool is_prespilled_parameter =
1630 first->arch_opcode() == ArchOpcode::kArchNop && first->OutputCount() == 2;
Jarin 2015/11/12 12:08:33 This looks really brittle because we do not even c
Mircea Trofin 2015/11/12 18:01:35 I see. I thought we used ArchNop just for introduc
1631
1628 for (size_t i = 0; i < first->OutputCount(); i++) { 1632 for (size_t i = 0; i < first->OutputCount(); i++) {
1629 InstructionOperand* output = first->OutputAt(i); 1633 InstructionOperand* output = first->OutputAt(i);
1630 if (output->IsConstant()) { 1634 if (output->IsConstant()) {
1631 int output_vreg = ConstantOperand::cast(output)->virtual_register(); 1635 int output_vreg = ConstantOperand::cast(output)->virtual_register();
1632 auto range = data()->GetOrCreateLiveRangeFor(output_vreg); 1636 auto range = data()->GetOrCreateLiveRangeFor(output_vreg);
1633 range->SetSpillStartIndex(instr_index + 1); 1637 range->SetSpillStartIndex(instr_index + 1);
1634 range->SetSpillOperand(output); 1638 range->SetSpillOperand(output);
1635 continue; 1639 continue;
1636 } 1640 }
1637 auto first_output = UnallocatedOperand::cast(output); 1641 auto first_output = UnallocatedOperand::cast(output);
1638 auto range = 1642 auto range =
1639 data()->GetOrCreateLiveRangeFor(first_output->virtual_register()); 1643 data()->GetOrCreateLiveRangeFor(first_output->virtual_register());
1640 bool assigned = false; 1644 bool assigned = false;
1641 if (first_output->HasFixedPolicy()) { 1645 if (first_output->HasFixedPolicy()) {
1642 int output_vreg = first_output->virtual_register(); 1646 int output_vreg = first_output->virtual_register();
1643 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg); 1647 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg);
1644 bool is_tagged = code()->IsReference(output_vreg); 1648 bool is_tagged = code()->IsReference(output_vreg);
1645 AllocateFixed(first_output, instr_index, is_tagged); 1649 AllocateFixed(first_output, instr_index, is_tagged);
1650 MoveOperands* def = data()->AddGapMove(
1651 instr_index + 1, Instruction::START, *first_output, output_copy);
1646 1652
1647 // This value is produced on the stack, we never need to spill it. 1653 // This value is produced on the stack, we never need to spill it.
1648 if (first_output->IsStackSlot()) { 1654 if (first_output->IsStackSlot()) {
1649 DCHECK(LocationOperand::cast(first_output)->index() < 1655 DCHECK(LocationOperand::cast(first_output)->index() <
1650 data()->frame()->GetTotalFrameSlotCount()); 1656 data()->frame()->GetTotalFrameSlotCount());
1651 range->SetSpillOperand(LocationOperand::cast(first_output)); 1657 range->SetSpillOperand(LocationOperand::cast(first_output));
1652 range->SetSpillStartIndex(instr_index + 1); 1658 range->SetSpillStartIndex(instr_index + 1);
1653 assigned = true; 1659 assigned = true;
1660 } else if (is_prespilled_parameter) {
1661 // we need the def so that the live range has the shape expected by
1662 // the rest of the pipeline. Upon assigning operands, if this move
1663 // ends up assigning to the stack slot the register value, we may
1664 // delete it.
Jarin 2015/11/12 12:08:33 To be honest, this MarkElidableDef business seems
Mircea Trofin 2015/11/12 18:01:35 Here's what happens with a vanilla fixed register:
1665 range->MarkElidableDef(def);
1666 UnallocatedOperand* spill_op =
1667 UnallocatedOperand::cast(first->OutputAt(1));
1668 AllocateFixed(spill_op, instr_index, is_tagged);
1669 range->SetSpillOperand(spill_op);
1670 range->SetSpillStartIndex(instr_index + 1);
1671 break;
1654 } 1672 }
1655 data()->AddGapMove(instr_index + 1, Instruction::START, *first_output,
1656 output_copy);
1657 } 1673 }
1658 // Make sure we add a gap move for spilling (if we have not done 1674 // Make sure we add a gap move for spilling (if we have not done
1659 // so already). 1675 // so already).
1660 if (!assigned) { 1676 if (!assigned) {
1661 range->SpillAtDefinition(allocation_zone(), instr_index + 1, 1677 range->SpillAtDefinition(allocation_zone(), instr_index + 1,
1662 first_output); 1678 first_output);
1663 range->SetSpillStartIndex(instr_index + 1); 1679 range->SetSpillStartIndex(instr_index + 1);
1664 } 1680 }
1665 } 1681 }
1666 } 1682 }
(...skipping 1342 matching lines...) Expand 10 before | Expand all | Expand 10 after
3009 if (top_range->is_phi()) { 3025 if (top_range->is_phi()) {
3010 data()->GetPhiMapValueFor(top_range)->CommitAssignment( 3026 data()->GetPhiMapValueFor(top_range)->CommitAssignment(
3011 top_range->GetAssignedOperand()); 3027 top_range->GetAssignedOperand());
3012 } 3028 }
3013 for (LiveRange* range = top_range; range != nullptr; 3029 for (LiveRange* range = top_range; range != nullptr;
3014 range = range->next()) { 3030 range = range->next()) {
3015 auto assigned = range->GetAssignedOperand(); 3031 auto assigned = range->GetAssignedOperand();
3016 range->ConvertUsesToOperand(assigned, spill_operand); 3032 range->ConvertUsesToOperand(assigned, spill_operand);
3017 } 3033 }
3018 3034
3035 MoveOperands* move = top_range->elidable_def();
3036 if (move != nullptr && move->destination().Equals(spill_operand)) {
3037 move->Eliminate();
3038 }
3039
3019 if (!spill_operand.IsInvalid()) { 3040 if (!spill_operand.IsInvalid()) {
3020 // If this top level range has a child spilled in a deferred block, we use 3041 // If this top level range has a child spilled in a deferred block, we use
3021 // the range and control flow connection mechanism instead of spilling at 3042 // the range and control flow connection mechanism instead of spilling at
3022 // definition. Refer to the ConnectLiveRanges and ResolveControlFlow 3043 // definition. Refer to the ConnectLiveRanges and ResolveControlFlow
3023 // phases. Normally, when we spill at definition, we do not insert a 3044 // phases. Normally, when we spill at definition, we do not insert a
3024 // connecting move when a successor child range is spilled - because the 3045 // connecting move when a successor child range is spilled - because the
3025 // spilled range picks up its value from the slot which was assigned at 3046 // 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 3047 // definition. For ranges that are determined to spill only in deferred
3027 // blocks, we let ConnectLiveRanges and ResolveControlFlow insert such 3048 // blocks, we let ConnectLiveRanges and ResolveControlFlow insert such
3028 // moves between ranges. Because of how the ranges are split around 3049 // moves between ranges. Because of how the ranges are split around
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3066 // for all spilled live ranges at this point. 3087 // for all spilled live ranges at this point.
3067 int last_range_start = 0; 3088 int last_range_start = 0;
3068 auto reference_maps = data()->code()->reference_maps(); 3089 auto reference_maps = data()->code()->reference_maps();
3069 ReferenceMapDeque::const_iterator first_it = reference_maps->begin(); 3090 ReferenceMapDeque::const_iterator first_it = reference_maps->begin();
3070 for (TopLevelLiveRange* range : data()->live_ranges()) { 3091 for (TopLevelLiveRange* range : data()->live_ranges()) {
3071 if (range == nullptr) continue; 3092 if (range == nullptr) continue;
3072 // Skip non-reference values. 3093 // Skip non-reference values.
3073 if (!data()->IsReference(range)) continue; 3094 if (!data()->IsReference(range)) continue;
3074 // Skip empty live ranges. 3095 // Skip empty live ranges.
3075 if (range->IsEmpty()) continue; 3096 if (range->IsEmpty()) continue;
3097 if (range->IsReferenceAccountedByCaller()) continue;
3076 3098
3077 // Find the extent of the range and its children. 3099 // Find the extent of the range and its children.
3078 int start = range->Start().ToInstructionIndex(); 3100 int start = range->Start().ToInstructionIndex();
3079 int end = 0; 3101 int end = 0;
3080 for (LiveRange* cur = range; cur != nullptr; cur = cur->next()) { 3102 for (LiveRange* cur = range; cur != nullptr; cur = cur->next()) {
3081 auto this_end = cur->End(); 3103 auto this_end = cur->End();
3082 if (this_end.ToInstructionIndex() > end) 3104 if (this_end.ToInstructionIndex() > end)
3083 end = this_end.ToInstructionIndex(); 3105 end = this_end.ToInstructionIndex();
3084 DCHECK(cur->Start().ToInstructionIndex() >= start); 3106 DCHECK(cur->Start().ToInstructionIndex() >= start);
3085 } 3107 }
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
3441 auto eliminate = moves->PrepareInsertAfter(move); 3463 auto eliminate = moves->PrepareInsertAfter(move);
3442 to_insert.push_back(move); 3464 to_insert.push_back(move);
3443 if (eliminate != nullptr) to_eliminate.push_back(eliminate); 3465 if (eliminate != nullptr) to_eliminate.push_back(eliminate);
3444 } 3466 }
3445 } 3467 }
3446 3468
3447 3469
3448 } // namespace compiler 3470 } // namespace compiler
3449 } // namespace internal 3471 } // namespace internal
3450 } // namespace v8 3472 } // namespace v8
OLDNEW
« src/compiler/register-allocator.h ('K') | « src/compiler/register-allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698