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

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

Issue 1472803004: [turbofan] Simplified splintering code. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years 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') | no next file » | 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 695 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 706
707 707
708 void TopLevelLiveRange::RecordSpillLocation(Zone* zone, int gap_index, 708 void TopLevelLiveRange::RecordSpillLocation(Zone* zone, int gap_index,
709 InstructionOperand* operand) { 709 InstructionOperand* operand) {
710 DCHECK(HasNoSpillType()); 710 DCHECK(HasNoSpillType());
711 spill_move_insertion_locations_ = new (zone) SpillMoveInsertionList( 711 spill_move_insertion_locations_ = new (zone) SpillMoveInsertionList(
712 gap_index, operand, spill_move_insertion_locations_); 712 gap_index, operand, spill_move_insertion_locations_);
713 } 713 }
714 714
715 715
716 void TopLevelLiveRange::MarkSpilledInDeferredBlock(
717 const InstructionSequence* code) {
718 if (!FLAG_turbo_preprocess_ranges || IsEmpty() || HasNoSpillType() ||
719 !HasSpillRange()) {
720 return;
721 }
722
723 int count = 0;
724 for (const LiveRange* child = this; child != nullptr; child = child->next()) {
725 int first_instr = child->Start().ToInstructionIndex();
726
727 // If the range starts at instruction end, the first instruction index is
728 // the next one.
729 if (!child->Start().IsGapPosition() && !child->Start().IsStart()) {
730 ++first_instr;
731 }
732
733 // We only look at where the range starts. It doesn't matter where it ends:
734 // if it ends past this block, then either there is a phi there already,
735 // or ResolveControlFlow will adapt the last instruction gap of this block
736 // as if there were a phi. In either case, data flow will be correct.
737 const InstructionBlock* block = code->GetInstructionBlock(first_instr);
738
739 // If we have slot uses in a subrange, bail out, because we need the value
740 // on the stack before that use.
741 bool has_slot_use = child->NextSlotPosition(child->Start()) != nullptr;
742 if (!block->IsDeferred()) {
743 if (child->spilled() || has_slot_use) {
744 TRACE(
745 "Live Range %d must be spilled at definition: found a "
746 "slot-requiring non-deferred child range %d.\n",
747 TopLevel()->vreg(), child->relative_id());
748 return;
749 }
750 } else {
751 if (child->spilled() || has_slot_use) ++count;
752 }
753 }
754 if (count == 0) return;
755
756 spill_start_index_ = -1;
757 spilled_in_deferred_blocks_ = true;
758 spill_move_insertion_locations_ = nullptr;
759 }
760
761
762 bool TopLevelLiveRange::TryCommitSpillInDeferredBlock( 716 bool TopLevelLiveRange::TryCommitSpillInDeferredBlock(
763 InstructionSequence* code, const InstructionOperand& spill_operand) { 717 InstructionSequence* code, const InstructionOperand& spill_operand) {
764 if (!IsSpilledOnlyInDeferredBlocks()) return false; 718 if (!IsSpilledOnlyInDeferredBlocks()) return false;
765 719
766 TRACE("Live Range %d will be spilled only in deferred blocks.\n", vreg()); 720 TRACE("Live Range %d will be spilled only in deferred blocks.\n", vreg());
767 // If we have ranges that aren't spilled but require the operand on the stack, 721 // If we have ranges that aren't spilled but require the operand on the stack,
768 // make sure we insert the spill. 722 // make sure we insert the spill.
769 for (const LiveRange* child = this; child != nullptr; child = child->next()) { 723 for (const LiveRange* child = this; child != nullptr; child = child->next()) {
770 if (!child->spilled() && 724 if (!child->spilled() &&
771 child->NextSlotPosition(child->Start()) != nullptr) { 725 child->NextSlotPosition(child->Start()) != nullptr) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 } 801 }
848 802
849 803
850 void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end, 804 void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end,
851 Zone* zone) { 805 Zone* zone) {
852 DCHECK(start != Start() || end != End()); 806 DCHECK(start != Start() || end != End());
853 DCHECK(start < end); 807 DCHECK(start < end);
854 808
855 TopLevelLiveRange splinter_temp(-1, machine_type()); 809 TopLevelLiveRange splinter_temp(-1, machine_type());
856 UsePosition* last_in_splinter = nullptr; 810 UsePosition* last_in_splinter = nullptr;
857 if (start <= Start()) { 811 // Live ranges defined in deferred blocks stay in deferred blocks, so we
858 // TODO(mtrofin): here, the TopLevel part is in the deferred range, so we 812 // don't need to splinter them. That means that start should always be
859 // may want to continue processing the splinter. However, if the value is 813 // after the beginning of the range.
860 // defined in a cold block, and then used in a hot block, it follows that 814 DCHECK(start > Start());
861 // it should terminate on the RHS of a phi, defined on the hot path. We 815
862 // should check this, however, this may not be the place, because we don't 816 if (end >= End()) {
863 // have access to the instruction sequence.
864 DCHECK(end < End());
865 DetachAt(end, &splinter_temp, zone);
866 next_ = nullptr;
867 } else if (end >= End()) {
868 DCHECK(start > Start()); 817 DCHECK(start > Start());
869 DetachAt(start, &splinter_temp, zone); 818 DetachAt(start, &splinter_temp, zone);
870 next_ = nullptr; 819 next_ = nullptr;
871 } else { 820 } else {
872 DCHECK(start < End() && Start() < end); 821 DCHECK(start < End() && Start() < end);
873 822
874 const int kInvalidId = std::numeric_limits<int>::max(); 823 const int kInvalidId = std::numeric_limits<int>::max();
875 824
876 UsePosition* last = DetachAt(start, &splinter_temp, zone); 825 UsePosition* last = DetachAt(start, &splinter_temp, zone);
877 826
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
1390 PrintF("\n"); 1339 PrintF("\n");
1391 } else { 1340 } else {
1392 PrintF(" (function: %s)\n", debug_name()); 1341 PrintF(" (function: %s)\n", debug_name());
1393 } 1342 }
1394 iterator.Advance(); 1343 iterator.Advance();
1395 } 1344 }
1396 return found; 1345 return found;
1397 } 1346 }
1398 1347
1399 1348
1349 // If a range is defined in a deferred block, we can expect all the range
1350 // to only cover positions in deferred blocks. Otherwise, a block on the
1351 // hot path would be dominated by a deferred block, meaning it is unreachable
1352 // without passing through the deferred block, which is contradictory.
1353 // In particular, when such a range contributes a result back on the hot
1354 // path, it will be as one of the inputs of a phi. In that case, the value
1355 // will be transferred via a move in the Gap::END's of the last instruction
1356 // of a deferred block.
1357 bool RegisterAllocationData::RangesDefinedInDeferredStayInDeferred() {
1358 for (const TopLevelLiveRange* range : live_ranges()) {
1359 if (range == nullptr || range->IsEmpty() ||
1360 !code()
1361 ->GetInstructionBlock(range->Start().ToInstructionIndex())
1362 ->IsDeferred()) {
1363 continue;
1364 }
1365 for (const UseInterval* i = range->first_interval(); i != nullptr;
1366 i = i->next()) {
1367 int first = i->FirstInstructionIndex();
1368 int last = i->LastInstructionIndex();
1369 for (int instr = first; instr <= last;) {
1370 const InstructionBlock* block = code()->GetInstructionBlock(instr);
1371 if (!block->IsDeferred()) return false;
1372 instr = block->last_instruction_index() + 1;
1373 }
1374 }
1375 }
1376 return true;
1377 }
1378
1379
1400 SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange( 1380 SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange(
1401 TopLevelLiveRange* range) { 1381 TopLevelLiveRange* range) {
1402 DCHECK(!range->HasSpillOperand()); 1382 DCHECK(!range->HasSpillOperand());
1403 1383
1404 SpillRange* spill_range = range->GetAllocatedSpillRange(); 1384 SpillRange* spill_range = range->GetAllocatedSpillRange();
1405 if (spill_range == nullptr) { 1385 if (spill_range == nullptr) {
1406 DCHECK(!range->IsSplinter()); 1386 DCHECK(!range->IsSplinter());
1407 spill_range = new (allocation_zone()) SpillRange(range, allocation_zone()); 1387 spill_range = new (allocation_zone()) SpillRange(range, allocation_zone());
1408 } 1388 }
1409 range->set_spill_type(TopLevelLiveRange::SpillType::kSpillRange); 1389 range->set_spill_type(TopLevelLiveRange::SpillType::kSpillRange);
(...skipping 1547 matching lines...) Expand 10 before | Expand all | Expand 10 after
2957 SpillSlotLocator::SpillSlotLocator(RegisterAllocationData* data) 2937 SpillSlotLocator::SpillSlotLocator(RegisterAllocationData* data)
2958 : data_(data) {} 2938 : data_(data) {}
2959 2939
2960 2940
2961 void SpillSlotLocator::LocateSpillSlots() { 2941 void SpillSlotLocator::LocateSpillSlots() {
2962 auto code = data()->code(); 2942 auto code = data()->code();
2963 for (TopLevelLiveRange* range : data()->live_ranges()) { 2943 for (TopLevelLiveRange* range : data()->live_ranges()) {
2964 if (range == nullptr || range->IsEmpty()) continue; 2944 if (range == nullptr || range->IsEmpty()) continue;
2965 // We care only about ranges which spill in the frame. 2945 // We care only about ranges which spill in the frame.
2966 if (!range->HasSpillRange()) continue; 2946 if (!range->HasSpillRange()) continue;
2967 range->MarkSpilledInDeferredBlock(data()->code());
2968 if (range->IsSpilledOnlyInDeferredBlocks()) { 2947 if (range->IsSpilledOnlyInDeferredBlocks()) {
2969 for (LiveRange* child = range; child != nullptr; child = child->next()) { 2948 for (LiveRange* child = range; child != nullptr; child = child->next()) {
2970 if (child->spilled()) { 2949 if (child->spilled()) {
2971 code->GetInstructionBlock(child->Start().ToInstructionIndex()) 2950 code->GetInstructionBlock(child->Start().ToInstructionIndex())
2972 ->mark_needs_frame(); 2951 ->mark_needs_frame();
2973 } 2952 }
2974 } 2953 }
2975 } else { 2954 } else {
2976 auto spills = range->spill_move_insertion_locations(); 2955 auto spills = range->spill_move_insertion_locations();
2977 DCHECK_NOT_NULL(spills); 2956 DCHECK_NOT_NULL(spills);
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
3466 auto eliminate = moves->PrepareInsertAfter(move); 3445 auto eliminate = moves->PrepareInsertAfter(move);
3467 to_insert.push_back(move); 3446 to_insert.push_back(move);
3468 if (eliminate != nullptr) to_eliminate.push_back(eliminate); 3447 if (eliminate != nullptr) to_eliminate.push_back(eliminate);
3469 } 3448 }
3470 } 3449 }
3471 3450
3472 3451
3473 } // namespace compiler 3452 } // namespace compiler
3474 } // namespace internal 3453 } // namespace internal
3475 } // namespace v8 3454 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698