register_allocator.cc revision c7dd295a4e0cc1d15c0c96088e55a85389bade74
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
19c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers#include <sstream>
20c7dd295a4e0cc1d15c0c96088e55a85389bade74Ian Rogers
21e77493c7217efdd1a0ecef521a6845a13da0305bIan Rogers#include "base/bit_vector-inl.h"
22a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray#include "code_generator.h"
23a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray#include "ssa_liveness_analysis.h"
24a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
25a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraynamespace art {
26a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
27a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraystatic constexpr size_t kMaxLifetimePosition = -1;
2831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffraystatic constexpr size_t kDefaultNumberOfSpillSlots = 4;
29a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
3086dbb9a12119273039ce272b41c809fa548b37b6Nicolas GeoffrayRegisterAllocator::RegisterAllocator(ArenaAllocator* allocator,
3186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                     CodeGenerator* codegen,
3286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                     const SsaLivenessAnalysis& liveness)
33a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      : allocator_(allocator),
34a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        codegen_(codegen),
3586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        liveness_(liveness),
363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        unhandled_core_intervals_(allocator, 0),
373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        unhandled_fp_intervals_(allocator, 0),
383946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        unhandled_(nullptr),
39a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        handled_(allocator, 0),
40a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        active_(allocator, 0),
41a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        inactive_(allocator, 0),
42102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray        physical_core_register_intervals_(allocator, codegen->GetNumberOfCoreRegisters()),
43102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray        physical_fp_register_intervals_(allocator, codegen->GetNumberOfFloatingPointRegisters()),
443946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        temp_intervals_(allocator, 4),
4531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        spill_slots_(allocator, kDefaultNumberOfSpillSlots),
463946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        safepoints_(allocator, 0),
47a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        processing_core_registers_(false),
48a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        number_of_registers_(-1),
49a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        registers_array_(nullptr),
50102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray        blocked_core_registers_(codegen->GetBlockedCoreRegisters()),
51102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray        blocked_fp_registers_(codegen->GetBlockedFloatingPointRegisters()),
523bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray        reserved_out_slots_(0),
533bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray        maximum_number_of_live_registers_(0) {
5471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray  codegen->SetupBlockedRegisters();
55102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  physical_core_register_intervals_.SetSize(codegen->GetNumberOfCoreRegisters());
56102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  physical_fp_register_intervals_.SetSize(codegen->GetNumberOfFloatingPointRegisters());
573946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // Always reserve for the current method and the graph's max out registers.
583946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // TODO: compute it instead.
593946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  reserved_out_slots_ = 1 + codegen->GetGraph()->GetMaximumNumberOfOutVRegs();
60a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
61a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
6286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraybool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph,
6386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                                InstructionSet instruction_set) {
6486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (!Supports(instruction_set)) {
6586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return false;
6686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
6786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (size_t i = 0, e = graph.GetBlocks().Size(); i < e; ++i) {
6886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    for (HInstructionIterator it(graph.GetBlocks().Get(i)->GetInstructions());
6986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray         !it.Done();
7086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray         it.Advance()) {
7186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      HInstruction* current = it.Current();
72412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray      if (current->GetType() == Primitive::kPrimLong && instruction_set != kX86_64) return false;
73102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      if ((current->GetType() == Primitive::kPrimFloat || current->GetType() == Primitive::kPrimDouble)
74102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray          && instruction_set != kX86_64) {
75102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray        return false;
76102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      }
7786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
7886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
7986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  return true;
8086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
8186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
8286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraystatic bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) {
833946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (interval == nullptr) return false;
8486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  bool is_core_register = (interval->GetType() != Primitive::kPrimDouble)
8586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      && (interval->GetType() != Primitive::kPrimFloat);
86a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  return processing_core_registers == is_core_register;
87a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
88a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
8986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::AllocateRegisters() {
9086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  AllocateRegistersInternal();
9186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  Resolve();
9286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
9386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (kIsDebugBuild) {
9486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    processing_core_registers_ = true;
9586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    ValidateInternal(true);
9686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    processing_core_registers_ = false;
9786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    ValidateInternal(true);
9886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
9986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
10086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
10186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::BlockRegister(Location location,
10286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                      size_t start,
103102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray                                      size_t end) {
10456b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray  int reg = location.reg();
105102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  DCHECK(location.IsRegister() || location.IsFpuRegister());
106102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  LiveInterval* interval = location.IsRegister()
107102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      ? physical_core_register_intervals_.Get(reg)
108102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      : physical_fp_register_intervals_.Get(reg);
109102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  Primitive::Type type = location.IsRegister()
110102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      ? Primitive::kPrimInt
111102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      : Primitive::kPrimDouble;
11286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (interval == nullptr) {
11386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    interval = LiveInterval::MakeFixedInterval(allocator_, reg, type);
114102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    if (location.IsRegister()) {
115102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      physical_core_register_intervals_.Put(reg, interval);
116102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    } else {
117102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      physical_fp_register_intervals_.Put(reg, interval);
118102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    }
11986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
12086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  DCHECK(interval->GetRegister() == reg);
12186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  interval->AddRange(start, end);
12286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
12386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
12486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::AllocateRegistersInternal() {
1253946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // Iterate post-order, to ensure the list is sorted, and the last added interval
1263946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // is the one with the lowest start position.
1273946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (HLinearPostOrderIterator it(liveness_); !it.Done(); it.Advance()) {
1283946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    HBasicBlock* block = it.Current();
1293946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    for (HBackwardInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
1303946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      ProcessInstruction(it.Current());
1313946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
1323946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
1333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      ProcessInstruction(it.Current());
1343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
1353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
136a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
1373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  number_of_registers_ = codegen_->GetNumberOfCoreRegisters();
138a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
1393946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  processing_core_registers_ = true;
1403946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  unhandled_ = &unhandled_core_intervals_;
141102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  for (size_t i = 0, e = physical_core_register_intervals_.Size(); i < e; ++i) {
142102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    LiveInterval* fixed = physical_core_register_intervals_.Get(i);
143102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    if (fixed != nullptr) {
144102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      inactive_.Add(fixed);
145102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    }
146102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  }
1473946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  LinearScan();
148a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
149102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  size_t saved_maximum_number_of_live_registers = maximum_number_of_live_registers_;
150102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  maximum_number_of_live_registers_ = 0;
151102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray
1523946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  inactive_.Reset();
1533946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  active_.Reset();
1543946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  handled_.Reset();
155a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
1563946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  number_of_registers_ = codegen_->GetNumberOfFloatingPointRegisters();
1573946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
1583946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  processing_core_registers_ = false;
1593946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  unhandled_ = &unhandled_fp_intervals_;
160102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  for (size_t i = 0, e = physical_fp_register_intervals_.Size(); i < e; ++i) {
161102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    LiveInterval* fixed = physical_fp_register_intervals_.Get(i);
162102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    if (fixed != nullptr) {
163102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      inactive_.Add(fixed);
164102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    }
165102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  }
1663946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  LinearScan();
167102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  maximum_number_of_live_registers_ += saved_maximum_number_of_live_registers;
1683946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray}
16986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
1703946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffrayvoid RegisterAllocator::ProcessInstruction(HInstruction* instruction) {
1713946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  LocationSummary* locations = instruction->GetLocations();
1723946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  size_t position = instruction->GetLifetimePosition();
1733946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
1743946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (locations == nullptr) return;
1753946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
1763946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // Create synthesized intervals for temporaries.
1773946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (size_t i = 0; i < locations->GetTempCount(); ++i) {
1783946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    Location temp = locations->GetTemp(i);
1793946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    if (temp.IsRegister()) {
180102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      BlockRegister(temp, position, position + 1);
1813946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    } else {
182102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      DCHECK(temp.IsUnallocated());
18301ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      LiveInterval* interval = LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimInt);
1843946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      temp_intervals_.Add(interval);
1853946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      interval->AddRange(position, position + 1);
1863946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      unhandled_core_intervals_.Add(interval);
187a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
188a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
18986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
1903bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  bool core_register = (instruction->GetType() != Primitive::kPrimDouble)
1913bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      && (instruction->GetType() != Primitive::kPrimFloat);
1923bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray
1933946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (locations->CanCall()) {
1943bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    if (!instruction->IsSuspendCheck()) {
1953bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      codegen_->MarkNotLeaf();
1963bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    }
1973946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    safepoints_.Add(instruction);
1983bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    if (locations->OnlyCallsOnSlowPath()) {
1993bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // We add a synthesized range at this position to record the live registers
2003bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // at this position. Ideally, we could just update the safepoints when locations
2013bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // are updated, but we currently need to know the full stack size before updating
2023bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // locations (because of parameters and the fact that we don't have a frame pointer).
2033bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // And knowing the full stack size requires to know the maximum number of live
2043bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // registers at calls in slow paths.
2053bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // By adding the following interval in the algorithm, we can compute this
2063bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // maximum before updating locations.
2073bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      LiveInterval* interval = LiveInterval::MakeSlowPathInterval(allocator_, instruction);
2083bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      interval->AddRange(position, position + 1);
209102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      unhandled_core_intervals_.Add(interval);
210102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      unhandled_fp_intervals_.Add(interval);
2113bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    }
2123bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  }
2133bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray
2143bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  if (locations->WillCall()) {
2153946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    // Block all registers.
2163946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) {
21756b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray      BlockRegister(Location::RegisterLocation(i),
2183946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray                    position,
219102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray                    position + 1);
220102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    }
221102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    for (size_t i = 0; i < codegen_->GetNumberOfFloatingPointRegisters(); ++i) {
222102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      BlockRegister(Location::FpuRegisterLocation(i),
223102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray                    position,
224102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray                    position + 1);
2253946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
2263946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
2273946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
2283946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (size_t i = 0; i < instruction->InputCount(); ++i) {
2293946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    Location input = locations->InAt(i);
230102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    if (input.IsRegister() || input.IsFpuRegister()) {
231102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      BlockRegister(input, position, position + 1);
2323946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
2333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
2343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
2353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  LiveInterval* current = instruction->GetLiveInterval();
2363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (current == nullptr) return;
2373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
238102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  GrowableArray<LiveInterval*>& unhandled = core_register
239102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      ? unhandled_core_intervals_
240102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      : unhandled_fp_intervals_;
241102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray
2427690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  DCHECK(unhandled.IsEmpty() || current->StartsBeforeOrAt(unhandled.Peek()));
2433946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // Some instructions define their output in fixed register/stack slot. We need
2443946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // to ensure we know these locations before doing register allocation. For a
2453946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // given register, we create an interval that covers these locations. The register
2463946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // will be unavailable at these locations when trying to allocate one for an
2473946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // interval.
2483946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  //
2493946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // The backwards walking ensures the ranges are ordered on increasing start positions.
2503946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  Location output = locations->Out();
251102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  if (output.IsRegister() || output.IsFpuRegister()) {
2523946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    // Shift the interval's start by one to account for the blocked register.
2533946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    current->SetFrom(position + 1);
25456b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray    current->SetRegister(output.reg());
255102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    BlockRegister(output, position, position + 1);
2568e3964b766652a0478e8e0e303e8556c997675f1Nicolas Geoffray  } else if (!locations->OutputOverlapsWithInputs()) {
2578e3964b766652a0478e8e0e303e8556c997675f1Nicolas Geoffray    // Shift the interval's start by one to not interfere with the inputs.
2588e3964b766652a0478e8e0e303e8556c997675f1Nicolas Geoffray    current->SetFrom(position + 1);
2593946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) {
2603946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    current->SetSpillSlot(output.GetStackIndex());
2613946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
2623946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
2633946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // If needed, add interval to the list of unhandled intervals.
2643946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (current->HasSpillSlot() || instruction->IsConstant()) {
265c8147a76ed2f440f38329dc08ff889d393b5c535Nicolas Geoffray    // Split just before first register use.
2663946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    size_t first_register_use = current->FirstRegisterUse();
2673946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    if (first_register_use != kNoLifetime) {
268c8147a76ed2f440f38329dc08ff889d393b5c535Nicolas Geoffray      LiveInterval* split = Split(current, first_register_use - 1);
2693946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      // Don't add direclty to `unhandled`, it needs to be sorted and the start
2703946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      // of this new interval might be after intervals already in the list.
2713946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      AddSorted(&unhandled, split);
2723946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    } else {
2733946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      // Nothing to do, we won't allocate a register for this value.
2743946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
2753946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  } else {
2767690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray    DCHECK(unhandled.IsEmpty() || current->StartsBeforeOrAt(unhandled.Peek()));
2773946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    unhandled.Add(current);
2783946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
279a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
280a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
28131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffrayclass AllRangesIterator : public ValueObject {
28231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray public:
28331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  explicit AllRangesIterator(LiveInterval* interval)
28431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      : current_interval_(interval),
28531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        current_range_(interval->GetFirstRange()) {}
28631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
28731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  bool Done() const { return current_interval_ == nullptr; }
28831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveRange* CurrentRange() const { return current_range_; }
28931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveInterval* CurrentInterval() const { return current_interval_; }
29031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
29131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  void Advance() {
29231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    current_range_ = current_range_->GetNext();
29331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    if (current_range_ == nullptr) {
29431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      current_interval_ = current_interval_->GetNextSibling();
29531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      if (current_interval_ != nullptr) {
29631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        current_range_ = current_interval_->GetFirstRange();
29731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      }
29831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    }
29931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  }
30031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
30131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray private:
30231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveInterval* current_interval_;
30331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveRange* current_range_;
30431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
30531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(AllRangesIterator);
30631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray};
30731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
30886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffraybool RegisterAllocator::ValidateInternal(bool log_fatal_on_failure) const {
30986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // To simplify unit testing, we eagerly create the array of intervals, and
31086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // call the helper method.
31186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  GrowableArray<LiveInterval*> intervals(allocator_, 0);
31286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) {
31386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
31486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (ShouldProcess(processing_core_registers_, instruction->GetLiveInterval())) {
31586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      intervals.Add(instruction->GetLiveInterval());
31686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
31786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
31886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
319102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  if (processing_core_registers_) {
320102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    for (size_t i = 0, e = physical_core_register_intervals_.Size(); i < e; ++i) {
321102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      LiveInterval* fixed = physical_core_register_intervals_.Get(i);
322102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      if (fixed != nullptr) {
323102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray        intervals.Add(fixed);
324102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      }
325102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    }
326102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  } else {
327102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    for (size_t i = 0, e = physical_fp_register_intervals_.Size(); i < e; ++i) {
328102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      LiveInterval* fixed = physical_fp_register_intervals_.Get(i);
329102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      if (fixed != nullptr) {
330102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray        intervals.Add(fixed);
331102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      }
33286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
33386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
33486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
3353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (size_t i = 0, e = temp_intervals_.Size(); i < e; ++i) {
3363946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    LiveInterval* temp = temp_intervals_.Get(i);
3373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    if (ShouldProcess(processing_core_registers_, temp)) {
3383946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      intervals.Add(temp);
3393946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
3403946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
3413946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
3423946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  return ValidateIntervals(intervals, spill_slots_.Size(), reserved_out_slots_, *codegen_,
3433946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray                           allocator_, processing_core_registers_, log_fatal_on_failure);
34486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
34586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
34631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffraybool RegisterAllocator::ValidateIntervals(const GrowableArray<LiveInterval*>& intervals,
34731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray                                          size_t number_of_spill_slots,
3483946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray                                          size_t number_of_out_slots,
349a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                                          const CodeGenerator& codegen,
350a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                                          ArenaAllocator* allocator,
351a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                                          bool processing_core_registers,
352a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                                          bool log_fatal_on_failure) {
353a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  size_t number_of_registers = processing_core_registers
354a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      ? codegen.GetNumberOfCoreRegisters()
355a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      : codegen.GetNumberOfFloatingPointRegisters();
35631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  GrowableArray<ArenaBitVector*> liveness_of_values(
35731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      allocator, number_of_registers + number_of_spill_slots);
358a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
359a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // Allocate a bit vector per register. A live interval that has a register
360a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // allocated will populate the associated bit vector based on its live ranges.
36131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  for (size_t i = 0; i < number_of_registers + number_of_spill_slots; ++i) {
36231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    liveness_of_values.Add(new (allocator) ArenaBitVector(allocator, 0, true));
363a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
364a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
36531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  for (size_t i = 0, e = intervals.Size(); i < e; ++i) {
36631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    for (AllRangesIterator it(intervals.Get(i)); !it.Done(); it.Advance()) {
36731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      LiveInterval* current = it.CurrentInterval();
36886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      HInstruction* defined_by = current->GetParent()->GetDefinedBy();
36986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (current->GetParent()->HasSpillSlot()
37086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray           // Parameters have their own stack slot.
37186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray           && !(defined_by != nullptr && defined_by->IsParameterValue())) {
3723946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        BitVector* liveness_of_spill_slot = liveness_of_values.Get(number_of_registers
3733946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray            + current->GetParent()->GetSpillSlot() / kVRegSize
3743946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray            - number_of_out_slots);
37531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
37631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray          if (liveness_of_spill_slot->IsBitSet(j)) {
37731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray            if (log_fatal_on_failure) {
37831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray              std::ostringstream message;
37931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray              message << "Spill slot conflict at " << j;
38031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray              LOG(FATAL) << message.str();
38131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray            } else {
38231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray              return false;
38331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray            }
38431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray          } else {
38531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray            liveness_of_spill_slot->SetBit(j);
38631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray          }
38731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        }
388a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      }
38931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
39031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      if (current->HasRegister()) {
39131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        BitVector* liveness_of_register = liveness_of_values.Get(current->GetRegister());
39231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray        for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
39331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray          if (liveness_of_register->IsBitSet(j)) {
394a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray            if (log_fatal_on_failure) {
395a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              std::ostringstream message;
3963946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray              message << "Register conflict at " << j << " ";
3973946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray              if (defined_by != nullptr) {
3983946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray                message << "(" << defined_by->DebugName() << ")";
3993946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray              }
4003946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray              message << "for ";
401a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              if (processing_core_registers) {
402a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                codegen.DumpCoreRegister(message, current->GetRegister());
403a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              } else {
404a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray                codegen.DumpFloatingPointRegister(message, current->GetRegister());
405a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              }
406a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              LOG(FATAL) << message.str();
407a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray            } else {
408a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray              return false;
409a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray            }
410a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray          } else {
41131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray            liveness_of_register->SetBit(j);
412a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray          }
413a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        }
41431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray      }
41531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    }
416a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
417a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  return true;
418a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
419a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
42086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::DumpInterval(std::ostream& stream, LiveInterval* interval) const {
421a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  interval->Dump(stream);
422a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  stream << ": ";
423a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  if (interval->HasRegister()) {
424102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    if (interval->IsFloatingPoint()) {
42586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      codegen_->DumpFloatingPointRegister(stream, interval->GetRegister());
426102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    } else {
427102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      codegen_->DumpCoreRegister(stream, interval->GetRegister());
428a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
429a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  } else {
430a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    stream << "spilled";
431a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
432a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  stream << std::endl;
433a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
434a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
435a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// By the book implementation of a linear scan register allocator.
436a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffrayvoid RegisterAllocator::LinearScan() {
4373946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  while (!unhandled_->IsEmpty()) {
438a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (1) Remove interval with the lowest start position from unhandled.
4393946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    LiveInterval* current = unhandled_->Pop();
4403946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    DCHECK(!current->IsFixed() && !current->HasSpillSlot());
441c8147a76ed2f440f38329dc08ff889d393b5c535Nicolas Geoffray    DCHECK(unhandled_->IsEmpty() || unhandled_->Peek()->GetStart() >= current->GetStart());
442a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    size_t position = current->GetStart();
443a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
444a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (2) Remove currently active intervals that are dead at this position.
445a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    //     Move active intervals that have a lifetime hole at this position
446a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    //     to inactive.
447a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    for (size_t i = 0; i < active_.Size(); ++i) {
448a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      LiveInterval* interval = active_.Get(i);
449a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      if (interval->IsDeadAt(position)) {
450a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        active_.Delete(interval);
451a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        --i;
452a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        handled_.Add(interval);
453a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      } else if (!interval->Covers(position)) {
454a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        active_.Delete(interval);
455a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        --i;
456a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        inactive_.Add(interval);
457a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      }
458a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
459a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
460a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (3) Remove currently inactive intervals that are dead at this position.
461a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    //     Move inactive intervals that cover this position to active.
462a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    for (size_t i = 0; i < inactive_.Size(); ++i) {
463a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      LiveInterval* interval = inactive_.Get(i);
464a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      if (interval->IsDeadAt(position)) {
465a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        inactive_.Delete(interval);
466a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        --i;
467a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        handled_.Add(interval);
468a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      } else if (interval->Covers(position)) {
469a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        inactive_.Delete(interval);
470a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        --i;
471a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        active_.Add(interval);
472a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      }
473a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
474a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
4753bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    if (current->IsSlowPathSafepoint()) {
4763bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // Synthesized interval to record the maximum number of live registers
4773bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      // at safepoints. No need to allocate a register for it.
4783bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      maximum_number_of_live_registers_ =
4793bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray          std::max(maximum_number_of_live_registers_, active_.Size());
4803bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      continue;
4813bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray    }
4823bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray
483a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (4) Try to find an available register.
484a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    bool success = TryAllocateFreeReg(current);
485a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
486a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (5) If no register could be found, we need to spill.
487a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (!success) {
488a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      success = AllocateBlockedReg(current);
489a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
490a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
491a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // (6) If the interval had a register allocated, add it to the list of active
492a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    //     intervals.
493a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (success) {
494a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      active_.Add(current);
495a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
496a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
497a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
498a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
499a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// Find a free register. If multiple are found, pick the register that
500a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// is free the longest.
501a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraybool RegisterAllocator::TryAllocateFreeReg(LiveInterval* current) {
502a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  size_t* free_until = registers_array_;
503a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
504a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // First set all registers to be free.
505a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0; i < number_of_registers_; ++i) {
506a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    free_until[i] = kMaxLifetimePosition;
507a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
508a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
509a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // For each inactive interval, set its register to be free until
510a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // the next intersection with `current`.
511a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // Thanks to SSA, this should only be needed for intervals
512a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // that are the result of a split.
513a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
514a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    LiveInterval* inactive = inactive_.Get(i);
515a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    DCHECK(inactive->HasRegister());
516a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    size_t next_intersection = inactive->FirstIntersectionWith(current);
517a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (next_intersection != kNoLifetime) {
518aac0f39a3501a7f7dd04b2342c2a16961969f139Nicolas Geoffray      free_until[inactive->GetRegister()] =
519aac0f39a3501a7f7dd04b2342c2a16961969f139Nicolas Geoffray          std::min(free_until[inactive->GetRegister()], next_intersection);
520a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
521a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
522a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
52386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // For each active interval, set its register to not free.
52486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (size_t i = 0, e = active_.Size(); i < e; ++i) {
52586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    LiveInterval* interval = active_.Get(i);
52686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    DCHECK(interval->HasRegister());
52786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    free_until[interval->GetRegister()] = 0;
52886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
52986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
530a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  int reg = -1;
5313946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  if (current->HasRegister()) {
5323946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    // Some instructions have a fixed register output.
5333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    reg = current->GetRegister();
5343946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    DCHECK_NE(free_until[reg], 0u);
5353946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  } else {
53601ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    int hint = current->FindFirstRegisterHint(free_until);
53701ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    if (hint != kNoRegister) {
53801ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      DCHECK(!IsBlocked(hint));
53901ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      reg = hint;
54001ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    } else {
54101ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      // Pick the register that is free the longest.
54201ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      for (size_t i = 0; i < number_of_registers_; ++i) {
54301ef345767ea609417fc511e42007705c9667546Nicolas Geoffray        if (IsBlocked(i)) continue;
54401ef345767ea609417fc511e42007705c9667546Nicolas Geoffray        if (reg == -1 || free_until[i] > free_until[reg]) {
54501ef345767ea609417fc511e42007705c9667546Nicolas Geoffray          reg = i;
54601ef345767ea609417fc511e42007705c9667546Nicolas Geoffray          if (free_until[i] == kMaxLifetimePosition) break;
54701ef345767ea609417fc511e42007705c9667546Nicolas Geoffray        }
5483946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      }
549a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
550a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
551a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
552a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // If we could not find a register, we need to spill.
553a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  if (reg == -1 || free_until[reg] == 0) {
554a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return false;
555a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
556a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
557a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  current->SetRegister(reg);
558a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  if (!current->IsDeadAt(free_until[reg])) {
559a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // If the register is only available for a subset of live ranges
560a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // covered by `current`, split `current` at the position where
561a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // the register is not available anymore.
562a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    LiveInterval* split = Split(current, free_until[reg]);
563a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    DCHECK(split != nullptr);
5643946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    AddSorted(unhandled_, split);
565a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
566a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  return true;
567a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
568a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
569a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraybool RegisterAllocator::IsBlocked(int reg) const {
570102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  return processing_core_registers_
571102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      ? blocked_core_registers_[reg]
572102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      : blocked_fp_registers_[reg];
573a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
574a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
575a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// Find the register that is used the last, and spill the interval
576a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// that holds it. If the first use of `current` is after that register
577a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray// we spill `current` instead.
578a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffraybool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
579a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  size_t first_register_use = current->FirstRegisterUse();
580412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  if (first_register_use == kNoLifetime) {
58131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    AllocateSpillSlotFor(current);
582a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return false;
583a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
584a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
585a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // First set all registers as not being used.
586a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  size_t* next_use = registers_array_;
587a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0; i < number_of_registers_; ++i) {
588a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    next_use[i] = kMaxLifetimePosition;
589a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
590a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
591a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // For each active interval, find the next use of its register after the
592a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // start of current.
593a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0, e = active_.Size(); i < e; ++i) {
594a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    LiveInterval* active = active_.Get(i);
595a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    DCHECK(active->HasRegister());
59686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (active->IsFixed()) {
59786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      next_use[active->GetRegister()] = current->GetStart();
59886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    } else {
59986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      size_t use = active->FirstRegisterUseAfter(current->GetStart());
60086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (use != kNoLifetime) {
60186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        next_use[active->GetRegister()] = use;
60286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
603a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
604a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
605a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
606a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // For each inactive interval, find the next use of its register after the
607a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // start of current.
608a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // Thanks to SSA, this should only be needed for intervals
609a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // that are the result of a split.
610a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
611a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    LiveInterval* inactive = inactive_.Get(i);
612a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    DCHECK(inactive->HasRegister());
61386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    size_t next_intersection = inactive->FirstIntersectionWith(current);
61486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (next_intersection != kNoLifetime) {
61586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (inactive->IsFixed()) {
61686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        next_use[inactive->GetRegister()] =
61786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            std::min(next_intersection, next_use[inactive->GetRegister()]);
61886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      } else {
61986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        size_t use = inactive->FirstRegisterUseAfter(current->GetStart());
62086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        if (use != kNoLifetime) {
62186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          next_use[inactive->GetRegister()] = std::min(use, next_use[inactive->GetRegister()]);
62286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        }
62386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
624a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
625a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
626a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
627a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  // Pick the register that is used the last.
628a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  int reg = -1;
629a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  for (size_t i = 0; i < number_of_registers_; ++i) {
630a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (IsBlocked(i)) continue;
631a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (reg == -1 || next_use[i] > next_use[reg]) {
632a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      reg = i;
633a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      if (next_use[i] == kMaxLifetimePosition) break;
634a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
635a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
636a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
637a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  if (first_register_use >= next_use[reg]) {
638a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // If the first use of that instruction is after the last use of the found
639a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // register, we split this interval just before its first register use.
64031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    AllocateSpillSlotFor(current);
641c8147a76ed2f440f38329dc08ff889d393b5c535Nicolas Geoffray    LiveInterval* split = Split(current, first_register_use - 1);
642c8147a76ed2f440f38329dc08ff889d393b5c535Nicolas Geoffray    DCHECK_NE(current, split) << "There is not enough registers available for "
643c8147a76ed2f440f38329dc08ff889d393b5c535Nicolas Geoffray      << split->GetParent()->GetDefinedBy()->DebugName();
6443946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    AddSorted(unhandled_, split);
645a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return false;
646a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  } else {
647a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // Use this register and spill the active and inactives interval that
648a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // have that register.
649a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    current->SetRegister(reg);
650a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
651a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    for (size_t i = 0, e = active_.Size(); i < e; ++i) {
652a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      LiveInterval* active = active_.Get(i);
653a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      if (active->GetRegister() == reg) {
65486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        DCHECK(!active->IsFixed());
655a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        LiveInterval* split = Split(active, current->GetStart());
656a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        active_.DeleteAt(i);
657a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        handled_.Add(active);
6583946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        AddSorted(unhandled_, split);
659a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray        break;
660a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      }
661a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
662a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
663a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    for (size_t i = 0; i < inactive_.Size(); ++i) {
664a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      LiveInterval* inactive = inactive_.Get(i);
665a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      if (inactive->GetRegister() == reg) {
66686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        size_t next_intersection = inactive->FirstIntersectionWith(current);
66786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        if (next_intersection != kNoLifetime) {
66886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          if (inactive->IsFixed()) {
66986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            LiveInterval* split = Split(current, next_intersection);
6703946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray            AddSorted(unhandled_, split);
67186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          } else {
67286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            LiveInterval* split = Split(inactive, current->GetStart());
67386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            inactive_.DeleteAt(i);
67486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            handled_.Add(inactive);
6753946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray            AddSorted(unhandled_, split);
67686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray            --i;
67786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          }
67886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        }
679a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      }
680a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
681a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
682a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return true;
683a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
684a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
685a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
6863946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffrayvoid RegisterAllocator::AddSorted(GrowableArray<LiveInterval*>* array, LiveInterval* interval) {
687c8147a76ed2f440f38329dc08ff889d393b5c535Nicolas Geoffray  DCHECK(!interval->IsFixed() && !interval->HasSpillSlot());
68886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  size_t insert_at = 0;
6893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (size_t i = array->Size(); i > 0; --i) {
6903946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    LiveInterval* current = array->Get(i - 1);
691a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    if (current->StartsAfter(interval)) {
69286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      insert_at = i;
693a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray      break;
694a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    }
695a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
6963946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  array->InsertAt(insert_at, interval);
697a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
698a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
699a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas GeoffrayLiveInterval* RegisterAllocator::Split(LiveInterval* interval, size_t position) {
700a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  DCHECK(position >= interval->GetStart());
701a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  DCHECK(!interval->IsDeadAt(position));
702a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  if (position == interval->GetStart()) {
703a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    // Spill slot will be allocated when handling `interval` again.
704a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    interval->ClearRegister();
705a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return interval;
706a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  } else {
707a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    LiveInterval* new_interval = interval->SplitAt(position);
708a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray    return new_interval;
709a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray  }
710a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}
711a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray
71231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffrayvoid RegisterAllocator::AllocateSpillSlotFor(LiveInterval* interval) {
71331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveInterval* parent = interval->GetParent();
71431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
71531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  // An instruction gets a spill slot for its entire lifetime. If the parent
71631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  // of this interval already has a spill slot, there is nothing to do.
71731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  if (parent->HasSpillSlot()) {
71831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    return;
71931d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  }
72031d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
72186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HInstruction* defined_by = parent->GetDefinedBy();
72286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (defined_by->IsParameterValue()) {
72386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Parameters have their own stack slot.
72486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    parent->SetSpillSlot(codegen_->GetStackSlotOfParameter(defined_by->AsParameterValue()));
72586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
72686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
72786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
72896f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray  if (defined_by->IsConstant()) {
72996f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray    // Constants don't need a spill slot.
73096f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray    return;
73196f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray  }
73296f89a290eb67d7bf4b1636798fa28df14309cc7Nicolas Geoffray
73331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  LiveInterval* last_sibling = interval;
73431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  while (last_sibling->GetNextSibling() != nullptr) {
73531d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    last_sibling = last_sibling->GetNextSibling();
73631d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  }
73731d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  size_t end = last_sibling->GetEnd();
73831d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
739412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  // Find an available spill slot.
740412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  size_t slot = 0;
741412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  for (size_t e = spill_slots_.Size(); slot < e; ++slot) {
742412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    // We check if it is less rather than less or equal because the parallel move
743412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    // resolver does not work when a single spill slot needs to be exchanged with
744412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    // a double spill slot. The strict comparison avoids needing to exchange these
745412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    // locations at the same lifetime position.
746412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    if (spill_slots_.Get(slot) < parent->GetStart()
747412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray        && (slot == (e - 1) || spill_slots_.Get(slot + 1) < parent->GetStart())) {
748412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray      break;
749412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray    }
750412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray  }
751412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray
75201ef345767ea609417fc511e42007705c9667546Nicolas Geoffray  if (parent->NeedsTwoSpillSlots()) {
7533c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    if (slot == spill_slots_.Size()) {
7543c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      // We need a new spill slot.
7553c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Add(end);
7563c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Add(end);
7573c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    } else if (slot == spill_slots_.Size() - 1) {
7583c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Put(slot, end);
7593c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Add(end);
7603c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    } else {
7613c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Put(slot, end);
7623c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Put(slot + 1, end);
76331d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray    }
76431d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  } else {
7653c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    if (slot == spill_slots_.Size()) {
7663c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      // We need a new spill slot.
7673c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Add(end);
7683c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    } else {
7693c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray      spill_slots_.Put(slot, end);
7703c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray    }
77131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray  }
77231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
7733946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  parent->SetSpillSlot((slot + reserved_out_slots_) * kVRegSize);
77486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
77586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
7762a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffraystatic bool IsValidDestination(Location destination) {
777102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray  return destination.IsRegister()
778102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      || destination.IsFpuRegister()
779102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      || destination.IsStackSlot()
780102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray      || destination.IsDoubleStackSlot();
7812a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray}
7822a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray
783740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffrayvoid RegisterAllocator::AddInputMoveFor(HInstruction* user,
78486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                        Location source,
78586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                        Location destination) const {
7862a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray  DCHECK(IsValidDestination(destination));
78786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (source.Equals(destination)) return;
78886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
789476df557fed5f0b3f32f8d11a654674bb403a8f8Roland Levillain  DCHECK(!user->IsPhi());
79086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
791740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  HInstruction* previous = user->GetPrevious();
79286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HParallelMove* move = nullptr;
79386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (previous == nullptr
794476df557fed5f0b3f32f8d11a654674bb403a8f8Roland Levillain      || !previous->IsParallelMove()
7958e3964b766652a0478e8e0e303e8556c997675f1Nicolas Geoffray      || previous->GetLifetimePosition() < user->GetLifetimePosition()) {
79686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = new (allocator_) HParallelMove(allocator_);
7978e3964b766652a0478e8e0e303e8556c997675f1Nicolas Geoffray    move->SetLifetimePosition(user->GetLifetimePosition());
798740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray    user->GetBlock()->InsertInstructionBefore(move, user);
79986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  } else {
80086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = previous->AsParallelMove();
80186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
8028e3964b766652a0478e8e0e303e8556c997675f1Nicolas Geoffray  DCHECK_EQ(move->GetLifetimePosition(), user->GetLifetimePosition());
803740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  move->AddMove(new (allocator_) MoveOperands(source, destination, nullptr));
80486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
80586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
80686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertParallelMoveAt(size_t position,
807740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray                                             HInstruction* instruction,
80886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                             Location source,
80986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                             Location destination) const {
8102a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray  DCHECK(IsValidDestination(destination));
81186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (source.Equals(destination)) return;
81286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
81386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HInstruction* at = liveness_.GetInstructionFromPosition(position / 2);
81486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (at == nullptr) {
81586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Block boundary, don't no anything the connection of split siblings will handle it.
81686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
81786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
81886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HParallelMove* move;
81986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if ((position & 1) == 1) {
82086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Move must happen after the instruction.
82186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    DCHECK(!at->IsControlFlow());
82286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = at->GetNext()->AsParallelMove();
823e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray    // This is a parallel move for connecting siblings in a same block. We need to
824e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray    // differentiate it with moves for connecting blocks, and input moves.
8258e3964b766652a0478e8e0e303e8556c997675f1Nicolas Geoffray    if (move == nullptr || move->GetLifetimePosition() > position) {
82686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      move = new (allocator_) HParallelMove(allocator_);
82786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      move->SetLifetimePosition(position);
82886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      at->GetBlock()->InsertInstructionBefore(move, at->GetNext());
82986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
83086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  } else {
83186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Move must happen before the instruction.
83286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HInstruction* previous = at->GetPrevious();
833740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray    if (previous == nullptr
834740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray        || !previous->IsParallelMove()
835740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray        || previous->GetLifetimePosition() != position) {
836740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray      // If the previous is a parallel move, then its position must be lower
837740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray      // than the given `position`: it was added just after the non-parallel
838740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray      // move instruction that precedes `instruction`.
839740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray      DCHECK(previous == nullptr
840740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray             || !previous->IsParallelMove()
841740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray             || previous->GetLifetimePosition() < position);
84286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      move = new (allocator_) HParallelMove(allocator_);
84386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      move->SetLifetimePosition(position);
84486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      at->GetBlock()->InsertInstructionBefore(move, at);
84586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    } else {
84686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      move = previous->AsParallelMove();
84786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
84886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
84901ef345767ea609417fc511e42007705c9667546Nicolas Geoffray  DCHECK_EQ(move->GetLifetimePosition(), position);
850740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
85186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
85286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
85386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block,
854740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray                                                   HInstruction* instruction,
85586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                                   Location source,
85686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                                   Location destination) const {
8572a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray  DCHECK(IsValidDestination(destination));
85886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (source.Equals(destination)) return;
85986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
86086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  DCHECK_EQ(block->GetSuccessors().Size(), 1u);
86186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HInstruction* last = block->GetLastInstruction();
862360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  // We insert moves at exit for phi predecessors and connecting blocks.
863360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  // A block ending with an if cannot branch to a block with phis because
864360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  // we do not allow critical edges. It can also not connect
865360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  // a split interval between two blocks: the move has to happen in the successor.
866360231a056e796c36ffe62348507e904dc9efb9bNicolas Geoffray  DCHECK(!last->IsIf());
86786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HInstruction* previous = last->GetPrevious();
86886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HParallelMove* move;
869e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // This is a parallel move for connecting blocks. We need to differentiate
870e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // it with moves for connecting siblings in a same block, and output moves.
871740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  if (previous == nullptr || !previous->IsParallelMove()
872e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray      || previous->AsParallelMove()->GetLifetimePosition() != block->GetLifetimeEnd()) {
87386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = new (allocator_) HParallelMove(allocator_);
874e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray    move->SetLifetimePosition(block->GetLifetimeEnd());
87586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    block->InsertInstructionBefore(move, last);
87686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  } else {
87786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = previous->AsParallelMove();
87886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
879740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
88086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
88186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
88286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertParallelMoveAtEntryOf(HBasicBlock* block,
883740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray                                                    HInstruction* instruction,
88486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                                    Location source,
88586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                                    Location destination) const {
8862a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray  DCHECK(IsValidDestination(destination));
88786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (source.Equals(destination)) return;
88886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
88986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HInstruction* first = block->GetFirstInstruction();
89086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HParallelMove* move = first->AsParallelMove();
891e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // This is a parallel move for connecting blocks. We need to differentiate
892e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // it with moves for connecting siblings in a same block, and input moves.
893e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  if (move == nullptr || move->GetLifetimePosition() != block->GetLifetimeStart()) {
89486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = new (allocator_) HParallelMove(allocator_);
89586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move->SetLifetimePosition(block->GetLifetimeStart());
89686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    block->InsertInstructionBefore(move, first);
89786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
898740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
89986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
90086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
90186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::InsertMoveAfter(HInstruction* instruction,
90286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                        Location source,
90386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                        Location destination) const {
9042a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray  DCHECK(IsValidDestination(destination));
90586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (source.Equals(destination)) return;
90686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
907476df557fed5f0b3f32f8d11a654674bb403a8f8Roland Levillain  if (instruction->IsPhi()) {
908740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray    InsertParallelMoveAtEntryOf(instruction->GetBlock(), instruction, source, destination);
90986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
91086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
91186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
912e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  size_t position = instruction->GetLifetimePosition() + 1;
91386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  HParallelMove* move = instruction->GetNext()->AsParallelMove();
914e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // This is a parallel move for moving the output of an instruction. We need
915e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // to differentiate with input moves, moves for connecting siblings in a
916e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  // and moves for connecting blocks.
917e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray  if (move == nullptr || move->GetLifetimePosition() != position) {
91886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    move = new (allocator_) HParallelMove(allocator_);
919e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray    move->SetLifetimePosition(position);
92086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    instruction->GetBlock()->InsertInstructionBefore(move, instruction->GetNext());
92186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
922740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray  move->AddMove(new (allocator_) MoveOperands(source, destination, instruction));
92386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
92486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
92586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::ConnectSiblings(LiveInterval* interval) {
92686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  LiveInterval* current = interval;
92786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (current->HasSpillSlot() && current->HasRegister()) {
92886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // We spill eagerly, so move must be at definition.
92986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    InsertMoveAfter(interval->GetDefinedBy(),
930102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray                    interval->IsFloatingPoint()
931102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray                        ? Location::FpuRegisterLocation(interval->GetRegister())
932102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray                        : Location::RegisterLocation(interval->GetRegister()),
93301ef345767ea609417fc511e42007705c9667546Nicolas Geoffray                    interval->NeedsTwoSpillSlots()
934412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray                        ? Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot())
935412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray                        : Location::StackSlot(interval->GetParent()->GetSpillSlot()));
93686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
93786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  UsePosition* use = current->GetFirstUse();
93886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
93986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Walk over all siblings, updating locations of use positions, and
94086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // connecting them when they are adjacent.
94186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  do {
94201ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    Location source = current->ToLocation();
94386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
94486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Walk over all uses covered by this interval, and update the location
94586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // information.
94686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    while (use != nullptr && use->GetPosition() <= current->GetEnd()) {
9473946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      LocationSummary* locations = use->GetUser()->GetLocations();
9483946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      if (use->GetIsEnvironment()) {
9493946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        locations->SetEnvironmentAt(use->GetInputIndex(), source);
9503946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      } else {
95186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        Location expected_location = locations->InAt(use->GetInputIndex());
95286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        if (expected_location.IsUnallocated()) {
95386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          locations->SetInAt(use->GetInputIndex(), source);
9542a877f32fe145ad50250389df958a559e7d4ad92Nicolas Geoffray        } else if (!expected_location.IsConstant()) {
95586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray          AddInputMoveFor(use->GetUser(), source, expected_location);
95686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        }
95786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
95886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      use = use->GetNext();
95986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
96086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
96186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // If the next interval starts just after this one, and has a register,
96286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // insert a move.
96386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    LiveInterval* next_sibling = current->GetNextSibling();
96486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (next_sibling != nullptr
96586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        && next_sibling->HasRegister()
96686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        && current->GetEnd() == next_sibling->GetStart()) {
96701ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      Location destination = next_sibling->ToLocation();
968740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray      InsertParallelMoveAt(current->GetEnd(), interval->GetDefinedBy(), source, destination);
96986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
9703946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
9713946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    // At each safepoint, we record stack and register information.
9723946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    for (size_t i = 0, e = safepoints_.Size(); i < e; ++i) {
9733946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      HInstruction* safepoint = safepoints_.Get(i);
9743946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      size_t position = safepoint->GetLifetimePosition();
9753946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      LocationSummary* locations = safepoint->GetLocations();
9763946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      if (!current->Covers(position)) continue;
9773946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
9783bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      if ((current->GetType() == Primitive::kPrimNot) && current->GetParent()->HasSpillSlot()) {
9793946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        locations->SetStackBit(current->GetParent()->GetSpillSlot() / kVRegSize);
9803946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      }
9813946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
9823946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      switch (source.GetKind()) {
9833946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        case Location::kRegister: {
9843bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray          locations->AddLiveRegister(source);
9853946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          if (current->GetType() == Primitive::kPrimNot) {
98656b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray            locations->SetRegisterBit(source.reg());
9873946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          }
9883946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          break;
9893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        }
990102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray        case Location::kFpuRegister: {
991102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray          locations->AddLiveRegister(source);
992102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray          break;
993102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray        }
9943946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        case Location::kStackSlot:  // Fall-through
9953946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        case Location::kDoubleStackSlot:  // Fall-through
9963946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        case Location::kConstant: {
9973946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          // Nothing to do.
9983946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          break;
9993946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        }
10003946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        default: {
10013946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray          LOG(FATAL) << "Unexpected location for object";
10023946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        }
10033946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      }
10043946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
100586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    current = next_sibling;
100686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  } while (current != nullptr);
100786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  DCHECK(use == nullptr);
100886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
100986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
101086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::ConnectSplitSiblings(LiveInterval* interval,
101186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                             HBasicBlock* from,
101286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray                                             HBasicBlock* to) const {
101386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (interval->GetNextSibling() == nullptr) {
101486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Nothing to connect. The whole range was allocated to the same location.
101586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
101686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
101786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
101886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  size_t from_position = from->GetLifetimeEnd() - 1;
10197690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  // When an instructions dies at entry of another, and the latter is the beginning
10207690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  // of a block, the register allocator ensures the former has a register
10217690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  // at block->GetLifetimeStart() + 1. Since this is at a block boundary, it must
10227690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  // must be handled in this method.
10237690562d40878f44823d5fb03a2084cfc677ec4aNicolas Geoffray  size_t to_position = to->GetLifetimeStart() + 1;
102486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
102586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  LiveInterval* destination = nullptr;
102686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  LiveInterval* source = nullptr;
102786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
102886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  LiveInterval* current = interval;
102986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
103086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Check the intervals that cover `from` and `to`.
103186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  while ((current != nullptr) && (source == nullptr || destination == nullptr)) {
103286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (current->Covers(from_position)) {
103386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      DCHECK(source == nullptr);
103486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      source = current;
103586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
103686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (current->Covers(to_position)) {
103786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      DCHECK(destination == nullptr);
103886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      destination = current;
103986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
104086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
104186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    current = current->GetNextSibling();
104286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
104386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
104486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (destination == source) {
104586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Interval was not split.
104686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
104786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
104886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
10498ddb00ca935733f5d3b07816e5bb33d6cabe6ec4Nicolas Geoffray  DCHECK(destination != nullptr && source != nullptr);
10508ddb00ca935733f5d3b07816e5bb33d6cabe6ec4Nicolas Geoffray
105186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (!destination->HasRegister()) {
105286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    // Values are eagerly spilled. Spill slot already contains appropriate value.
105386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    return;
105486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
105586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
105686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // If `from` has only one successor, we can put the moves at the exit of it. Otherwise
105786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // we need to put the moves at the entry of `to`.
105886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  if (from->GetSuccessors().Size() == 1) {
1059740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray    InsertParallelMoveAtExitOf(from,
1060740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray                               interval->GetParent()->GetDefinedBy(),
106101ef345767ea609417fc511e42007705c9667546Nicolas Geoffray                               source->ToLocation(),
106201ef345767ea609417fc511e42007705c9667546Nicolas Geoffray                               destination->ToLocation());
106386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  } else {
106486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    DCHECK_EQ(to->GetPredecessors().Size(), 1u);
1065740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray    InsertParallelMoveAtEntryOf(to,
1066740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray                                interval->GetParent()->GetDefinedBy(),
106701ef345767ea609417fc511e42007705c9667546Nicolas Geoffray                                source->ToLocation(),
106801ef345767ea609417fc511e42007705c9667546Nicolas Geoffray                                destination->ToLocation());
106986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
107086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray}
107186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
107286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffrayvoid RegisterAllocator::Resolve() {
10733bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray  codegen_->ComputeFrameSize(
10743bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray      spill_slots_.Size(), maximum_number_of_live_registers_, reserved_out_slots_);
107586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
107686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Adjust the Out Location of instructions.
107786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // TODO: Use pointers of Location inside LiveInterval to avoid doing another iteration.
107886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) {
107986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
108086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    LiveInterval* current = instruction->GetLiveInterval();
108186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    LocationSummary* locations = instruction->GetLocations();
108286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    Location location = locations->Out();
1083476df557fed5f0b3f32f8d11a654674bb403a8f8Roland Levillain    if (instruction->IsParameterValue()) {
108486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      // Now that we know the frame size, adjust the parameter's location.
108586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (location.IsStackSlot()) {
108686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
108786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        current->SetSpillSlot(location.GetStackIndex());
108886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        locations->SetOut(location);
108986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      } else if (location.IsDoubleStackSlot()) {
109086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
109186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        current->SetSpillSlot(location.GetStackIndex());
109286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        locations->SetOut(location);
109386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      } else if (current->HasSpillSlot()) {
109486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        current->SetSpillSlot(current->GetSpillSlot() + codegen_->GetFrameSize());
109586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
109686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
109786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
109801ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    Location source = current->ToLocation();
109986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
110086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    if (location.IsUnallocated()) {
110186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      if (location.GetPolicy() == Location::kSameAsFirstInput) {
110286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        locations->SetInAt(0, source);
110386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
110486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      locations->SetOut(source);
110586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    } else {
110686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      DCHECK(source.Equals(location));
110786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
110886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
110986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
111086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Connect siblings.
111186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) {
111286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
111386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    ConnectSiblings(instruction->GetLiveInterval());
111486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
111586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
111686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Resolve non-linear control flow across branches. Order does not matter.
111786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (HLinearOrderIterator it(liveness_); !it.Done(); it.Advance()) {
111886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HBasicBlock* block = it.Current();
111986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    BitVector* live = liveness_.GetLiveInSet(*block);
112086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    for (uint32_t idx : live->Indexes()) {
112186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      HInstruction* current = liveness_.GetInstructionFromSsaIndex(idx);
112286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      LiveInterval* interval = current->GetLiveInterval();
112386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
112486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        ConnectSplitSiblings(interval, block->GetPredecessors().Get(i), block);
112586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
112686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
112786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
112886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray
112986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  // Resolve phi inputs. Order does not matter.
113086dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  for (HLinearOrderIterator it(liveness_); !it.Done(); it.Advance()) {
113186dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    HBasicBlock* current = it.Current();
113286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    for (HInstructionIterator it(current->GetPhis()); !it.Done(); it.Advance()) {
113386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      HInstruction* phi = it.Current();
113486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      for (size_t i = 0, e = current->GetPredecessors().Size(); i < e; ++i) {
113586dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        HBasicBlock* predecessor = current->GetPredecessors().Get(i);
113686dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        DCHECK_EQ(predecessor->GetSuccessors().Size(), 1u);
113786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray        HInstruction* input = phi->InputAt(i);
113801ef345767ea609417fc511e42007705c9667546Nicolas Geoffray        Location source = input->GetLiveInterval()->GetLocationAt(
113901ef345767ea609417fc511e42007705c9667546Nicolas Geoffray            predecessor->GetLifetimeEnd() - 1);
114001ef345767ea609417fc511e42007705c9667546Nicolas Geoffray        Location destination = phi->GetLiveInterval()->ToLocation();
1141740475d5f45b8caa2c3c6fc51e657ecf4f3547e5Nicolas Geoffray        InsertParallelMoveAtExitOf(predecessor, nullptr, source, destination);
114286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray      }
114386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray    }
114486dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray  }
11453946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
11463946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  // Assign temp locations.
11473946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  HInstruction* current = nullptr;
11483946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  size_t temp_index = 0;
11493946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  for (size_t i = 0; i < temp_intervals_.Size(); ++i) {
11503946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    LiveInterval* temp = temp_intervals_.Get(i);
115101ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    HInstruction* at = liveness_.GetTempUser(temp);
115201ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    if (at != current) {
11533946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      temp_index = 0;
115401ef345767ea609417fc511e42007705c9667546Nicolas Geoffray      current = at;
11553946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    }
115601ef345767ea609417fc511e42007705c9667546Nicolas Geoffray    LocationSummary* locations = at->GetLocations();
1157102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray    DCHECK(temp->GetType() == Primitive::kPrimInt);
11583946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    locations->SetTempAt(
115956b9ee6fe1d6880c5fca0e7feb28b25a1ded2e2fNicolas Geoffray        temp_index++, Location::RegisterLocation(temp->GetRegister()));
11603946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray  }
116131d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray}
116231d76b42ef5165351499da3f8ee0ac147428c5edNicolas Geoffray
1163a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray}  // namespace art
1164