1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "register_allocator.h" 18 19 #include "code_generator.h" 20 #include "ssa_liveness_analysis.h" 21 22 namespace art { 23 24 static constexpr size_t kMaxLifetimePosition = -1; 25 static constexpr size_t kDefaultNumberOfSpillSlots = 4; 26 27 RegisterAllocator::RegisterAllocator(ArenaAllocator* allocator, 28 CodeGenerator* codegen, 29 const SsaLivenessAnalysis& liveness) 30 : allocator_(allocator), 31 codegen_(codegen), 32 liveness_(liveness), 33 unhandled_(allocator, 0), 34 handled_(allocator, 0), 35 active_(allocator, 0), 36 inactive_(allocator, 0), 37 physical_register_intervals_(allocator, codegen->GetNumberOfRegisters()), 38 spill_slots_(allocator, kDefaultNumberOfSpillSlots), 39 processing_core_registers_(false), 40 number_of_registers_(-1), 41 registers_array_(nullptr), 42 blocked_registers_(allocator->AllocArray<bool>(codegen->GetNumberOfRegisters())) { 43 codegen->SetupBlockedRegisters(blocked_registers_); 44 physical_register_intervals_.SetSize(codegen->GetNumberOfRegisters()); 45 } 46 47 bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph, 48 InstructionSet instruction_set) { 49 if (!Supports(instruction_set)) { 50 return false; 51 } 52 for (size_t i = 0, e = graph.GetBlocks().Size(); i < e; ++i) { 53 for (HInstructionIterator it(graph.GetBlocks().Get(i)->GetInstructions()); 54 !it.Done(); 55 it.Advance()) { 56 HInstruction* current = it.Current(); 57 if (current->NeedsEnvironment()) return false; 58 if (current->GetType() == Primitive::kPrimLong && instruction_set != kX86_64) return false; 59 if (current->GetType() == Primitive::kPrimFloat) return false; 60 if (current->GetType() == Primitive::kPrimDouble) return false; 61 } 62 } 63 return true; 64 } 65 66 static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) { 67 bool is_core_register = (interval->GetType() != Primitive::kPrimDouble) 68 && (interval->GetType() != Primitive::kPrimFloat); 69 return processing_core_registers == is_core_register; 70 } 71 72 void RegisterAllocator::AllocateRegisters() { 73 processing_core_registers_ = true; 74 AllocateRegistersInternal(); 75 processing_core_registers_ = false; 76 AllocateRegistersInternal(); 77 78 Resolve(); 79 80 if (kIsDebugBuild) { 81 processing_core_registers_ = true; 82 ValidateInternal(true); 83 processing_core_registers_ = false; 84 ValidateInternal(true); 85 } 86 } 87 88 void RegisterAllocator::BlockRegister(Location location, 89 size_t start, 90 size_t end, 91 Primitive::Type type) { 92 int reg = location.reg().RegId(); 93 LiveInterval* interval = physical_register_intervals_.Get(reg); 94 if (interval == nullptr) { 95 interval = LiveInterval::MakeFixedInterval(allocator_, reg, type); 96 physical_register_intervals_.Put(reg, interval); 97 inactive_.Add(interval); 98 } 99 DCHECK(interval->GetRegister() == reg); 100 interval->AddRange(start, end); 101 } 102 103 // TODO: make the register allocator understand instructions like HCondition 104 // that may not need to be materialized. It doesn't need to allocate any 105 // registers for it. 106 void RegisterAllocator::AllocateRegistersInternal() { 107 number_of_registers_ = processing_core_registers_ 108 ? codegen_->GetNumberOfCoreRegisters() 109 : codegen_->GetNumberOfFloatingPointRegisters(); 110 111 registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_); 112 113 // Iterate post-order, to ensure the list is sorted, and the last added interval 114 // is the one with the lowest start position. 115 for (size_t i = liveness_.GetNumberOfSsaValues(); i > 0; --i) { 116 HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i - 1); 117 LiveInterval* current = instruction->GetLiveInterval(); 118 if (ShouldProcess(processing_core_registers_, current)) { 119 DCHECK(unhandled_.IsEmpty() || current->StartsBefore(unhandled_.Peek())); 120 121 LocationSummary* locations = instruction->GetLocations(); 122 if (locations->GetTempCount() != 0) { 123 // Note that we already filtered out instructions requiring temporaries in 124 // RegisterAllocator::CanAllocateRegistersFor. 125 LOG(FATAL) << "Unimplemented"; 126 } 127 128 // Some instructions define their output in fixed register/stack slot. We need 129 // to ensure we know these locations before doing register allocation. For a 130 // given register, we create an interval that covers these locations. The register 131 // will be unavailable at these locations when trying to allocate one for an 132 // interval. 133 // 134 // The backwards walking ensures the ranges are ordered on increasing start positions. 135 Location output = locations->Out(); 136 size_t position = instruction->GetLifetimePosition(); 137 if (output.IsRegister()) { 138 // Shift the interval's start by one to account for the blocked register. 139 current->SetFrom(position + 1); 140 current->SetRegister(output.reg().RegId()); 141 BlockRegister(output, position, position + 1, instruction->GetType()); 142 } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) { 143 current->SetSpillSlot(output.GetStackIndex()); 144 } 145 for (size_t i = 0; i < instruction->InputCount(); ++i) { 146 Location input = locations->InAt(i); 147 if (input.IsRegister()) { 148 BlockRegister(input, position, position + 1, instruction->InputAt(i)->GetType()); 149 } 150 } 151 152 // Add the interval to the correct list. 153 if (current->HasRegister()) { 154 DCHECK(instruction->IsParameterValue()); 155 inactive_.Add(current); 156 } else if (current->HasSpillSlot() || instruction->IsConstant()) { 157 // Split before first register use. 158 size_t first_register_use = current->FirstRegisterUse(); 159 if (first_register_use != kNoLifetime) { 160 LiveInterval* split = Split(current, first_register_use - 1); 161 // Don't add direclty to `unhandled_`, it needs to be sorted and the start 162 // of this new interval might be after intervals already in the list. 163 AddToUnhandled(split); 164 } else { 165 // Nothing to do, we won't allocate a register for this value. 166 } 167 } else { 168 DCHECK(unhandled_.IsEmpty() || current->StartsBefore(unhandled_.Peek())); 169 unhandled_.Add(current); 170 } 171 } 172 } 173 174 LinearScan(); 175 } 176 177 class AllRangesIterator : public ValueObject { 178 public: 179 explicit AllRangesIterator(LiveInterval* interval) 180 : current_interval_(interval), 181 current_range_(interval->GetFirstRange()) {} 182 183 bool Done() const { return current_interval_ == nullptr; } 184 LiveRange* CurrentRange() const { return current_range_; } 185 LiveInterval* CurrentInterval() const { return current_interval_; } 186 187 void Advance() { 188 current_range_ = current_range_->GetNext(); 189 if (current_range_ == nullptr) { 190 current_interval_ = current_interval_->GetNextSibling(); 191 if (current_interval_ != nullptr) { 192 current_range_ = current_interval_->GetFirstRange(); 193 } 194 } 195 } 196 197 private: 198 LiveInterval* current_interval_; 199 LiveRange* current_range_; 200 201 DISALLOW_COPY_AND_ASSIGN(AllRangesIterator); 202 }; 203 204 bool RegisterAllocator::ValidateInternal(bool log_fatal_on_failure) const { 205 // To simplify unit testing, we eagerly create the array of intervals, and 206 // call the helper method. 207 GrowableArray<LiveInterval*> intervals(allocator_, 0); 208 for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) { 209 HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i); 210 if (ShouldProcess(processing_core_registers_, instruction->GetLiveInterval())) { 211 intervals.Add(instruction->GetLiveInterval()); 212 } 213 } 214 215 for (size_t i = 0, e = physical_register_intervals_.Size(); i < e; ++i) { 216 LiveInterval* fixed = physical_register_intervals_.Get(i); 217 if (fixed != nullptr && ShouldProcess(processing_core_registers_, fixed)) { 218 intervals.Add(fixed); 219 } 220 } 221 222 return ValidateIntervals(intervals, spill_slots_.Size(), *codegen_, allocator_, 223 processing_core_registers_, log_fatal_on_failure); 224 } 225 226 bool RegisterAllocator::ValidateIntervals(const GrowableArray<LiveInterval*>& intervals, 227 size_t number_of_spill_slots, 228 const CodeGenerator& codegen, 229 ArenaAllocator* allocator, 230 bool processing_core_registers, 231 bool log_fatal_on_failure) { 232 size_t number_of_registers = processing_core_registers 233 ? codegen.GetNumberOfCoreRegisters() 234 : codegen.GetNumberOfFloatingPointRegisters(); 235 GrowableArray<ArenaBitVector*> liveness_of_values( 236 allocator, number_of_registers + number_of_spill_slots); 237 238 // Allocate a bit vector per register. A live interval that has a register 239 // allocated will populate the associated bit vector based on its live ranges. 240 for (size_t i = 0; i < number_of_registers + number_of_spill_slots; ++i) { 241 liveness_of_values.Add(new (allocator) ArenaBitVector(allocator, 0, true)); 242 } 243 244 for (size_t i = 0, e = intervals.Size(); i < e; ++i) { 245 for (AllRangesIterator it(intervals.Get(i)); !it.Done(); it.Advance()) { 246 LiveInterval* current = it.CurrentInterval(); 247 HInstruction* defined_by = current->GetParent()->GetDefinedBy(); 248 if (current->GetParent()->HasSpillSlot() 249 // Parameters have their own stack slot. 250 && !(defined_by != nullptr && defined_by->IsParameterValue())) { 251 BitVector* liveness_of_spill_slot = liveness_of_values.Get( 252 number_of_registers + current->GetParent()->GetSpillSlot() / kVRegSize); 253 for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) { 254 if (liveness_of_spill_slot->IsBitSet(j)) { 255 if (log_fatal_on_failure) { 256 std::ostringstream message; 257 message << "Spill slot conflict at " << j; 258 LOG(FATAL) << message.str(); 259 } else { 260 return false; 261 } 262 } else { 263 liveness_of_spill_slot->SetBit(j); 264 } 265 } 266 } 267 268 if (current->HasRegister()) { 269 BitVector* liveness_of_register = liveness_of_values.Get(current->GetRegister()); 270 for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) { 271 if (liveness_of_register->IsBitSet(j)) { 272 if (log_fatal_on_failure) { 273 std::ostringstream message; 274 message << "Register conflict at " << j << " for "; 275 if (processing_core_registers) { 276 codegen.DumpCoreRegister(message, current->GetRegister()); 277 } else { 278 codegen.DumpFloatingPointRegister(message, current->GetRegister()); 279 } 280 LOG(FATAL) << message.str(); 281 } else { 282 return false; 283 } 284 } else { 285 liveness_of_register->SetBit(j); 286 } 287 } 288 } 289 } 290 } 291 return true; 292 } 293 294 void RegisterAllocator::DumpInterval(std::ostream& stream, LiveInterval* interval) const { 295 interval->Dump(stream); 296 stream << ": "; 297 if (interval->HasRegister()) { 298 if (processing_core_registers_) { 299 codegen_->DumpCoreRegister(stream, interval->GetRegister()); 300 } else { 301 codegen_->DumpFloatingPointRegister(stream, interval->GetRegister()); 302 } 303 } else { 304 stream << "spilled"; 305 } 306 stream << std::endl; 307 } 308 309 // By the book implementation of a linear scan register allocator. 310 void RegisterAllocator::LinearScan() { 311 while (!unhandled_.IsEmpty()) { 312 // (1) Remove interval with the lowest start position from unhandled. 313 LiveInterval* current = unhandled_.Pop(); 314 DCHECK(!current->IsFixed() && !current->HasRegister() && !current->HasSpillSlot()); 315 size_t position = current->GetStart(); 316 317 // (2) Remove currently active intervals that are dead at this position. 318 // Move active intervals that have a lifetime hole at this position 319 // to inactive. 320 for (size_t i = 0; i < active_.Size(); ++i) { 321 LiveInterval* interval = active_.Get(i); 322 if (interval->IsDeadAt(position)) { 323 active_.Delete(interval); 324 --i; 325 handled_.Add(interval); 326 } else if (!interval->Covers(position)) { 327 active_.Delete(interval); 328 --i; 329 inactive_.Add(interval); 330 } 331 } 332 333 // (3) Remove currently inactive intervals that are dead at this position. 334 // Move inactive intervals that cover this position to active. 335 for (size_t i = 0; i < inactive_.Size(); ++i) { 336 LiveInterval* interval = inactive_.Get(i); 337 if (interval->IsDeadAt(position)) { 338 inactive_.Delete(interval); 339 --i; 340 handled_.Add(interval); 341 } else if (interval->Covers(position)) { 342 inactive_.Delete(interval); 343 --i; 344 active_.Add(interval); 345 } 346 } 347 348 // (4) Try to find an available register. 349 bool success = TryAllocateFreeReg(current); 350 351 // (5) If no register could be found, we need to spill. 352 if (!success) { 353 success = AllocateBlockedReg(current); 354 } 355 356 // (6) If the interval had a register allocated, add it to the list of active 357 // intervals. 358 if (success) { 359 active_.Add(current); 360 } 361 } 362 } 363 364 // Find a free register. If multiple are found, pick the register that 365 // is free the longest. 366 bool RegisterAllocator::TryAllocateFreeReg(LiveInterval* current) { 367 size_t* free_until = registers_array_; 368 369 // First set all registers to be free. 370 for (size_t i = 0; i < number_of_registers_; ++i) { 371 free_until[i] = kMaxLifetimePosition; 372 } 373 374 // For each inactive interval, set its register to be free until 375 // the next intersection with `current`. 376 // Thanks to SSA, this should only be needed for intervals 377 // that are the result of a split. 378 for (size_t i = 0, e = inactive_.Size(); i < e; ++i) { 379 LiveInterval* inactive = inactive_.Get(i); 380 DCHECK(inactive->HasRegister()); 381 size_t next_intersection = inactive->FirstIntersectionWith(current); 382 if (next_intersection != kNoLifetime) { 383 free_until[inactive->GetRegister()] = next_intersection; 384 } 385 } 386 387 // For each active interval, set its register to not free. 388 for (size_t i = 0, e = active_.Size(); i < e; ++i) { 389 LiveInterval* interval = active_.Get(i); 390 DCHECK(interval->HasRegister()); 391 free_until[interval->GetRegister()] = 0; 392 } 393 394 // Pick the register that is free the longest. 395 int reg = -1; 396 for (size_t i = 0; i < number_of_registers_; ++i) { 397 if (IsBlocked(i)) continue; 398 if (reg == -1 || free_until[i] > free_until[reg]) { 399 reg = i; 400 if (free_until[i] == kMaxLifetimePosition) break; 401 } 402 } 403 404 // If we could not find a register, we need to spill. 405 if (reg == -1 || free_until[reg] == 0) { 406 return false; 407 } 408 409 current->SetRegister(reg); 410 if (!current->IsDeadAt(free_until[reg])) { 411 // If the register is only available for a subset of live ranges 412 // covered by `current`, split `current` at the position where 413 // the register is not available anymore. 414 LiveInterval* split = Split(current, free_until[reg]); 415 DCHECK(split != nullptr); 416 AddToUnhandled(split); 417 } 418 return true; 419 } 420 421 bool RegisterAllocator::IsBlocked(int reg) const { 422 // TODO: This only works for core registers and needs to be adjusted for 423 // floating point registers. 424 DCHECK(processing_core_registers_); 425 return blocked_registers_[reg]; 426 } 427 428 // Find the register that is used the last, and spill the interval 429 // that holds it. If the first use of `current` is after that register 430 // we spill `current` instead. 431 bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) { 432 size_t first_register_use = current->FirstRegisterUse(); 433 if (first_register_use == kNoLifetime) { 434 AllocateSpillSlotFor(current); 435 return false; 436 } 437 438 // First set all registers as not being used. 439 size_t* next_use = registers_array_; 440 for (size_t i = 0; i < number_of_registers_; ++i) { 441 next_use[i] = kMaxLifetimePosition; 442 } 443 444 // For each active interval, find the next use of its register after the 445 // start of current. 446 for (size_t i = 0, e = active_.Size(); i < e; ++i) { 447 LiveInterval* active = active_.Get(i); 448 DCHECK(active->HasRegister()); 449 if (active->IsFixed()) { 450 next_use[active->GetRegister()] = current->GetStart(); 451 } else { 452 size_t use = active->FirstRegisterUseAfter(current->GetStart()); 453 if (use != kNoLifetime) { 454 next_use[active->GetRegister()] = use; 455 } 456 } 457 } 458 459 // For each inactive interval, find the next use of its register after the 460 // start of current. 461 // Thanks to SSA, this should only be needed for intervals 462 // that are the result of a split. 463 for (size_t i = 0, e = inactive_.Size(); i < e; ++i) { 464 LiveInterval* inactive = inactive_.Get(i); 465 DCHECK(inactive->HasRegister()); 466 size_t next_intersection = inactive->FirstIntersectionWith(current); 467 if (next_intersection != kNoLifetime) { 468 if (inactive->IsFixed()) { 469 next_use[inactive->GetRegister()] = 470 std::min(next_intersection, next_use[inactive->GetRegister()]); 471 } else { 472 size_t use = inactive->FirstRegisterUseAfter(current->GetStart()); 473 if (use != kNoLifetime) { 474 next_use[inactive->GetRegister()] = std::min(use, next_use[inactive->GetRegister()]); 475 } 476 } 477 } 478 } 479 480 // Pick the register that is used the last. 481 int reg = -1; 482 for (size_t i = 0; i < number_of_registers_; ++i) { 483 if (IsBlocked(i)) continue; 484 if (reg == -1 || next_use[i] > next_use[reg]) { 485 reg = i; 486 if (next_use[i] == kMaxLifetimePosition) break; 487 } 488 } 489 490 if (first_register_use >= next_use[reg]) { 491 // If the first use of that instruction is after the last use of the found 492 // register, we split this interval just before its first register use. 493 AllocateSpillSlotFor(current); 494 LiveInterval* split = Split(current, first_register_use - 1); 495 AddToUnhandled(split); 496 return false; 497 } else { 498 // Use this register and spill the active and inactives interval that 499 // have that register. 500 current->SetRegister(reg); 501 502 for (size_t i = 0, e = active_.Size(); i < e; ++i) { 503 LiveInterval* active = active_.Get(i); 504 if (active->GetRegister() == reg) { 505 DCHECK(!active->IsFixed()); 506 LiveInterval* split = Split(active, current->GetStart()); 507 active_.DeleteAt(i); 508 handled_.Add(active); 509 AddToUnhandled(split); 510 break; 511 } 512 } 513 514 for (size_t i = 0; i < inactive_.Size(); ++i) { 515 LiveInterval* inactive = inactive_.Get(i); 516 if (inactive->GetRegister() == reg) { 517 size_t next_intersection = inactive->FirstIntersectionWith(current); 518 if (next_intersection != kNoLifetime) { 519 if (inactive->IsFixed()) { 520 LiveInterval* split = Split(current, next_intersection); 521 AddToUnhandled(split); 522 } else { 523 LiveInterval* split = Split(inactive, current->GetStart()); 524 inactive_.DeleteAt(i); 525 handled_.Add(inactive); 526 AddToUnhandled(split); 527 --i; 528 } 529 } 530 } 531 } 532 533 return true; 534 } 535 } 536 537 void RegisterAllocator::AddToUnhandled(LiveInterval* interval) { 538 size_t insert_at = 0; 539 for (size_t i = unhandled_.Size(); i > 0; --i) { 540 LiveInterval* current = unhandled_.Get(i - 1); 541 if (current->StartsAfter(interval)) { 542 insert_at = i; 543 break; 544 } 545 } 546 unhandled_.InsertAt(insert_at, interval); 547 } 548 549 LiveInterval* RegisterAllocator::Split(LiveInterval* interval, size_t position) { 550 DCHECK(position >= interval->GetStart()); 551 DCHECK(!interval->IsDeadAt(position)); 552 if (position == interval->GetStart()) { 553 // Spill slot will be allocated when handling `interval` again. 554 interval->ClearRegister(); 555 return interval; 556 } else { 557 LiveInterval* new_interval = interval->SplitAt(position); 558 return new_interval; 559 } 560 } 561 562 static bool NeedTwoSpillSlot(Primitive::Type type) { 563 return type == Primitive::kPrimLong || type == Primitive::kPrimDouble; 564 } 565 566 void RegisterAllocator::AllocateSpillSlotFor(LiveInterval* interval) { 567 LiveInterval* parent = interval->GetParent(); 568 569 // An instruction gets a spill slot for its entire lifetime. If the parent 570 // of this interval already has a spill slot, there is nothing to do. 571 if (parent->HasSpillSlot()) { 572 return; 573 } 574 575 HInstruction* defined_by = parent->GetDefinedBy(); 576 if (defined_by->IsParameterValue()) { 577 // Parameters have their own stack slot. 578 parent->SetSpillSlot(codegen_->GetStackSlotOfParameter(defined_by->AsParameterValue())); 579 return; 580 } 581 582 if (defined_by->IsConstant()) { 583 // Constants don't need a spill slot. 584 return; 585 } 586 587 LiveInterval* last_sibling = interval; 588 while (last_sibling->GetNextSibling() != nullptr) { 589 last_sibling = last_sibling->GetNextSibling(); 590 } 591 size_t end = last_sibling->GetEnd(); 592 593 if (NeedTwoSpillSlot(parent->GetType())) { 594 AllocateTwoSpillSlots(parent, end); 595 } else { 596 AllocateOneSpillSlot(parent, end); 597 } 598 } 599 600 void RegisterAllocator::AllocateTwoSpillSlots(LiveInterval* parent, size_t end) { 601 // Find an available spill slot. 602 size_t slot = 0; 603 for (size_t e = spill_slots_.Size(); slot < e; ++slot) { 604 // We check if it is less rather than less or equal because the parallel move 605 // resolver does not work when a single spill slot needs to be exchanged with 606 // a double spill slot. The strict comparison avoids needing to exchange these 607 // locations at the same lifetime position. 608 if (spill_slots_.Get(slot) < parent->GetStart() 609 && (slot == (e - 1) || spill_slots_.Get(slot + 1) < parent->GetStart())) { 610 break; 611 } 612 } 613 614 if (slot == spill_slots_.Size()) { 615 // We need a new spill slot. 616 spill_slots_.Add(end); 617 spill_slots_.Add(end); 618 } else if (slot == spill_slots_.Size() - 1) { 619 spill_slots_.Put(slot, end); 620 spill_slots_.Add(end); 621 } else { 622 spill_slots_.Put(slot, end); 623 spill_slots_.Put(slot + 1, end); 624 } 625 626 parent->SetSpillSlot(slot * kVRegSize); 627 } 628 629 void RegisterAllocator::AllocateOneSpillSlot(LiveInterval* parent, size_t end) { 630 // Find an available spill slot. 631 size_t slot = 0; 632 for (size_t e = spill_slots_.Size(); slot < e; ++slot) { 633 if (spill_slots_.Get(slot) <= parent->GetStart()) { 634 break; 635 } 636 } 637 638 if (slot == spill_slots_.Size()) { 639 // We need a new spill slot. 640 spill_slots_.Add(end); 641 } else { 642 spill_slots_.Put(slot, end); 643 } 644 645 parent->SetSpillSlot(slot * kVRegSize); 646 } 647 648 static Location ConvertToLocation(LiveInterval* interval) { 649 if (interval->HasRegister()) { 650 return Location::RegisterLocation(ManagedRegister(interval->GetRegister())); 651 } else { 652 HInstruction* defined_by = interval->GetParent()->GetDefinedBy(); 653 if (defined_by->IsConstant()) { 654 return defined_by->GetLocations()->Out(); 655 } else { 656 DCHECK(interval->GetParent()->HasSpillSlot()); 657 if (NeedTwoSpillSlot(interval->GetType())) { 658 return Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot()); 659 } else { 660 return Location::StackSlot(interval->GetParent()->GetSpillSlot()); 661 } 662 } 663 } 664 } 665 666 // We create a special marker for inputs moves to differentiate them from 667 // moves created during resolution. They must be different instructions 668 // because the input moves work on the assumption that the interval moves 669 // have been executed. 670 static constexpr size_t kInputMoveLifetimePosition = 0; 671 static bool IsInputMove(HInstruction* instruction) { 672 return instruction->GetLifetimePosition() == kInputMoveLifetimePosition; 673 } 674 675 void RegisterAllocator::AddInputMoveFor(HInstruction* instruction, 676 Location source, 677 Location destination) const { 678 if (source.Equals(destination)) return; 679 680 DCHECK(instruction->AsPhi() == nullptr); 681 682 HInstruction* previous = instruction->GetPrevious(); 683 HParallelMove* move = nullptr; 684 if (previous == nullptr 685 || previous->AsParallelMove() == nullptr 686 || !IsInputMove(previous)) { 687 move = new (allocator_) HParallelMove(allocator_); 688 move->SetLifetimePosition(kInputMoveLifetimePosition); 689 instruction->GetBlock()->InsertInstructionBefore(move, instruction); 690 } else { 691 move = previous->AsParallelMove(); 692 } 693 DCHECK(IsInputMove(move)); 694 move->AddMove(new (allocator_) MoveOperands(source, destination)); 695 } 696 697 void RegisterAllocator::InsertParallelMoveAt(size_t position, 698 Location source, 699 Location destination) const { 700 if (source.Equals(destination)) return; 701 702 HInstruction* at = liveness_.GetInstructionFromPosition(position / 2); 703 if (at == nullptr) { 704 // Block boundary, don't no anything the connection of split siblings will handle it. 705 return; 706 } 707 HParallelMove* move; 708 if ((position & 1) == 1) { 709 // Move must happen after the instruction. 710 DCHECK(!at->IsControlFlow()); 711 move = at->GetNext()->AsParallelMove(); 712 // This is a parallel move for connecting siblings in a same block. We need to 713 // differentiate it with moves for connecting blocks, and input moves. 714 if (move == nullptr || move->GetLifetimePosition() != position) { 715 move = new (allocator_) HParallelMove(allocator_); 716 move->SetLifetimePosition(position); 717 at->GetBlock()->InsertInstructionBefore(move, at->GetNext()); 718 } 719 } else { 720 // Move must happen before the instruction. 721 HInstruction* previous = at->GetPrevious(); 722 if (previous != nullptr && previous->AsParallelMove() != nullptr) { 723 // This is a parallel move for connecting siblings in a same block. We need to 724 // differentiate it with moves for connecting blocks, and input moves. 725 if (previous->GetLifetimePosition() != position) { 726 previous = previous->GetPrevious(); 727 } 728 } 729 if (previous == nullptr || previous->AsParallelMove() == nullptr) { 730 move = new (allocator_) HParallelMove(allocator_); 731 move->SetLifetimePosition(position); 732 at->GetBlock()->InsertInstructionBefore(move, at); 733 } else { 734 move = previous->AsParallelMove(); 735 } 736 } 737 move->AddMove(new (allocator_) MoveOperands(source, destination)); 738 } 739 740 void RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block, 741 Location source, 742 Location destination) const { 743 if (source.Equals(destination)) return; 744 745 DCHECK_EQ(block->GetSuccessors().Size(), 1u); 746 HInstruction* last = block->GetLastInstruction(); 747 HInstruction* previous = last->GetPrevious(); 748 HParallelMove* move; 749 // This is a parallel move for connecting blocks. We need to differentiate 750 // it with moves for connecting siblings in a same block, and output moves. 751 if (previous == nullptr || previous->AsParallelMove() == nullptr 752 || previous->AsParallelMove()->GetLifetimePosition() != block->GetLifetimeEnd()) { 753 move = new (allocator_) HParallelMove(allocator_); 754 move->SetLifetimePosition(block->GetLifetimeEnd()); 755 block->InsertInstructionBefore(move, last); 756 } else { 757 move = previous->AsParallelMove(); 758 } 759 move->AddMove(new (allocator_) MoveOperands(source, destination)); 760 } 761 762 void RegisterAllocator::InsertParallelMoveAtEntryOf(HBasicBlock* block, 763 Location source, 764 Location destination) const { 765 if (source.Equals(destination)) return; 766 767 HInstruction* first = block->GetFirstInstruction(); 768 HParallelMove* move = first->AsParallelMove(); 769 // This is a parallel move for connecting blocks. We need to differentiate 770 // it with moves for connecting siblings in a same block, and input moves. 771 if (move == nullptr || move->GetLifetimePosition() != block->GetLifetimeStart()) { 772 move = new (allocator_) HParallelMove(allocator_); 773 move->SetLifetimePosition(block->GetLifetimeStart()); 774 block->InsertInstructionBefore(move, first); 775 } 776 move->AddMove(new (allocator_) MoveOperands(source, destination)); 777 } 778 779 void RegisterAllocator::InsertMoveAfter(HInstruction* instruction, 780 Location source, 781 Location destination) const { 782 if (source.Equals(destination)) return; 783 784 if (instruction->AsPhi() != nullptr) { 785 InsertParallelMoveAtEntryOf(instruction->GetBlock(), source, destination); 786 return; 787 } 788 789 size_t position = instruction->GetLifetimePosition() + 1; 790 HParallelMove* move = instruction->GetNext()->AsParallelMove(); 791 // This is a parallel move for moving the output of an instruction. We need 792 // to differentiate with input moves, moves for connecting siblings in a 793 // and moves for connecting blocks. 794 if (move == nullptr || move->GetLifetimePosition() != position) { 795 move = new (allocator_) HParallelMove(allocator_); 796 move->SetLifetimePosition(position); 797 instruction->GetBlock()->InsertInstructionBefore(move, instruction->GetNext()); 798 } 799 move->AddMove(new (allocator_) MoveOperands(source, destination)); 800 } 801 802 void RegisterAllocator::ConnectSiblings(LiveInterval* interval) { 803 LiveInterval* current = interval; 804 if (current->HasSpillSlot() && current->HasRegister()) { 805 // We spill eagerly, so move must be at definition. 806 InsertMoveAfter(interval->GetDefinedBy(), 807 Location::RegisterLocation(ManagedRegister(interval->GetRegister())), 808 NeedTwoSpillSlot(interval->GetType()) 809 ? Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot()) 810 : Location::StackSlot(interval->GetParent()->GetSpillSlot())); 811 } 812 UsePosition* use = current->GetFirstUse(); 813 814 // Walk over all siblings, updating locations of use positions, and 815 // connecting them when they are adjacent. 816 do { 817 Location source = ConvertToLocation(current); 818 819 // Walk over all uses covered by this interval, and update the location 820 // information. 821 while (use != nullptr && use->GetPosition() <= current->GetEnd()) { 822 if (!use->GetIsEnvironment()) { 823 LocationSummary* locations = use->GetUser()->GetLocations(); 824 Location expected_location = locations->InAt(use->GetInputIndex()); 825 if (expected_location.IsUnallocated()) { 826 locations->SetInAt(use->GetInputIndex(), source); 827 } else { 828 AddInputMoveFor(use->GetUser(), source, expected_location); 829 } 830 } 831 use = use->GetNext(); 832 } 833 834 // If the next interval starts just after this one, and has a register, 835 // insert a move. 836 LiveInterval* next_sibling = current->GetNextSibling(); 837 if (next_sibling != nullptr 838 && next_sibling->HasRegister() 839 && current->GetEnd() == next_sibling->GetStart()) { 840 Location destination = ConvertToLocation(next_sibling); 841 InsertParallelMoveAt(current->GetEnd(), source, destination); 842 } 843 current = next_sibling; 844 } while (current != nullptr); 845 DCHECK(use == nullptr); 846 } 847 848 void RegisterAllocator::ConnectSplitSiblings(LiveInterval* interval, 849 HBasicBlock* from, 850 HBasicBlock* to) const { 851 if (interval->GetNextSibling() == nullptr) { 852 // Nothing to connect. The whole range was allocated to the same location. 853 return; 854 } 855 856 size_t from_position = from->GetLifetimeEnd() - 1; 857 size_t to_position = to->GetLifetimeStart(); 858 859 LiveInterval* destination = nullptr; 860 LiveInterval* source = nullptr; 861 862 LiveInterval* current = interval; 863 864 // Check the intervals that cover `from` and `to`. 865 while ((current != nullptr) && (source == nullptr || destination == nullptr)) { 866 if (current->Covers(from_position)) { 867 DCHECK(source == nullptr); 868 source = current; 869 } 870 if (current->Covers(to_position)) { 871 DCHECK(destination == nullptr); 872 destination = current; 873 } 874 875 current = current->GetNextSibling(); 876 } 877 878 if (destination == source) { 879 // Interval was not split. 880 return; 881 } 882 883 if (!destination->HasRegister()) { 884 // Values are eagerly spilled. Spill slot already contains appropriate value. 885 return; 886 } 887 888 // If `from` has only one successor, we can put the moves at the exit of it. Otherwise 889 // we need to put the moves at the entry of `to`. 890 if (from->GetSuccessors().Size() == 1) { 891 InsertParallelMoveAtExitOf(from, ConvertToLocation(source), ConvertToLocation(destination)); 892 } else { 893 DCHECK_EQ(to->GetPredecessors().Size(), 1u); 894 InsertParallelMoveAtEntryOf(to, ConvertToLocation(source), ConvertToLocation(destination)); 895 } 896 } 897 898 // Returns the location of `interval`, or siblings of `interval`, at `position`. 899 static Location FindLocationAt(LiveInterval* interval, size_t position) { 900 LiveInterval* current = interval; 901 while (!current->Covers(position)) { 902 current = current->GetNextSibling(); 903 DCHECK(current != nullptr); 904 } 905 return ConvertToLocation(current); 906 } 907 908 void RegisterAllocator::Resolve() { 909 codegen_->ComputeFrameSize(spill_slots_.Size()); 910 911 // Adjust the Out Location of instructions. 912 // TODO: Use pointers of Location inside LiveInterval to avoid doing another iteration. 913 for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) { 914 HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i); 915 LiveInterval* current = instruction->GetLiveInterval(); 916 LocationSummary* locations = instruction->GetLocations(); 917 Location location = locations->Out(); 918 if (instruction->AsParameterValue() != nullptr) { 919 // Now that we know the frame size, adjust the parameter's location. 920 if (location.IsStackSlot()) { 921 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize()); 922 current->SetSpillSlot(location.GetStackIndex()); 923 locations->SetOut(location); 924 } else if (location.IsDoubleStackSlot()) { 925 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize()); 926 current->SetSpillSlot(location.GetStackIndex()); 927 locations->SetOut(location); 928 } else if (current->HasSpillSlot()) { 929 current->SetSpillSlot(current->GetSpillSlot() + codegen_->GetFrameSize()); 930 } 931 } 932 933 Location source = ConvertToLocation(current); 934 935 if (location.IsUnallocated()) { 936 if (location.GetPolicy() == Location::kSameAsFirstInput) { 937 locations->SetInAt(0, source); 938 } 939 locations->SetOut(source); 940 } else { 941 DCHECK(source.Equals(location)); 942 } 943 } 944 945 // Connect siblings. 946 for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) { 947 HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i); 948 ConnectSiblings(instruction->GetLiveInterval()); 949 } 950 951 // Resolve non-linear control flow across branches. Order does not matter. 952 for (HLinearOrderIterator it(liveness_); !it.Done(); it.Advance()) { 953 HBasicBlock* block = it.Current(); 954 BitVector* live = liveness_.GetLiveInSet(*block); 955 for (uint32_t idx : live->Indexes()) { 956 HInstruction* current = liveness_.GetInstructionFromSsaIndex(idx); 957 LiveInterval* interval = current->GetLiveInterval(); 958 for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) { 959 ConnectSplitSiblings(interval, block->GetPredecessors().Get(i), block); 960 } 961 } 962 } 963 964 // Resolve phi inputs. Order does not matter. 965 for (HLinearOrderIterator it(liveness_); !it.Done(); it.Advance()) { 966 HBasicBlock* current = it.Current(); 967 for (HInstructionIterator it(current->GetPhis()); !it.Done(); it.Advance()) { 968 HInstruction* phi = it.Current(); 969 for (size_t i = 0, e = current->GetPredecessors().Size(); i < e; ++i) { 970 HBasicBlock* predecessor = current->GetPredecessors().Get(i); 971 DCHECK_EQ(predecessor->GetSuccessors().Size(), 1u); 972 HInstruction* input = phi->InputAt(i); 973 Location source = FindLocationAt(input->GetLiveInterval(), 974 predecessor->GetLastInstruction()->GetLifetimePosition()); 975 Location destination = ConvertToLocation(phi->GetLiveInterval()); 976 InsertParallelMoveAtExitOf(predecessor, source, destination); 977 } 978 } 979 } 980 } 981 982 } // namespace art 983