Home | History | Annotate | Download | only in optimizing
      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