register_allocator.cc revision 71175b7f19a4f6cf9cc264feafd820dbafa371fb
1a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray/*
2a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
3a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray *
4a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
5a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * you may not use this file except in compliance with the License.
6a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * You may obtain a copy of the License at
7a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray *
8a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
9a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray *
10a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * Unless required by applicable law or agreed to in writing, software
11a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
12a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * See the License for the specific language governing permissions and
14a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray * limitations under the License.
15a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray */
16a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
17a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray#include "register_allocator.h"
18a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
19e77493c7217efdd1a0ecef521a6845a13da0305bIan Rogers#include "base/bit_vector-inl.h"
20a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray#include "code_generator.h"
21a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray#include "ssa_liveness_analysis.h"
22a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
23a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraynamespace art {
24a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
25a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraystatic constexpr size_t kMaxLifetimePosition = -1;
2631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffraystatic constexpr size_t kDefaultNumberOfSpillSlots = 4;
27a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
2886dbb9a12119273039ce272b41c809fa548b37b6Nicolas GeoffrayRegisterAllocator::RegisterAllocator(ArenaAllocator* allocator,
2986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                     CodeGenerator* codegen,
3086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                     const SsaLivenessAnalysis& liveness)
31a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      : allocator_(allocator),
32a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        codegen_(codegen),
3386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        liveness_(liveness),
343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        unhandled_core_intervals_(allocator, 0),
353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        unhandled_fp_intervals_(allocator, 0),
363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        unhandled_(nullptr),
37a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        handled_(allocator, 0),
38a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        active_(allocator, 0),
39a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        inactive_(allocator, 0),
4071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        physical_register_intervals_(allocator, codegen->GetNumberOfCoreRegisters()),
413946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        temp_intervals_(allocator, 4),
4231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        spill_slots_(allocator, kDefaultNumberOfSpillSlots),
433946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        safepoints_(allocator, 0),
44a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        processing_core_registers_(false),
45a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        number_of_registers_(-1),
46a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        registers_array_(nullptr),
4771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray        blocked_registers_(codegen->GetBlockedCoreRegisters()),
483bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray        reserved_out_slots_(0),
493bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray        maximum_number_of_live_registers_(0) {
5071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  codegen->SetupBlockedRegisters();
5171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  physical_register_intervals_.SetSize(codegen->GetNumberOfCoreRegisters());
523946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // Always reserve for the current method and the graph's max out registers.
533946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // TODO: compute it instead.
543946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  reserved_out_slots_ = 1 + codegen->GetGraph()->GetMaximumNumberOfOutVRegs();
55a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
56a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
5786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraybool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph,
5886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                                InstructionSet instruction_set) {
5986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (!Supports(instruction_set)) {
6086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return false;
6186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
6286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (size_t i = 0, e = graph.GetBlocks().Size(); i < e; ++i) {
6386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    for (HInstructionIterator it(graph.GetBlocks().Get(i)->GetInstructions());
6486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray         !it.Done();
6586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray         it.Advance()) {
6686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      HInstruction* current = it.Current();
67412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray      if (current->GetType() == Primitive::kPrimLong && instruction_set != kX86_64) return false;
6886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (current->GetType() == Primitive::kPrimFloat) return false;
6986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (current->GetType() == Primitive::kPrimDouble) return false;
7086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
7186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
7286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  return true;
7386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
7486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
7586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraystatic bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) {
763946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (interval == nullptr) return false;
7786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  bool is_core_register = (interval->GetType() != Primitive::kPrimDouble)
7886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      && (interval->GetType() != Primitive::kPrimFloat);
79a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  return processing_core_registers == is_core_register;
80a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
81a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
8286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::AllocateRegisters() {
8386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  AllocateRegistersInternal();
8486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  Resolve();
8586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
8686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (kIsDebugBuild) {
8786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    processing_core_registers_ = true;
8886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    ValidateInternal(true);
8986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    processing_core_registers_ = false;
9086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    ValidateInternal(true);
9186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
9286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
9386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
9486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::BlockRegister(Location location,
9586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                      size_t start,
9686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                      size_t end,
9786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                      Primitive::Type type) {
9856b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray  int reg = location.reg();
9986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  LiveInterval* interval = physical_register_intervals_.Get(reg);
10086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (interval == nullptr) {
10186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    interval = LiveInterval::MakeFixedInterval(allocator_, reg, type);
10286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    physical_register_intervals_.Put(reg, interval);
10386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    inactive_.Add(interval);
10486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
10586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  DCHECK(interval->GetRegister() == reg);
10686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  interval->AddRange(start, end);
10786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
10886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
10986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::AllocateRegistersInternal() {
1103946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // Iterate post-order, to ensure the list is sorted, and the last added interval
1113946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // is the one with the lowest start position.
1123946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (HLinearPostOrderIterator it(liveness_); !it.Done(); it.Advance()) {
1133946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    HBasicBlock* block = it.Current();
1143946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    for (HBackwardInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
1153946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      ProcessInstruction(it.Current());
1163946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
1173946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
1183946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      ProcessInstruction(it.Current());
1193946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
1203946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
121a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
1223946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  number_of_registers_ = codegen_->GetNumberOfCoreRegisters();
123a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
1243946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  processing_core_registers_ = true;
1253946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  unhandled_ = &unhandled_core_intervals_;
1263946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  LinearScan();
127a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
1283946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  inactive_.Reset();
1293946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  active_.Reset();
1303946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  handled_.Reset();
131a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
1323946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  number_of_registers_ = codegen_->GetNumberOfFloatingPointRegisters();
1333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
1343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  processing_core_registers_ = false;
1353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  unhandled_ = &unhandled_fp_intervals_;
1363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // TODO: Enable FP register allocation.
1373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  DCHECK(unhandled_->IsEmpty());
1383946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  LinearScan();
1393946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray}
14086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
1413946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffrayvoid RegisterAllocator::ProcessInstruction(HInstruction* instruction) {
1423946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  LocationSummary* locations = instruction->GetLocations();
1433946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  size_t position = instruction->GetLifetimePosition();
1443946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
1453946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (locations == nullptr) return;
1463946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
1473946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // Create synthesized intervals for temporaries.
1483946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (size_t i = 0; i < locations->GetTempCount(); ++i) {
1493946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    Location temp = locations->GetTemp(i);
1503946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    if (temp.IsRegister()) {
1513946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      BlockRegister(temp, position, position + 1, Primitive::kPrimInt);
1523946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    } else {
15301ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      LiveInterval* interval = LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimInt);
1543946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      temp_intervals_.Add(interval);
1553946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      interval->AddRange(position, position + 1);
1563946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      unhandled_core_intervals_.Add(interval);
157a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
158a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
15986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
1603bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  bool core_register = (instruction->GetType() != Primitive::kPrimDouble)
1613bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      && (instruction->GetType() != Primitive::kPrimFloat);
1623bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray
1633bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  GrowableArray<LiveInterval*>& unhandled = core_register
1643bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      ? unhandled_core_intervals_
1653bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      : unhandled_fp_intervals_;
1663bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray
1673946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (locations->CanCall()) {
1683bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    if (!instruction->IsSuspendCheck()) {
1693bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      codegen_->MarkNotLeaf();
1703bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    }
1713946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    safepoints_.Add(instruction);
1723bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    if (locations->OnlyCallsOnSlowPath()) {
1733bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // We add a synthesized range at this position to record the live registers
1743bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // at this position. Ideally, we could just update the safepoints when locations
1753bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // are updated, but we currently need to know the full stack size before updating
1763bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // locations (because of parameters and the fact that we don't have a frame pointer).
1773bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // And knowing the full stack size requires to know the maximum number of live
1783bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // registers at calls in slow paths.
1793bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // By adding the following interval in the algorithm, we can compute this
1803bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // maximum before updating locations.
1813bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      LiveInterval* interval = LiveInterval::MakeSlowPathInterval(allocator_, instruction);
1823bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      interval->AddRange(position, position + 1);
1833bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      unhandled.Add(interval);
1843bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    }
1853bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  }
1863bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray
1873bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  if (locations->WillCall()) {
1883946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    // Block all registers.
1893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) {
19056b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray      BlockRegister(Location::RegisterLocation(i),
1913946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray                    position,
1923946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray                    position + 1,
1933946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray                    Primitive::kPrimInt);
1943946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
1953946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
1963946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
1973946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (size_t i = 0; i < instruction->InputCount(); ++i) {
1983946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    Location input = locations->InAt(i);
1993946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    if (input.IsRegister()) {
2003946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      BlockRegister(input, position, position + 1, instruction->InputAt(i)->GetType());
2013946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
2023946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
2033946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
2043946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  LiveInterval* current = instruction->GetLiveInterval();
2053946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (current == nullptr) return;
2063946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
2077690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  DCHECK(unhandled.IsEmpty() || current->StartsBeforeOrAt(unhandled.Peek()));
2083946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // Some instructions define their output in fixed register/stack slot. We need
2093946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // to ensure we know these locations before doing register allocation. For a
2103946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // given register, we create an interval that covers these locations. The register
2113946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // will be unavailable at these locations when trying to allocate one for an
2123946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // interval.
2133946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  //
2143946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // The backwards walking ensures the ranges are ordered on increasing start positions.
2153946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  Location output = locations->Out();
2163946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (output.IsRegister()) {
2173946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    // Shift the interval's start by one to account for the blocked register.
2183946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    current->SetFrom(position + 1);
21956b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray    current->SetRegister(output.reg());
2203946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    BlockRegister(output, position, position + 1, instruction->GetType());
2213946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) {
2223946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    current->SetSpillSlot(output.GetStackIndex());
2233946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
2243946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
2253946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // If needed, add interval to the list of unhandled intervals.
2263946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (current->HasSpillSlot() || instruction->IsConstant()) {
2273946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    // Split before first register use.
2283946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    size_t first_register_use = current->FirstRegisterUse();
2293946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    if (first_register_use != kNoLifetime) {
2307690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray      LiveInterval* split = Split(current, first_register_use);
2313946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      // Don't add direclty to `unhandled`, it needs to be sorted and the start
2323946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      // of this new interval might be after intervals already in the list.
2333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      AddSorted(&unhandled, split);
2343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    } else {
2353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      // Nothing to do, we won't allocate a register for this value.
2363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
2373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  } else {
2387690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray    DCHECK(unhandled.IsEmpty() || current->StartsBeforeOrAt(unhandled.Peek()));
2393946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    unhandled.Add(current);
2403946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
241a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
242a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
24331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffrayclass AllRangesIterator : public ValueObject {
24431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray public:
24531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  explicit AllRangesIterator(LiveInterval* interval)
24631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      : current_interval_(interval),
24731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        current_range_(interval->GetFirstRange()) {}
24831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
24931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  bool Done() const { return current_interval_ == nullptr; }
25031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveRange* CurrentRange() const { return current_range_; }
25131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveInterval* CurrentInterval() const { return current_interval_; }
25231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
25331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  void Advance() {
25431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    current_range_ = current_range_->GetNext();
25531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    if (current_range_ == nullptr) {
25631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      current_interval_ = current_interval_->GetNextSibling();
25731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      if (current_interval_ != nullptr) {
25831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        current_range_ = current_interval_->GetFirstRange();
25931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      }
26031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    }
26131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  }
26231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
26331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray private:
26431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveInterval* current_interval_;
26531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveRange* current_range_;
26631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
26731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(AllRangesIterator);
26831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray};
26931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
27086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraybool RegisterAllocator::ValidateInternal(bool log_fatal_on_failure) const {
27186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // To simplify unit testing, we eagerly create the array of intervals, and
27286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // call the helper method.
27386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  GrowableArray<LiveInterval*> intervals(allocator_, 0);
27486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) {
27586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
27686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (ShouldProcess(processing_core_registers_, instruction->GetLiveInterval())) {
27786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      intervals.Add(instruction->GetLiveInterval());
27886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
27986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
28086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
28186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (size_t i = 0, e = physical_register_intervals_.Size(); i < e; ++i) {
28286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    LiveInterval* fixed = physical_register_intervals_.Get(i);
28386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (fixed != nullptr && ShouldProcess(processing_core_registers_, fixed)) {
28486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      intervals.Add(fixed);
28586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
28686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
28786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
2883946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (size_t i = 0, e = temp_intervals_.Size(); i < e; ++i) {
2893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    LiveInterval* temp = temp_intervals_.Get(i);
2903946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    if (ShouldProcess(processing_core_registers_, temp)) {
2913946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      intervals.Add(temp);
2923946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
2933946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
2943946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
2953946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  return ValidateIntervals(intervals, spill_slots_.Size(), reserved_out_slots_, *codegen_,
2963946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray                           allocator_, processing_core_registers_, log_fatal_on_failure);
29786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
29886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
29931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffraybool RegisterAllocator::ValidateIntervals(const GrowableArray<LiveInterval*>& intervals,
30031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray                                          size_t number_of_spill_slots,
3013946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray                                          size_t number_of_out_slots,
302a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                                          const CodeGenerator& codegen,
303a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                                          ArenaAllocator* allocator,
304a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                                          bool processing_core_registers,
305a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                                          bool log_fatal_on_failure) {
306a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  size_t number_of_registers = processing_core_registers
307a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      ? codegen.GetNumberOfCoreRegisters()
308a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      : codegen.GetNumberOfFloatingPointRegisters();
30931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  GrowableArray<ArenaBitVector*> liveness_of_values(
31031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      allocator, number_of_registers + number_of_spill_slots);
311a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
312a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // Allocate a bit vector per register. A live interval that has a register
313a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // allocated will populate the associated bit vector based on its live ranges.
31431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  for (size_t i = 0; i < number_of_registers + number_of_spill_slots; ++i) {
31531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    liveness_of_values.Add(new (allocator) ArenaBitVector(allocator, 0, true));
316a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
317a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
31831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  for (size_t i = 0, e = intervals.Size(); i < e; ++i) {
31931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    for (AllRangesIterator it(intervals.Get(i)); !it.Done(); it.Advance()) {
32031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      LiveInterval* current = it.CurrentInterval();
32186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      HInstruction* defined_by = current->GetParent()->GetDefinedBy();
32286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (current->GetParent()->HasSpillSlot()
32386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray           // Parameters have their own stack slot.
32486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray           && !(defined_by != nullptr && defined_by->IsParameterValue())) {
3253946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        BitVector* liveness_of_spill_slot = liveness_of_values.Get(number_of_registers
3263946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray            + current->GetParent()->GetSpillSlot() / kVRegSize
3273946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray            - number_of_out_slots);
32831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
32931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray          if (liveness_of_spill_slot->IsBitSet(j)) {
33031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray            if (log_fatal_on_failure) {
33131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray              std::ostringstream message;
33231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray              message << "Spill slot conflict at " << j;
33331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray              LOG(FATAL) << message.str();
33431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray            } else {
33531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray              return false;
33631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray            }
33731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray          } else {
33831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray            liveness_of_spill_slot->SetBit(j);
33931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray          }
34031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        }
341a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      }
34231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
34331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      if (current->HasRegister()) {
34431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        BitVector* liveness_of_register = liveness_of_values.Get(current->GetRegister());
34531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
34631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray          if (liveness_of_register->IsBitSet(j)) {
347a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray            if (log_fatal_on_failure) {
348a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              std::ostringstream message;
3493946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray              message << "Register conflict at " << j << " ";
3503946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray              if (defined_by != nullptr) {
3513946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray                message << "(" << defined_by->DebugName() << ")";
3523946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray              }
3533946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray              message << "for ";
354a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              if (processing_core_registers) {
355a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                codegen.DumpCoreRegister(message, current->GetRegister());
356a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              } else {
357a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                codegen.DumpFloatingPointRegister(message, current->GetRegister());
358a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              }
359a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              LOG(FATAL) << message.str();
360a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray            } else {
361a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              return false;
362a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray            }
363a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray          } else {
36431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray            liveness_of_register->SetBit(j);
365a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray          }
366a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        }
36731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      }
36831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    }
369a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
370a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  return true;
371a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
372a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
37386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::DumpInterval(std::ostream& stream, LiveInterval* interval) const {
374a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  interval->Dump(stream);
375a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  stream << ": ";
376a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  if (interval->HasRegister()) {
377a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (processing_core_registers_) {
37886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      codegen_->DumpCoreRegister(stream, interval->GetRegister());
379a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    } else {
38086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      codegen_->DumpFloatingPointRegister(stream, interval->GetRegister());
381a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
382a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  } else {
383a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    stream << "spilled";
384a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
385a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  stream << std::endl;
386a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
387a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
388a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// By the book implementation of a linear scan register allocator.
389a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffrayvoid RegisterAllocator::LinearScan() {
3903946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  while (!unhandled_->IsEmpty()) {
391a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (1) Remove interval with the lowest start position from unhandled.
3923946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    LiveInterval* current = unhandled_->Pop();
3933946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    DCHECK(!current->IsFixed() && !current->HasSpillSlot());
394a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    size_t position = current->GetStart();
395a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
396a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (2) Remove currently active intervals that are dead at this position.
397a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    //     Move active intervals that have a lifetime hole at this position
398a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    //     to inactive.
399a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    for (size_t i = 0; i < active_.Size(); ++i) {
400a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      LiveInterval* interval = active_.Get(i);
401a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      if (interval->IsDeadAt(position)) {
402a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        active_.Delete(interval);
403a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        --i;
404a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        handled_.Add(interval);
405a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      } else if (!interval->Covers(position)) {
406a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        active_.Delete(interval);
407a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        --i;
408a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        inactive_.Add(interval);
409a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      }
410a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
411a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
412a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (3) Remove currently inactive intervals that are dead at this position.
413a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    //     Move inactive intervals that cover this position to active.
414a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    for (size_t i = 0; i < inactive_.Size(); ++i) {
415a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      LiveInterval* interval = inactive_.Get(i);
416a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      if (interval->IsDeadAt(position)) {
417a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        inactive_.Delete(interval);
418a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        --i;
419a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        handled_.Add(interval);
420a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      } else if (interval->Covers(position)) {
421a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        inactive_.Delete(interval);
422a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        --i;
423a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        active_.Add(interval);
424a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      }
425a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
426a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
4273bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    if (current->IsSlowPathSafepoint()) {
4283bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // Synthesized interval to record the maximum number of live registers
4293bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // at safepoints. No need to allocate a register for it.
4303bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      maximum_number_of_live_registers_ =
4313bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray          std::max(maximum_number_of_live_registers_, active_.Size());
4323bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      continue;
4333bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    }
4343bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray
435a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (4) Try to find an available register.
436a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    bool success = TryAllocateFreeReg(current);
437a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
438a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (5) If no register could be found, we need to spill.
439a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (!success) {
440a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      success = AllocateBlockedReg(current);
441a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
442a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
443a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (6) If the interval had a register allocated, add it to the list of active
444a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    //     intervals.
445a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (success) {
446a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      active_.Add(current);
447a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
448a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
449a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
450a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
451a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// Find a free register. If multiple are found, pick the register that
452a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// is free the longest.
453a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraybool RegisterAllocator::TryAllocateFreeReg(LiveInterval* current) {
454a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  size_t* free_until = registers_array_;
455a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
456a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // First set all registers to be free.
457a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0; i < number_of_registers_; ++i) {
458a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    free_until[i] = kMaxLifetimePosition;
459a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
460a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
461a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // For each inactive interval, set its register to be free until
462a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // the next intersection with `current`.
463a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // Thanks to SSA, this should only be needed for intervals
464a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // that are the result of a split.
465a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
466a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    LiveInterval* inactive = inactive_.Get(i);
467a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    DCHECK(inactive->HasRegister());
468a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    size_t next_intersection = inactive->FirstIntersectionWith(current);
469a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (next_intersection != kNoLifetime) {
470aac0f39a3501a7f7dd04b2342c2a16961969f139Nicolas Geoffray      free_until[inactive->GetRegister()] =
471aac0f39a3501a7f7dd04b2342c2a16961969f139Nicolas Geoffray          std::min(free_until[inactive->GetRegister()], next_intersection);
472a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
473a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
474a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
47586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // For each active interval, set its register to not free.
47686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (size_t i = 0, e = active_.Size(); i < e; ++i) {
47786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    LiveInterval* interval = active_.Get(i);
47886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    DCHECK(interval->HasRegister());
47986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    free_until[interval->GetRegister()] = 0;
48086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
48186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
482a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  int reg = -1;
4833946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (current->HasRegister()) {
4843946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    // Some instructions have a fixed register output.
4853946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    reg = current->GetRegister();
4863946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    DCHECK_NE(free_until[reg], 0u);
4873946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  } else {
48801ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    int hint = current->FindFirstRegisterHint(free_until);
48901ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    if (hint != kNoRegister) {
49001ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      DCHECK(!IsBlocked(hint));
49101ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      reg = hint;
49201ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    } else {
49301ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      // Pick the register that is free the longest.
49401ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      for (size_t i = 0; i < number_of_registers_; ++i) {
49501ef345767ea609417fc511e42007705c9667546Nicolas Geoffray        if (IsBlocked(i)) continue;
49601ef345767ea609417fc511e42007705c9667546Nicolas Geoffray        if (reg == -1 || free_until[i] > free_until[reg]) {
49701ef345767ea609417fc511e42007705c9667546Nicolas Geoffray          reg = i;
49801ef345767ea609417fc511e42007705c9667546Nicolas Geoffray          if (free_until[i] == kMaxLifetimePosition) break;
49901ef345767ea609417fc511e42007705c9667546Nicolas Geoffray        }
5003946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      }
501a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
502a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
503a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
504a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // If we could not find a register, we need to spill.
505a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  if (reg == -1 || free_until[reg] == 0) {
506a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return false;
507a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
508a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
509a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  current->SetRegister(reg);
510a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  if (!current->IsDeadAt(free_until[reg])) {
511a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // If the register is only available for a subset of live ranges
512a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // covered by `current`, split `current` at the position where
513a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // the register is not available anymore.
514a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    LiveInterval* split = Split(current, free_until[reg]);
515a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    DCHECK(split != nullptr);
5163946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    AddSorted(unhandled_, split);
517a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
518a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  return true;
519a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
520a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
521a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraybool RegisterAllocator::IsBlocked(int reg) const {
522a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // TODO: This only works for core registers and needs to be adjusted for
523a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // floating point registers.
524a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  DCHECK(processing_core_registers_);
525a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  return blocked_registers_[reg];
526a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
527a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
528a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// Find the register that is used the last, and spill the interval
529a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// that holds it. If the first use of `current` is after that register
530a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// we spill `current` instead.
531a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraybool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
532a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  size_t first_register_use = current->FirstRegisterUse();
533412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  if (first_register_use == kNoLifetime) {
53431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    AllocateSpillSlotFor(current);
535a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return false;
536a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
537a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
538a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // First set all registers as not being used.
539a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  size_t* next_use = registers_array_;
540a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0; i < number_of_registers_; ++i) {
541a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    next_use[i] = kMaxLifetimePosition;
542a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
543a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
544a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // For each active interval, find the next use of its register after the
545a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // start of current.
546a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0, e = active_.Size(); i < e; ++i) {
547a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    LiveInterval* active = active_.Get(i);
548a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    DCHECK(active->HasRegister());
54986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (active->IsFixed()) {
55086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      next_use[active->GetRegister()] = current->GetStart();
55186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    } else {
55286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      size_t use = active->FirstRegisterUseAfter(current->GetStart());
55386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (use != kNoLifetime) {
55486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        next_use[active->GetRegister()] = use;
55586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
556a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
557a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
558a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
559a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // For each inactive interval, find the next use of its register after the
560a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // start of current.
561a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // Thanks to SSA, this should only be needed for intervals
562a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // that are the result of a split.
563a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
564a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    LiveInterval* inactive = inactive_.Get(i);
565a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    DCHECK(inactive->HasRegister());
56686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    size_t next_intersection = inactive->FirstIntersectionWith(current);
56786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (next_intersection != kNoLifetime) {
56886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (inactive->IsFixed()) {
56986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        next_use[inactive->GetRegister()] =
57086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            std::min(next_intersection, next_use[inactive->GetRegister()]);
57186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      } else {
57286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        size_t use = inactive->FirstRegisterUseAfter(current->GetStart());
57386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        if (use != kNoLifetime) {
57486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          next_use[inactive->GetRegister()] = std::min(use, next_use[inactive->GetRegister()]);
57586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        }
57686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
577a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
578a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
579a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
580a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // Pick the register that is used the last.
581a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  int reg = -1;
582a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0; i < number_of_registers_; ++i) {
583a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (IsBlocked(i)) continue;
584a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (reg == -1 || next_use[i] > next_use[reg]) {
585a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      reg = i;
586a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      if (next_use[i] == kMaxLifetimePosition) break;
587a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
588a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
589a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
590a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  if (first_register_use >= next_use[reg]) {
591a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // If the first use of that instruction is after the last use of the found
592a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // register, we split this interval just before its first register use.
59331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    AllocateSpillSlotFor(current);
5947690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray    LiveInterval* split = Split(current, first_register_use);
5953946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    AddSorted(unhandled_, split);
596a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return false;
597a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  } else {
598a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // Use this register and spill the active and inactives interval that
599a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // have that register.
600a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    current->SetRegister(reg);
601a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
602a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    for (size_t i = 0, e = active_.Size(); i < e; ++i) {
603a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      LiveInterval* active = active_.Get(i);
604a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      if (active->GetRegister() == reg) {
60586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        DCHECK(!active->IsFixed());
606a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        LiveInterval* split = Split(active, current->GetStart());
607a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        active_.DeleteAt(i);
608a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        handled_.Add(active);
6093946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        AddSorted(unhandled_, split);
610a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        break;
611a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      }
612a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
613a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
614a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    for (size_t i = 0; i < inactive_.Size(); ++i) {
615a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      LiveInterval* inactive = inactive_.Get(i);
616a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      if (inactive->GetRegister() == reg) {
61786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        size_t next_intersection = inactive->FirstIntersectionWith(current);
61886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        if (next_intersection != kNoLifetime) {
61986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          if (inactive->IsFixed()) {
62086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            LiveInterval* split = Split(current, next_intersection);
6213946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray            AddSorted(unhandled_, split);
62286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          } else {
62386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            LiveInterval* split = Split(inactive, current->GetStart());
62486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            inactive_.DeleteAt(i);
62586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            handled_.Add(inactive);
6263946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray            AddSorted(unhandled_, split);
62786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            --i;
62886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          }
62986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        }
630a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      }
631a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
632a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
633a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return true;
634a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
635a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
636a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
6373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffrayvoid RegisterAllocator::AddSorted(GrowableArray<LiveInterval*>* array, LiveInterval* interval) {
63886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  size_t insert_at = 0;
6393946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (size_t i = array->Size(); i > 0; --i) {
6403946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    LiveInterval* current = array->Get(i - 1);
641a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (current->StartsAfter(interval)) {
64286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      insert_at = i;
643a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      break;
644a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
645a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
6463946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  array->InsertAt(insert_at, interval);
647a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
648a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
649a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas GeoffrayLiveInterval* RegisterAllocator::Split(LiveInterval* interval, size_t position) {
650a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  DCHECK(position >= interval->GetStart());
651a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  DCHECK(!interval->IsDeadAt(position));
652a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  if (position == interval->GetStart()) {
653a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // Spill slot will be allocated when handling `interval` again.
654a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    interval->ClearRegister();
655a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return interval;
656a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  } else {
657a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    LiveInterval* new_interval = interval->SplitAt(position);
658a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return new_interval;
659a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
660a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
661a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
66231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffrayvoid RegisterAllocator::AllocateSpillSlotFor(LiveInterval* interval) {
66331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveInterval* parent = interval->GetParent();
66431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
66531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  // An instruction gets a spill slot for its entire lifetime. If the parent
66631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  // of this interval already has a spill slot, there is nothing to do.
66731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  if (parent->HasSpillSlot()) {
66831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    return;
66931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  }
67031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
67186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HInstruction* defined_by = parent->GetDefinedBy();
67286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (defined_by->IsParameterValue()) {
67386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Parameters have their own stack slot.
67486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    parent->SetSpillSlot(codegen_->GetStackSlotOfParameter(defined_by->AsParameterValue()));
67586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
67686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
67786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
67896f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray  if (defined_by->IsConstant()) {
67996f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray    // Constants don't need a spill slot.
68096f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray    return;
68196f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray  }
68296f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray
68331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveInterval* last_sibling = interval;
68431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  while (last_sibling->GetNextSibling() != nullptr) {
68531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    last_sibling = last_sibling->GetNextSibling();
68631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  }
68731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  size_t end = last_sibling->GetEnd();
68831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
689412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  // Find an available spill slot.
690412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  size_t slot = 0;
691412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  for (size_t e = spill_slots_.Size(); slot < e; ++slot) {
692412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    // We check if it is less rather than less or equal because the parallel move
693412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    // resolver does not work when a single spill slot needs to be exchanged with
694412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    // a double spill slot. The strict comparison avoids needing to exchange these
695412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    // locations at the same lifetime position.
696412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    if (spill_slots_.Get(slot) < parent->GetStart()
697412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray        && (slot == (e - 1) || spill_slots_.Get(slot + 1) < parent->GetStart())) {
698412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray      break;
699412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    }
700412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  }
701412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray
70201ef345767ea609417fc511e42007705c9667546Nicolas Geoffray  if (parent->NeedsTwoSpillSlots()) {
7033c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    if (slot == spill_slots_.Size()) {
7043c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      // We need a new spill slot.
7053c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Add(end);
7063c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Add(end);
7073c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    } else if (slot == spill_slots_.Size() - 1) {
7083c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Put(slot, end);
7093c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Add(end);
7103c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    } else {
7113c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Put(slot, end);
7123c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Put(slot + 1, end);
71331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    }
71431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  } else {
7153c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    if (slot == spill_slots_.Size()) {
7163c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      // We need a new spill slot.
7173c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Add(end);
7183c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    } else {
7193c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Put(slot, end);
7203c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    }
72131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  }
72231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
7233946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  parent->SetSpillSlot((slot + reserved_out_slots_) * kVRegSize);
72486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
72586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
72686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray// We create a special marker for inputs moves to differentiate them from
72786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray// moves created during resolution. They must be different instructions
72886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray// because the input moves work on the assumption that the interval moves
72986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray// have been executed.
73086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraystatic constexpr size_t kInputMoveLifetimePosition = 0;
73186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraystatic bool IsInputMove(HInstruction* instruction) {
73286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  return instruction->GetLifetimePosition() == kInputMoveLifetimePosition;
73386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
73486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
7352a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffraystatic bool IsValidDestination(Location destination) {
7362a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray  return destination.IsRegister() || destination.IsStackSlot() || destination.IsDoubleStackSlot();
7372a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray}
7382a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray
739740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffrayvoid RegisterAllocator::AddInputMoveFor(HInstruction* user,
74086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                        Location source,
74186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                        Location destination) const {
7422a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray  DCHECK(IsValidDestination(destination));
74386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (source.Equals(destination)) return;
74486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
745740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  DCHECK(user->AsPhi() == nullptr);
74686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
747740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  HInstruction* previous = user->GetPrevious();
74886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HParallelMove* move = nullptr;
74986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (previous == nullptr
75086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      || previous->AsParallelMove() == nullptr
75186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      || !IsInputMove(previous)) {
75286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = new (allocator_) HParallelMove(allocator_);
75386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move->SetLifetimePosition(kInputMoveLifetimePosition);
754740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray    user->GetBlock()->InsertInstructionBefore(move, user);
75586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  } else {
75686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = previous->AsParallelMove();
75786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
75886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  DCHECK(IsInputMove(move));
759740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  move->AddMove(new (allocator_) MoveOperands(source, destination, nullptr));
76086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
76186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
76286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertParallelMoveAt(size_t position,
763740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray                                             HInstruction* instruction,
76486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                             Location source,
76586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                             Location destination) const {
7662a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray  DCHECK(IsValidDestination(destination));
76786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (source.Equals(destination)) return;
76886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
76986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HInstruction* at = liveness_.GetInstructionFromPosition(position / 2);
77086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (at == nullptr) {
77186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Block boundary, don't no anything the connection of split siblings will handle it.
77286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
77386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
77486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HParallelMove* move;
77586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if ((position & 1) == 1) {
77686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Move must happen after the instruction.
77786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    DCHECK(!at->IsControlFlow());
77886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = at->GetNext()->AsParallelMove();
779e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray    // This is a parallel move for connecting siblings in a same block. We need to
780e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray    // differentiate it with moves for connecting blocks, and input moves.
78126a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray    if (move == nullptr || IsInputMove(move) || move->GetLifetimePosition() > position) {
78286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      move = new (allocator_) HParallelMove(allocator_);
78386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      move->SetLifetimePosition(position);
78486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      at->GetBlock()->InsertInstructionBefore(move, at->GetNext());
78586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
78686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  } else {
78786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Move must happen before the instruction.
78886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HInstruction* previous = at->GetPrevious();
78926a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray    if (previous != nullptr && previous->IsParallelMove() && IsInputMove(previous)) {
790e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray      // This is a parallel move for connecting siblings in a same block. We need to
79126a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray      // differentiate it with input moves.
79226a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray      at = previous;
79326a25ef62a13f409f941aa39825a51b4d6f0f047Nicolas Geoffray      previous = previous->GetPrevious();
79486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
795740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray    if (previous == nullptr
796740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray        || !previous->IsParallelMove()
797740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray        || previous->GetLifetimePosition() != position) {
798740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray      // If the previous is a parallel move, then its position must be lower
799740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray      // than the given `position`: it was added just after the non-parallel
800740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray      // move instruction that precedes `instruction`.
801740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray      DCHECK(previous == nullptr
802740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray             || !previous->IsParallelMove()
803740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray             || previous->GetLifetimePosition() < position);
80486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      move = new (allocator_) HParallelMove(allocator_);
80586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      move->SetLifetimePosition(position);
80686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      at->GetBlock()->InsertInstructionBefore(move, at);
80786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    } else {
80886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      move = previous->AsParallelMove();
80986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
81086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
81101ef345767ea609417fc511e42007705c9667546Nicolas Geoffray  DCHECK_EQ(move->GetLifetimePosition(), position);
812740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
81386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
81486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
81586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block,
816740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray                                                   HInstruction* instruction,
81786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                                   Location source,
81886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                                   Location destination) const {
8192a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray  DCHECK(IsValidDestination(destination));
82086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (source.Equals(destination)) return;
82186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
82286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  DCHECK_EQ(block->GetSuccessors().Size(), 1u);
82386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HInstruction* last = block->GetLastInstruction();
824360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  // We insert moves at exit for phi predecessors and connecting blocks.
825360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  // A block ending with an if cannot branch to a block with phis because
826360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  // we do not allow critical edges. It can also not connect
827360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  // a split interval between two blocks: the move has to happen in the successor.
828360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  DCHECK(!last->IsIf());
82986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HInstruction* previous = last->GetPrevious();
83086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HParallelMove* move;
831e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // This is a parallel move for connecting blocks. We need to differentiate
832e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // it with moves for connecting siblings in a same block, and output moves.
833740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  if (previous == nullptr || !previous->IsParallelMove()
834e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray      || previous->AsParallelMove()->GetLifetimePosition() != block->GetLifetimeEnd()) {
83586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = new (allocator_) HParallelMove(allocator_);
836e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray    move->SetLifetimePosition(block->GetLifetimeEnd());
83786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    block->InsertInstructionBefore(move, last);
83886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  } else {
83986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = previous->AsParallelMove();
84086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
841740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
84286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
84386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
84486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertParallelMoveAtEntryOf(HBasicBlock* block,
845740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray                                                    HInstruction* instruction,
84686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                                    Location source,
84786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                                    Location destination) const {
8482a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray  DCHECK(IsValidDestination(destination));
84986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (source.Equals(destination)) return;
85086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
85186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HInstruction* first = block->GetFirstInstruction();
85286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HParallelMove* move = first->AsParallelMove();
853e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // This is a parallel move for connecting blocks. We need to differentiate
854e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // it with moves for connecting siblings in a same block, and input moves.
855e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  if (move == nullptr || move->GetLifetimePosition() != block->GetLifetimeStart()) {
85686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = new (allocator_) HParallelMove(allocator_);
85786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move->SetLifetimePosition(block->GetLifetimeStart());
85886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    block->InsertInstructionBefore(move, first);
85986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
860740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
86186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
86286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
86386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertMoveAfter(HInstruction* instruction,
86486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                        Location source,
86586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                        Location destination) const {
8662a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray  DCHECK(IsValidDestination(destination));
86786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (source.Equals(destination)) return;
86886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
86986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (instruction->AsPhi() != nullptr) {
870740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray    InsertParallelMoveAtEntryOf(instruction->GetBlock(), instruction, source, destination);
87186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
87286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
87386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
874e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  size_t position = instruction->GetLifetimePosition() + 1;
87586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HParallelMove* move = instruction->GetNext()->AsParallelMove();
876e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // This is a parallel move for moving the output of an instruction. We need
877e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // to differentiate with input moves, moves for connecting siblings in a
878e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // and moves for connecting blocks.
879e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  if (move == nullptr || move->GetLifetimePosition() != position) {
88086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = new (allocator_) HParallelMove(allocator_);
881e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray    move->SetLifetimePosition(position);
88286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    instruction->GetBlock()->InsertInstructionBefore(move, instruction->GetNext());
88386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
884740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
88586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
88686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
88786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::ConnectSiblings(LiveInterval* interval) {
88886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  LiveInterval* current = interval;
88986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (current->HasSpillSlot() && current->HasRegister()) {
89086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // We spill eagerly, so move must be at definition.
89186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    InsertMoveAfter(interval->GetDefinedBy(),
89256b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray                    Location::RegisterLocation(interval->GetRegister()),
89301ef345767ea609417fc511e42007705c9667546Nicolas Geoffray                    interval->NeedsTwoSpillSlots()
894412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray                        ? Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot())
895412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray                        : Location::StackSlot(interval->GetParent()->GetSpillSlot()));
89686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
89786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  UsePosition* use = current->GetFirstUse();
89886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
89986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Walk over all siblings, updating locations of use positions, and
90086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // connecting them when they are adjacent.
90186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  do {
90201ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    Location source = current->ToLocation();
90386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
90486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Walk over all uses covered by this interval, and update the location
90586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // information.
90686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    while (use != nullptr && use->GetPosition() <= current->GetEnd()) {
9073946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      LocationSummary* locations = use->GetUser()->GetLocations();
9083946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      if (use->GetIsEnvironment()) {
9093946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        locations->SetEnvironmentAt(use->GetInputIndex(), source);
9103946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      } else {
91186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        Location expected_location = locations->InAt(use->GetInputIndex());
91286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        if (expected_location.IsUnallocated()) {
91386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          locations->SetInAt(use->GetInputIndex(), source);
9142a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray        } else if (!expected_location.IsConstant()) {
91586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          AddInputMoveFor(use->GetUser(), source, expected_location);
91686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        }
91786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
91886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      use = use->GetNext();
91986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
92086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
92186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // If the next interval starts just after this one, and has a register,
92286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // insert a move.
92386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    LiveInterval* next_sibling = current->GetNextSibling();
92486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (next_sibling != nullptr
92586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        && next_sibling->HasRegister()
92686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        && current->GetEnd() == next_sibling->GetStart()) {
92701ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      Location destination = next_sibling->ToLocation();
928740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray      InsertParallelMoveAt(current->GetEnd(), interval->GetDefinedBy(), source, destination);
92986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
9303946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
9313946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    // At each safepoint, we record stack and register information.
9323946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    for (size_t i = 0, e = safepoints_.Size(); i < e; ++i) {
9333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      HInstruction* safepoint = safepoints_.Get(i);
9343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      size_t position = safepoint->GetLifetimePosition();
9353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      LocationSummary* locations = safepoint->GetLocations();
9363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      if (!current->Covers(position)) continue;
9373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
9383bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      if ((current->GetType() == Primitive::kPrimNot) && current->GetParent()->HasSpillSlot()) {
9393946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        locations->SetStackBit(current->GetParent()->GetSpillSlot() / kVRegSize);
9403946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      }
9413946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
9423946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      switch (source.GetKind()) {
9433946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        case Location::kRegister: {
9443bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray          locations->AddLiveRegister(source);
9453946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          if (current->GetType() == Primitive::kPrimNot) {
94656b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray            locations->SetRegisterBit(source.reg());
9473946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          }
9483946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          break;
9493946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        }
9503946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        case Location::kStackSlot:  // Fall-through
9513946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        case Location::kDoubleStackSlot:  // Fall-through
9523946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        case Location::kConstant: {
9533946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          // Nothing to do.
9543946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          break;
9553946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        }
9563946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        default: {
9573946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          LOG(FATAL) << "Unexpected location for object";
9583946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        }
9593946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      }
9603946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
96186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    current = next_sibling;
96286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  } while (current != nullptr);
96386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  DCHECK(use == nullptr);
96486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
96586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
96686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::ConnectSplitSiblings(LiveInterval* interval,
96786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                             HBasicBlock* from,
96886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                             HBasicBlock* to) const {
96986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (interval->GetNextSibling() == nullptr) {
97086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Nothing to connect. The whole range was allocated to the same location.
97186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
97286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
97386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
97486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  size_t from_position = from->GetLifetimeEnd() - 1;
9757690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  // When an instructions dies at entry of another, and the latter is the beginning
9767690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  // of a block, the register allocator ensures the former has a register
9777690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  // at block->GetLifetimeStart() + 1. Since this is at a block boundary, it must
9787690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  // must be handled in this method.
9797690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  size_t to_position = to->GetLifetimeStart() + 1;
98086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
98186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  LiveInterval* destination = nullptr;
98286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  LiveInterval* source = nullptr;
98386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
98486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  LiveInterval* current = interval;
98586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
98686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Check the intervals that cover `from` and `to`.
98786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  while ((current != nullptr) && (source == nullptr || destination == nullptr)) {
98886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (current->Covers(from_position)) {
98986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      DCHECK(source == nullptr);
99086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      source = current;
99186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
99286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (current->Covers(to_position)) {
99386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      DCHECK(destination == nullptr);
99486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      destination = current;
99586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
99686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
99786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    current = current->GetNextSibling();
99886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
99986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
100086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (destination == source) {
100186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Interval was not split.
100286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
100386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
100486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
10058ddb00ca935733f5d3b07816e5bb33d6cabe6ec4Nicolas Geoffray  DCHECK(destination != nullptr && source != nullptr);
10068ddb00ca935733f5d3b07816e5bb33d6cabe6ec4Nicolas Geoffray
100786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (!destination->HasRegister()) {
100886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Values are eagerly spilled. Spill slot already contains appropriate value.
100986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
101086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
101186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
101286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // If `from` has only one successor, we can put the moves at the exit of it. Otherwise
101386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // we need to put the moves at the entry of `to`.
101486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (from->GetSuccessors().Size() == 1) {
1015740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray    InsertParallelMoveAtExitOf(from,
1016740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray                               interval->GetParent()->GetDefinedBy(),
101701ef345767ea609417fc511e42007705c9667546Nicolas Geoffray                               source->ToLocation(),
101801ef345767ea609417fc511e42007705c9667546Nicolas Geoffray                               destination->ToLocation());
101986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  } else {
102086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    DCHECK_EQ(to->GetPredecessors().Size(), 1u);
1021740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray    InsertParallelMoveAtEntryOf(to,
1022740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray                                interval->GetParent()->GetDefinedBy(),
102301ef345767ea609417fc511e42007705c9667546Nicolas Geoffray                                source->ToLocation(),
102401ef345767ea609417fc511e42007705c9667546Nicolas Geoffray                                destination->ToLocation());
102586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
102686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
102786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
102886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::Resolve() {
10293bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  codegen_->ComputeFrameSize(
10303bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      spill_slots_.Size(), maximum_number_of_live_registers_, reserved_out_slots_);
103186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
103286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Adjust the Out Location of instructions.
103386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // TODO: Use pointers of Location inside LiveInterval to avoid doing another iteration.
103486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) {
103586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
103686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    LiveInterval* current = instruction->GetLiveInterval();
103786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    LocationSummary* locations = instruction->GetLocations();
103886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    Location location = locations->Out();
103986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (instruction->AsParameterValue() != nullptr) {
104086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      // Now that we know the frame size, adjust the parameter's location.
104186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (location.IsStackSlot()) {
104286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
104386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        current->SetSpillSlot(location.GetStackIndex());
104486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        locations->SetOut(location);
104586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      } else if (location.IsDoubleStackSlot()) {
104686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
104786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        current->SetSpillSlot(location.GetStackIndex());
104886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        locations->SetOut(location);
104986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      } else if (current->HasSpillSlot()) {
105086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        current->SetSpillSlot(current->GetSpillSlot() + codegen_->GetFrameSize());
105186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
105286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
105386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
105401ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    Location source = current->ToLocation();
105586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
105686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (location.IsUnallocated()) {
105786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (location.GetPolicy() == Location::kSameAsFirstInput) {
105886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        locations->SetInAt(0, source);
105986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
106086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      locations->SetOut(source);
106186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    } else {
106286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      DCHECK(source.Equals(location));
106386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
106486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
106586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
106686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Connect siblings.
106786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) {
106886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
106986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    ConnectSiblings(instruction->GetLiveInterval());
107086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
107186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
107286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Resolve non-linear control flow across branches. Order does not matter.
107386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (HLinearOrderIterator it(liveness_); !it.Done(); it.Advance()) {
107486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HBasicBlock* block = it.Current();
107586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    BitVector* live = liveness_.GetLiveInSet(*block);
107686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    for (uint32_t idx : live->Indexes()) {
107786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      HInstruction* current = liveness_.GetInstructionFromSsaIndex(idx);
107886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      LiveInterval* interval = current->GetLiveInterval();
107986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
108086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        ConnectSplitSiblings(interval, block->GetPredecessors().Get(i), block);
108186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
108286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
108386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
108486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
108586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Resolve phi inputs. Order does not matter.
108686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (HLinearOrderIterator it(liveness_); !it.Done(); it.Advance()) {
108786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HBasicBlock* current = it.Current();
108886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    for (HInstructionIterator it(current->GetPhis()); !it.Done(); it.Advance()) {
108986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      HInstruction* phi = it.Current();
109086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      for (size_t i = 0, e = current->GetPredecessors().Size(); i < e; ++i) {
109186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        HBasicBlock* predecessor = current->GetPredecessors().Get(i);
109286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        DCHECK_EQ(predecessor->GetSuccessors().Size(), 1u);
109386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        HInstruction* input = phi->InputAt(i);
109401ef345767ea609417fc511e42007705c9667546Nicolas Geoffray        Location source = input->GetLiveInterval()->GetLocationAt(
109501ef345767ea609417fc511e42007705c9667546Nicolas Geoffray            predecessor->GetLifetimeEnd() - 1);
109601ef345767ea609417fc511e42007705c9667546Nicolas Geoffray        Location destination = phi->GetLiveInterval()->ToLocation();
1097740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray        InsertParallelMoveAtExitOf(predecessor, nullptr, source, destination);
109886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
109986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
110086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
11013946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
11023946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // Assign temp locations.
11033946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  HInstruction* current = nullptr;
11043946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  size_t temp_index = 0;
11053946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (size_t i = 0; i < temp_intervals_.Size(); ++i) {
11063946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    LiveInterval* temp = temp_intervals_.Get(i);
110701ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    HInstruction* at = liveness_.GetTempUser(temp);
110801ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    if (at != current) {
11093946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      temp_index = 0;
111001ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      current = at;
11113946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
111201ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    LocationSummary* locations = at->GetLocations();
11133946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    locations->SetTempAt(
111456b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray        temp_index++, Location::RegisterLocation(temp->GetRegister()));
11153946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
111631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray}
111731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
1118a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}  // namespace art
1119