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

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

Issue 1085623002: [turbofan] remove register operand cache (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months 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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 next_(nullptr), 130 next_(nullptr),
131 current_interval_(nullptr), 131 current_interval_(nullptr),
132 last_processed_use_(nullptr), 132 last_processed_use_(nullptr),
133 current_hint_operand_(nullptr), 133 current_hint_operand_(nullptr),
134 spill_start_index_(kMaxInt), 134 spill_start_index_(kMaxInt),
135 spill_type_(SpillType::kNoSpillType), 135 spill_type_(SpillType::kNoSpillType),
136 spill_operand_(nullptr), 136 spill_operand_(nullptr),
137 spills_at_definition_(nullptr) {} 137 spills_at_definition_(nullptr) {}
138 138
139 139
140 void LiveRange::set_assigned_register(int reg, 140 void LiveRange::set_assigned_register(int reg) {
141 InstructionOperandCache* operand_cache) {
142 DCHECK(!HasRegisterAssigned() && !IsSpilled()); 141 DCHECK(!HasRegisterAssigned() && !IsSpilled());
143 assigned_register_ = reg; 142 assigned_register_ = reg;
144 // TODO(dcarney): stop aliasing hint operands. 143 // TODO(dcarney): stop aliasing hint operands.
145 ConvertUsesToOperand(GetAssignedOperand(operand_cache), nullptr); 144 ConvertUsesToOperand(GetAssignedOperand(), nullptr);
146 } 145 }
147 146
148 147
149 void LiveRange::MakeSpilled() { 148 void LiveRange::MakeSpilled() {
150 DCHECK(!IsSpilled()); 149 DCHECK(!IsSpilled());
151 DCHECK(!TopLevel()->HasNoSpillType()); 150 DCHECK(!TopLevel()->HasNoSpillType());
152 spilled_ = true; 151 spilled_ = true;
153 assigned_register_ = kInvalidAssignment; 152 assigned_register_ = kInvalidAssignment;
154 } 153 }
155 154
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 260
262 bool LiveRange::CanBeSpilled(LifetimePosition pos) { 261 bool LiveRange::CanBeSpilled(LifetimePosition pos) {
263 // We cannot spill a live range that has a use requiring a register 262 // We cannot spill a live range that has a use requiring a register
264 // at the current or the immediate next position. 263 // at the current or the immediate next position.
265 auto use_pos = NextRegisterPosition(pos); 264 auto use_pos = NextRegisterPosition(pos);
266 if (use_pos == nullptr) return true; 265 if (use_pos == nullptr) return true;
267 return use_pos->pos().Value() > pos.NextStart().End().Value(); 266 return use_pos->pos().Value() > pos.NextStart().End().Value();
268 } 267 }
269 268
270 269
271 InstructionOperand* LiveRange::GetAssignedOperand(
272 InstructionOperandCache* cache) const {
273 if (HasRegisterAssigned()) {
274 DCHECK(!IsSpilled());
275 switch (Kind()) {
276 case GENERAL_REGISTERS:
277 return cache->GetRegisterOperand(assigned_register());
278 case DOUBLE_REGISTERS:
279 return cache->GetDoubleRegisterOperand(assigned_register());
280 default:
281 UNREACHABLE();
282 }
283 }
284 DCHECK(IsSpilled());
285 DCHECK(!HasRegisterAssigned());
286 auto op = TopLevel()->GetSpillOperand();
287 DCHECK(!op->IsUnallocated());
288 return op;
289 }
290
291
292 InstructionOperand LiveRange::GetAssignedOperand() const { 270 InstructionOperand LiveRange::GetAssignedOperand() const {
293 if (HasRegisterAssigned()) { 271 if (HasRegisterAssigned()) {
294 DCHECK(!IsSpilled()); 272 DCHECK(!IsSpilled());
295 switch (Kind()) { 273 switch (Kind()) {
296 case GENERAL_REGISTERS: 274 case GENERAL_REGISTERS:
297 return RegisterOperand(assigned_register()); 275 return RegisterOperand(assigned_register());
298 case DOUBLE_REGISTERS: 276 case DOUBLE_REGISTERS:
299 return DoubleRegisterOperand(assigned_register()); 277 return DoubleRegisterOperand(assigned_register());
300 default: 278 default:
301 UNREACHABLE(); 279 UNREACHABLE();
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 use_pos->next_ = prev->next_; 497 use_pos->next_ = prev->next_;
520 prev->next_ = use_pos; 498 prev->next_ = use_pos;
521 } 499 }
522 500
523 if (prev_hint == nullptr && use_pos->HasHint()) { 501 if (prev_hint == nullptr && use_pos->HasHint()) {
524 current_hint_operand_ = hint; 502 current_hint_operand_ = hint;
525 } 503 }
526 } 504 }
527 505
528 506
529 void LiveRange::ConvertUsesToOperand(InstructionOperand* op, 507 void LiveRange::ConvertUsesToOperand(const InstructionOperand& op,
530 InstructionOperand* spill_op) { 508 InstructionOperand* spill_op) {
531 for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) { 509 for (auto pos = first_pos(); pos != nullptr; pos = pos->next()) {
532 DCHECK(Start().Value() <= pos->pos().Value() && 510 DCHECK(Start().Value() <= pos->pos().Value() &&
533 pos->pos().Value() <= End().Value()); 511 pos->pos().Value() <= End().Value());
534 if (!pos->HasOperand()) { 512 if (!pos->HasOperand()) {
535 continue; 513 continue;
536 } 514 }
537 switch (pos->type()) { 515 switch (pos->type()) {
538 case UsePositionType::kRequiresSlot: 516 case UsePositionType::kRequiresSlot:
539 if (spill_op != nullptr) { 517 if (spill_op != nullptr) {
540 InstructionOperand::ReplaceWith(pos->operand(), spill_op); 518 InstructionOperand::ReplaceWith(pos->operand(), spill_op);
541 } 519 }
542 break; 520 break;
543 case UsePositionType::kRequiresRegister: 521 case UsePositionType::kRequiresRegister:
544 DCHECK(op->IsRegister() || op->IsDoubleRegister()); 522 DCHECK(op.IsRegister() || op.IsDoubleRegister());
545 // Fall through. 523 // Fall through.
546 case UsePositionType::kAny: 524 case UsePositionType::kAny:
547 InstructionOperand::ReplaceWith(pos->operand(), op); 525 InstructionOperand::ReplaceWith(pos->operand(), &op);
548 break; 526 break;
549 } 527 }
550 } 528 }
551 } 529 }
552 530
553 531
554 bool LiveRange::CanCover(LifetimePosition position) const { 532 bool LiveRange::CanCover(LifetimePosition position) const {
555 if (IsEmpty()) return false; 533 if (IsEmpty()) return false;
556 return Start().Value() <= position.Value() && 534 return Start().Value() <= position.Value() &&
557 position.Value() < End().Value(); 535 position.Value() < End().Value();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 if (a == nullptr || a->start().Value() > other->End().Value()) break; 568 if (a == nullptr || a->start().Value() > other->End().Value()) break;
591 AdvanceLastProcessedMarker(a, advance_last_processed_up_to); 569 AdvanceLastProcessedMarker(a, advance_last_processed_up_to);
592 } else { 570 } else {
593 b = b->next(); 571 b = b->next();
594 } 572 }
595 } 573 }
596 return LifetimePosition::Invalid(); 574 return LifetimePosition::Invalid();
597 } 575 }
598 576
599 577
600 InstructionOperandCache::InstructionOperandCache() {
601 for (size_t i = 0; i < arraysize(general_register_operands_); ++i) {
602 general_register_operands_[i] = RegisterOperand(static_cast<int>(i));
603 }
604 for (size_t i = 0; i < arraysize(double_register_operands_); ++i) {
605 double_register_operands_[i] = DoubleRegisterOperand(static_cast<int>(i));
606 }
607 }
608
609
610 RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config, 578 RegisterAllocator::RegisterAllocator(const RegisterConfiguration* config,
611 Zone* zone, Frame* frame, 579 Zone* zone, Frame* frame,
612 InstructionSequence* code, 580 InstructionSequence* code,
613 const char* debug_name) 581 const char* debug_name)
614 : local_zone_(zone), 582 : local_zone_(zone),
615 frame_(frame), 583 frame_(frame),
616 code_(code), 584 code_(code),
617 debug_name_(debug_name), 585 debug_name_(debug_name),
618 config_(config), 586 config_(config),
619 operand_cache_(new (code_zone()) InstructionOperandCache()),
620 phi_map_(local_zone()), 587 phi_map_(local_zone()),
621 live_in_sets_(code->InstructionBlockCount(), nullptr, local_zone()), 588 live_in_sets_(code->InstructionBlockCount(), nullptr, local_zone()),
622 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, local_zone()), 589 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, local_zone()),
623 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, 590 fixed_live_ranges_(this->config()->num_general_registers(), nullptr,
624 local_zone()), 591 local_zone()),
625 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, 592 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr,
626 local_zone()), 593 local_zone()),
627 unhandled_live_ranges_(local_zone()), 594 unhandled_live_ranges_(local_zone()),
628 active_live_ranges_(local_zone()), 595 active_live_ranges_(local_zone()),
629 inactive_live_ranges_(local_zone()), 596 inactive_live_ranges_(local_zone()),
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 : AllocatedOperand::STACK_SLOT; 947 : AllocatedOperand::STACK_SLOT;
981 auto op = AllocatedOperand::New(code_zone(), op_kind, index); 948 auto op = AllocatedOperand::New(code_zone(), op_kind, index);
982 range->SetOperand(op); 949 range->SetOperand(op);
983 } 950 }
984 } 951 }
985 952
986 953
987 void RegisterAllocator::CommitAssignment() { 954 void RegisterAllocator::CommitAssignment() {
988 for (auto range : live_ranges()) { 955 for (auto range : live_ranges()) {
989 if (range == nullptr || range->IsEmpty()) continue; 956 if (range == nullptr || range->IsEmpty()) continue;
990 auto assigned = range->GetAssignedOperand(operand_cache());
991 InstructionOperand* spill_operand = nullptr; 957 InstructionOperand* spill_operand = nullptr;
992 if (!range->TopLevel()->HasNoSpillType()) { 958 if (!range->TopLevel()->HasNoSpillType()) {
993 spill_operand = range->TopLevel()->GetSpillOperand(); 959 spill_operand = range->TopLevel()->GetSpillOperand();
994 } 960 }
961 auto assigned = range->GetAssignedOperand();
995 range->ConvertUsesToOperand(assigned, spill_operand); 962 range->ConvertUsesToOperand(assigned, spill_operand);
996 if (!range->IsChild() && spill_operand != nullptr) { 963 if (!range->IsChild() && spill_operand != nullptr) {
997 range->CommitSpillsAtDefinition(code(), spill_operand, 964 range->CommitSpillsAtDefinition(code(), spill_operand,
998 range->has_slot_use()); 965 range->has_slot_use());
999 } 966 }
1000 } 967 }
1001 } 968 }
1002 969
1003 970
1004 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { 971 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) {
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
1456 first_range = second_range, second_range = second_range->next()) { 1423 first_range = second_range, second_range = second_range->next()) {
1457 auto pos = second_range->Start(); 1424 auto pos = second_range->Start();
1458 // Add gap move if the two live ranges touch and there is no block 1425 // Add gap move if the two live ranges touch and there is no block
1459 // boundary. 1426 // boundary.
1460 if (second_range->IsSpilled()) continue; 1427 if (second_range->IsSpilled()) continue;
1461 if (first_range->End().Value() != pos.Value()) continue; 1428 if (first_range->End().Value() != pos.Value()) continue;
1462 if (IsBlockBoundary(pos) && 1429 if (IsBlockBoundary(pos) &&
1463 !CanEagerlyResolveControlFlow(GetInstructionBlock(pos))) { 1430 !CanEagerlyResolveControlFlow(GetInstructionBlock(pos))) {
1464 continue; 1431 continue;
1465 } 1432 }
1466 auto prev_operand = first_range->GetAssignedOperand(operand_cache()); 1433 auto prev = first_range->GetAssignedOperand();
1467 auto cur_operand = second_range->GetAssignedOperand(operand_cache()); 1434 auto cur = second_range->GetAssignedOperand();
1468 if (prev_operand->Equals(cur_operand)) continue; 1435 if (prev == cur) continue;
1469 bool delay_insertion = false; 1436 bool delay_insertion = false;
1470 Instruction::GapPosition gap_pos; 1437 Instruction::GapPosition gap_pos;
1471 int gap_index = pos.ToInstructionIndex(); 1438 int gap_index = pos.ToInstructionIndex();
1472 if (pos.IsGapPosition()) { 1439 if (pos.IsGapPosition()) {
1473 gap_pos = pos.IsStart() ? Instruction::START : Instruction::END; 1440 gap_pos = pos.IsStart() ? Instruction::START : Instruction::END;
1474 } else { 1441 } else {
1475 if (pos.IsStart()) { 1442 if (pos.IsStart()) {
1476 delay_insertion = true; 1443 delay_insertion = true;
1477 } else { 1444 } else {
1478 gap_index++; 1445 gap_index++;
1479 } 1446 }
1480 gap_pos = delay_insertion ? Instruction::END : Instruction::START; 1447 gap_pos = delay_insertion ? Instruction::END : Instruction::START;
1481 } 1448 }
1482 auto move = code()->InstructionAt(gap_index)->GetOrCreateParallelMove( 1449 auto move = code()->InstructionAt(gap_index)->GetOrCreateParallelMove(
1483 gap_pos, code_zone()); 1450 gap_pos, code_zone());
1451 auto prev_operand = InstructionOperand::New(code_zone(), prev);
1452 auto cur_operand = InstructionOperand::New(code_zone(), cur);
1484 if (!delay_insertion) { 1453 if (!delay_insertion) {
1485 move->AddMove(prev_operand, cur_operand, code_zone()); 1454 move->AddMove(prev_operand, cur_operand, code_zone());
1486 } else { 1455 } else {
1487 delayed_insertion_map.insert( 1456 delayed_insertion_map.insert(
1488 std::make_pair(std::make_pair(move, prev_operand), cur_operand)); 1457 std::make_pair(std::make_pair(move, prev_operand), cur_operand));
1489 } 1458 }
1490 } 1459 }
1491 } 1460 }
1492 if (delayed_insertion_map.empty()) return; 1461 if (delayed_insertion_map.empty()) return;
1493 // Insert all the moves which should occur after the stored move. 1462 // Insert all the moves which should occur after the stored move.
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1671 BitVector::Iterator iterator(live); 1640 BitVector::Iterator iterator(live);
1672 while (!iterator.Done()) { 1641 while (!iterator.Done()) {
1673 auto* array = finder.ArrayFor(iterator.Current()); 1642 auto* array = finder.ArrayFor(iterator.Current());
1674 for (auto pred : block->predecessors()) { 1643 for (auto pred : block->predecessors()) {
1675 FindResult result; 1644 FindResult result;
1676 const auto* pred_block = code()->InstructionBlockAt(pred); 1645 const auto* pred_block = code()->InstructionBlockAt(pred);
1677 array->Find(block, pred_block, &result); 1646 array->Find(block, pred_block, &result);
1678 if (result.cur_cover_ == result.pred_cover_ || 1647 if (result.cur_cover_ == result.pred_cover_ ||
1679 result.cur_cover_->IsSpilled()) 1648 result.cur_cover_->IsSpilled())
1680 continue; 1649 continue;
1681 auto pred_op = result.pred_cover_->GetAssignedOperand(operand_cache()); 1650 auto pred_op = result.pred_cover_->GetAssignedOperand();
1682 auto cur_op = result.cur_cover_->GetAssignedOperand(operand_cache()); 1651 auto cur_op = result.cur_cover_->GetAssignedOperand();
1683 ResolveControlFlow(block, cur_op, pred_block, pred_op); 1652 if (pred_op == cur_op) continue;
1653 auto pred_ptr = InstructionOperand::New(code_zone(), pred_op);
1654 auto cur_ptr = InstructionOperand::New(code_zone(), cur_op);
1655 ResolveControlFlow(block, cur_ptr, pred_block, pred_ptr);
1684 } 1656 }
1685 iterator.Advance(); 1657 iterator.Advance();
1686 } 1658 }
1687 } 1659 }
1688 } 1660 }
1689 1661
1690 1662
1691 void RegisterAllocator::ResolveControlFlow(const InstructionBlock* block, 1663 void RegisterAllocator::ResolveControlFlow(const InstructionBlock* block,
1692 InstructionOperand* cur_op, 1664 InstructionOperand* cur_op,
1693 const InstructionBlock* pred, 1665 const InstructionBlock* pred,
1694 InstructionOperand* pred_op) { 1666 InstructionOperand* pred_op) {
1695 if (pred_op->Equals(cur_op)) return; 1667 DCHECK(!pred_op->Equals(cur_op));
1696 int gap_index; 1668 int gap_index;
1697 Instruction::GapPosition position; 1669 Instruction::GapPosition position;
1698 if (block->PredecessorCount() == 1) { 1670 if (block->PredecessorCount() == 1) {
1699 gap_index = block->first_instruction_index(); 1671 gap_index = block->first_instruction_index();
1700 position = Instruction::START; 1672 position = Instruction::START;
1701 } else { 1673 } else {
1702 DCHECK(pred->SuccessorCount() == 1); 1674 DCHECK(pred->SuccessorCount() == 1);
1703 DCHECK(!InstructionAt(pred->last_instruction_index())->HasReferenceMap()); 1675 DCHECK(!InstructionAt(pred->last_instruction_index())->HasReferenceMap());
1704 gap_index = pred->last_instruction_index(); 1676 gap_index = pred->last_instruction_index();
1705 position = Instruction::END; 1677 position = Instruction::END;
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after
2527 2499
2528 2500
2529 void RegisterAllocator::SetLiveRangeAssignedRegister(LiveRange* range, 2501 void RegisterAllocator::SetLiveRangeAssignedRegister(LiveRange* range,
2530 int reg) { 2502 int reg) {
2531 if (range->Kind() == DOUBLE_REGISTERS) { 2503 if (range->Kind() == DOUBLE_REGISTERS) {
2532 assigned_double_registers_->Add(reg); 2504 assigned_double_registers_->Add(reg);
2533 } else { 2505 } else {
2534 DCHECK(range->Kind() == GENERAL_REGISTERS); 2506 DCHECK(range->Kind() == GENERAL_REGISTERS);
2535 assigned_registers_->Add(reg); 2507 assigned_registers_->Add(reg);
2536 } 2508 }
2537 range->set_assigned_register(reg, operand_cache()); 2509 range->set_assigned_register(reg);
2538 } 2510 }
2539 2511
2540 } // namespace compiler 2512 } // namespace compiler
2541 } // namespace internal 2513 } // namespace internal
2542 } // namespace v8 2514 } // 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