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 3// found in the LICENSE file. 4 5#include "src/base/adapters.h" 6#include "src/compiler/linkage.h" 7#include "src/compiler/register-allocator.h" 8#include "src/string-stream.h" 9 10namespace v8 { 11namespace internal { 12namespace compiler { 13 14#define TRACE(...) \ 15 do { \ 16 if (FLAG_trace_alloc) PrintF(__VA_ARGS__); \ 17 } while (false) 18 19 20namespace { 21 22static const int kFloatRepBit = 23 1 << static_cast<int>(MachineRepresentation::kFloat32); 24static const int kSimd128RepBit = 25 1 << static_cast<int>(MachineRepresentation::kSimd128); 26 27void RemoveElement(ZoneVector<LiveRange*>* v, LiveRange* range) { 28 auto it = std::find(v->begin(), v->end(), range); 29 DCHECK(it != v->end()); 30 v->erase(it); 31} 32 33int GetRegisterCount(const RegisterConfiguration* cfg, RegisterKind kind) { 34 return kind == FP_REGISTERS ? cfg->num_double_registers() 35 : cfg->num_general_registers(); 36} 37 38 39int GetAllocatableRegisterCount(const RegisterConfiguration* cfg, 40 RegisterKind kind) { 41 return kind == FP_REGISTERS ? cfg->num_allocatable_double_registers() 42 : cfg->num_allocatable_general_registers(); 43} 44 45 46const int* GetAllocatableRegisterCodes(const RegisterConfiguration* cfg, 47 RegisterKind kind) { 48 return kind == FP_REGISTERS ? cfg->allocatable_double_codes() 49 : cfg->allocatable_general_codes(); 50} 51 52 53const InstructionBlock* GetContainingLoop(const InstructionSequence* sequence, 54 const InstructionBlock* block) { 55 RpoNumber index = block->loop_header(); 56 if (!index.IsValid()) return nullptr; 57 return sequence->InstructionBlockAt(index); 58} 59 60 61const InstructionBlock* GetInstructionBlock(const InstructionSequence* code, 62 LifetimePosition pos) { 63 return code->GetInstructionBlock(pos.ToInstructionIndex()); 64} 65 66 67Instruction* GetLastInstruction(InstructionSequence* code, 68 const InstructionBlock* block) { 69 return code->InstructionAt(block->last_instruction_index()); 70} 71 72// TODO(dcarney): fix frame to allow frame accesses to half size location. 73int GetByteWidth(MachineRepresentation rep) { 74 switch (rep) { 75 case MachineRepresentation::kBit: 76 case MachineRepresentation::kWord8: 77 case MachineRepresentation::kWord16: 78 case MachineRepresentation::kWord32: 79 case MachineRepresentation::kTaggedSigned: 80 case MachineRepresentation::kTaggedPointer: 81 case MachineRepresentation::kTagged: 82 case MachineRepresentation::kFloat32: 83 return kPointerSize; 84 case MachineRepresentation::kWord64: 85 case MachineRepresentation::kFloat64: 86 return kDoubleSize; 87 case MachineRepresentation::kSimd128: 88 return kSimd128Size; 89 case MachineRepresentation::kSimd1x4: 90 case MachineRepresentation::kSimd1x8: 91 case MachineRepresentation::kSimd1x16: 92 return kSimdMaskRegisters ? kPointerSize : kSimd128Size; 93 case MachineRepresentation::kNone: 94 break; 95 } 96 UNREACHABLE(); 97 return 0; 98} 99 100} // namespace 101 102class LiveRangeBound { 103 public: 104 explicit LiveRangeBound(LiveRange* range, bool skip) 105 : range_(range), start_(range->Start()), end_(range->End()), skip_(skip) { 106 DCHECK(!range->IsEmpty()); 107 } 108 109 bool CanCover(LifetimePosition position) { 110 return start_ <= position && position < end_; 111 } 112 113 LiveRange* const range_; 114 const LifetimePosition start_; 115 const LifetimePosition end_; 116 const bool skip_; 117 118 private: 119 DISALLOW_COPY_AND_ASSIGN(LiveRangeBound); 120}; 121 122 123struct FindResult { 124 LiveRange* cur_cover_; 125 LiveRange* pred_cover_; 126}; 127 128 129class LiveRangeBoundArray { 130 public: 131 LiveRangeBoundArray() : length_(0), start_(nullptr) {} 132 133 bool ShouldInitialize() { return start_ == nullptr; } 134 135 void Initialize(Zone* zone, TopLevelLiveRange* range) { 136 length_ = range->GetChildCount(); 137 138 start_ = zone->NewArray<LiveRangeBound>(length_); 139 LiveRangeBound* curr = start_; 140 // Normally, spilled ranges do not need connecting moves, because the spill 141 // location has been assigned at definition. For ranges spilled in deferred 142 // blocks, that is not the case, so we need to connect the spilled children. 143 for (LiveRange *i = range; i != nullptr; i = i->next(), ++curr) { 144 new (curr) LiveRangeBound(i, i->spilled()); 145 } 146 } 147 148 LiveRangeBound* Find(const LifetimePosition position) const { 149 size_t left_index = 0; 150 size_t right_index = length_; 151 while (true) { 152 size_t current_index = left_index + (right_index - left_index) / 2; 153 DCHECK(right_index > current_index); 154 LiveRangeBound* bound = &start_[current_index]; 155 if (bound->start_ <= position) { 156 if (position < bound->end_) return bound; 157 DCHECK(left_index < current_index); 158 left_index = current_index; 159 } else { 160 right_index = current_index; 161 } 162 } 163 } 164 165 LiveRangeBound* FindPred(const InstructionBlock* pred) { 166 LifetimePosition pred_end = 167 LifetimePosition::InstructionFromInstructionIndex( 168 pred->last_instruction_index()); 169 return Find(pred_end); 170 } 171 172 LiveRangeBound* FindSucc(const InstructionBlock* succ) { 173 LifetimePosition succ_start = LifetimePosition::GapFromInstructionIndex( 174 succ->first_instruction_index()); 175 return Find(succ_start); 176 } 177 178 bool FindConnectableSubranges(const InstructionBlock* block, 179 const InstructionBlock* pred, 180 FindResult* result) const { 181 LifetimePosition pred_end = 182 LifetimePosition::InstructionFromInstructionIndex( 183 pred->last_instruction_index()); 184 LiveRangeBound* bound = Find(pred_end); 185 result->pred_cover_ = bound->range_; 186 LifetimePosition cur_start = LifetimePosition::GapFromInstructionIndex( 187 block->first_instruction_index()); 188 189 if (bound->CanCover(cur_start)) { 190 // Both blocks are covered by the same range, so there is nothing to 191 // connect. 192 return false; 193 } 194 bound = Find(cur_start); 195 if (bound->skip_) { 196 return false; 197 } 198 result->cur_cover_ = bound->range_; 199 DCHECK(result->pred_cover_ != nullptr && result->cur_cover_ != nullptr); 200 return (result->cur_cover_ != result->pred_cover_); 201 } 202 203 private: 204 size_t length_; 205 LiveRangeBound* start_; 206 207 DISALLOW_COPY_AND_ASSIGN(LiveRangeBoundArray); 208}; 209 210 211class LiveRangeFinder { 212 public: 213 explicit LiveRangeFinder(const RegisterAllocationData* data, Zone* zone) 214 : data_(data), 215 bounds_length_(static_cast<int>(data_->live_ranges().size())), 216 bounds_(zone->NewArray<LiveRangeBoundArray>(bounds_length_)), 217 zone_(zone) { 218 for (int i = 0; i < bounds_length_; ++i) { 219 new (&bounds_[i]) LiveRangeBoundArray(); 220 } 221 } 222 223 LiveRangeBoundArray* ArrayFor(int operand_index) { 224 DCHECK(operand_index < bounds_length_); 225 TopLevelLiveRange* range = data_->live_ranges()[operand_index]; 226 DCHECK(range != nullptr && !range->IsEmpty()); 227 LiveRangeBoundArray* array = &bounds_[operand_index]; 228 if (array->ShouldInitialize()) { 229 array->Initialize(zone_, range); 230 } 231 return array; 232 } 233 234 private: 235 const RegisterAllocationData* const data_; 236 const int bounds_length_; 237 LiveRangeBoundArray* const bounds_; 238 Zone* const zone_; 239 240 DISALLOW_COPY_AND_ASSIGN(LiveRangeFinder); 241}; 242 243 244typedef std::pair<ParallelMove*, InstructionOperand> DelayedInsertionMapKey; 245 246 247struct DelayedInsertionMapCompare { 248 bool operator()(const DelayedInsertionMapKey& a, 249 const DelayedInsertionMapKey& b) const { 250 if (a.first == b.first) { 251 return a.second.Compare(b.second); 252 } 253 return a.first < b.first; 254 } 255}; 256 257 258typedef ZoneMap<DelayedInsertionMapKey, InstructionOperand, 259 DelayedInsertionMapCompare> DelayedInsertionMap; 260 261 262UsePosition::UsePosition(LifetimePosition pos, InstructionOperand* operand, 263 void* hint, UsePositionHintType hint_type) 264 : operand_(operand), hint_(hint), next_(nullptr), pos_(pos), flags_(0) { 265 DCHECK_IMPLIES(hint == nullptr, hint_type == UsePositionHintType::kNone); 266 bool register_beneficial = true; 267 UsePositionType type = UsePositionType::kAny; 268 if (operand_ != nullptr && operand_->IsUnallocated()) { 269 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(operand_); 270 if (unalloc->HasRegisterPolicy()) { 271 type = UsePositionType::kRequiresRegister; 272 } else if (unalloc->HasSlotPolicy()) { 273 type = UsePositionType::kRequiresSlot; 274 register_beneficial = false; 275 } else { 276 register_beneficial = !unalloc->HasAnyPolicy(); 277 } 278 } 279 flags_ = TypeField::encode(type) | HintTypeField::encode(hint_type) | 280 RegisterBeneficialField::encode(register_beneficial) | 281 AssignedRegisterField::encode(kUnassignedRegister); 282 DCHECK(pos_.IsValid()); 283} 284 285 286bool UsePosition::HasHint() const { 287 int hint_register; 288 return HintRegister(&hint_register); 289} 290 291 292bool UsePosition::HintRegister(int* register_code) const { 293 if (hint_ == nullptr) return false; 294 switch (HintTypeField::decode(flags_)) { 295 case UsePositionHintType::kNone: 296 case UsePositionHintType::kUnresolved: 297 return false; 298 case UsePositionHintType::kUsePos: { 299 UsePosition* use_pos = reinterpret_cast<UsePosition*>(hint_); 300 int assigned_register = AssignedRegisterField::decode(use_pos->flags_); 301 if (assigned_register == kUnassignedRegister) return false; 302 *register_code = assigned_register; 303 return true; 304 } 305 case UsePositionHintType::kOperand: { 306 InstructionOperand* operand = 307 reinterpret_cast<InstructionOperand*>(hint_); 308 *register_code = LocationOperand::cast(operand)->register_code(); 309 return true; 310 } 311 case UsePositionHintType::kPhi: { 312 RegisterAllocationData::PhiMapValue* phi = 313 reinterpret_cast<RegisterAllocationData::PhiMapValue*>(hint_); 314 int assigned_register = phi->assigned_register(); 315 if (assigned_register == kUnassignedRegister) return false; 316 *register_code = assigned_register; 317 return true; 318 } 319 } 320 UNREACHABLE(); 321 return false; 322} 323 324 325UsePositionHintType UsePosition::HintTypeForOperand( 326 const InstructionOperand& op) { 327 switch (op.kind()) { 328 case InstructionOperand::CONSTANT: 329 case InstructionOperand::IMMEDIATE: 330 case InstructionOperand::EXPLICIT: 331 return UsePositionHintType::kNone; 332 case InstructionOperand::UNALLOCATED: 333 return UsePositionHintType::kUnresolved; 334 case InstructionOperand::ALLOCATED: 335 if (op.IsRegister() || op.IsFPRegister()) { 336 return UsePositionHintType::kOperand; 337 } else { 338 DCHECK(op.IsStackSlot() || op.IsFPStackSlot()); 339 return UsePositionHintType::kNone; 340 } 341 case InstructionOperand::INVALID: 342 break; 343 } 344 UNREACHABLE(); 345 return UsePositionHintType::kNone; 346} 347 348void UsePosition::SetHint(UsePosition* use_pos) { 349 DCHECK_NOT_NULL(use_pos); 350 hint_ = use_pos; 351 flags_ = HintTypeField::update(flags_, UsePositionHintType::kUsePos); 352} 353 354void UsePosition::ResolveHint(UsePosition* use_pos) { 355 DCHECK_NOT_NULL(use_pos); 356 if (HintTypeField::decode(flags_) != UsePositionHintType::kUnresolved) return; 357 hint_ = use_pos; 358 flags_ = HintTypeField::update(flags_, UsePositionHintType::kUsePos); 359} 360 361 362void UsePosition::set_type(UsePositionType type, bool register_beneficial) { 363 DCHECK_IMPLIES(type == UsePositionType::kRequiresSlot, !register_beneficial); 364 DCHECK_EQ(kUnassignedRegister, AssignedRegisterField::decode(flags_)); 365 flags_ = TypeField::encode(type) | 366 RegisterBeneficialField::encode(register_beneficial) | 367 HintTypeField::encode(HintTypeField::decode(flags_)) | 368 AssignedRegisterField::encode(kUnassignedRegister); 369} 370 371 372UseInterval* UseInterval::SplitAt(LifetimePosition pos, Zone* zone) { 373 DCHECK(Contains(pos) && pos != start()); 374 UseInterval* after = new (zone) UseInterval(pos, end_); 375 after->next_ = next_; 376 next_ = nullptr; 377 end_ = pos; 378 return after; 379} 380 381 382void LifetimePosition::Print() const { 383 OFStream os(stdout); 384 os << *this << std::endl; 385} 386 387 388std::ostream& operator<<(std::ostream& os, const LifetimePosition pos) { 389 os << '@' << pos.ToInstructionIndex(); 390 if (pos.IsGapPosition()) { 391 os << 'g'; 392 } else { 393 os << 'i'; 394 } 395 if (pos.IsStart()) { 396 os << 's'; 397 } else { 398 os << 'e'; 399 } 400 return os; 401} 402 403LiveRange::LiveRange(int relative_id, MachineRepresentation rep, 404 TopLevelLiveRange* top_level) 405 : relative_id_(relative_id), 406 bits_(0), 407 last_interval_(nullptr), 408 first_interval_(nullptr), 409 first_pos_(nullptr), 410 top_level_(top_level), 411 next_(nullptr), 412 current_interval_(nullptr), 413 last_processed_use_(nullptr), 414 current_hint_position_(nullptr), 415 splitting_pointer_(nullptr) { 416 DCHECK(AllocatedOperand::IsSupportedRepresentation(rep)); 417 bits_ = AssignedRegisterField::encode(kUnassignedRegister) | 418 RepresentationField::encode(rep); 419} 420 421 422void LiveRange::VerifyPositions() const { 423 // Walk the positions, verifying that each is in an interval. 424 UseInterval* interval = first_interval_; 425 for (UsePosition* pos = first_pos_; pos != nullptr; pos = pos->next()) { 426 CHECK(Start() <= pos->pos()); 427 CHECK(pos->pos() <= End()); 428 CHECK_NOT_NULL(interval); 429 while (!interval->Contains(pos->pos()) && interval->end() != pos->pos()) { 430 interval = interval->next(); 431 CHECK_NOT_NULL(interval); 432 } 433 } 434} 435 436 437void LiveRange::VerifyIntervals() const { 438 DCHECK(first_interval()->start() == Start()); 439 LifetimePosition last_end = first_interval()->end(); 440 for (UseInterval* interval = first_interval()->next(); interval != nullptr; 441 interval = interval->next()) { 442 DCHECK(last_end <= interval->start()); 443 last_end = interval->end(); 444 } 445 DCHECK(last_end == End()); 446} 447 448 449void LiveRange::set_assigned_register(int reg) { 450 DCHECK(!HasRegisterAssigned() && !spilled()); 451 bits_ = AssignedRegisterField::update(bits_, reg); 452} 453 454 455void LiveRange::UnsetAssignedRegister() { 456 DCHECK(HasRegisterAssigned() && !spilled()); 457 bits_ = AssignedRegisterField::update(bits_, kUnassignedRegister); 458} 459 460 461void LiveRange::Spill() { 462 DCHECK(!spilled()); 463 DCHECK(!TopLevel()->HasNoSpillType()); 464 set_spilled(true); 465 bits_ = AssignedRegisterField::update(bits_, kUnassignedRegister); 466} 467 468 469RegisterKind LiveRange::kind() const { 470 return IsFloatingPoint(representation()) ? FP_REGISTERS : GENERAL_REGISTERS; 471} 472 473 474UsePosition* LiveRange::FirstHintPosition(int* register_index) const { 475 for (UsePosition* pos = first_pos_; pos != nullptr; pos = pos->next()) { 476 if (pos->HintRegister(register_index)) return pos; 477 } 478 return nullptr; 479} 480 481 482UsePosition* LiveRange::NextUsePosition(LifetimePosition start) const { 483 UsePosition* use_pos = last_processed_use_; 484 if (use_pos == nullptr || use_pos->pos() > start) { 485 use_pos = first_pos(); 486 } 487 while (use_pos != nullptr && use_pos->pos() < start) { 488 use_pos = use_pos->next(); 489 } 490 last_processed_use_ = use_pos; 491 return use_pos; 492} 493 494 495UsePosition* LiveRange::NextUsePositionRegisterIsBeneficial( 496 LifetimePosition start) const { 497 UsePosition* pos = NextUsePosition(start); 498 while (pos != nullptr && !pos->RegisterIsBeneficial()) { 499 pos = pos->next(); 500 } 501 return pos; 502} 503 504LifetimePosition LiveRange::NextLifetimePositionRegisterIsBeneficial( 505 const LifetimePosition& start) const { 506 UsePosition* next_use = NextUsePositionRegisterIsBeneficial(start); 507 if (next_use == nullptr) return End(); 508 return next_use->pos(); 509} 510 511UsePosition* LiveRange::PreviousUsePositionRegisterIsBeneficial( 512 LifetimePosition start) const { 513 UsePosition* pos = first_pos(); 514 UsePosition* prev = nullptr; 515 while (pos != nullptr && pos->pos() < start) { 516 if (pos->RegisterIsBeneficial()) prev = pos; 517 pos = pos->next(); 518 } 519 return prev; 520} 521 522 523UsePosition* LiveRange::NextRegisterPosition(LifetimePosition start) const { 524 UsePosition* pos = NextUsePosition(start); 525 while (pos != nullptr && pos->type() != UsePositionType::kRequiresRegister) { 526 pos = pos->next(); 527 } 528 return pos; 529} 530 531 532UsePosition* LiveRange::NextSlotPosition(LifetimePosition start) const { 533 for (UsePosition* pos = NextUsePosition(start); pos != nullptr; 534 pos = pos->next()) { 535 if (pos->type() != UsePositionType::kRequiresSlot) continue; 536 return pos; 537 } 538 return nullptr; 539} 540 541 542bool LiveRange::CanBeSpilled(LifetimePosition pos) const { 543 // We cannot spill a live range that has a use requiring a register 544 // at the current or the immediate next position. 545 UsePosition* use_pos = NextRegisterPosition(pos); 546 if (use_pos == nullptr) return true; 547 return use_pos->pos() > pos.NextStart().End(); 548} 549 550 551bool LiveRange::IsTopLevel() const { return top_level_ == this; } 552 553 554InstructionOperand LiveRange::GetAssignedOperand() const { 555 if (HasRegisterAssigned()) { 556 DCHECK(!spilled()); 557 return AllocatedOperand(LocationOperand::REGISTER, representation(), 558 assigned_register()); 559 } 560 DCHECK(spilled()); 561 DCHECK(!HasRegisterAssigned()); 562 if (TopLevel()->HasSpillOperand()) { 563 InstructionOperand* op = TopLevel()->GetSpillOperand(); 564 DCHECK(!op->IsUnallocated()); 565 return *op; 566 } 567 return TopLevel()->GetSpillRangeOperand(); 568} 569 570 571UseInterval* LiveRange::FirstSearchIntervalForPosition( 572 LifetimePosition position) const { 573 if (current_interval_ == nullptr) return first_interval_; 574 if (current_interval_->start() > position) { 575 current_interval_ = nullptr; 576 return first_interval_; 577 } 578 return current_interval_; 579} 580 581 582void LiveRange::AdvanceLastProcessedMarker( 583 UseInterval* to_start_of, LifetimePosition but_not_past) const { 584 if (to_start_of == nullptr) return; 585 if (to_start_of->start() > but_not_past) return; 586 LifetimePosition start = current_interval_ == nullptr 587 ? LifetimePosition::Invalid() 588 : current_interval_->start(); 589 if (to_start_of->start() > start) { 590 current_interval_ = to_start_of; 591 } 592} 593 594 595LiveRange* LiveRange::SplitAt(LifetimePosition position, Zone* zone) { 596 int new_id = TopLevel()->GetNextChildId(); 597 LiveRange* child = new (zone) LiveRange(new_id, representation(), TopLevel()); 598 // If we split, we do so because we're about to switch registers or move 599 // to/from a slot, so there's no value in connecting hints. 600 DetachAt(position, child, zone, DoNotConnectHints); 601 602 child->top_level_ = TopLevel(); 603 child->next_ = next_; 604 next_ = child; 605 return child; 606} 607 608UsePosition* LiveRange::DetachAt(LifetimePosition position, LiveRange* result, 609 Zone* zone, 610 HintConnectionOption connect_hints) { 611 DCHECK(Start() < position); 612 DCHECK(End() > position); 613 DCHECK(result->IsEmpty()); 614 // Find the last interval that ends before the position. If the 615 // position is contained in one of the intervals in the chain, we 616 // split that interval and use the first part. 617 UseInterval* current = FirstSearchIntervalForPosition(position); 618 619 // If the split position coincides with the beginning of a use interval 620 // we need to split use positons in a special way. 621 bool split_at_start = false; 622 623 if (current->start() == position) { 624 // When splitting at start we need to locate the previous use interval. 625 current = first_interval_; 626 } 627 628 UseInterval* after = nullptr; 629 while (current != nullptr) { 630 if (current->Contains(position)) { 631 after = current->SplitAt(position, zone); 632 break; 633 } 634 UseInterval* next = current->next(); 635 if (next->start() >= position) { 636 split_at_start = (next->start() == position); 637 after = next; 638 current->set_next(nullptr); 639 break; 640 } 641 current = next; 642 } 643 DCHECK(nullptr != after); 644 645 // Partition original use intervals to the two live ranges. 646 UseInterval* before = current; 647 result->last_interval_ = 648 (last_interval_ == before) 649 ? after // Only interval in the range after split. 650 : last_interval_; // Last interval of the original range. 651 result->first_interval_ = after; 652 last_interval_ = before; 653 654 // Find the last use position before the split and the first use 655 // position after it. 656 UsePosition* use_after = 657 splitting_pointer_ == nullptr || splitting_pointer_->pos() > position 658 ? first_pos() 659 : splitting_pointer_; 660 UsePosition* use_before = nullptr; 661 if (split_at_start) { 662 // The split position coincides with the beginning of a use interval (the 663 // end of a lifetime hole). Use at this position should be attributed to 664 // the split child because split child owns use interval covering it. 665 while (use_after != nullptr && use_after->pos() < position) { 666 use_before = use_after; 667 use_after = use_after->next(); 668 } 669 } else { 670 while (use_after != nullptr && use_after->pos() <= position) { 671 use_before = use_after; 672 use_after = use_after->next(); 673 } 674 } 675 676 // Partition original use positions to the two live ranges. 677 if (use_before != nullptr) { 678 use_before->set_next(nullptr); 679 } else { 680 first_pos_ = nullptr; 681 } 682 result->first_pos_ = use_after; 683 684 // Discard cached iteration state. It might be pointing 685 // to the use that no longer belongs to this live range. 686 last_processed_use_ = nullptr; 687 current_interval_ = nullptr; 688 689 if (connect_hints == ConnectHints && use_before != nullptr && 690 use_after != nullptr) { 691 use_after->SetHint(use_before); 692 } 693#ifdef DEBUG 694 VerifyChildStructure(); 695 result->VerifyChildStructure(); 696#endif 697 return use_before; 698} 699 700 701void LiveRange::UpdateParentForAllChildren(TopLevelLiveRange* new_top_level) { 702 LiveRange* child = this; 703 for (; child != nullptr; child = child->next()) { 704 child->top_level_ = new_top_level; 705 } 706} 707 708 709void LiveRange::ConvertUsesToOperand(const InstructionOperand& op, 710 const InstructionOperand& spill_op) { 711 for (UsePosition* pos = first_pos(); pos != nullptr; pos = pos->next()) { 712 DCHECK(Start() <= pos->pos() && pos->pos() <= End()); 713 if (!pos->HasOperand()) continue; 714 switch (pos->type()) { 715 case UsePositionType::kRequiresSlot: 716 DCHECK(spill_op.IsStackSlot() || spill_op.IsFPStackSlot()); 717 InstructionOperand::ReplaceWith(pos->operand(), &spill_op); 718 break; 719 case UsePositionType::kRequiresRegister: 720 DCHECK(op.IsRegister() || op.IsFPRegister()); 721 // Fall through. 722 case UsePositionType::kAny: 723 InstructionOperand::ReplaceWith(pos->operand(), &op); 724 break; 725 } 726 } 727} 728 729 730// This implements an ordering on live ranges so that they are ordered by their 731// start positions. This is needed for the correctness of the register 732// allocation algorithm. If two live ranges start at the same offset then there 733// is a tie breaker based on where the value is first used. This part of the 734// ordering is merely a heuristic. 735bool LiveRange::ShouldBeAllocatedBefore(const LiveRange* other) const { 736 LifetimePosition start = Start(); 737 LifetimePosition other_start = other->Start(); 738 if (start == other_start) { 739 UsePosition* pos = first_pos(); 740 if (pos == nullptr) return false; 741 UsePosition* other_pos = other->first_pos(); 742 if (other_pos == nullptr) return true; 743 return pos->pos() < other_pos->pos(); 744 } 745 return start < other_start; 746} 747 748 749void LiveRange::SetUseHints(int register_index) { 750 for (UsePosition* pos = first_pos(); pos != nullptr; pos = pos->next()) { 751 if (!pos->HasOperand()) continue; 752 switch (pos->type()) { 753 case UsePositionType::kRequiresSlot: 754 break; 755 case UsePositionType::kRequiresRegister: 756 case UsePositionType::kAny: 757 pos->set_assigned_register(register_index); 758 break; 759 } 760 } 761} 762 763 764bool LiveRange::CanCover(LifetimePosition position) const { 765 if (IsEmpty()) return false; 766 return Start() <= position && position < End(); 767} 768 769 770bool LiveRange::Covers(LifetimePosition position) const { 771 if (!CanCover(position)) return false; 772 UseInterval* start_search = FirstSearchIntervalForPosition(position); 773 for (UseInterval* interval = start_search; interval != nullptr; 774 interval = interval->next()) { 775 DCHECK(interval->next() == nullptr || 776 interval->next()->start() >= interval->start()); 777 AdvanceLastProcessedMarker(interval, position); 778 if (interval->Contains(position)) return true; 779 if (interval->start() > position) return false; 780 } 781 return false; 782} 783 784 785LifetimePosition LiveRange::FirstIntersection(LiveRange* other) const { 786 UseInterval* b = other->first_interval(); 787 if (b == nullptr) return LifetimePosition::Invalid(); 788 LifetimePosition advance_last_processed_up_to = b->start(); 789 UseInterval* a = FirstSearchIntervalForPosition(b->start()); 790 while (a != nullptr && b != nullptr) { 791 if (a->start() > other->End()) break; 792 if (b->start() > End()) break; 793 LifetimePosition cur_intersection = a->Intersect(b); 794 if (cur_intersection.IsValid()) { 795 return cur_intersection; 796 } 797 if (a->start() < b->start()) { 798 a = a->next(); 799 if (a == nullptr || a->start() > other->End()) break; 800 AdvanceLastProcessedMarker(a, advance_last_processed_up_to); 801 } else { 802 b = b->next(); 803 } 804 } 805 return LifetimePosition::Invalid(); 806} 807 808void LiveRange::Print(const RegisterConfiguration* config, 809 bool with_children) const { 810 OFStream os(stdout); 811 PrintableLiveRange wrapper; 812 wrapper.register_configuration_ = config; 813 for (const LiveRange* i = this; i != nullptr; i = i->next()) { 814 wrapper.range_ = i; 815 os << wrapper << std::endl; 816 if (!with_children) break; 817 } 818} 819 820 821void LiveRange::Print(bool with_children) const { 822 Print(RegisterConfiguration::Turbofan(), with_children); 823} 824 825 826struct TopLevelLiveRange::SpillMoveInsertionList : ZoneObject { 827 SpillMoveInsertionList(int gap_index, InstructionOperand* operand, 828 SpillMoveInsertionList* next) 829 : gap_index(gap_index), operand(operand), next(next) {} 830 const int gap_index; 831 InstructionOperand* const operand; 832 SpillMoveInsertionList* const next; 833}; 834 835 836TopLevelLiveRange::TopLevelLiveRange(int vreg, MachineRepresentation rep) 837 : LiveRange(0, rep, this), 838 vreg_(vreg), 839 last_child_id_(0), 840 splintered_from_(nullptr), 841 spill_operand_(nullptr), 842 spill_move_insertion_locations_(nullptr), 843 spilled_in_deferred_blocks_(false), 844 spill_start_index_(kMaxInt), 845 last_pos_(nullptr), 846 splinter_(nullptr), 847 has_preassigned_slot_(false) { 848 bits_ |= SpillTypeField::encode(SpillType::kNoSpillType); 849} 850 851 852#if DEBUG 853int TopLevelLiveRange::debug_virt_reg() const { 854 return IsSplinter() ? splintered_from()->vreg() : vreg(); 855} 856#endif 857 858 859void TopLevelLiveRange::RecordSpillLocation(Zone* zone, int gap_index, 860 InstructionOperand* operand) { 861 DCHECK(HasNoSpillType()); 862 spill_move_insertion_locations_ = new (zone) SpillMoveInsertionList( 863 gap_index, operand, spill_move_insertion_locations_); 864} 865 866void TopLevelLiveRange::CommitSpillMoves(InstructionSequence* sequence, 867 const InstructionOperand& op, 868 bool might_be_duplicated) { 869 DCHECK_IMPLIES(op.IsConstant(), GetSpillMoveInsertionLocations() == nullptr); 870 Zone* zone = sequence->zone(); 871 872 for (SpillMoveInsertionList* to_spill = GetSpillMoveInsertionLocations(); 873 to_spill != nullptr; to_spill = to_spill->next) { 874 Instruction* instr = sequence->InstructionAt(to_spill->gap_index); 875 ParallelMove* move = 876 instr->GetOrCreateParallelMove(Instruction::START, zone); 877 // Skip insertion if it's possible that the move exists already as a 878 // constraint move from a fixed output register to a slot. 879 if (might_be_duplicated || has_preassigned_slot()) { 880 bool found = false; 881 for (MoveOperands* move_op : *move) { 882 if (move_op->IsEliminated()) continue; 883 if (move_op->source().Equals(*to_spill->operand) && 884 move_op->destination().Equals(op)) { 885 found = true; 886 if (has_preassigned_slot()) move_op->Eliminate(); 887 break; 888 } 889 } 890 if (found) continue; 891 } 892 if (!has_preassigned_slot()) { 893 move->AddMove(*to_spill->operand, op); 894 } 895 } 896} 897 898 899void TopLevelLiveRange::SetSpillOperand(InstructionOperand* operand) { 900 DCHECK(HasNoSpillType()); 901 DCHECK(!operand->IsUnallocated() && !operand->IsImmediate()); 902 set_spill_type(SpillType::kSpillOperand); 903 spill_operand_ = operand; 904} 905 906 907void TopLevelLiveRange::SetSpillRange(SpillRange* spill_range) { 908 DCHECK(!HasSpillOperand()); 909 DCHECK(spill_range); 910 spill_range_ = spill_range; 911} 912 913 914AllocatedOperand TopLevelLiveRange::GetSpillRangeOperand() const { 915 SpillRange* spill_range = GetSpillRange(); 916 int index = spill_range->assigned_slot(); 917 return AllocatedOperand(LocationOperand::STACK_SLOT, representation(), index); 918} 919 920 921void TopLevelLiveRange::Splinter(LifetimePosition start, LifetimePosition end, 922 Zone* zone) { 923 DCHECK(start != Start() || end != End()); 924 DCHECK(start < end); 925 926 TopLevelLiveRange splinter_temp(-1, representation()); 927 UsePosition* last_in_splinter = nullptr; 928 // Live ranges defined in deferred blocks stay in deferred blocks, so we 929 // don't need to splinter them. That means that start should always be 930 // after the beginning of the range. 931 DCHECK(start > Start()); 932 933 if (end >= End()) { 934 DCHECK(start > Start()); 935 DetachAt(start, &splinter_temp, zone, ConnectHints); 936 next_ = nullptr; 937 } else { 938 DCHECK(start < End() && Start() < end); 939 940 const int kInvalidId = std::numeric_limits<int>::max(); 941 942 UsePosition* last = DetachAt(start, &splinter_temp, zone, ConnectHints); 943 944 LiveRange end_part(kInvalidId, this->representation(), nullptr); 945 // The last chunk exits the deferred region, and we don't want to connect 946 // hints here, because the non-deferred region shouldn't be affected 947 // by allocation decisions on the deferred path. 948 last_in_splinter = 949 splinter_temp.DetachAt(end, &end_part, zone, DoNotConnectHints); 950 951 next_ = end_part.next_; 952 last_interval_->set_next(end_part.first_interval_); 953 // The next splinter will happen either at or after the current interval. 954 // We can optimize DetachAt by setting current_interval_ accordingly, 955 // which will then be picked up by FirstSearchIntervalForPosition. 956 current_interval_ = last_interval_; 957 last_interval_ = end_part.last_interval_; 958 959 if (first_pos_ == nullptr) { 960 first_pos_ = end_part.first_pos_; 961 } else { 962 splitting_pointer_ = last; 963 if (last != nullptr) last->set_next(end_part.first_pos_); 964 } 965 } 966 967 if (splinter()->IsEmpty()) { 968 splinter()->first_interval_ = splinter_temp.first_interval_; 969 splinter()->last_interval_ = splinter_temp.last_interval_; 970 } else { 971 splinter()->last_interval_->set_next(splinter_temp.first_interval_); 972 splinter()->last_interval_ = splinter_temp.last_interval_; 973 } 974 if (splinter()->first_pos() == nullptr) { 975 splinter()->first_pos_ = splinter_temp.first_pos_; 976 } else { 977 splinter()->last_pos_->set_next(splinter_temp.first_pos_); 978 } 979 if (last_in_splinter != nullptr) { 980 splinter()->last_pos_ = last_in_splinter; 981 } else { 982 if (splinter()->first_pos() != nullptr && 983 splinter()->last_pos_ == nullptr) { 984 splinter()->last_pos_ = splinter()->first_pos(); 985 for (UsePosition* pos = splinter()->first_pos(); pos != nullptr; 986 pos = pos->next()) { 987 splinter()->last_pos_ = pos; 988 } 989 } 990 } 991#if DEBUG 992 Verify(); 993 splinter()->Verify(); 994#endif 995} 996 997 998void TopLevelLiveRange::SetSplinteredFrom(TopLevelLiveRange* splinter_parent) { 999 splintered_from_ = splinter_parent; 1000 if (!HasSpillOperand() && splinter_parent->spill_range_ != nullptr) { 1001 SetSpillRange(splinter_parent->spill_range_); 1002 } 1003} 1004 1005 1006void TopLevelLiveRange::UpdateSpillRangePostMerge(TopLevelLiveRange* merged) { 1007 DCHECK(merged->TopLevel() == this); 1008 1009 if (HasNoSpillType() && merged->HasSpillRange()) { 1010 set_spill_type(merged->spill_type()); 1011 DCHECK(GetSpillRange()->live_ranges().size() > 0); 1012 merged->spill_range_ = nullptr; 1013 merged->bits_ = 1014 SpillTypeField::update(merged->bits_, SpillType::kNoSpillType); 1015 } 1016} 1017 1018 1019void TopLevelLiveRange::Merge(TopLevelLiveRange* other, Zone* zone) { 1020 DCHECK(Start() < other->Start()); 1021 DCHECK(other->splintered_from() == this); 1022 1023 LiveRange* first = this; 1024 LiveRange* second = other; 1025 DCHECK(first->Start() < second->Start()); 1026 while (first != nullptr && second != nullptr) { 1027 DCHECK(first != second); 1028 // Make sure the ranges are in order each time we iterate. 1029 if (second->Start() < first->Start()) { 1030 LiveRange* tmp = second; 1031 second = first; 1032 first = tmp; 1033 continue; 1034 } 1035 1036 if (first->End() <= second->Start()) { 1037 if (first->next() == nullptr || 1038 first->next()->Start() > second->Start()) { 1039 // First is in order before second. 1040 LiveRange* temp = first->next(); 1041 first->next_ = second; 1042 first = temp; 1043 } else { 1044 // First is in order before its successor (or second), so advance first. 1045 first = first->next(); 1046 } 1047 continue; 1048 } 1049 1050 DCHECK(first->Start() < second->Start()); 1051 // If first and second intersect, split first. 1052 if (first->Start() < second->End() && second->Start() < first->End()) { 1053 LiveRange* temp = first->SplitAt(second->Start(), zone); 1054 CHECK(temp != first); 1055 temp->set_spilled(first->spilled()); 1056 if (!temp->spilled()) 1057 temp->set_assigned_register(first->assigned_register()); 1058 1059 first->next_ = second; 1060 first = temp; 1061 continue; 1062 } 1063 DCHECK(first->End() <= second->Start()); 1064 } 1065 1066 TopLevel()->UpdateParentForAllChildren(TopLevel()); 1067 TopLevel()->UpdateSpillRangePostMerge(other); 1068 TopLevel()->set_has_slot_use(TopLevel()->has_slot_use() || 1069 other->has_slot_use()); 1070 1071#if DEBUG 1072 Verify(); 1073#endif 1074} 1075 1076 1077void TopLevelLiveRange::VerifyChildrenInOrder() const { 1078 LifetimePosition last_end = End(); 1079 for (const LiveRange* child = this->next(); child != nullptr; 1080 child = child->next()) { 1081 DCHECK(last_end <= child->Start()); 1082 last_end = child->End(); 1083 } 1084} 1085 1086 1087void TopLevelLiveRange::Verify() const { 1088 VerifyChildrenInOrder(); 1089 for (const LiveRange* child = this; child != nullptr; child = child->next()) { 1090 VerifyChildStructure(); 1091 } 1092} 1093 1094 1095void TopLevelLiveRange::ShortenTo(LifetimePosition start) { 1096 TRACE("Shorten live range %d to [%d\n", vreg(), start.value()); 1097 DCHECK(first_interval_ != nullptr); 1098 DCHECK(first_interval_->start() <= start); 1099 DCHECK(start < first_interval_->end()); 1100 first_interval_->set_start(start); 1101} 1102 1103 1104void TopLevelLiveRange::EnsureInterval(LifetimePosition start, 1105 LifetimePosition end, Zone* zone) { 1106 TRACE("Ensure live range %d in interval [%d %d[\n", vreg(), start.value(), 1107 end.value()); 1108 LifetimePosition new_end = end; 1109 while (first_interval_ != nullptr && first_interval_->start() <= end) { 1110 if (first_interval_->end() > end) { 1111 new_end = first_interval_->end(); 1112 } 1113 first_interval_ = first_interval_->next(); 1114 } 1115 1116 UseInterval* new_interval = new (zone) UseInterval(start, new_end); 1117 new_interval->set_next(first_interval_); 1118 first_interval_ = new_interval; 1119 if (new_interval->next() == nullptr) { 1120 last_interval_ = new_interval; 1121 } 1122} 1123 1124 1125void TopLevelLiveRange::AddUseInterval(LifetimePosition start, 1126 LifetimePosition end, Zone* zone) { 1127 TRACE("Add to live range %d interval [%d %d[\n", vreg(), start.value(), 1128 end.value()); 1129 if (first_interval_ == nullptr) { 1130 UseInterval* interval = new (zone) UseInterval(start, end); 1131 first_interval_ = interval; 1132 last_interval_ = interval; 1133 } else { 1134 if (end == first_interval_->start()) { 1135 first_interval_->set_start(start); 1136 } else if (end < first_interval_->start()) { 1137 UseInterval* interval = new (zone) UseInterval(start, end); 1138 interval->set_next(first_interval_); 1139 first_interval_ = interval; 1140 } else { 1141 // Order of instruction's processing (see ProcessInstructions) guarantees 1142 // that each new use interval either precedes, intersects with or touches 1143 // the last added interval. 1144 DCHECK(start <= first_interval_->end()); 1145 first_interval_->set_start(Min(start, first_interval_->start())); 1146 first_interval_->set_end(Max(end, first_interval_->end())); 1147 } 1148 } 1149} 1150 1151 1152void TopLevelLiveRange::AddUsePosition(UsePosition* use_pos) { 1153 LifetimePosition pos = use_pos->pos(); 1154 TRACE("Add to live range %d use position %d\n", vreg(), pos.value()); 1155 UsePosition* prev_hint = nullptr; 1156 UsePosition* prev = nullptr; 1157 UsePosition* current = first_pos_; 1158 while (current != nullptr && current->pos() < pos) { 1159 prev_hint = current->HasHint() ? current : prev_hint; 1160 prev = current; 1161 current = current->next(); 1162 } 1163 1164 if (prev == nullptr) { 1165 use_pos->set_next(first_pos_); 1166 first_pos_ = use_pos; 1167 } else { 1168 use_pos->set_next(prev->next()); 1169 prev->set_next(use_pos); 1170 } 1171 1172 if (prev_hint == nullptr && use_pos->HasHint()) { 1173 current_hint_position_ = use_pos; 1174 } 1175} 1176 1177 1178static bool AreUseIntervalsIntersecting(UseInterval* interval1, 1179 UseInterval* interval2) { 1180 while (interval1 != nullptr && interval2 != nullptr) { 1181 if (interval1->start() < interval2->start()) { 1182 if (interval1->end() > interval2->start()) { 1183 return true; 1184 } 1185 interval1 = interval1->next(); 1186 } else { 1187 if (interval2->end() > interval1->start()) { 1188 return true; 1189 } 1190 interval2 = interval2->next(); 1191 } 1192 } 1193 return false; 1194} 1195 1196 1197std::ostream& operator<<(std::ostream& os, 1198 const PrintableLiveRange& printable_range) { 1199 const LiveRange* range = printable_range.range_; 1200 os << "Range: " << range->TopLevel()->vreg() << ":" << range->relative_id() 1201 << " "; 1202 if (range->TopLevel()->is_phi()) os << "phi "; 1203 if (range->TopLevel()->is_non_loop_phi()) os << "nlphi "; 1204 1205 os << "{" << std::endl; 1206 UseInterval* interval = range->first_interval(); 1207 UsePosition* use_pos = range->first_pos(); 1208 PrintableInstructionOperand pio; 1209 pio.register_configuration_ = printable_range.register_configuration_; 1210 while (use_pos != nullptr) { 1211 if (use_pos->HasOperand()) { 1212 pio.op_ = *use_pos->operand(); 1213 os << pio << use_pos->pos() << " "; 1214 } 1215 use_pos = use_pos->next(); 1216 } 1217 os << std::endl; 1218 1219 while (interval != nullptr) { 1220 os << '[' << interval->start() << ", " << interval->end() << ')' 1221 << std::endl; 1222 interval = interval->next(); 1223 } 1224 os << "}"; 1225 return os; 1226} 1227 1228SpillRange::SpillRange(TopLevelLiveRange* parent, Zone* zone) 1229 : live_ranges_(zone), 1230 assigned_slot_(kUnassignedSlot), 1231 byte_width_(GetByteWidth(parent->representation())) { 1232 // Spill ranges are created for top level, non-splintered ranges. This is so 1233 // that, when merging decisions are made, we consider the full extent of the 1234 // virtual register, and avoid clobbering it. 1235 DCHECK(!parent->IsSplinter()); 1236 UseInterval* result = nullptr; 1237 UseInterval* node = nullptr; 1238 // Copy the intervals for all ranges. 1239 for (LiveRange* range = parent; range != nullptr; range = range->next()) { 1240 UseInterval* src = range->first_interval(); 1241 while (src != nullptr) { 1242 UseInterval* new_node = new (zone) UseInterval(src->start(), src->end()); 1243 if (result == nullptr) { 1244 result = new_node; 1245 } else { 1246 node->set_next(new_node); 1247 } 1248 node = new_node; 1249 src = src->next(); 1250 } 1251 } 1252 use_interval_ = result; 1253 live_ranges().push_back(parent); 1254 end_position_ = node->end(); 1255 parent->SetSpillRange(this); 1256} 1257 1258bool SpillRange::IsIntersectingWith(SpillRange* other) const { 1259 if (this->use_interval_ == nullptr || other->use_interval_ == nullptr || 1260 this->End() <= other->use_interval_->start() || 1261 other->End() <= this->use_interval_->start()) { 1262 return false; 1263 } 1264 return AreUseIntervalsIntersecting(use_interval_, other->use_interval_); 1265} 1266 1267 1268bool SpillRange::TryMerge(SpillRange* other) { 1269 if (HasSlot() || other->HasSlot()) return false; 1270 if (byte_width() != other->byte_width() || IsIntersectingWith(other)) 1271 return false; 1272 1273 LifetimePosition max = LifetimePosition::MaxPosition(); 1274 if (End() < other->End() && other->End() != max) { 1275 end_position_ = other->End(); 1276 } 1277 other->end_position_ = max; 1278 1279 MergeDisjointIntervals(other->use_interval_); 1280 other->use_interval_ = nullptr; 1281 1282 for (TopLevelLiveRange* range : other->live_ranges()) { 1283 DCHECK(range->GetSpillRange() == other); 1284 range->SetSpillRange(this); 1285 } 1286 1287 live_ranges().insert(live_ranges().end(), other->live_ranges().begin(), 1288 other->live_ranges().end()); 1289 other->live_ranges().clear(); 1290 1291 return true; 1292} 1293 1294 1295void SpillRange::MergeDisjointIntervals(UseInterval* other) { 1296 UseInterval* tail = nullptr; 1297 UseInterval* current = use_interval_; 1298 while (other != nullptr) { 1299 // Make sure the 'current' list starts first 1300 if (current == nullptr || current->start() > other->start()) { 1301 std::swap(current, other); 1302 } 1303 // Check disjointness 1304 DCHECK(other == nullptr || current->end() <= other->start()); 1305 // Append the 'current' node to the result accumulator and move forward 1306 if (tail == nullptr) { 1307 use_interval_ = current; 1308 } else { 1309 tail->set_next(current); 1310 } 1311 tail = current; 1312 current = current->next(); 1313 } 1314 // Other list is empty => we are done 1315} 1316 1317 1318void SpillRange::Print() const { 1319 OFStream os(stdout); 1320 os << "{" << std::endl; 1321 for (TopLevelLiveRange* range : live_ranges()) { 1322 os << range->vreg() << " "; 1323 } 1324 os << std::endl; 1325 1326 for (UseInterval* i = interval(); i != nullptr; i = i->next()) { 1327 os << '[' << i->start() << ", " << i->end() << ')' << std::endl; 1328 } 1329 os << "}" << std::endl; 1330} 1331 1332 1333RegisterAllocationData::PhiMapValue::PhiMapValue(PhiInstruction* phi, 1334 const InstructionBlock* block, 1335 Zone* zone) 1336 : phi_(phi), 1337 block_(block), 1338 incoming_operands_(zone), 1339 assigned_register_(kUnassignedRegister) { 1340 incoming_operands_.reserve(phi->operands().size()); 1341} 1342 1343 1344void RegisterAllocationData::PhiMapValue::AddOperand( 1345 InstructionOperand* operand) { 1346 incoming_operands_.push_back(operand); 1347} 1348 1349 1350void RegisterAllocationData::PhiMapValue::CommitAssignment( 1351 const InstructionOperand& assigned) { 1352 for (InstructionOperand* operand : incoming_operands_) { 1353 InstructionOperand::ReplaceWith(operand, &assigned); 1354 } 1355} 1356 1357RegisterAllocationData::RegisterAllocationData( 1358 const RegisterConfiguration* config, Zone* zone, Frame* frame, 1359 InstructionSequence* code, const char* debug_name) 1360 : allocation_zone_(zone), 1361 frame_(frame), 1362 code_(code), 1363 debug_name_(debug_name), 1364 config_(config), 1365 phi_map_(allocation_zone()), 1366 live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), 1367 live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()), 1368 live_ranges_(code->VirtualRegisterCount() * 2, nullptr, 1369 allocation_zone()), 1370 fixed_live_ranges_(this->config()->num_general_registers(), nullptr, 1371 allocation_zone()), 1372 fixed_float_live_ranges_(allocation_zone()), 1373 fixed_double_live_ranges_(this->config()->num_double_registers(), nullptr, 1374 allocation_zone()), 1375 fixed_simd128_live_ranges_(allocation_zone()), 1376 spill_ranges_(code->VirtualRegisterCount(), nullptr, allocation_zone()), 1377 delayed_references_(allocation_zone()), 1378 assigned_registers_(nullptr), 1379 assigned_double_registers_(nullptr), 1380 virtual_register_count_(code->VirtualRegisterCount()), 1381 preassigned_slot_ranges_(zone) { 1382 if (!kSimpleFPAliasing) { 1383 fixed_float_live_ranges_.resize(this->config()->num_float_registers(), 1384 nullptr); 1385 fixed_simd128_live_ranges_.resize(this->config()->num_simd128_registers(), 1386 nullptr); 1387 } 1388 1389 assigned_registers_ = new (code_zone()) 1390 BitVector(this->config()->num_general_registers(), code_zone()); 1391 assigned_double_registers_ = new (code_zone()) 1392 BitVector(this->config()->num_double_registers(), code_zone()); 1393 this->frame()->SetAllocatedRegisters(assigned_registers_); 1394 this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_); 1395} 1396 1397 1398MoveOperands* RegisterAllocationData::AddGapMove( 1399 int index, Instruction::GapPosition position, 1400 const InstructionOperand& from, const InstructionOperand& to) { 1401 Instruction* instr = code()->InstructionAt(index); 1402 ParallelMove* moves = instr->GetOrCreateParallelMove(position, code_zone()); 1403 return moves->AddMove(from, to); 1404} 1405 1406 1407MachineRepresentation RegisterAllocationData::RepresentationFor( 1408 int virtual_register) { 1409 DCHECK_LT(virtual_register, code()->VirtualRegisterCount()); 1410 return code()->GetRepresentation(virtual_register); 1411} 1412 1413 1414TopLevelLiveRange* RegisterAllocationData::GetOrCreateLiveRangeFor(int index) { 1415 if (index >= static_cast<int>(live_ranges().size())) { 1416 live_ranges().resize(index + 1, nullptr); 1417 } 1418 TopLevelLiveRange* result = live_ranges()[index]; 1419 if (result == nullptr) { 1420 result = NewLiveRange(index, RepresentationFor(index)); 1421 live_ranges()[index] = result; 1422 } 1423 return result; 1424} 1425 1426 1427TopLevelLiveRange* RegisterAllocationData::NewLiveRange( 1428 int index, MachineRepresentation rep) { 1429 return new (allocation_zone()) TopLevelLiveRange(index, rep); 1430} 1431 1432 1433int RegisterAllocationData::GetNextLiveRangeId() { 1434 int vreg = virtual_register_count_++; 1435 if (vreg >= static_cast<int>(live_ranges().size())) { 1436 live_ranges().resize(vreg + 1, nullptr); 1437 } 1438 return vreg; 1439} 1440 1441 1442TopLevelLiveRange* RegisterAllocationData::NextLiveRange( 1443 MachineRepresentation rep) { 1444 int vreg = GetNextLiveRangeId(); 1445 TopLevelLiveRange* ret = NewLiveRange(vreg, rep); 1446 return ret; 1447} 1448 1449 1450RegisterAllocationData::PhiMapValue* RegisterAllocationData::InitializePhiMap( 1451 const InstructionBlock* block, PhiInstruction* phi) { 1452 RegisterAllocationData::PhiMapValue* map_value = new (allocation_zone()) 1453 RegisterAllocationData::PhiMapValue(phi, block, allocation_zone()); 1454 auto res = 1455 phi_map_.insert(std::make_pair(phi->virtual_register(), map_value)); 1456 DCHECK(res.second); 1457 USE(res); 1458 return map_value; 1459} 1460 1461 1462RegisterAllocationData::PhiMapValue* RegisterAllocationData::GetPhiMapValueFor( 1463 int virtual_register) { 1464 auto it = phi_map_.find(virtual_register); 1465 DCHECK(it != phi_map_.end()); 1466 return it->second; 1467} 1468 1469 1470RegisterAllocationData::PhiMapValue* RegisterAllocationData::GetPhiMapValueFor( 1471 TopLevelLiveRange* top_range) { 1472 return GetPhiMapValueFor(top_range->vreg()); 1473} 1474 1475 1476bool RegisterAllocationData::ExistsUseWithoutDefinition() { 1477 bool found = false; 1478 BitVector::Iterator iterator(live_in_sets()[0]); 1479 while (!iterator.Done()) { 1480 found = true; 1481 int operand_index = iterator.Current(); 1482 PrintF("Register allocator error: live v%d reached first block.\n", 1483 operand_index); 1484 LiveRange* range = GetOrCreateLiveRangeFor(operand_index); 1485 PrintF(" (first use is at %d)\n", range->first_pos()->pos().value()); 1486 if (debug_name() == nullptr) { 1487 PrintF("\n"); 1488 } else { 1489 PrintF(" (function: %s)\n", debug_name()); 1490 } 1491 iterator.Advance(); 1492 } 1493 return found; 1494} 1495 1496 1497// If a range is defined in a deferred block, we can expect all the range 1498// to only cover positions in deferred blocks. Otherwise, a block on the 1499// hot path would be dominated by a deferred block, meaning it is unreachable 1500// without passing through the deferred block, which is contradictory. 1501// In particular, when such a range contributes a result back on the hot 1502// path, it will be as one of the inputs of a phi. In that case, the value 1503// will be transferred via a move in the Gap::END's of the last instruction 1504// of a deferred block. 1505bool RegisterAllocationData::RangesDefinedInDeferredStayInDeferred() { 1506 for (const TopLevelLiveRange* range : live_ranges()) { 1507 if (range == nullptr || range->IsEmpty() || 1508 !code() 1509 ->GetInstructionBlock(range->Start().ToInstructionIndex()) 1510 ->IsDeferred()) { 1511 continue; 1512 } 1513 for (const UseInterval* i = range->first_interval(); i != nullptr; 1514 i = i->next()) { 1515 int first = i->FirstGapIndex(); 1516 int last = i->LastGapIndex(); 1517 for (int instr = first; instr <= last;) { 1518 const InstructionBlock* block = code()->GetInstructionBlock(instr); 1519 if (!block->IsDeferred()) return false; 1520 instr = block->last_instruction_index() + 1; 1521 } 1522 } 1523 } 1524 return true; 1525} 1526 1527SpillRange* RegisterAllocationData::AssignSpillRangeToLiveRange( 1528 TopLevelLiveRange* range) { 1529 DCHECK(!range->HasSpillOperand()); 1530 1531 SpillRange* spill_range = range->GetAllocatedSpillRange(); 1532 if (spill_range == nullptr) { 1533 DCHECK(!range->IsSplinter()); 1534 spill_range = new (allocation_zone()) SpillRange(range, allocation_zone()); 1535 } 1536 range->set_spill_type(TopLevelLiveRange::SpillType::kSpillRange); 1537 1538 int spill_range_index = 1539 range->IsSplinter() ? range->splintered_from()->vreg() : range->vreg(); 1540 1541 spill_ranges()[spill_range_index] = spill_range; 1542 1543 return spill_range; 1544} 1545 1546 1547SpillRange* RegisterAllocationData::CreateSpillRangeForLiveRange( 1548 TopLevelLiveRange* range) { 1549 DCHECK(!range->HasSpillOperand()); 1550 DCHECK(!range->IsSplinter()); 1551 SpillRange* spill_range = 1552 new (allocation_zone()) SpillRange(range, allocation_zone()); 1553 return spill_range; 1554} 1555 1556void RegisterAllocationData::MarkAllocated(MachineRepresentation rep, 1557 int index) { 1558 switch (rep) { 1559 case MachineRepresentation::kFloat32: 1560 case MachineRepresentation::kSimd128: 1561 if (kSimpleFPAliasing) { 1562 assigned_double_registers_->Add(index); 1563 } else { 1564 int alias_base_index = -1; 1565 int aliases = config()->GetAliases( 1566 rep, index, MachineRepresentation::kFloat64, &alias_base_index); 1567 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); 1568 while (aliases--) { 1569 int aliased_reg = alias_base_index + aliases; 1570 assigned_double_registers_->Add(aliased_reg); 1571 } 1572 } 1573 break; 1574 case MachineRepresentation::kFloat64: 1575 assigned_double_registers_->Add(index); 1576 break; 1577 default: 1578 DCHECK(!IsFloatingPoint(rep)); 1579 assigned_registers_->Add(index); 1580 break; 1581 } 1582} 1583 1584bool RegisterAllocationData::IsBlockBoundary(LifetimePosition pos) const { 1585 return pos.IsFullStart() && 1586 code()->GetInstructionBlock(pos.ToInstructionIndex())->code_start() == 1587 pos.ToInstructionIndex(); 1588} 1589 1590 1591ConstraintBuilder::ConstraintBuilder(RegisterAllocationData* data) 1592 : data_(data) {} 1593 1594 1595InstructionOperand* ConstraintBuilder::AllocateFixed( 1596 UnallocatedOperand* operand, int pos, bool is_tagged) { 1597 TRACE("Allocating fixed reg for op %d\n", operand->virtual_register()); 1598 DCHECK(operand->HasFixedPolicy()); 1599 InstructionOperand allocated; 1600 MachineRepresentation rep = InstructionSequence::DefaultRepresentation(); 1601 int virtual_register = operand->virtual_register(); 1602 if (virtual_register != InstructionOperand::kInvalidVirtualRegister) { 1603 rep = data()->RepresentationFor(virtual_register); 1604 } 1605 if (operand->HasFixedSlotPolicy()) { 1606 allocated = AllocatedOperand(AllocatedOperand::STACK_SLOT, rep, 1607 operand->fixed_slot_index()); 1608 } else if (operand->HasFixedRegisterPolicy()) { 1609 DCHECK(!IsFloatingPoint(rep)); 1610 allocated = AllocatedOperand(AllocatedOperand::REGISTER, rep, 1611 operand->fixed_register_index()); 1612 } else if (operand->HasFixedFPRegisterPolicy()) { 1613 DCHECK(IsFloatingPoint(rep)); 1614 DCHECK_NE(InstructionOperand::kInvalidVirtualRegister, virtual_register); 1615 allocated = AllocatedOperand(AllocatedOperand::REGISTER, rep, 1616 operand->fixed_register_index()); 1617 } else { 1618 UNREACHABLE(); 1619 } 1620 InstructionOperand::ReplaceWith(operand, &allocated); 1621 if (is_tagged) { 1622 TRACE("Fixed reg is tagged at %d\n", pos); 1623 Instruction* instr = code()->InstructionAt(pos); 1624 if (instr->HasReferenceMap()) { 1625 instr->reference_map()->RecordReference(*AllocatedOperand::cast(operand)); 1626 } 1627 } 1628 return operand; 1629} 1630 1631 1632void ConstraintBuilder::MeetRegisterConstraints() { 1633 for (InstructionBlock* block : code()->instruction_blocks()) { 1634 MeetRegisterConstraints(block); 1635 } 1636} 1637 1638 1639void ConstraintBuilder::MeetRegisterConstraints(const InstructionBlock* block) { 1640 int start = block->first_instruction_index(); 1641 int end = block->last_instruction_index(); 1642 DCHECK_NE(-1, start); 1643 for (int i = start; i <= end; ++i) { 1644 MeetConstraintsBefore(i); 1645 if (i != end) MeetConstraintsAfter(i); 1646 } 1647 // Meet register constraints for the instruction in the end. 1648 MeetRegisterConstraintsForLastInstructionInBlock(block); 1649} 1650 1651 1652void ConstraintBuilder::MeetRegisterConstraintsForLastInstructionInBlock( 1653 const InstructionBlock* block) { 1654 int end = block->last_instruction_index(); 1655 Instruction* last_instruction = code()->InstructionAt(end); 1656 for (size_t i = 0; i < last_instruction->OutputCount(); i++) { 1657 InstructionOperand* output_operand = last_instruction->OutputAt(i); 1658 DCHECK(!output_operand->IsConstant()); 1659 UnallocatedOperand* output = UnallocatedOperand::cast(output_operand); 1660 int output_vreg = output->virtual_register(); 1661 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(output_vreg); 1662 bool assigned = false; 1663 if (output->HasFixedPolicy()) { 1664 AllocateFixed(output, -1, false); 1665 // This value is produced on the stack, we never need to spill it. 1666 if (output->IsStackSlot()) { 1667 DCHECK(LocationOperand::cast(output)->index() < 1668 data()->frame()->GetSpillSlotCount()); 1669 range->SetSpillOperand(LocationOperand::cast(output)); 1670 range->SetSpillStartIndex(end); 1671 assigned = true; 1672 } 1673 1674 for (const RpoNumber& succ : block->successors()) { 1675 const InstructionBlock* successor = code()->InstructionBlockAt(succ); 1676 DCHECK(successor->PredecessorCount() == 1); 1677 int gap_index = successor->first_instruction_index(); 1678 // Create an unconstrained operand for the same virtual register 1679 // and insert a gap move from the fixed output to the operand. 1680 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg); 1681 data()->AddGapMove(gap_index, Instruction::START, *output, output_copy); 1682 } 1683 } 1684 1685 if (!assigned) { 1686 for (const RpoNumber& succ : block->successors()) { 1687 const InstructionBlock* successor = code()->InstructionBlockAt(succ); 1688 DCHECK(successor->PredecessorCount() == 1); 1689 int gap_index = successor->first_instruction_index(); 1690 range->RecordSpillLocation(allocation_zone(), gap_index, output); 1691 range->SetSpillStartIndex(gap_index); 1692 } 1693 } 1694 } 1695} 1696 1697 1698void ConstraintBuilder::MeetConstraintsAfter(int instr_index) { 1699 Instruction* first = code()->InstructionAt(instr_index); 1700 // Handle fixed temporaries. 1701 for (size_t i = 0; i < first->TempCount(); i++) { 1702 UnallocatedOperand* temp = UnallocatedOperand::cast(first->TempAt(i)); 1703 if (temp->HasFixedPolicy()) AllocateFixed(temp, instr_index, false); 1704 } 1705 // Handle constant/fixed output operands. 1706 for (size_t i = 0; i < first->OutputCount(); i++) { 1707 InstructionOperand* output = first->OutputAt(i); 1708 if (output->IsConstant()) { 1709 int output_vreg = ConstantOperand::cast(output)->virtual_register(); 1710 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(output_vreg); 1711 range->SetSpillStartIndex(instr_index + 1); 1712 range->SetSpillOperand(output); 1713 continue; 1714 } 1715 UnallocatedOperand* first_output = UnallocatedOperand::cast(output); 1716 TopLevelLiveRange* range = 1717 data()->GetOrCreateLiveRangeFor(first_output->virtual_register()); 1718 bool assigned = false; 1719 if (first_output->HasFixedPolicy()) { 1720 int output_vreg = first_output->virtual_register(); 1721 UnallocatedOperand output_copy(UnallocatedOperand::ANY, output_vreg); 1722 bool is_tagged = code()->IsReference(output_vreg); 1723 if (first_output->HasSecondaryStorage()) { 1724 range->MarkHasPreassignedSlot(); 1725 data()->preassigned_slot_ranges().push_back( 1726 std::make_pair(range, first_output->GetSecondaryStorage())); 1727 } 1728 AllocateFixed(first_output, instr_index, is_tagged); 1729 1730 // This value is produced on the stack, we never need to spill it. 1731 if (first_output->IsStackSlot()) { 1732 DCHECK(LocationOperand::cast(first_output)->index() < 1733 data()->frame()->GetTotalFrameSlotCount()); 1734 range->SetSpillOperand(LocationOperand::cast(first_output)); 1735 range->SetSpillStartIndex(instr_index + 1); 1736 assigned = true; 1737 } 1738 data()->AddGapMove(instr_index + 1, Instruction::START, *first_output, 1739 output_copy); 1740 } 1741 // Make sure we add a gap move for spilling (if we have not done 1742 // so already). 1743 if (!assigned) { 1744 range->RecordSpillLocation(allocation_zone(), instr_index + 1, 1745 first_output); 1746 range->SetSpillStartIndex(instr_index + 1); 1747 } 1748 } 1749} 1750 1751 1752void ConstraintBuilder::MeetConstraintsBefore(int instr_index) { 1753 Instruction* second = code()->InstructionAt(instr_index); 1754 // Handle fixed input operands of second instruction. 1755 for (size_t i = 0; i < second->InputCount(); i++) { 1756 InstructionOperand* input = second->InputAt(i); 1757 if (input->IsImmediate() || input->IsExplicit()) { 1758 continue; // Ignore immediates and explicitly reserved registers. 1759 } 1760 UnallocatedOperand* cur_input = UnallocatedOperand::cast(input); 1761 if (cur_input->HasFixedPolicy()) { 1762 int input_vreg = cur_input->virtual_register(); 1763 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg); 1764 bool is_tagged = code()->IsReference(input_vreg); 1765 AllocateFixed(cur_input, instr_index, is_tagged); 1766 data()->AddGapMove(instr_index, Instruction::END, input_copy, *cur_input); 1767 } 1768 } 1769 // Handle "output same as input" for second instruction. 1770 for (size_t i = 0; i < second->OutputCount(); i++) { 1771 InstructionOperand* output = second->OutputAt(i); 1772 if (!output->IsUnallocated()) continue; 1773 UnallocatedOperand* second_output = UnallocatedOperand::cast(output); 1774 if (!second_output->HasSameAsInputPolicy()) continue; 1775 DCHECK(i == 0); // Only valid for first output. 1776 UnallocatedOperand* cur_input = 1777 UnallocatedOperand::cast(second->InputAt(0)); 1778 int output_vreg = second_output->virtual_register(); 1779 int input_vreg = cur_input->virtual_register(); 1780 UnallocatedOperand input_copy(UnallocatedOperand::ANY, input_vreg); 1781 cur_input->set_virtual_register(second_output->virtual_register()); 1782 MoveOperands* gap_move = data()->AddGapMove(instr_index, Instruction::END, 1783 input_copy, *cur_input); 1784 if (code()->IsReference(input_vreg) && !code()->IsReference(output_vreg)) { 1785 if (second->HasReferenceMap()) { 1786 RegisterAllocationData::DelayedReference delayed_reference = { 1787 second->reference_map(), &gap_move->source()}; 1788 data()->delayed_references().push_back(delayed_reference); 1789 } 1790 } else if (!code()->IsReference(input_vreg) && 1791 code()->IsReference(output_vreg)) { 1792 // The input is assumed to immediately have a tagged representation, 1793 // before the pointer map can be used. I.e. the pointer map at the 1794 // instruction will include the output operand (whose value at the 1795 // beginning of the instruction is equal to the input operand). If 1796 // this is not desired, then the pointer map at this instruction needs 1797 // to be adjusted manually. 1798 } 1799 } 1800} 1801 1802 1803void ConstraintBuilder::ResolvePhis() { 1804 // Process the blocks in reverse order. 1805 for (InstructionBlock* block : base::Reversed(code()->instruction_blocks())) { 1806 ResolvePhis(block); 1807 } 1808} 1809 1810 1811void ConstraintBuilder::ResolvePhis(const InstructionBlock* block) { 1812 for (PhiInstruction* phi : block->phis()) { 1813 int phi_vreg = phi->virtual_register(); 1814 RegisterAllocationData::PhiMapValue* map_value = 1815 data()->InitializePhiMap(block, phi); 1816 InstructionOperand& output = phi->output(); 1817 // Map the destination operands, so the commitment phase can find them. 1818 for (size_t i = 0; i < phi->operands().size(); ++i) { 1819 InstructionBlock* cur_block = 1820 code()->InstructionBlockAt(block->predecessors()[i]); 1821 UnallocatedOperand input(UnallocatedOperand::ANY, phi->operands()[i]); 1822 MoveOperands* move = data()->AddGapMove( 1823 cur_block->last_instruction_index(), Instruction::END, input, output); 1824 map_value->AddOperand(&move->destination()); 1825 DCHECK(!code() 1826 ->InstructionAt(cur_block->last_instruction_index()) 1827 ->HasReferenceMap()); 1828 } 1829 TopLevelLiveRange* live_range = data()->GetOrCreateLiveRangeFor(phi_vreg); 1830 int gap_index = block->first_instruction_index(); 1831 live_range->RecordSpillLocation(allocation_zone(), gap_index, &output); 1832 live_range->SetSpillStartIndex(gap_index); 1833 // We use the phi-ness of some nodes in some later heuristics. 1834 live_range->set_is_phi(true); 1835 live_range->set_is_non_loop_phi(!block->IsLoopHeader()); 1836 } 1837} 1838 1839 1840LiveRangeBuilder::LiveRangeBuilder(RegisterAllocationData* data, 1841 Zone* local_zone) 1842 : data_(data), phi_hints_(local_zone) {} 1843 1844 1845BitVector* LiveRangeBuilder::ComputeLiveOut(const InstructionBlock* block, 1846 RegisterAllocationData* data) { 1847 size_t block_index = block->rpo_number().ToSize(); 1848 BitVector* live_out = data->live_out_sets()[block_index]; 1849 if (live_out == nullptr) { 1850 // Compute live out for the given block, except not including backward 1851 // successor edges. 1852 Zone* zone = data->allocation_zone(); 1853 const InstructionSequence* code = data->code(); 1854 1855 live_out = new (zone) BitVector(code->VirtualRegisterCount(), zone); 1856 1857 // Process all successor blocks. 1858 for (const RpoNumber& succ : block->successors()) { 1859 // Add values live on entry to the successor. 1860 if (succ <= block->rpo_number()) continue; 1861 BitVector* live_in = data->live_in_sets()[succ.ToSize()]; 1862 if (live_in != nullptr) live_out->Union(*live_in); 1863 1864 // All phi input operands corresponding to this successor edge are live 1865 // out from this block. 1866 const InstructionBlock* successor = code->InstructionBlockAt(succ); 1867 size_t index = successor->PredecessorIndexOf(block->rpo_number()); 1868 DCHECK(index < successor->PredecessorCount()); 1869 for (PhiInstruction* phi : successor->phis()) { 1870 live_out->Add(phi->operands()[index]); 1871 } 1872 } 1873 data->live_out_sets()[block_index] = live_out; 1874 } 1875 return live_out; 1876} 1877 1878 1879void LiveRangeBuilder::AddInitialIntervals(const InstructionBlock* block, 1880 BitVector* live_out) { 1881 // Add an interval that includes the entire block to the live range for 1882 // each live_out value. 1883 LifetimePosition start = LifetimePosition::GapFromInstructionIndex( 1884 block->first_instruction_index()); 1885 LifetimePosition end = LifetimePosition::InstructionFromInstructionIndex( 1886 block->last_instruction_index()) 1887 .NextStart(); 1888 BitVector::Iterator iterator(live_out); 1889 while (!iterator.Done()) { 1890 int operand_index = iterator.Current(); 1891 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(operand_index); 1892 range->AddUseInterval(start, end, allocation_zone()); 1893 iterator.Advance(); 1894 } 1895} 1896 1897int LiveRangeBuilder::FixedFPLiveRangeID(int index, MachineRepresentation rep) { 1898 int result = -index - 1; 1899 switch (rep) { 1900 case MachineRepresentation::kSimd128: 1901 result -= config()->num_float_registers(); 1902 // Fall through. 1903 case MachineRepresentation::kFloat32: 1904 result -= config()->num_double_registers(); 1905 // Fall through. 1906 case MachineRepresentation::kFloat64: 1907 result -= config()->num_general_registers(); 1908 break; 1909 default: 1910 UNREACHABLE(); 1911 break; 1912 } 1913 return result; 1914} 1915 1916TopLevelLiveRange* LiveRangeBuilder::FixedLiveRangeFor(int index) { 1917 DCHECK(index < config()->num_general_registers()); 1918 TopLevelLiveRange* result = data()->fixed_live_ranges()[index]; 1919 if (result == nullptr) { 1920 MachineRepresentation rep = InstructionSequence::DefaultRepresentation(); 1921 result = data()->NewLiveRange(FixedLiveRangeID(index), rep); 1922 DCHECK(result->IsFixed()); 1923 result->set_assigned_register(index); 1924 data()->MarkAllocated(rep, index); 1925 data()->fixed_live_ranges()[index] = result; 1926 } 1927 return result; 1928} 1929 1930TopLevelLiveRange* LiveRangeBuilder::FixedFPLiveRangeFor( 1931 int index, MachineRepresentation rep) { 1932 int num_regs = config()->num_double_registers(); 1933 ZoneVector<TopLevelLiveRange*>* live_ranges = 1934 &data()->fixed_double_live_ranges(); 1935 if (!kSimpleFPAliasing) { 1936 switch (rep) { 1937 case MachineRepresentation::kFloat32: 1938 num_regs = config()->num_float_registers(); 1939 live_ranges = &data()->fixed_float_live_ranges(); 1940 break; 1941 case MachineRepresentation::kSimd128: 1942 num_regs = config()->num_simd128_registers(); 1943 live_ranges = &data()->fixed_simd128_live_ranges(); 1944 break; 1945 default: 1946 break; 1947 } 1948 } 1949 1950 DCHECK(index < num_regs); 1951 USE(num_regs); 1952 TopLevelLiveRange* result = (*live_ranges)[index]; 1953 if (result == nullptr) { 1954 result = data()->NewLiveRange(FixedFPLiveRangeID(index, rep), rep); 1955 DCHECK(result->IsFixed()); 1956 result->set_assigned_register(index); 1957 data()->MarkAllocated(rep, index); 1958 (*live_ranges)[index] = result; 1959 } 1960 return result; 1961} 1962 1963TopLevelLiveRange* LiveRangeBuilder::LiveRangeFor(InstructionOperand* operand) { 1964 if (operand->IsUnallocated()) { 1965 return data()->GetOrCreateLiveRangeFor( 1966 UnallocatedOperand::cast(operand)->virtual_register()); 1967 } else if (operand->IsConstant()) { 1968 return data()->GetOrCreateLiveRangeFor( 1969 ConstantOperand::cast(operand)->virtual_register()); 1970 } else if (operand->IsRegister()) { 1971 return FixedLiveRangeFor( 1972 LocationOperand::cast(operand)->GetRegister().code()); 1973 } else if (operand->IsFPRegister()) { 1974 LocationOperand* op = LocationOperand::cast(operand); 1975 return FixedFPLiveRangeFor(op->register_code(), op->representation()); 1976 } else { 1977 return nullptr; 1978 } 1979} 1980 1981 1982UsePosition* LiveRangeBuilder::NewUsePosition(LifetimePosition pos, 1983 InstructionOperand* operand, 1984 void* hint, 1985 UsePositionHintType hint_type) { 1986 return new (allocation_zone()) UsePosition(pos, operand, hint, hint_type); 1987} 1988 1989 1990UsePosition* LiveRangeBuilder::Define(LifetimePosition position, 1991 InstructionOperand* operand, void* hint, 1992 UsePositionHintType hint_type) { 1993 TopLevelLiveRange* range = LiveRangeFor(operand); 1994 if (range == nullptr) return nullptr; 1995 1996 if (range->IsEmpty() || range->Start() > position) { 1997 // Can happen if there is a definition without use. 1998 range->AddUseInterval(position, position.NextStart(), allocation_zone()); 1999 range->AddUsePosition(NewUsePosition(position.NextStart())); 2000 } else { 2001 range->ShortenTo(position); 2002 } 2003 if (!operand->IsUnallocated()) return nullptr; 2004 UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand); 2005 UsePosition* use_pos = 2006 NewUsePosition(position, unalloc_operand, hint, hint_type); 2007 range->AddUsePosition(use_pos); 2008 return use_pos; 2009} 2010 2011 2012UsePosition* LiveRangeBuilder::Use(LifetimePosition block_start, 2013 LifetimePosition position, 2014 InstructionOperand* operand, void* hint, 2015 UsePositionHintType hint_type) { 2016 TopLevelLiveRange* range = LiveRangeFor(operand); 2017 if (range == nullptr) return nullptr; 2018 UsePosition* use_pos = nullptr; 2019 if (operand->IsUnallocated()) { 2020 UnallocatedOperand* unalloc_operand = UnallocatedOperand::cast(operand); 2021 use_pos = NewUsePosition(position, unalloc_operand, hint, hint_type); 2022 range->AddUsePosition(use_pos); 2023 } 2024 range->AddUseInterval(block_start, position, allocation_zone()); 2025 return use_pos; 2026} 2027 2028 2029void LiveRangeBuilder::ProcessInstructions(const InstructionBlock* block, 2030 BitVector* live) { 2031 int block_start = block->first_instruction_index(); 2032 LifetimePosition block_start_position = 2033 LifetimePosition::GapFromInstructionIndex(block_start); 2034 bool fixed_float_live_ranges = false; 2035 bool fixed_simd128_live_ranges = false; 2036 if (!kSimpleFPAliasing) { 2037 int mask = data()->code()->representation_mask(); 2038 fixed_float_live_ranges = (mask & kFloatRepBit) != 0; 2039 fixed_simd128_live_ranges = (mask & kSimd128RepBit) != 0; 2040 } 2041 2042 for (int index = block->last_instruction_index(); index >= block_start; 2043 index--) { 2044 LifetimePosition curr_position = 2045 LifetimePosition::InstructionFromInstructionIndex(index); 2046 Instruction* instr = code()->InstructionAt(index); 2047 DCHECK(instr != nullptr); 2048 DCHECK(curr_position.IsInstructionPosition()); 2049 // Process output, inputs, and temps of this instruction. 2050 for (size_t i = 0; i < instr->OutputCount(); i++) { 2051 InstructionOperand* output = instr->OutputAt(i); 2052 if (output->IsUnallocated()) { 2053 // Unsupported. 2054 DCHECK(!UnallocatedOperand::cast(output)->HasSlotPolicy()); 2055 int out_vreg = UnallocatedOperand::cast(output)->virtual_register(); 2056 live->Remove(out_vreg); 2057 } else if (output->IsConstant()) { 2058 int out_vreg = ConstantOperand::cast(output)->virtual_register(); 2059 live->Remove(out_vreg); 2060 } 2061 if (block->IsHandler() && index == block_start && output->IsAllocated() && 2062 output->IsRegister() && 2063 AllocatedOperand::cast(output)->GetRegister().is( 2064 v8::internal::kReturnRegister0)) { 2065 // The register defined here is blocked from gap start - it is the 2066 // exception value. 2067 // TODO(mtrofin): should we explore an explicit opcode for 2068 // the first instruction in the handler? 2069 Define(LifetimePosition::GapFromInstructionIndex(index), output); 2070 } else { 2071 Define(curr_position, output); 2072 } 2073 } 2074 2075 if (instr->ClobbersRegisters()) { 2076 for (int i = 0; i < config()->num_allocatable_general_registers(); ++i) { 2077 // Create a UseInterval at this instruction for all fixed registers, 2078 // (including the instruction outputs). Adding another UseInterval here 2079 // is OK because AddUseInterval will just merge it with the existing 2080 // one at the end of the range. 2081 int code = config()->GetAllocatableGeneralCode(i); 2082 TopLevelLiveRange* range = FixedLiveRangeFor(code); 2083 range->AddUseInterval(curr_position, curr_position.End(), 2084 allocation_zone()); 2085 } 2086 } 2087 2088 if (instr->ClobbersDoubleRegisters()) { 2089 for (int i = 0; i < config()->num_allocatable_double_registers(); ++i) { 2090 // Add a UseInterval for all DoubleRegisters. See comment above for 2091 // general registers. 2092 int code = config()->GetAllocatableDoubleCode(i); 2093 TopLevelLiveRange* range = 2094 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat64); 2095 range->AddUseInterval(curr_position, curr_position.End(), 2096 allocation_zone()); 2097 } 2098 // Clobber fixed float registers on archs with non-simple aliasing. 2099 if (!kSimpleFPAliasing) { 2100 if (fixed_float_live_ranges) { 2101 for (int i = 0; i < config()->num_allocatable_float_registers(); 2102 ++i) { 2103 // Add a UseInterval for all FloatRegisters. See comment above for 2104 // general registers. 2105 int code = config()->GetAllocatableFloatCode(i); 2106 TopLevelLiveRange* range = 2107 FixedFPLiveRangeFor(code, MachineRepresentation::kFloat32); 2108 range->AddUseInterval(curr_position, curr_position.End(), 2109 allocation_zone()); 2110 } 2111 } 2112 if (fixed_simd128_live_ranges) { 2113 for (int i = 0; i < config()->num_allocatable_simd128_registers(); 2114 ++i) { 2115 int code = config()->GetAllocatableSimd128Code(i); 2116 TopLevelLiveRange* range = 2117 FixedFPLiveRangeFor(code, MachineRepresentation::kSimd128); 2118 range->AddUseInterval(curr_position, curr_position.End(), 2119 allocation_zone()); 2120 } 2121 } 2122 } 2123 } 2124 2125 for (size_t i = 0; i < instr->InputCount(); i++) { 2126 InstructionOperand* input = instr->InputAt(i); 2127 if (input->IsImmediate() || input->IsExplicit()) { 2128 continue; // Ignore immediates and explicitly reserved registers. 2129 } 2130 LifetimePosition use_pos; 2131 if (input->IsUnallocated() && 2132 UnallocatedOperand::cast(input)->IsUsedAtStart()) { 2133 use_pos = curr_position; 2134 } else { 2135 use_pos = curr_position.End(); 2136 } 2137 2138 if (input->IsUnallocated()) { 2139 UnallocatedOperand* unalloc = UnallocatedOperand::cast(input); 2140 int vreg = unalloc->virtual_register(); 2141 live->Add(vreg); 2142 if (unalloc->HasSlotPolicy()) { 2143 data()->GetOrCreateLiveRangeFor(vreg)->set_has_slot_use(true); 2144 } 2145 } 2146 Use(block_start_position, use_pos, input); 2147 } 2148 2149 for (size_t i = 0; i < instr->TempCount(); i++) { 2150 InstructionOperand* temp = instr->TempAt(i); 2151 // Unsupported. 2152 DCHECK_IMPLIES(temp->IsUnallocated(), 2153 !UnallocatedOperand::cast(temp)->HasSlotPolicy()); 2154 if (instr->ClobbersTemps()) { 2155 if (temp->IsRegister()) continue; 2156 if (temp->IsUnallocated()) { 2157 UnallocatedOperand* temp_unalloc = UnallocatedOperand::cast(temp); 2158 if (temp_unalloc->HasFixedPolicy()) { 2159 continue; 2160 } 2161 } 2162 } 2163 Use(block_start_position, curr_position.End(), temp); 2164 Define(curr_position, temp); 2165 } 2166 2167 // Process the moves of the instruction's gaps, making their sources live. 2168 const Instruction::GapPosition kPositions[] = {Instruction::END, 2169 Instruction::START}; 2170 curr_position = curr_position.PrevStart(); 2171 DCHECK(curr_position.IsGapPosition()); 2172 for (const Instruction::GapPosition& position : kPositions) { 2173 ParallelMove* move = instr->GetParallelMove(position); 2174 if (move == nullptr) continue; 2175 if (position == Instruction::END) { 2176 curr_position = curr_position.End(); 2177 } else { 2178 curr_position = curr_position.Start(); 2179 } 2180 for (MoveOperands* cur : *move) { 2181 InstructionOperand& from = cur->source(); 2182 InstructionOperand& to = cur->destination(); 2183 void* hint = &to; 2184 UsePositionHintType hint_type = UsePosition::HintTypeForOperand(to); 2185 UsePosition* to_use = nullptr; 2186 int phi_vreg = -1; 2187 if (to.IsUnallocated()) { 2188 int to_vreg = UnallocatedOperand::cast(to).virtual_register(); 2189 TopLevelLiveRange* to_range = 2190 data()->GetOrCreateLiveRangeFor(to_vreg); 2191 if (to_range->is_phi()) { 2192 phi_vreg = to_vreg; 2193 if (to_range->is_non_loop_phi()) { 2194 hint = to_range->current_hint_position(); 2195 hint_type = hint == nullptr ? UsePositionHintType::kNone 2196 : UsePositionHintType::kUsePos; 2197 } else { 2198 hint_type = UsePositionHintType::kPhi; 2199 hint = data()->GetPhiMapValueFor(to_vreg); 2200 } 2201 } else { 2202 if (live->Contains(to_vreg)) { 2203 to_use = Define(curr_position, &to, &from, 2204 UsePosition::HintTypeForOperand(from)); 2205 live->Remove(to_vreg); 2206 } else { 2207 cur->Eliminate(); 2208 continue; 2209 } 2210 } 2211 } else { 2212 Define(curr_position, &to); 2213 } 2214 UsePosition* from_use = 2215 Use(block_start_position, curr_position, &from, hint, hint_type); 2216 // Mark range live. 2217 if (from.IsUnallocated()) { 2218 live->Add(UnallocatedOperand::cast(from).virtual_register()); 2219 } 2220 // Resolve use position hints just created. 2221 if (to_use != nullptr && from_use != nullptr) { 2222 to_use->ResolveHint(from_use); 2223 from_use->ResolveHint(to_use); 2224 } 2225 DCHECK_IMPLIES(to_use != nullptr, to_use->IsResolved()); 2226 DCHECK_IMPLIES(from_use != nullptr, from_use->IsResolved()); 2227 // Potentially resolve phi hint. 2228 if (phi_vreg != -1) ResolvePhiHint(&from, from_use); 2229 } 2230 } 2231 } 2232} 2233 2234void LiveRangeBuilder::ProcessPhis(const InstructionBlock* block, 2235 BitVector* live) { 2236 for (PhiInstruction* phi : block->phis()) { 2237 // The live range interval already ends at the first instruction of the 2238 // block. 2239 int phi_vreg = phi->virtual_register(); 2240 live->Remove(phi_vreg); 2241 // Select a hint from a predecessor block that preceeds this block in the 2242 // rpo order. In order of priority: 2243 // - Avoid hints from deferred blocks. 2244 // - Prefer hints from allocated (or explicit) operands. 2245 // - Prefer hints from empty blocks (containing just parallel moves and a 2246 // jump). In these cases, if we can elide the moves, the jump threader 2247 // is likely to be able to elide the jump. 2248 // The enforcement of hinting in rpo order is required because hint 2249 // resolution that happens later in the compiler pipeline visits 2250 // instructions in reverse rpo order, relying on the fact that phis are 2251 // encountered before their hints. 2252 InstructionOperand* hint = nullptr; 2253 int hint_preference = 0; 2254 2255 // The cost of hinting increases with the number of predecessors. At the 2256 // same time, the typical benefit decreases, since this hinting only 2257 // optimises the execution path through one predecessor. A limit of 2 is 2258 // sufficient to hit the common if/else pattern. 2259 int predecessor_limit = 2; 2260 2261 for (RpoNumber predecessor : block->predecessors()) { 2262 const InstructionBlock* predecessor_block = 2263 code()->InstructionBlockAt(predecessor); 2264 DCHECK_EQ(predecessor_block->rpo_number(), predecessor); 2265 2266 // Only take hints from earlier rpo numbers. 2267 if (predecessor >= block->rpo_number()) continue; 2268 2269 // Look up the predecessor instruction. 2270 const Instruction* predecessor_instr = 2271 GetLastInstruction(code(), predecessor_block); 2272 InstructionOperand* predecessor_hint = nullptr; 2273 // Phis are assigned in the END position of the last instruction in each 2274 // predecessor block. 2275 for (MoveOperands* move : 2276 *predecessor_instr->GetParallelMove(Instruction::END)) { 2277 InstructionOperand& to = move->destination(); 2278 if (to.IsUnallocated() && 2279 UnallocatedOperand::cast(to).virtual_register() == phi_vreg) { 2280 predecessor_hint = &move->source(); 2281 break; 2282 } 2283 } 2284 DCHECK_NOT_NULL(predecessor_hint); 2285 2286 // For each predecessor, generate a score according to the priorities 2287 // described above, and pick the best one. Flags in higher-order bits have 2288 // a higher priority than those in lower-order bits. 2289 int predecessor_hint_preference = 0; 2290 const int kNotDeferredBlockPreference = (1 << 2); 2291 const int kMoveIsAllocatedPreference = (1 << 1); 2292 const int kBlockIsEmptyPreference = (1 << 0); 2293 2294 // - Avoid hints from deferred blocks. 2295 if (!predecessor_block->IsDeferred()) { 2296 predecessor_hint_preference |= kNotDeferredBlockPreference; 2297 } 2298 2299 // - Prefer hints from allocated (or explicit) operands. 2300 // 2301 // Already-allocated or explicit operands are typically assigned using 2302 // the parallel moves on the last instruction. For example: 2303 // 2304 // gap (v101 = [x0|R|w32]) (v100 = v101) 2305 // ArchJmp 2306 // ... 2307 // phi: v100 = v101 v102 2308 // 2309 // We have already found the END move, so look for a matching START move 2310 // from an allocated (or explicit) operand. 2311 // 2312 // Note that we cannot simply look up data()->live_ranges()[vreg] here 2313 // because the live ranges are still being built when this function is 2314 // called. 2315 // TODO(v8): Find a way to separate hinting from live range analysis in 2316 // BuildLiveRanges so that we can use the O(1) live-range look-up. 2317 auto moves = predecessor_instr->GetParallelMove(Instruction::START); 2318 if (moves != nullptr) { 2319 for (MoveOperands* move : *moves) { 2320 InstructionOperand& to = move->destination(); 2321 if (predecessor_hint->Equals(to)) { 2322 if (move->source().IsAllocated() || move->source().IsExplicit()) { 2323 predecessor_hint_preference |= kMoveIsAllocatedPreference; 2324 } 2325 break; 2326 } 2327 } 2328 } 2329 2330 // - Prefer hints from empty blocks. 2331 if (predecessor_block->last_instruction_index() == 2332 predecessor_block->first_instruction_index()) { 2333 predecessor_hint_preference |= kBlockIsEmptyPreference; 2334 } 2335 2336 if ((hint == nullptr) || 2337 (predecessor_hint_preference > hint_preference)) { 2338 // Take the hint from this predecessor. 2339 hint = predecessor_hint; 2340 hint_preference = predecessor_hint_preference; 2341 } 2342 2343 if (--predecessor_limit <= 0) break; 2344 } 2345 DCHECK_NOT_NULL(hint); 2346 2347 LifetimePosition block_start = LifetimePosition::GapFromInstructionIndex( 2348 block->first_instruction_index()); 2349 UsePosition* use_pos = Define(block_start, &phi->output(), hint, 2350 UsePosition::HintTypeForOperand(*hint)); 2351 MapPhiHint(hint, use_pos); 2352 } 2353} 2354 2355 2356void LiveRangeBuilder::ProcessLoopHeader(const InstructionBlock* block, 2357 BitVector* live) { 2358 DCHECK(block->IsLoopHeader()); 2359 // Add a live range stretching from the first loop instruction to the last 2360 // for each value live on entry to the header. 2361 BitVector::Iterator iterator(live); 2362 LifetimePosition start = LifetimePosition::GapFromInstructionIndex( 2363 block->first_instruction_index()); 2364 LifetimePosition end = LifetimePosition::GapFromInstructionIndex( 2365 code()->LastLoopInstructionIndex(block)) 2366 .NextFullStart(); 2367 while (!iterator.Done()) { 2368 int operand_index = iterator.Current(); 2369 TopLevelLiveRange* range = data()->GetOrCreateLiveRangeFor(operand_index); 2370 range->EnsureInterval(start, end, allocation_zone()); 2371 iterator.Advance(); 2372 } 2373 // Insert all values into the live in sets of all blocks in the loop. 2374 for (int i = block->rpo_number().ToInt() + 1; i < block->loop_end().ToInt(); 2375 ++i) { 2376 live_in_sets()[i]->Union(*live); 2377 } 2378} 2379 2380 2381void LiveRangeBuilder::BuildLiveRanges() { 2382 // Process the blocks in reverse order. 2383 for (int block_id = code()->InstructionBlockCount() - 1; block_id >= 0; 2384 --block_id) { 2385 InstructionBlock* block = 2386 code()->InstructionBlockAt(RpoNumber::FromInt(block_id)); 2387 BitVector* live = ComputeLiveOut(block, data()); 2388 // Initially consider all live_out values live for the entire block. We 2389 // will shorten these intervals if necessary. 2390 AddInitialIntervals(block, live); 2391 // Process the instructions in reverse order, generating and killing 2392 // live values. 2393 ProcessInstructions(block, live); 2394 // All phi output operands are killed by this block. 2395 ProcessPhis(block, live); 2396 // Now live is live_in for this block except not including values live 2397 // out on backward successor edges. 2398 if (block->IsLoopHeader()) ProcessLoopHeader(block, live); 2399 live_in_sets()[block_id] = live; 2400 } 2401 // Postprocess the ranges. 2402 for (TopLevelLiveRange* range : data()->live_ranges()) { 2403 if (range == nullptr) continue; 2404 // Give slots to all ranges with a non fixed slot use. 2405 if (range->has_slot_use() && range->HasNoSpillType()) { 2406 data()->AssignSpillRangeToLiveRange(range); 2407 } 2408 // TODO(bmeurer): This is a horrible hack to make sure that for constant 2409 // live ranges, every use requires the constant to be in a register. 2410 // Without this hack, all uses with "any" policy would get the constant 2411 // operand assigned. 2412 if (range->HasSpillOperand() && range->GetSpillOperand()->IsConstant()) { 2413 for (UsePosition* pos = range->first_pos(); pos != nullptr; 2414 pos = pos->next()) { 2415 if (pos->type() == UsePositionType::kRequiresSlot) continue; 2416 UsePositionType new_type = UsePositionType::kAny; 2417 // Can't mark phis as needing a register. 2418 if (!pos->pos().IsGapPosition()) { 2419 new_type = UsePositionType::kRequiresRegister; 2420 } 2421 pos->set_type(new_type, true); 2422 } 2423 } 2424 } 2425 for (auto preassigned : data()->preassigned_slot_ranges()) { 2426 TopLevelLiveRange* range = preassigned.first; 2427 int slot_id = preassigned.second; 2428 SpillRange* spill = range->HasSpillRange() 2429 ? range->GetSpillRange() 2430 : data()->AssignSpillRangeToLiveRange(range); 2431 spill->set_assigned_slot(slot_id); 2432 } 2433#ifdef DEBUG 2434 Verify(); 2435#endif 2436} 2437 2438 2439void LiveRangeBuilder::MapPhiHint(InstructionOperand* operand, 2440 UsePosition* use_pos) { 2441 DCHECK(!use_pos->IsResolved()); 2442 auto res = phi_hints_.insert(std::make_pair(operand, use_pos)); 2443 DCHECK(res.second); 2444 USE(res); 2445} 2446 2447 2448void LiveRangeBuilder::ResolvePhiHint(InstructionOperand* operand, 2449 UsePosition* use_pos) { 2450 auto it = phi_hints_.find(operand); 2451 if (it == phi_hints_.end()) return; 2452 DCHECK(!it->second->IsResolved()); 2453 it->second->ResolveHint(use_pos); 2454} 2455 2456 2457void LiveRangeBuilder::Verify() const { 2458 for (auto& hint : phi_hints_) { 2459 CHECK(hint.second->IsResolved()); 2460 } 2461 for (const TopLevelLiveRange* current : data()->live_ranges()) { 2462 if (current != nullptr && !current->IsEmpty()) { 2463 // New LiveRanges should not be split. 2464 CHECK_NULL(current->next()); 2465 // General integrity check. 2466 current->Verify(); 2467 const UseInterval* first = current->first_interval(); 2468 if (first->next() == nullptr) continue; 2469 2470 // Consecutive intervals should not end and start in the same block, 2471 // otherwise the intervals should have been joined, because the 2472 // variable is live throughout that block. 2473 CHECK(NextIntervalStartsInDifferentBlocks(first)); 2474 2475 for (const UseInterval* i = first->next(); i != nullptr; i = i->next()) { 2476 // Except for the first interval, the other intevals must start at 2477 // a block boundary, otherwise data wouldn't flow to them. 2478 CHECK(IntervalStartsAtBlockBoundary(i)); 2479 // The last instruction of the predecessors of the block the interval 2480 // starts must be covered by the range. 2481 CHECK(IntervalPredecessorsCoveredByRange(i, current)); 2482 if (i->next() != nullptr) { 2483 // Check the consecutive intervals property, except for the last 2484 // interval, where it doesn't apply. 2485 CHECK(NextIntervalStartsInDifferentBlocks(i)); 2486 } 2487 } 2488 } 2489 } 2490} 2491 2492bool LiveRangeBuilder::IntervalStartsAtBlockBoundary( 2493 const UseInterval* interval) const { 2494 LifetimePosition start = interval->start(); 2495 if (!start.IsFullStart()) return false; 2496 int instruction_index = start.ToInstructionIndex(); 2497 const InstructionBlock* block = 2498 data()->code()->GetInstructionBlock(instruction_index); 2499 return block->first_instruction_index() == instruction_index; 2500} 2501 2502bool LiveRangeBuilder::IntervalPredecessorsCoveredByRange( 2503 const UseInterval* interval, const TopLevelLiveRange* range) const { 2504 LifetimePosition start = interval->start(); 2505 int instruction_index = start.ToInstructionIndex(); 2506 const InstructionBlock* block = 2507 data()->code()->GetInstructionBlock(instruction_index); 2508 for (RpoNumber pred_index : block->predecessors()) { 2509 const InstructionBlock* predecessor = 2510 data()->code()->InstructionBlockAt(pred_index); 2511 LifetimePosition last_pos = LifetimePosition::GapFromInstructionIndex( 2512 predecessor->last_instruction_index()); 2513 last_pos = last_pos.NextStart().End(); 2514 if (!range->Covers(last_pos)) return false; 2515 } 2516 return true; 2517} 2518 2519bool LiveRangeBuilder::NextIntervalStartsInDifferentBlocks( 2520 const UseInterval* interval) const { 2521 DCHECK_NOT_NULL(interval->next()); 2522 LifetimePosition end = interval->end(); 2523 LifetimePosition next_start = interval->next()->start(); 2524 // Since end is not covered, but the previous position is, move back a 2525 // position 2526 end = end.IsStart() ? end.PrevStart().End() : end.Start(); 2527 int last_covered_index = end.ToInstructionIndex(); 2528 const InstructionBlock* block = 2529 data()->code()->GetInstructionBlock(last_covered_index); 2530 const InstructionBlock* next_block = 2531 data()->code()->GetInstructionBlock(next_start.ToInstructionIndex()); 2532 return block->rpo_number() < next_block->rpo_number(); 2533} 2534 2535RegisterAllocator::RegisterAllocator(RegisterAllocationData* data, 2536 RegisterKind kind) 2537 : data_(data), 2538 mode_(kind), 2539 num_registers_(GetRegisterCount(data->config(), kind)), 2540 num_allocatable_registers_( 2541 GetAllocatableRegisterCount(data->config(), kind)), 2542 allocatable_register_codes_( 2543 GetAllocatableRegisterCodes(data->config(), kind)), 2544 check_fp_aliasing_(false) { 2545 if (!kSimpleFPAliasing && kind == FP_REGISTERS) { 2546 check_fp_aliasing_ = (data->code()->representation_mask() & 2547 (kFloatRepBit | kSimd128RepBit)) != 0; 2548 } 2549} 2550 2551LifetimePosition RegisterAllocator::GetSplitPositionForInstruction( 2552 const LiveRange* range, int instruction_index) { 2553 LifetimePosition ret = LifetimePosition::Invalid(); 2554 2555 ret = LifetimePosition::GapFromInstructionIndex(instruction_index); 2556 if (range->Start() >= ret || ret >= range->End()) { 2557 return LifetimePosition::Invalid(); 2558 } 2559 return ret; 2560} 2561 2562void RegisterAllocator::SplitAndSpillRangesDefinedByMemoryOperand() { 2563 size_t initial_range_count = data()->live_ranges().size(); 2564 for (size_t i = 0; i < initial_range_count; ++i) { 2565 TopLevelLiveRange* range = data()->live_ranges()[i]; 2566 if (!CanProcessRange(range)) continue; 2567 if (range->HasNoSpillType() || 2568 (range->HasSpillRange() && !range->has_slot_use())) { 2569 continue; 2570 } 2571 LifetimePosition start = range->Start(); 2572 TRACE("Live range %d:%d is defined by a spill operand.\n", 2573 range->TopLevel()->vreg(), range->relative_id()); 2574 LifetimePosition next_pos = start; 2575 if (next_pos.IsGapPosition()) { 2576 next_pos = next_pos.NextStart(); 2577 } 2578 2579 // With splinters, we can be more strict and skip over positions 2580 // not strictly needing registers. 2581 UsePosition* pos = 2582 range->IsSplinter() 2583 ? range->NextRegisterPosition(next_pos) 2584 : range->NextUsePositionRegisterIsBeneficial(next_pos); 2585 // If the range already has a spill operand and it doesn't need a 2586 // register immediately, split it and spill the first part of the range. 2587 if (pos == nullptr) { 2588 Spill(range); 2589 } else if (pos->pos() > range->Start().NextStart()) { 2590 // Do not spill live range eagerly if use position that can benefit from 2591 // the register is too close to the start of live range. 2592 LifetimePosition split_pos = GetSplitPositionForInstruction( 2593 range, pos->pos().ToInstructionIndex()); 2594 // There is no place to split, so we can't split and spill. 2595 if (!split_pos.IsValid()) continue; 2596 2597 split_pos = 2598 FindOptimalSplitPos(range->Start().NextFullStart(), split_pos); 2599 2600 SplitRangeAt(range, split_pos); 2601 Spill(range); 2602 } 2603 } 2604} 2605 2606 2607LiveRange* RegisterAllocator::SplitRangeAt(LiveRange* range, 2608 LifetimePosition pos) { 2609 DCHECK(!range->TopLevel()->IsFixed()); 2610 TRACE("Splitting live range %d:%d at %d\n", range->TopLevel()->vreg(), 2611 range->relative_id(), pos.value()); 2612 2613 if (pos <= range->Start()) return range; 2614 2615 // We can't properly connect liveranges if splitting occurred at the end 2616 // a block. 2617 DCHECK(pos.IsStart() || pos.IsGapPosition() || 2618 (GetInstructionBlock(code(), pos)->last_instruction_index() != 2619 pos.ToInstructionIndex())); 2620 2621 LiveRange* result = range->SplitAt(pos, allocation_zone()); 2622 return result; 2623} 2624 2625 2626LiveRange* RegisterAllocator::SplitBetween(LiveRange* range, 2627 LifetimePosition start, 2628 LifetimePosition end) { 2629 DCHECK(!range->TopLevel()->IsFixed()); 2630 TRACE("Splitting live range %d:%d in position between [%d, %d]\n", 2631 range->TopLevel()->vreg(), range->relative_id(), start.value(), 2632 end.value()); 2633 2634 LifetimePosition split_pos = FindOptimalSplitPos(start, end); 2635 DCHECK(split_pos >= start); 2636 return SplitRangeAt(range, split_pos); 2637} 2638 2639 2640LifetimePosition RegisterAllocator::FindOptimalSplitPos(LifetimePosition start, 2641 LifetimePosition end) { 2642 int start_instr = start.ToInstructionIndex(); 2643 int end_instr = end.ToInstructionIndex(); 2644 DCHECK(start_instr <= end_instr); 2645 2646 // We have no choice 2647 if (start_instr == end_instr) return end; 2648 2649 const InstructionBlock* start_block = GetInstructionBlock(code(), start); 2650 const InstructionBlock* end_block = GetInstructionBlock(code(), end); 2651 2652 if (end_block == start_block) { 2653 // The interval is split in the same basic block. Split at the latest 2654 // possible position. 2655 return end; 2656 } 2657 2658 const InstructionBlock* block = end_block; 2659 // Find header of outermost loop. 2660 do { 2661 const InstructionBlock* loop = GetContainingLoop(code(), block); 2662 if (loop == nullptr || 2663 loop->rpo_number().ToInt() <= start_block->rpo_number().ToInt()) { 2664 // No more loops or loop starts before the lifetime start. 2665 break; 2666 } 2667 block = loop; 2668 } while (true); 2669 2670 // We did not find any suitable outer loop. Split at the latest possible 2671 // position unless end_block is a loop header itself. 2672 if (block == end_block && !end_block->IsLoopHeader()) return end; 2673 2674 return LifetimePosition::GapFromInstructionIndex( 2675 block->first_instruction_index()); 2676} 2677 2678 2679LifetimePosition RegisterAllocator::FindOptimalSpillingPos( 2680 LiveRange* range, LifetimePosition pos) { 2681 const InstructionBlock* block = GetInstructionBlock(code(), pos.Start()); 2682 const InstructionBlock* loop_header = 2683 block->IsLoopHeader() ? block : GetContainingLoop(code(), block); 2684 2685 if (loop_header == nullptr) return pos; 2686 2687 const UsePosition* prev_use = 2688 range->PreviousUsePositionRegisterIsBeneficial(pos); 2689 2690 while (loop_header != nullptr) { 2691 // We are going to spill live range inside the loop. 2692 // If possible try to move spilling position backwards to loop header. 2693 // This will reduce number of memory moves on the back edge. 2694 LifetimePosition loop_start = LifetimePosition::GapFromInstructionIndex( 2695 loop_header->first_instruction_index()); 2696 2697 if (range->Covers(loop_start)) { 2698 if (prev_use == nullptr || prev_use->pos() < loop_start) { 2699 // No register beneficial use inside the loop before the pos. 2700 pos = loop_start; 2701 } 2702 } 2703 2704 // Try hoisting out to an outer loop. 2705 loop_header = GetContainingLoop(code(), loop_header); 2706 } 2707 2708 return pos; 2709} 2710 2711 2712void RegisterAllocator::Spill(LiveRange* range) { 2713 DCHECK(!range->spilled()); 2714 TopLevelLiveRange* first = range->TopLevel(); 2715 TRACE("Spilling live range %d:%d\n", first->vreg(), range->relative_id()); 2716 2717 if (first->HasNoSpillType()) { 2718 data()->AssignSpillRangeToLiveRange(first); 2719 } 2720 range->Spill(); 2721} 2722 2723const char* RegisterAllocator::RegisterName(int register_code) const { 2724 if (mode() == GENERAL_REGISTERS) { 2725 return data()->config()->GetGeneralRegisterName(register_code); 2726 } else { 2727 return data()->config()->GetDoubleRegisterName(register_code); 2728 } 2729} 2730 2731 2732LinearScanAllocator::LinearScanAllocator(RegisterAllocationData* data, 2733 RegisterKind kind, Zone* local_zone) 2734 : RegisterAllocator(data, kind), 2735 unhandled_live_ranges_(local_zone), 2736 active_live_ranges_(local_zone), 2737 inactive_live_ranges_(local_zone) { 2738 unhandled_live_ranges().reserve( 2739 static_cast<size_t>(code()->VirtualRegisterCount() * 2)); 2740 active_live_ranges().reserve(8); 2741 inactive_live_ranges().reserve(8); 2742 // TryAllocateFreeReg and AllocateBlockedReg assume this 2743 // when allocating local arrays. 2744 DCHECK(RegisterConfiguration::kMaxFPRegisters >= 2745 this->data()->config()->num_general_registers()); 2746} 2747 2748 2749void LinearScanAllocator::AllocateRegisters() { 2750 DCHECK(unhandled_live_ranges().empty()); 2751 DCHECK(active_live_ranges().empty()); 2752 DCHECK(inactive_live_ranges().empty()); 2753 2754 SplitAndSpillRangesDefinedByMemoryOperand(); 2755 2756 for (TopLevelLiveRange* range : data()->live_ranges()) { 2757 if (!CanProcessRange(range)) continue; 2758 for (LiveRange* to_add = range; to_add != nullptr; 2759 to_add = to_add->next()) { 2760 if (!to_add->spilled()) { 2761 AddToUnhandledUnsorted(to_add); 2762 } 2763 } 2764 } 2765 SortUnhandled(); 2766 DCHECK(UnhandledIsSorted()); 2767 2768 if (mode() == GENERAL_REGISTERS) { 2769 for (TopLevelLiveRange* current : data()->fixed_live_ranges()) { 2770 if (current != nullptr) AddToInactive(current); 2771 } 2772 } else { 2773 for (TopLevelLiveRange* current : data()->fixed_double_live_ranges()) { 2774 if (current != nullptr) AddToInactive(current); 2775 } 2776 if (!kSimpleFPAliasing && check_fp_aliasing()) { 2777 for (TopLevelLiveRange* current : data()->fixed_float_live_ranges()) { 2778 if (current != nullptr) AddToInactive(current); 2779 } 2780 for (TopLevelLiveRange* current : data()->fixed_simd128_live_ranges()) { 2781 if (current != nullptr) AddToInactive(current); 2782 } 2783 } 2784 } 2785 2786 while (!unhandled_live_ranges().empty()) { 2787 DCHECK(UnhandledIsSorted()); 2788 LiveRange* current = unhandled_live_ranges().back(); 2789 unhandled_live_ranges().pop_back(); 2790 DCHECK(UnhandledIsSorted()); 2791 LifetimePosition position = current->Start(); 2792#ifdef DEBUG 2793 allocation_finger_ = position; 2794#endif 2795 TRACE("Processing interval %d:%d start=%d\n", current->TopLevel()->vreg(), 2796 current->relative_id(), position.value()); 2797 2798 if (current->IsTopLevel() && TryReuseSpillForPhi(current->TopLevel())) 2799 continue; 2800 2801 for (size_t i = 0; i < active_live_ranges().size(); ++i) { 2802 LiveRange* cur_active = active_live_ranges()[i]; 2803 if (cur_active->End() <= position) { 2804 ActiveToHandled(cur_active); 2805 --i; // The live range was removed from the list of active live ranges. 2806 } else if (!cur_active->Covers(position)) { 2807 ActiveToInactive(cur_active); 2808 --i; // The live range was removed from the list of active live ranges. 2809 } 2810 } 2811 2812 for (size_t i = 0; i < inactive_live_ranges().size(); ++i) { 2813 LiveRange* cur_inactive = inactive_live_ranges()[i]; 2814 if (cur_inactive->End() <= position) { 2815 InactiveToHandled(cur_inactive); 2816 --i; // Live range was removed from the list of inactive live ranges. 2817 } else if (cur_inactive->Covers(position)) { 2818 InactiveToActive(cur_inactive); 2819 --i; // Live range was removed from the list of inactive live ranges. 2820 } 2821 } 2822 2823 DCHECK(!current->HasRegisterAssigned() && !current->spilled()); 2824 2825 ProcessCurrentRange(current); 2826 } 2827} 2828 2829bool LinearScanAllocator::TrySplitAndSpillSplinter(LiveRange* range) { 2830 DCHECK(range->TopLevel()->IsSplinter()); 2831 // If we can spill the whole range, great. Otherwise, split above the 2832 // first use needing a register and spill the top part. 2833 const UsePosition* next_reg = range->NextRegisterPosition(range->Start()); 2834 if (next_reg == nullptr) { 2835 Spill(range); 2836 return true; 2837 } else if (range->FirstHintPosition() == nullptr) { 2838 // If there was no hint, but we have a use position requiring a 2839 // register, apply the hot path heuristics. 2840 return false; 2841 } else if (next_reg->pos().PrevStart() > range->Start()) { 2842 LiveRange* tail = SplitRangeAt(range, next_reg->pos().PrevStart()); 2843 AddToUnhandledSorted(tail); 2844 Spill(range); 2845 return true; 2846 } 2847 return false; 2848} 2849 2850void LinearScanAllocator::SetLiveRangeAssignedRegister(LiveRange* range, 2851 int reg) { 2852 data()->MarkAllocated(range->representation(), reg); 2853 range->set_assigned_register(reg); 2854 range->SetUseHints(reg); 2855 if (range->IsTopLevel() && range->TopLevel()->is_phi()) { 2856 data()->GetPhiMapValueFor(range->TopLevel())->set_assigned_register(reg); 2857 } 2858} 2859 2860 2861void LinearScanAllocator::AddToActive(LiveRange* range) { 2862 TRACE("Add live range %d:%d to active\n", range->TopLevel()->vreg(), 2863 range->relative_id()); 2864 active_live_ranges().push_back(range); 2865} 2866 2867 2868void LinearScanAllocator::AddToInactive(LiveRange* range) { 2869 TRACE("Add live range %d:%d to inactive\n", range->TopLevel()->vreg(), 2870 range->relative_id()); 2871 inactive_live_ranges().push_back(range); 2872} 2873 2874 2875void LinearScanAllocator::AddToUnhandledSorted(LiveRange* range) { 2876 if (range == nullptr || range->IsEmpty()) return; 2877 DCHECK(!range->HasRegisterAssigned() && !range->spilled()); 2878 DCHECK(allocation_finger_ <= range->Start()); 2879 for (int i = static_cast<int>(unhandled_live_ranges().size() - 1); i >= 0; 2880 --i) { 2881 LiveRange* cur_range = unhandled_live_ranges().at(i); 2882 if (!range->ShouldBeAllocatedBefore(cur_range)) continue; 2883 TRACE("Add live range %d:%d to unhandled at %d\n", 2884 range->TopLevel()->vreg(), range->relative_id(), i + 1); 2885 auto it = unhandled_live_ranges().begin() + (i + 1); 2886 unhandled_live_ranges().insert(it, range); 2887 DCHECK(UnhandledIsSorted()); 2888 return; 2889 } 2890 TRACE("Add live range %d:%d to unhandled at start\n", 2891 range->TopLevel()->vreg(), range->relative_id()); 2892 unhandled_live_ranges().insert(unhandled_live_ranges().begin(), range); 2893 DCHECK(UnhandledIsSorted()); 2894} 2895 2896 2897void LinearScanAllocator::AddToUnhandledUnsorted(LiveRange* range) { 2898 if (range == nullptr || range->IsEmpty()) return; 2899 DCHECK(!range->HasRegisterAssigned() && !range->spilled()); 2900 TRACE("Add live range %d:%d to unhandled unsorted at end\n", 2901 range->TopLevel()->vreg(), range->relative_id()); 2902 unhandled_live_ranges().push_back(range); 2903} 2904 2905 2906static bool UnhandledSortHelper(LiveRange* a, LiveRange* b) { 2907 DCHECK(!a->ShouldBeAllocatedBefore(b) || !b->ShouldBeAllocatedBefore(a)); 2908 if (a->ShouldBeAllocatedBefore(b)) return false; 2909 if (b->ShouldBeAllocatedBefore(a)) return true; 2910 return a->TopLevel()->vreg() < b->TopLevel()->vreg(); 2911} 2912 2913 2914// Sort the unhandled live ranges so that the ranges to be processed first are 2915// at the end of the array list. This is convenient for the register allocation 2916// algorithm because it is efficient to remove elements from the end. 2917void LinearScanAllocator::SortUnhandled() { 2918 TRACE("Sort unhandled\n"); 2919 std::sort(unhandled_live_ranges().begin(), unhandled_live_ranges().end(), 2920 &UnhandledSortHelper); 2921} 2922 2923 2924bool LinearScanAllocator::UnhandledIsSorted() { 2925 size_t len = unhandled_live_ranges().size(); 2926 for (size_t i = 1; i < len; i++) { 2927 LiveRange* a = unhandled_live_ranges().at(i - 1); 2928 LiveRange* b = unhandled_live_ranges().at(i); 2929 if (a->Start() < b->Start()) return false; 2930 } 2931 return true; 2932} 2933 2934 2935void LinearScanAllocator::ActiveToHandled(LiveRange* range) { 2936 RemoveElement(&active_live_ranges(), range); 2937 TRACE("Moving live range %d:%d from active to handled\n", 2938 range->TopLevel()->vreg(), range->relative_id()); 2939} 2940 2941 2942void LinearScanAllocator::ActiveToInactive(LiveRange* range) { 2943 RemoveElement(&active_live_ranges(), range); 2944 inactive_live_ranges().push_back(range); 2945 TRACE("Moving live range %d:%d from active to inactive\n", 2946 range->TopLevel()->vreg(), range->relative_id()); 2947} 2948 2949 2950void LinearScanAllocator::InactiveToHandled(LiveRange* range) { 2951 RemoveElement(&inactive_live_ranges(), range); 2952 TRACE("Moving live range %d:%d from inactive to handled\n", 2953 range->TopLevel()->vreg(), range->relative_id()); 2954} 2955 2956 2957void LinearScanAllocator::InactiveToActive(LiveRange* range) { 2958 RemoveElement(&inactive_live_ranges(), range); 2959 active_live_ranges().push_back(range); 2960 TRACE("Moving live range %d:%d from inactive to active\n", 2961 range->TopLevel()->vreg(), range->relative_id()); 2962} 2963 2964void LinearScanAllocator::GetFPRegisterSet(MachineRepresentation rep, 2965 int* num_regs, int* num_codes, 2966 const int** codes) const { 2967 DCHECK(!kSimpleFPAliasing); 2968 if (rep == MachineRepresentation::kFloat32) { 2969 *num_regs = data()->config()->num_float_registers(); 2970 *num_codes = data()->config()->num_allocatable_float_registers(); 2971 *codes = data()->config()->allocatable_float_codes(); 2972 } else if (rep == MachineRepresentation::kSimd128) { 2973 *num_regs = data()->config()->num_simd128_registers(); 2974 *num_codes = data()->config()->num_allocatable_simd128_registers(); 2975 *codes = data()->config()->allocatable_simd128_codes(); 2976 } else { 2977 UNREACHABLE(); 2978 } 2979} 2980 2981void LinearScanAllocator::FindFreeRegistersForRange( 2982 LiveRange* range, Vector<LifetimePosition> positions) { 2983 int num_regs = num_registers(); 2984 int num_codes = num_allocatable_registers(); 2985 const int* codes = allocatable_register_codes(); 2986 MachineRepresentation rep = range->representation(); 2987 if (!kSimpleFPAliasing && (rep == MachineRepresentation::kFloat32 || 2988 rep == MachineRepresentation::kSimd128)) 2989 GetFPRegisterSet(rep, &num_regs, &num_codes, &codes); 2990 DCHECK_GE(positions.length(), num_regs); 2991 2992 for (int i = 0; i < num_regs; ++i) { 2993 positions[i] = LifetimePosition::MaxPosition(); 2994 } 2995 2996 for (LiveRange* cur_active : active_live_ranges()) { 2997 int cur_reg = cur_active->assigned_register(); 2998 if (kSimpleFPAliasing || !check_fp_aliasing()) { 2999 positions[cur_reg] = LifetimePosition::GapFromInstructionIndex(0); 3000 TRACE("Register %s is free until pos %d (1)\n", RegisterName(cur_reg), 3001 LifetimePosition::GapFromInstructionIndex(0).value()); 3002 } else { 3003 int alias_base_index = -1; 3004 int aliases = data()->config()->GetAliases( 3005 cur_active->representation(), cur_reg, rep, &alias_base_index); 3006 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); 3007 while (aliases--) { 3008 int aliased_reg = alias_base_index + aliases; 3009 positions[aliased_reg] = LifetimePosition::GapFromInstructionIndex(0); 3010 } 3011 } 3012 } 3013 3014 for (LiveRange* cur_inactive : inactive_live_ranges()) { 3015 DCHECK(cur_inactive->End() > range->Start()); 3016 int cur_reg = cur_inactive->assigned_register(); 3017 // No need to carry out intersections, when this register won't be 3018 // interesting to this range anyway. 3019 // TODO(mtrofin): extend to aliased ranges, too. 3020 if ((kSimpleFPAliasing || !check_fp_aliasing()) && 3021 positions[cur_reg] < range->Start()) { 3022 continue; 3023 } 3024 3025 LifetimePosition next_intersection = cur_inactive->FirstIntersection(range); 3026 if (!next_intersection.IsValid()) continue; 3027 if (kSimpleFPAliasing || !check_fp_aliasing()) { 3028 positions[cur_reg] = Min(positions[cur_reg], next_intersection); 3029 TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg), 3030 Min(positions[cur_reg], next_intersection).value()); 3031 } else { 3032 int alias_base_index = -1; 3033 int aliases = data()->config()->GetAliases( 3034 cur_inactive->representation(), cur_reg, rep, &alias_base_index); 3035 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); 3036 while (aliases--) { 3037 int aliased_reg = alias_base_index + aliases; 3038 positions[aliased_reg] = Min(positions[aliased_reg], next_intersection); 3039 } 3040 } 3041 } 3042} 3043 3044// High-level register allocation summary: 3045// 3046// For regular, or hot (i.e. not splinter) ranges, we attempt to first 3047// allocate first the preferred (hint) register. If that is not possible, 3048// we find a register that's free, and allocate that. If that's not possible, 3049// we search for a register to steal from a range that was allocated. The 3050// goal is to optimize for throughput by avoiding register-to-memory 3051// moves, which are expensive. 3052// 3053// For splinters, the goal is to minimize the number of moves. First we try 3054// to allocate the preferred register (more discussion follows). Failing that, 3055// we bail out and spill as far as we can, unless the first use is at start, 3056// case in which we apply the same behavior as we do for regular ranges. 3057// If there is no hint, we apply the hot-path behavior. 3058// 3059// For the splinter, the hint register may come from: 3060// 3061// - the hot path (we set it at splintering time with SetHint). In this case, if 3062// we cannot offer the hint register, spilling is better because it's at most 3063// 1 move, while trying to find and offer another register is at least 1 move. 3064// 3065// - a constraint. If we cannot offer that register, it's because there is some 3066// interference. So offering the hint register up to the interference would 3067// result 3068// in a move at the interference, plus a move to satisfy the constraint. This is 3069// also the number of moves if we spill, with the potential of the range being 3070// already spilled and thus saving a move (the spill). 3071// Note that this can only be an input constraint, if it were an output one, 3072// the range wouldn't be a splinter because it means it'd be defined in a 3073// deferred 3074// block, and we don't mark those as splinters (they live in deferred blocks 3075// only). 3076// 3077// - a phi. The same analysis as in the case of the input constraint applies. 3078// 3079void LinearScanAllocator::ProcessCurrentRange(LiveRange* current) { 3080 LifetimePosition free_until_pos_buff[RegisterConfiguration::kMaxFPRegisters]; 3081 Vector<LifetimePosition> free_until_pos( 3082 free_until_pos_buff, RegisterConfiguration::kMaxFPRegisters); 3083 FindFreeRegistersForRange(current, free_until_pos); 3084 if (!TryAllocatePreferredReg(current, free_until_pos)) { 3085 if (current->TopLevel()->IsSplinter()) { 3086 if (TrySplitAndSpillSplinter(current)) return; 3087 } 3088 if (!TryAllocateFreeReg(current, free_until_pos)) { 3089 AllocateBlockedReg(current); 3090 } 3091 } 3092 if (current->HasRegisterAssigned()) { 3093 AddToActive(current); 3094 } 3095} 3096 3097bool LinearScanAllocator::TryAllocatePreferredReg( 3098 LiveRange* current, const Vector<LifetimePosition>& free_until_pos) { 3099 int hint_register; 3100 if (current->FirstHintPosition(&hint_register) != nullptr) { 3101 TRACE( 3102 "Found reg hint %s (free until [%d) for live range %d:%d (end %d[).\n", 3103 RegisterName(hint_register), free_until_pos[hint_register].value(), 3104 current->TopLevel()->vreg(), current->relative_id(), 3105 current->End().value()); 3106 3107 // The desired register is free until the end of the current live range. 3108 if (free_until_pos[hint_register] >= current->End()) { 3109 TRACE("Assigning preferred reg %s to live range %d:%d\n", 3110 RegisterName(hint_register), current->TopLevel()->vreg(), 3111 current->relative_id()); 3112 SetLiveRangeAssignedRegister(current, hint_register); 3113 return true; 3114 } 3115 } 3116 return false; 3117} 3118 3119bool LinearScanAllocator::TryAllocateFreeReg( 3120 LiveRange* current, const Vector<LifetimePosition>& free_until_pos) { 3121 int num_regs = 0; // used only for the call to GetFPRegisterSet. 3122 int num_codes = num_allocatable_registers(); 3123 const int* codes = allocatable_register_codes(); 3124 MachineRepresentation rep = current->representation(); 3125 if (!kSimpleFPAliasing && (rep == MachineRepresentation::kFloat32 || 3126 rep == MachineRepresentation::kSimd128)) { 3127 GetFPRegisterSet(rep, &num_regs, &num_codes, &codes); 3128 } 3129 3130 DCHECK_GE(free_until_pos.length(), num_codes); 3131 3132 // Find the register which stays free for the longest time. 3133 int reg = codes[0]; 3134 for (int i = 1; i < num_codes; ++i) { 3135 int code = codes[i]; 3136 if (free_until_pos[code] > free_until_pos[reg]) { 3137 reg = code; 3138 } 3139 } 3140 3141 LifetimePosition pos = free_until_pos[reg]; 3142 3143 if (pos <= current->Start()) { 3144 // All registers are blocked. 3145 return false; 3146 } 3147 3148 if (pos < current->End()) { 3149 // Register reg is available at the range start but becomes blocked before 3150 // the range end. Split current at position where it becomes blocked. 3151 LiveRange* tail = SplitRangeAt(current, pos); 3152 AddToUnhandledSorted(tail); 3153 } 3154 3155 // Register reg is available at the range start and is free until the range 3156 // end. 3157 DCHECK(pos >= current->End()); 3158 TRACE("Assigning free reg %s to live range %d:%d\n", RegisterName(reg), 3159 current->TopLevel()->vreg(), current->relative_id()); 3160 SetLiveRangeAssignedRegister(current, reg); 3161 3162 return true; 3163} 3164 3165void LinearScanAllocator::AllocateBlockedReg(LiveRange* current) { 3166 UsePosition* register_use = current->NextRegisterPosition(current->Start()); 3167 if (register_use == nullptr) { 3168 // There is no use in the current live range that requires a register. 3169 // We can just spill it. 3170 Spill(current); 3171 return; 3172 } 3173 3174 int num_regs = num_registers(); 3175 int num_codes = num_allocatable_registers(); 3176 const int* codes = allocatable_register_codes(); 3177 MachineRepresentation rep = current->representation(); 3178 if (!kSimpleFPAliasing && (rep == MachineRepresentation::kFloat32 || 3179 rep == MachineRepresentation::kSimd128)) 3180 GetFPRegisterSet(rep, &num_regs, &num_codes, &codes); 3181 3182 // use_pos keeps track of positions a register/alias is used at. 3183 // block_pos keeps track of positions where a register/alias is blocked 3184 // from. 3185 LifetimePosition use_pos[RegisterConfiguration::kMaxFPRegisters]; 3186 LifetimePosition block_pos[RegisterConfiguration::kMaxFPRegisters]; 3187 for (int i = 0; i < num_regs; i++) { 3188 use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition(); 3189 } 3190 3191 for (LiveRange* range : active_live_ranges()) { 3192 int cur_reg = range->assigned_register(); 3193 bool is_fixed_or_cant_spill = 3194 range->TopLevel()->IsFixed() || !range->CanBeSpilled(current->Start()); 3195 if (kSimpleFPAliasing || !check_fp_aliasing()) { 3196 if (is_fixed_or_cant_spill) { 3197 block_pos[cur_reg] = use_pos[cur_reg] = 3198 LifetimePosition::GapFromInstructionIndex(0); 3199 } else { 3200 DCHECK_NE(LifetimePosition::GapFromInstructionIndex(0), 3201 block_pos[cur_reg]); 3202 use_pos[cur_reg] = 3203 range->NextLifetimePositionRegisterIsBeneficial(current->Start()); 3204 } 3205 } else { 3206 int alias_base_index = -1; 3207 int aliases = data()->config()->GetAliases( 3208 range->representation(), cur_reg, rep, &alias_base_index); 3209 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); 3210 while (aliases--) { 3211 int aliased_reg = alias_base_index + aliases; 3212 if (is_fixed_or_cant_spill) { 3213 block_pos[aliased_reg] = use_pos[aliased_reg] = 3214 LifetimePosition::GapFromInstructionIndex(0); 3215 } else { 3216 use_pos[aliased_reg] = 3217 Min(block_pos[aliased_reg], 3218 range->NextLifetimePositionRegisterIsBeneficial( 3219 current->Start())); 3220 } 3221 } 3222 } 3223 } 3224 3225 for (LiveRange* range : inactive_live_ranges()) { 3226 DCHECK(range->End() > current->Start()); 3227 int cur_reg = range->assigned_register(); 3228 bool is_fixed = range->TopLevel()->IsFixed(); 3229 3230 // Don't perform costly intersections if they are guaranteed to not update 3231 // block_pos or use_pos. 3232 // TODO(mtrofin): extend to aliased ranges, too. 3233 if ((kSimpleFPAliasing || !check_fp_aliasing())) { 3234 if (is_fixed) { 3235 if (block_pos[cur_reg] < range->Start()) continue; 3236 } else { 3237 if (use_pos[cur_reg] < range->Start()) continue; 3238 } 3239 } 3240 3241 LifetimePosition next_intersection = range->FirstIntersection(current); 3242 if (!next_intersection.IsValid()) continue; 3243 3244 if (kSimpleFPAliasing || !check_fp_aliasing()) { 3245 if (is_fixed) { 3246 block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection); 3247 use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]); 3248 } else { 3249 use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection); 3250 } 3251 } else { 3252 int alias_base_index = -1; 3253 int aliases = data()->config()->GetAliases( 3254 range->representation(), cur_reg, rep, &alias_base_index); 3255 DCHECK(aliases > 0 || (aliases == 0 && alias_base_index == -1)); 3256 while (aliases--) { 3257 int aliased_reg = alias_base_index + aliases; 3258 if (is_fixed) { 3259 block_pos[aliased_reg] = 3260 Min(block_pos[aliased_reg], next_intersection); 3261 use_pos[aliased_reg] = 3262 Min(block_pos[aliased_reg], use_pos[aliased_reg]); 3263 } else { 3264 use_pos[aliased_reg] = Min(use_pos[aliased_reg], next_intersection); 3265 } 3266 } 3267 } 3268 } 3269 3270 int reg = codes[0]; 3271 for (int i = 1; i < num_codes; ++i) { 3272 int code = codes[i]; 3273 if (use_pos[code] > use_pos[reg]) { 3274 reg = code; 3275 } 3276 } 3277 3278 if (use_pos[reg] < register_use->pos()) { 3279 // If there is a gap position before the next register use, we can 3280 // spill until there. The gap position will then fit the fill move. 3281 if (LifetimePosition::ExistsGapPositionBetween(current->Start(), 3282 register_use->pos())) { 3283 SpillBetween(current, current->Start(), register_use->pos()); 3284 return; 3285 } 3286 } 3287 3288 // We couldn't spill until the next register use. Split before the register 3289 // is blocked, if applicable. 3290 if (block_pos[reg] < current->End()) { 3291 // Register becomes blocked before the current range end. Split before that 3292 // position. 3293 LiveRange* tail = 3294 SplitBetween(current, current->Start(), block_pos[reg].Start()); 3295 AddToUnhandledSorted(tail); 3296 } 3297 3298 // Register reg is not blocked for the whole range. 3299 DCHECK(block_pos[reg] >= current->End()); 3300 TRACE("Assigning blocked reg %s to live range %d:%d\n", RegisterName(reg), 3301 current->TopLevel()->vreg(), current->relative_id()); 3302 SetLiveRangeAssignedRegister(current, reg); 3303 3304 // This register was not free. Thus we need to find and spill 3305 // parts of active and inactive live regions that use the same register 3306 // at the same lifetime positions as current. 3307 SplitAndSpillIntersecting(current); 3308} 3309 3310 3311void LinearScanAllocator::SplitAndSpillIntersecting(LiveRange* current) { 3312 DCHECK(current->HasRegisterAssigned()); 3313 int reg = current->assigned_register(); 3314 LifetimePosition split_pos = current->Start(); 3315 for (size_t i = 0; i < active_live_ranges().size(); ++i) { 3316 LiveRange* range = active_live_ranges()[i]; 3317 if (kSimpleFPAliasing || !check_fp_aliasing()) { 3318 if (range->assigned_register() != reg) continue; 3319 } else { 3320 if (!data()->config()->AreAliases(current->representation(), reg, 3321 range->representation(), 3322 range->assigned_register())) { 3323 continue; 3324 } 3325 } 3326 3327 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); 3328 LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos); 3329 if (next_pos == nullptr) { 3330 SpillAfter(range, spill_pos); 3331 } else { 3332 // When spilling between spill_pos and next_pos ensure that the range 3333 // remains spilled at least until the start of the current live range. 3334 // This guarantees that we will not introduce new unhandled ranges that 3335 // start before the current range as this violates allocation invariants 3336 // and will lead to an inconsistent state of active and inactive 3337 // live-ranges: ranges are allocated in order of their start positions, 3338 // ranges are retired from active/inactive when the start of the 3339 // current live-range is larger than their end. 3340 DCHECK(LifetimePosition::ExistsGapPositionBetween(current->Start(), 3341 next_pos->pos())); 3342 SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos()); 3343 } 3344 ActiveToHandled(range); 3345 --i; 3346 } 3347 3348 for (size_t i = 0; i < inactive_live_ranges().size(); ++i) { 3349 LiveRange* range = inactive_live_ranges()[i]; 3350 DCHECK(range->End() > current->Start()); 3351 if (range->TopLevel()->IsFixed()) continue; 3352 if (kSimpleFPAliasing || !check_fp_aliasing()) { 3353 if (range->assigned_register() != reg) continue; 3354 } else { 3355 if (!data()->config()->AreAliases(current->representation(), reg, 3356 range->representation(), 3357 range->assigned_register())) 3358 continue; 3359 } 3360 3361 LifetimePosition next_intersection = range->FirstIntersection(current); 3362 if (next_intersection.IsValid()) { 3363 UsePosition* next_pos = range->NextRegisterPosition(current->Start()); 3364 if (next_pos == nullptr) { 3365 SpillAfter(range, split_pos); 3366 } else { 3367 next_intersection = Min(next_intersection, next_pos->pos()); 3368 SpillBetween(range, split_pos, next_intersection); 3369 } 3370 InactiveToHandled(range); 3371 --i; 3372 } 3373 } 3374} 3375 3376 3377bool LinearScanAllocator::TryReuseSpillForPhi(TopLevelLiveRange* range) { 3378 if (!range->is_phi()) return false; 3379 3380 DCHECK(!range->HasSpillOperand()); 3381 RegisterAllocationData::PhiMapValue* phi_map_value = 3382 data()->GetPhiMapValueFor(range); 3383 const PhiInstruction* phi = phi_map_value->phi(); 3384 const InstructionBlock* block = phi_map_value->block(); 3385 // Count the number of spilled operands. 3386 size_t spilled_count = 0; 3387 LiveRange* first_op = nullptr; 3388 for (size_t i = 0; i < phi->operands().size(); i++) { 3389 int op = phi->operands()[i]; 3390 LiveRange* op_range = data()->GetOrCreateLiveRangeFor(op); 3391 if (!op_range->TopLevel()->HasSpillRange()) continue; 3392 const InstructionBlock* pred = 3393 code()->InstructionBlockAt(block->predecessors()[i]); 3394 LifetimePosition pred_end = 3395 LifetimePosition::InstructionFromInstructionIndex( 3396 pred->last_instruction_index()); 3397 while (op_range != nullptr && !op_range->CanCover(pred_end)) { 3398 op_range = op_range->next(); 3399 } 3400 if (op_range != nullptr && op_range->spilled()) { 3401 spilled_count++; 3402 if (first_op == nullptr) { 3403 first_op = op_range->TopLevel(); 3404 } 3405 } 3406 } 3407 3408 // Only continue if more than half of the operands are spilled. 3409 if (spilled_count * 2 <= phi->operands().size()) { 3410 return false; 3411 } 3412 3413 // Try to merge the spilled operands and count the number of merged spilled 3414 // operands. 3415 DCHECK(first_op != nullptr); 3416 SpillRange* first_op_spill = first_op->TopLevel()->GetSpillRange(); 3417 size_t num_merged = 1; 3418 for (size_t i = 1; i < phi->operands().size(); i++) { 3419 int op = phi->operands()[i]; 3420 TopLevelLiveRange* op_range = data()->live_ranges()[op]; 3421 if (!op_range->HasSpillRange()) continue; 3422 SpillRange* op_spill = op_range->GetSpillRange(); 3423 if (op_spill == first_op_spill || first_op_spill->TryMerge(op_spill)) { 3424 num_merged++; 3425 } 3426 } 3427 3428 // Only continue if enough operands could be merged to the 3429 // same spill slot. 3430 if (num_merged * 2 <= phi->operands().size() || 3431 AreUseIntervalsIntersecting(first_op_spill->interval(), 3432 range->first_interval())) { 3433 return false; 3434 } 3435 3436 // If the range does not need register soon, spill it to the merged 3437 // spill range. 3438 LifetimePosition next_pos = range->Start(); 3439 if (next_pos.IsGapPosition()) next_pos = next_pos.NextStart(); 3440 UsePosition* pos = range->NextUsePositionRegisterIsBeneficial(next_pos); 3441 if (pos == nullptr) { 3442 SpillRange* spill_range = 3443 range->TopLevel()->HasSpillRange() 3444 ? range->TopLevel()->GetSpillRange() 3445 : data()->AssignSpillRangeToLiveRange(range->TopLevel()); 3446 bool merged = first_op_spill->TryMerge(spill_range); 3447 if (!merged) return false; 3448 Spill(range); 3449 return true; 3450 } else if (pos->pos() > range->Start().NextStart()) { 3451 SpillRange* spill_range = 3452 range->TopLevel()->HasSpillRange() 3453 ? range->TopLevel()->GetSpillRange() 3454 : data()->AssignSpillRangeToLiveRange(range->TopLevel()); 3455 bool merged = first_op_spill->TryMerge(spill_range); 3456 if (!merged) return false; 3457 SpillBetween(range, range->Start(), pos->pos()); 3458 DCHECK(UnhandledIsSorted()); 3459 return true; 3460 } 3461 return false; 3462} 3463 3464 3465void LinearScanAllocator::SpillAfter(LiveRange* range, LifetimePosition pos) { 3466 LiveRange* second_part = SplitRangeAt(range, pos); 3467 Spill(second_part); 3468} 3469 3470 3471void LinearScanAllocator::SpillBetween(LiveRange* range, LifetimePosition start, 3472 LifetimePosition end) { 3473 SpillBetweenUntil(range, start, start, end); 3474} 3475 3476 3477void LinearScanAllocator::SpillBetweenUntil(LiveRange* range, 3478 LifetimePosition start, 3479 LifetimePosition until, 3480 LifetimePosition end) { 3481 CHECK(start < end); 3482 LiveRange* second_part = SplitRangeAt(range, start); 3483 3484 if (second_part->Start() < end) { 3485 // The split result intersects with [start, end[. 3486 // Split it at position between ]start+1, end[, spill the middle part 3487 // and put the rest to unhandled. 3488 LifetimePosition third_part_end = end.PrevStart().End(); 3489 if (data()->IsBlockBoundary(end.Start())) { 3490 third_part_end = end.Start(); 3491 } 3492 LiveRange* third_part = SplitBetween( 3493 second_part, Max(second_part->Start().End(), until), third_part_end); 3494 3495 DCHECK(third_part != second_part); 3496 3497 Spill(second_part); 3498 AddToUnhandledSorted(third_part); 3499 } else { 3500 // The split result does not intersect with [start, end[. 3501 // Nothing to spill. Just put it to unhandled as whole. 3502 AddToUnhandledSorted(second_part); 3503 } 3504} 3505 3506 3507SpillSlotLocator::SpillSlotLocator(RegisterAllocationData* data) 3508 : data_(data) {} 3509 3510 3511void SpillSlotLocator::LocateSpillSlots() { 3512 const InstructionSequence* code = data()->code(); 3513 for (TopLevelLiveRange* range : data()->live_ranges()) { 3514 if (range == nullptr || range->IsEmpty()) continue; 3515 // We care only about ranges which spill in the frame. 3516 if (!range->HasSpillRange() || range->IsSpilledOnlyInDeferredBlocks()) { 3517 continue; 3518 } 3519 TopLevelLiveRange::SpillMoveInsertionList* spills = 3520 range->GetSpillMoveInsertionLocations(); 3521 DCHECK_NOT_NULL(spills); 3522 for (; spills != nullptr; spills = spills->next) { 3523 code->GetInstructionBlock(spills->gap_index)->mark_needs_frame(); 3524 } 3525 } 3526} 3527 3528 3529OperandAssigner::OperandAssigner(RegisterAllocationData* data) : data_(data) {} 3530 3531 3532void OperandAssigner::AssignSpillSlots() { 3533 ZoneVector<SpillRange*>& spill_ranges = data()->spill_ranges(); 3534 // Merge disjoint spill ranges 3535 for (size_t i = 0; i < spill_ranges.size(); ++i) { 3536 SpillRange* range = spill_ranges[i]; 3537 if (range == nullptr) continue; 3538 if (range->IsEmpty()) continue; 3539 for (size_t j = i + 1; j < spill_ranges.size(); ++j) { 3540 SpillRange* other = spill_ranges[j]; 3541 if (other != nullptr && !other->IsEmpty()) { 3542 range->TryMerge(other); 3543 } 3544 } 3545 } 3546 // Allocate slots for the merged spill ranges. 3547 for (SpillRange* range : spill_ranges) { 3548 if (range == nullptr || range->IsEmpty()) continue; 3549 // Allocate a new operand referring to the spill slot. 3550 if (!range->HasSlot()) { 3551 int index = data()->frame()->AllocateSpillSlot(range->byte_width()); 3552 range->set_assigned_slot(index); 3553 } 3554 } 3555} 3556 3557 3558void OperandAssigner::CommitAssignment() { 3559 for (TopLevelLiveRange* top_range : data()->live_ranges()) { 3560 if (top_range == nullptr || top_range->IsEmpty()) continue; 3561 InstructionOperand spill_operand; 3562 if (top_range->HasSpillOperand()) { 3563 spill_operand = *top_range->TopLevel()->GetSpillOperand(); 3564 } else if (top_range->TopLevel()->HasSpillRange()) { 3565 spill_operand = top_range->TopLevel()->GetSpillRangeOperand(); 3566 } 3567 if (top_range->is_phi()) { 3568 data()->GetPhiMapValueFor(top_range)->CommitAssignment( 3569 top_range->GetAssignedOperand()); 3570 } 3571 for (LiveRange* range = top_range; range != nullptr; 3572 range = range->next()) { 3573 InstructionOperand assigned = range->GetAssignedOperand(); 3574 range->ConvertUsesToOperand(assigned, spill_operand); 3575 } 3576 3577 if (!spill_operand.IsInvalid()) { 3578 // If this top level range has a child spilled in a deferred block, we use 3579 // the range and control flow connection mechanism instead of spilling at 3580 // definition. Refer to the ConnectLiveRanges and ResolveControlFlow 3581 // phases. Normally, when we spill at definition, we do not insert a 3582 // connecting move when a successor child range is spilled - because the 3583 // spilled range picks up its value from the slot which was assigned at 3584 // definition. For ranges that are determined to spill only in deferred 3585 // blocks, we let ConnectLiveRanges and ResolveControlFlow find the blocks 3586 // where a spill operand is expected, and then finalize by inserting the 3587 // spills in the deferred blocks dominators. 3588 if (!top_range->IsSpilledOnlyInDeferredBlocks()) { 3589 // Spill at definition if the range isn't spilled only in deferred 3590 // blocks. 3591 top_range->CommitSpillMoves( 3592 data()->code(), spill_operand, 3593 top_range->has_slot_use() || top_range->spilled()); 3594 } 3595 } 3596 } 3597} 3598 3599 3600ReferenceMapPopulator::ReferenceMapPopulator(RegisterAllocationData* data) 3601 : data_(data) {} 3602 3603 3604bool ReferenceMapPopulator::SafePointsAreInOrder() const { 3605 int safe_point = 0; 3606 for (ReferenceMap* map : *data()->code()->reference_maps()) { 3607 if (safe_point > map->instruction_position()) return false; 3608 safe_point = map->instruction_position(); 3609 } 3610 return true; 3611} 3612 3613 3614void ReferenceMapPopulator::PopulateReferenceMaps() { 3615 DCHECK(SafePointsAreInOrder()); 3616 // Map all delayed references. 3617 for (RegisterAllocationData::DelayedReference& delayed_reference : 3618 data()->delayed_references()) { 3619 delayed_reference.map->RecordReference( 3620 AllocatedOperand::cast(*delayed_reference.operand)); 3621 } 3622 // Iterate over all safe point positions and record a pointer 3623 // for all spilled live ranges at this point. 3624 int last_range_start = 0; 3625 const ReferenceMapDeque* reference_maps = data()->code()->reference_maps(); 3626 ReferenceMapDeque::const_iterator first_it = reference_maps->begin(); 3627 for (TopLevelLiveRange* range : data()->live_ranges()) { 3628 if (range == nullptr) continue; 3629 // Skip non-reference values. 3630 if (!data()->IsReference(range)) continue; 3631 // Skip empty live ranges. 3632 if (range->IsEmpty()) continue; 3633 if (range->has_preassigned_slot()) continue; 3634 3635 // Find the extent of the range and its children. 3636 int start = range->Start().ToInstructionIndex(); 3637 int end = 0; 3638 for (LiveRange* cur = range; cur != nullptr; cur = cur->next()) { 3639 LifetimePosition this_end = cur->End(); 3640 if (this_end.ToInstructionIndex() > end) 3641 end = this_end.ToInstructionIndex(); 3642 DCHECK(cur->Start().ToInstructionIndex() >= start); 3643 } 3644 3645 // Most of the ranges are in order, but not all. Keep an eye on when they 3646 // step backwards and reset the first_it so we don't miss any safe points. 3647 if (start < last_range_start) first_it = reference_maps->begin(); 3648 last_range_start = start; 3649 3650 // Step across all the safe points that are before the start of this range, 3651 // recording how far we step in order to save doing this for the next range. 3652 for (; first_it != reference_maps->end(); ++first_it) { 3653 ReferenceMap* map = *first_it; 3654 if (map->instruction_position() >= start) break; 3655 } 3656 3657 InstructionOperand spill_operand; 3658 if (((range->HasSpillOperand() && 3659 !range->GetSpillOperand()->IsConstant()) || 3660 range->HasSpillRange())) { 3661 if (range->HasSpillOperand()) { 3662 spill_operand = *range->GetSpillOperand(); 3663 } else { 3664 spill_operand = range->GetSpillRangeOperand(); 3665 } 3666 DCHECK(spill_operand.IsStackSlot()); 3667 DCHECK(CanBeTaggedPointer( 3668 AllocatedOperand::cast(spill_operand).representation())); 3669 } 3670 3671 LiveRange* cur = range; 3672 // Step through the safe points to see whether they are in the range. 3673 for (auto it = first_it; it != reference_maps->end(); ++it) { 3674 ReferenceMap* map = *it; 3675 int safe_point = map->instruction_position(); 3676 3677 // The safe points are sorted so we can stop searching here. 3678 if (safe_point - 1 > end) break; 3679 3680 // Advance to the next active range that covers the current 3681 // safe point position. 3682 LifetimePosition safe_point_pos = 3683 LifetimePosition::InstructionFromInstructionIndex(safe_point); 3684 3685 // Search for the child range (cur) that covers safe_point_pos. If we 3686 // don't find it before the children pass safe_point_pos, keep cur at 3687 // the last child, because the next safe_point_pos may be covered by cur. 3688 // This may happen if cur has more than one interval, and the current 3689 // safe_point_pos is in between intervals. 3690 // For that reason, cur may be at most the last child. 3691 DCHECK_NOT_NULL(cur); 3692 DCHECK(safe_point_pos >= cur->Start() || range == cur); 3693 bool found = false; 3694 while (!found) { 3695 if (cur->Covers(safe_point_pos)) { 3696 found = true; 3697 } else { 3698 LiveRange* next = cur->next(); 3699 if (next == nullptr || next->Start() > safe_point_pos) { 3700 break; 3701 } 3702 cur = next; 3703 } 3704 } 3705 3706 if (!found) { 3707 continue; 3708 } 3709 3710 // Check if the live range is spilled and the safe point is after 3711 // the spill position. 3712 int spill_index = range->IsSpilledOnlyInDeferredBlocks() 3713 ? cur->Start().ToInstructionIndex() 3714 : range->spill_start_index(); 3715 3716 if (!spill_operand.IsInvalid() && safe_point >= spill_index) { 3717 TRACE("Pointer for range %d (spilled at %d) at safe point %d\n", 3718 range->vreg(), spill_index, safe_point); 3719 map->RecordReference(AllocatedOperand::cast(spill_operand)); 3720 } 3721 3722 if (!cur->spilled()) { 3723 TRACE( 3724 "Pointer in register for range %d:%d (start at %d) " 3725 "at safe point %d\n", 3726 range->vreg(), cur->relative_id(), cur->Start().value(), 3727 safe_point); 3728 InstructionOperand operand = cur->GetAssignedOperand(); 3729 DCHECK(!operand.IsStackSlot()); 3730 DCHECK(CanBeTaggedPointer( 3731 AllocatedOperand::cast(operand).representation())); 3732 map->RecordReference(AllocatedOperand::cast(operand)); 3733 } 3734 } 3735 } 3736} 3737 3738 3739LiveRangeConnector::LiveRangeConnector(RegisterAllocationData* data) 3740 : data_(data) {} 3741 3742 3743bool LiveRangeConnector::CanEagerlyResolveControlFlow( 3744 const InstructionBlock* block) const { 3745 if (block->PredecessorCount() != 1) return false; 3746 return block->predecessors()[0].IsNext(block->rpo_number()); 3747} 3748 3749 3750void LiveRangeConnector::ResolveControlFlow(Zone* local_zone) { 3751 // Lazily linearize live ranges in memory for fast lookup. 3752 LiveRangeFinder finder(data(), local_zone); 3753 ZoneVector<BitVector*>& live_in_sets = data()->live_in_sets(); 3754 for (const InstructionBlock* block : code()->instruction_blocks()) { 3755 if (CanEagerlyResolveControlFlow(block)) continue; 3756 BitVector* live = live_in_sets[block->rpo_number().ToInt()]; 3757 BitVector::Iterator iterator(live); 3758 while (!iterator.Done()) { 3759 int vreg = iterator.Current(); 3760 LiveRangeBoundArray* array = finder.ArrayFor(vreg); 3761 for (const RpoNumber& pred : block->predecessors()) { 3762 FindResult result; 3763 const InstructionBlock* pred_block = code()->InstructionBlockAt(pred); 3764 if (!array->FindConnectableSubranges(block, pred_block, &result)) { 3765 continue; 3766 } 3767 InstructionOperand pred_op = result.pred_cover_->GetAssignedOperand(); 3768 InstructionOperand cur_op = result.cur_cover_->GetAssignedOperand(); 3769 if (pred_op.Equals(cur_op)) continue; 3770 if (!pred_op.IsAnyRegister() && cur_op.IsAnyRegister()) { 3771 // We're doing a reload. 3772 // We don't need to, if: 3773 // 1) there's no register use in this block, and 3774 // 2) the range ends before the block does, and 3775 // 3) we don't have a successor, or the successor is spilled. 3776 LifetimePosition block_start = 3777 LifetimePosition::GapFromInstructionIndex(block->code_start()); 3778 LifetimePosition block_end = 3779 LifetimePosition::GapFromInstructionIndex(block->code_end()); 3780 const LiveRange* current = result.cur_cover_; 3781 const LiveRange* successor = current->next(); 3782 if (current->End() < block_end && 3783 (successor == nullptr || successor->spilled())) { 3784 // verify point 1: no register use. We can go to the end of the 3785 // range, since it's all within the block. 3786 3787 bool uses_reg = false; 3788 for (const UsePosition* use = current->NextUsePosition(block_start); 3789 use != nullptr; use = use->next()) { 3790 if (use->operand()->IsAnyRegister()) { 3791 uses_reg = true; 3792 break; 3793 } 3794 } 3795 if (!uses_reg) continue; 3796 } 3797 if (current->TopLevel()->IsSpilledOnlyInDeferredBlocks() && 3798 pred_block->IsDeferred()) { 3799 // The spill location should be defined in pred_block, so add 3800 // pred_block to the list of blocks requiring a spill operand. 3801 current->TopLevel()->GetListOfBlocksRequiringSpillOperands()->Add( 3802 pred_block->rpo_number().ToInt()); 3803 } 3804 } 3805 int move_loc = ResolveControlFlow(block, cur_op, pred_block, pred_op); 3806 USE(move_loc); 3807 DCHECK_IMPLIES( 3808 result.cur_cover_->TopLevel()->IsSpilledOnlyInDeferredBlocks() && 3809 !(pred_op.IsAnyRegister() && cur_op.IsAnyRegister()), 3810 code()->GetInstructionBlock(move_loc)->IsDeferred()); 3811 } 3812 iterator.Advance(); 3813 } 3814 } 3815 3816 // At this stage, we collected blocks needing a spill operand from 3817 // ConnectRanges and from ResolveControlFlow. Time to commit the spills for 3818 // deferred blocks. 3819 for (TopLevelLiveRange* top : data()->live_ranges()) { 3820 if (top == nullptr || top->IsEmpty() || 3821 !top->IsSpilledOnlyInDeferredBlocks()) 3822 continue; 3823 CommitSpillsInDeferredBlocks(top, finder.ArrayFor(top->vreg()), local_zone); 3824 } 3825} 3826 3827 3828int LiveRangeConnector::ResolveControlFlow(const InstructionBlock* block, 3829 const InstructionOperand& cur_op, 3830 const InstructionBlock* pred, 3831 const InstructionOperand& pred_op) { 3832 DCHECK(!pred_op.Equals(cur_op)); 3833 int gap_index; 3834 Instruction::GapPosition position; 3835 if (block->PredecessorCount() == 1) { 3836 gap_index = block->first_instruction_index(); 3837 position = Instruction::START; 3838 } else { 3839 DCHECK(pred->SuccessorCount() == 1); 3840 DCHECK(!code() 3841 ->InstructionAt(pred->last_instruction_index()) 3842 ->HasReferenceMap()); 3843 gap_index = pred->last_instruction_index(); 3844 position = Instruction::END; 3845 } 3846 data()->AddGapMove(gap_index, position, pred_op, cur_op); 3847 return gap_index; 3848} 3849 3850void LiveRangeConnector::ConnectRanges(Zone* local_zone) { 3851 DelayedInsertionMap delayed_insertion_map(local_zone); 3852 for (TopLevelLiveRange* top_range : data()->live_ranges()) { 3853 if (top_range == nullptr) continue; 3854 bool connect_spilled = top_range->IsSpilledOnlyInDeferredBlocks(); 3855 LiveRange* first_range = top_range; 3856 for (LiveRange *second_range = first_range->next(); second_range != nullptr; 3857 first_range = second_range, second_range = second_range->next()) { 3858 LifetimePosition pos = second_range->Start(); 3859 // Add gap move if the two live ranges touch and there is no block 3860 // boundary. 3861 if (second_range->spilled()) continue; 3862 if (first_range->End() != pos) continue; 3863 if (data()->IsBlockBoundary(pos) && 3864 !CanEagerlyResolveControlFlow(GetInstructionBlock(code(), pos))) { 3865 continue; 3866 } 3867 InstructionOperand prev_operand = first_range->GetAssignedOperand(); 3868 InstructionOperand cur_operand = second_range->GetAssignedOperand(); 3869 if (prev_operand.Equals(cur_operand)) continue; 3870 bool delay_insertion = false; 3871 Instruction::GapPosition gap_pos; 3872 int gap_index = pos.ToInstructionIndex(); 3873 if (connect_spilled && !prev_operand.IsAnyRegister() && 3874 cur_operand.IsAnyRegister()) { 3875 const InstructionBlock* block = code()->GetInstructionBlock(gap_index); 3876 DCHECK(block->IsDeferred()); 3877 // Performing a reload in this block, meaning the spill operand must 3878 // be defined here. 3879 top_range->GetListOfBlocksRequiringSpillOperands()->Add( 3880 block->rpo_number().ToInt()); 3881 } 3882 3883 if (pos.IsGapPosition()) { 3884 gap_pos = pos.IsStart() ? Instruction::START : Instruction::END; 3885 } else { 3886 if (pos.IsStart()) { 3887 delay_insertion = true; 3888 } else { 3889 gap_index++; 3890 } 3891 gap_pos = delay_insertion ? Instruction::END : Instruction::START; 3892 } 3893 // Reloads or spills for spilled in deferred blocks ranges must happen 3894 // only in deferred blocks. 3895 DCHECK_IMPLIES( 3896 connect_spilled && 3897 !(prev_operand.IsAnyRegister() && cur_operand.IsAnyRegister()), 3898 code()->GetInstructionBlock(gap_index)->IsDeferred()); 3899 3900 ParallelMove* move = 3901 code()->InstructionAt(gap_index)->GetOrCreateParallelMove( 3902 gap_pos, code_zone()); 3903 if (!delay_insertion) { 3904 move->AddMove(prev_operand, cur_operand); 3905 } else { 3906 delayed_insertion_map.insert( 3907 std::make_pair(std::make_pair(move, prev_operand), cur_operand)); 3908 } 3909 } 3910 } 3911 if (delayed_insertion_map.empty()) return; 3912 // Insert all the moves which should occur after the stored move. 3913 ZoneVector<MoveOperands*> to_insert(local_zone); 3914 ZoneVector<MoveOperands*> to_eliminate(local_zone); 3915 to_insert.reserve(4); 3916 to_eliminate.reserve(4); 3917 ParallelMove* moves = delayed_insertion_map.begin()->first.first; 3918 for (auto it = delayed_insertion_map.begin();; ++it) { 3919 bool done = it == delayed_insertion_map.end(); 3920 if (done || it->first.first != moves) { 3921 // Commit the MoveOperands for current ParallelMove. 3922 for (MoveOperands* move : to_eliminate) { 3923 move->Eliminate(); 3924 } 3925 for (MoveOperands* move : to_insert) { 3926 moves->push_back(move); 3927 } 3928 if (done) break; 3929 // Reset state. 3930 to_eliminate.clear(); 3931 to_insert.clear(); 3932 moves = it->first.first; 3933 } 3934 // Gather all MoveOperands for a single ParallelMove. 3935 MoveOperands* move = 3936 new (code_zone()) MoveOperands(it->first.second, it->second); 3937 moves->PrepareInsertAfter(move, &to_eliminate); 3938 to_insert.push_back(move); 3939 } 3940} 3941 3942 3943void LiveRangeConnector::CommitSpillsInDeferredBlocks( 3944 TopLevelLiveRange* range, LiveRangeBoundArray* array, Zone* temp_zone) { 3945 DCHECK(range->IsSpilledOnlyInDeferredBlocks()); 3946 DCHECK(!range->spilled()); 3947 3948 InstructionSequence* code = data()->code(); 3949 InstructionOperand spill_operand = range->GetSpillRangeOperand(); 3950 3951 TRACE("Live Range %d will be spilled only in deferred blocks.\n", 3952 range->vreg()); 3953 // If we have ranges that aren't spilled but require the operand on the stack, 3954 // make sure we insert the spill. 3955 for (const LiveRange* child = range; child != nullptr; 3956 child = child->next()) { 3957 for (const UsePosition* pos = child->first_pos(); pos != nullptr; 3958 pos = pos->next()) { 3959 if (pos->type() != UsePositionType::kRequiresSlot && !child->spilled()) 3960 continue; 3961 range->AddBlockRequiringSpillOperand( 3962 code->GetInstructionBlock(pos->pos().ToInstructionIndex()) 3963 ->rpo_number()); 3964 } 3965 } 3966 3967 ZoneQueue<int> worklist(temp_zone); 3968 3969 for (BitVector::Iterator iterator( 3970 range->GetListOfBlocksRequiringSpillOperands()); 3971 !iterator.Done(); iterator.Advance()) { 3972 worklist.push(iterator.Current()); 3973 } 3974 3975 ZoneSet<std::pair<RpoNumber, int>> done_moves(temp_zone); 3976 // Seek the deferred blocks that dominate locations requiring spill operands, 3977 // and spill there. We only need to spill at the start of such blocks. 3978 BitVector done_blocks( 3979 range->GetListOfBlocksRequiringSpillOperands()->length(), temp_zone); 3980 while (!worklist.empty()) { 3981 int block_id = worklist.front(); 3982 worklist.pop(); 3983 if (done_blocks.Contains(block_id)) continue; 3984 done_blocks.Add(block_id); 3985 InstructionBlock* spill_block = 3986 code->InstructionBlockAt(RpoNumber::FromInt(block_id)); 3987 3988 for (const RpoNumber& pred : spill_block->predecessors()) { 3989 const InstructionBlock* pred_block = code->InstructionBlockAt(pred); 3990 3991 if (pred_block->IsDeferred()) { 3992 worklist.push(pred_block->rpo_number().ToInt()); 3993 } else { 3994 LifetimePosition pred_end = 3995 LifetimePosition::InstructionFromInstructionIndex( 3996 pred_block->last_instruction_index()); 3997 3998 LiveRangeBound* bound = array->Find(pred_end); 3999 4000 InstructionOperand pred_op = bound->range_->GetAssignedOperand(); 4001 4002 RpoNumber spill_block_number = spill_block->rpo_number(); 4003 if (done_moves.find(std::make_pair( 4004 spill_block_number, range->vreg())) == done_moves.end()) { 4005 data()->AddGapMove(spill_block->first_instruction_index(), 4006 Instruction::GapPosition::START, pred_op, 4007 spill_operand); 4008 done_moves.insert(std::make_pair(spill_block_number, range->vreg())); 4009 spill_block->mark_needs_frame(); 4010 } 4011 } 4012 } 4013 } 4014} 4015 4016 4017} // namespace compiler 4018} // namespace internal 4019} // namespace v8 4020