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

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

Issue 777403003: [turbofan] reuse spill slots for phis (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 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/compiler/linkage.h" 5 #include "src/compiler/linkage.h"
6 #include "src/compiler/register-allocator.h" 6 #include "src/compiler/register-allocator.h"
7 #include "src/string-stream.h" 7 #include "src/string-stream.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 527
528 RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config, 528 RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config,
529 Zone* zone, Frame* frame, 529 Zone* zone, Frame* frame,
530 InstructionSequence* code, 530 InstructionSequence* code,
531 const char* debug_name) 531 const char* debug_name)
532 : local_zone_(zone), 532 : local_zone_(zone),
533 frame_(frame), 533 frame_(frame),
534 code_(code), 534 code_(code),
535 debug_name_(debug_name), 535 debug_name_(debug_name),
536 config_(config), 536 config_(config),
537 phi_map_(PhiMap::key_compare(), PhiMap::allocator_type(local_zone())),
537 live_in_sets_(code->InstructionBlockCount(), local_zone()), 538 live_in_sets_(code->InstructionBlockCount(), local_zone()),
538 live_ranges_(code->VirtualRegisterCount() * 2, local_zone()), 539 live_ranges_(code->VirtualRegisterCount() * 2, local_zone()),
539 fixed_live_ranges_(this->config()->num_general_registers(), NULL, 540 fixed_live_ranges_(this->config()->num_general_registers(), NULL,
540 local_zone()), 541 local_zone()),
541 fixed_double_live_ranges_(this->config()->num_double_registers(), NULL, 542 fixed_double_live_ranges_(this->config()->num_double_registers(), NULL,
542 local_zone()), 543 local_zone()),
543 unhandled_live_ranges_(code->VirtualRegisterCount() * 2, local_zone()), 544 unhandled_live_ranges_(code->VirtualRegisterCount() * 2, local_zone()),
544 active_live_ranges_(8, local_zone()), 545 active_live_ranges_(8, local_zone()),
545 inactive_live_ranges_(8, local_zone()), 546 inactive_live_ranges_(8, local_zone()),
546 reusable_slots_(8, local_zone()), 547 reusable_slots_(8, local_zone()),
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { 919 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) {
919 DCHECK(FLAG_turbo_reuse_spill_slots); 920 DCHECK(FLAG_turbo_reuse_spill_slots);
920 int spill_id = spill_ranges_.length(); 921 int spill_id = spill_ranges_.length();
921 SpillRange* spill_range = 922 SpillRange* spill_range =
922 new (local_zone()) SpillRange(range, spill_id, local_zone()); 923 new (local_zone()) SpillRange(range, spill_id, local_zone());
923 spill_ranges_.Add(spill_range, local_zone()); 924 spill_ranges_.Add(spill_range, local_zone());
924 return spill_range; 925 return spill_range;
925 } 926 }
926 927
927 928
929 bool RegisterAllocator::TryReuseSpillForPhi(LiveRange* range) {
930 DCHECK(FLAG_turbo_reuse_spill_slots);
931 DCHECK(!range->HasAllocatedSpillOperand());
932 if (range->IsChild() || !range->is_phi()) return false;
933
934 auto lookup = phi_map_.find(range->id());
935 DCHECK(lookup != phi_map_.end());
936 auto phi = lookup->second.phi;
937 auto block = lookup->second.block;
938 // Count the number of spilled operands.
939 size_t spilled_count = 0;
940 LiveRange* first_op = nullptr;
941 for (size_t i = 0; i < phi->operands().size(); i++) {
942 int op = phi->operands()[i];
943 LiveRange* op_range = LiveRangeFor(op);
944 if (op_range->GetSpillRange() == nullptr) continue;
945 auto pred = code()->InstructionBlockAt(block->predecessors()[i]);
946 LifetimePosition pred_end =
947 LifetimePosition::FromInstructionIndex(pred->last_instruction_index());
948 while (op_range != nullptr && !op_range->CanCover(pred_end)) {
949 op_range = op_range->next();
950 }
951 if (op_range != nullptr && op_range->IsSpilled()) {
952 spilled_count++;
953 if (first_op == nullptr) {
954 first_op = op_range->TopLevel();
955 }
956 }
957 }
958
959 // Only continue if more than half of the operands are spilled.
960 if (spilled_count * 2 <= phi->operands().size()) {
961 return false;
962 }
963
964 // Try to merge the spilled operands and count the number of merged spilled
965 // operands.
966 DCHECK(first_op != NULL);
967 SpillRange* first_op_spill = first_op->GetSpillRange();
968 size_t num_merged = 1;
969 for (size_t i = 1; i < phi->operands().size(); i++) {
970 int op = phi->operands()[i];
971 LiveRange* op_range = LiveRangeFor(op);
972 SpillRange* op_spill = op_range->GetSpillRange();
973 if (op_spill != NULL) {
974 if (op_spill->id() == first_op_spill->id() ||
975 first_op_spill->TryMerge(op_spill, local_zone())) {
976 num_merged++;
977 }
978 }
979 }
980
981 // Only continue if enough operands could be merged to the
982 // same spill slot.
983 if (num_merged * 2 <= phi->operands().size() ||
984 AreUseIntervalsIntersecting(first_op_spill->interval(),
985 range->first_interval())) {
986 return false;
987 }
988
989 // If the range does not need register soon, spill it to the merged
990 // spill range.
991 LifetimePosition next_pos = range->Start();
992 if (code()->IsGapAt(next_pos.InstructionIndex())) {
993 next_pos = next_pos.NextInstruction();
994 }
995 UsePosition* pos = range->NextUsePositionRegisterIsBeneficial(next_pos);
996 if (pos == NULL) {
997 SpillRange* spill_range = AssignSpillRangeToLiveRange(range->TopLevel());
998 CHECK(first_op_spill->TryMerge(spill_range, local_zone()));
999 Spill(range);
1000 return true;
1001 } else if (pos->pos().Value() > range->Start().NextInstruction().Value()) {
1002 SpillRange* spill_range = AssignSpillRangeToLiveRange(range->TopLevel());
1003 CHECK(first_op_spill->TryMerge(spill_range, local_zone()));
1004 SpillBetween(range, range->Start(), pos->pos());
1005 if (!AllocationOk()) return false;
1006 DCHECK(UnhandledIsSorted());
1007 return true;
1008 }
1009 return false;
1010 }
1011
1012
928 void RegisterAllocator::MeetRegisterConstraints(const InstructionBlock* block) { 1013 void RegisterAllocator::MeetRegisterConstraints(const InstructionBlock* block) {
929 int start = block->first_instruction_index(); 1014 int start = block->first_instruction_index();
930 int end = block->last_instruction_index(); 1015 int end = block->last_instruction_index();
931 DCHECK_NE(-1, start); 1016 DCHECK_NE(-1, start);
932 for (int i = start; i <= end; ++i) { 1017 for (int i = start; i <= end; ++i) {
933 if (code()->IsGapAt(i)) { 1018 if (code()->IsGapAt(i)) {
934 Instruction* instr = NULL; 1019 Instruction* instr = NULL;
935 Instruction* prev_instr = NULL; 1020 Instruction* prev_instr = NULL;
936 if (i < end) instr = InstructionAt(i + 1); 1021 if (i < end) instr = InstructionAt(i + 1);
937 if (i > start) prev_instr = InstructionAt(i - 1); 1022 if (i > start) prev_instr = InstructionAt(i - 1);
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
1250 Use(block_start_position, curr_position.InstructionEnd(), temp, NULL); 1335 Use(block_start_position, curr_position.InstructionEnd(), temp, NULL);
1251 Define(curr_position, temp, NULL); 1336 Define(curr_position, temp, NULL);
1252 } 1337 }
1253 } 1338 }
1254 } 1339 }
1255 } 1340 }
1256 1341
1257 1342
1258 void RegisterAllocator::ResolvePhis(const InstructionBlock* block) { 1343 void RegisterAllocator::ResolvePhis(const InstructionBlock* block) {
1259 for (auto phi : block->phis()) { 1344 for (auto phi : block->phis()) {
1345 if (FLAG_turbo_reuse_spill_slots) {
1346 auto res = phi_map_.insert(
1347 std::make_pair(phi->virtual_register(), PhiMapValue(phi, block)));
1348 DCHECK(res.second);
1349 USE(res);
1350 }
1260 auto output = phi->output(); 1351 auto output = phi->output();
1261 int phi_vreg = phi->virtual_register(); 1352 int phi_vreg = phi->virtual_register();
1262 if (!FLAG_turbo_delay_ssa_decon) { 1353 if (!FLAG_turbo_delay_ssa_decon) {
1263 for (size_t i = 0; i < phi->operands().size(); ++i) { 1354 for (size_t i = 0; i < phi->operands().size(); ++i) {
1264 InstructionBlock* cur_block = 1355 InstructionBlock* cur_block =
1265 code()->InstructionBlockAt(block->predecessors()[i]); 1356 code()->InstructionBlockAt(block->predecessors()[i]);
1266 // The gap move must be added without any special processing as in 1357 // The gap move must be added without any special processing as in
1267 // the AddConstraintsGapMove. 1358 // the AddConstraintsGapMove.
1268 code()->AddGapMove(cur_block->last_instruction_index() - 1, 1359 code()->AddGapMove(cur_block->last_instruction_index() - 1,
1269 phi->inputs()[i], output); 1360 phi->inputs()[i], output);
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after
1860 current->Start().NextInstruction().Value()) { 1951 current->Start().NextInstruction().Value()) {
1861 // Do not spill live range eagerly if use position that can benefit from 1952 // Do not spill live range eagerly if use position that can benefit from
1862 // the register is too close to the start of live range. 1953 // the register is too close to the start of live range.
1863 SpillBetween(current, current->Start(), pos->pos()); 1954 SpillBetween(current, current->Start(), pos->pos());
1864 if (!AllocationOk()) return; 1955 if (!AllocationOk()) return;
1865 DCHECK(UnhandledIsSorted()); 1956 DCHECK(UnhandledIsSorted());
1866 continue; 1957 continue;
1867 } 1958 }
1868 } 1959 }
1869 1960
1961 if (FLAG_turbo_reuse_spill_slots) {
1962 if (TryReuseSpillForPhi(current)) {
1963 continue;
1964 }
1965 if (!AllocationOk()) return;
1966 }
1967
1870 for (int i = 0; i < active_live_ranges_.length(); ++i) { 1968 for (int i = 0; i < active_live_ranges_.length(); ++i) {
1871 LiveRange* cur_active = active_live_ranges_.at(i); 1969 LiveRange* cur_active = active_live_ranges_.at(i);
1872 if (cur_active->End().Value() <= position.Value()) { 1970 if (cur_active->End().Value() <= position.Value()) {
1873 ActiveToHandled(cur_active); 1971 ActiveToHandled(cur_active);
1874 --i; // The live range was removed from the list of active live ranges. 1972 --i; // The live range was removed from the list of active live ranges.
1875 } else if (!cur_active->Covers(position)) { 1973 } else if (!cur_active->Covers(position)) {
1876 ActiveToInactive(cur_active); 1974 ActiveToInactive(cur_active);
1877 --i; // The live range was removed from the list of active live ranges. 1975 --i; // The live range was removed from the list of active live ranges.
1878 } 1976 }
1879 } 1977 }
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
2476 } else { 2574 } else {
2477 DCHECK(range->Kind() == GENERAL_REGISTERS); 2575 DCHECK(range->Kind() == GENERAL_REGISTERS);
2478 assigned_registers_->Add(reg); 2576 assigned_registers_->Add(reg);
2479 } 2577 }
2480 range->set_assigned_register(reg, code_zone()); 2578 range->set_assigned_register(reg, code_zone());
2481 } 2579 }
2482 2580
2483 } // namespace compiler 2581 } // namespace compiler
2484 } // namespace internal 2582 } // namespace internal
2485 } // namespace v8 2583 } // 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