blob: 6910c71ead4076fc43687dfd6ffa6c856ab176fc [file] [log] [blame]
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Matthew Gharritye9288852016-07-14 14:08:16 -070017#include "register_allocator_linear_scan.h"
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010018
Nicolas Geoffray234d69d2015-03-09 10:28:50 +000019#include <iostream>
Ian Rogersc7dd2952014-10-21 23:31:19 -070020#include <sstream>
21
Ian Rogerse77493c2014-08-20 15:08:45 -070022#include "base/bit_vector-inl.h"
Andreas Gampe542451c2016-07-26 09:02:02 -070023#include "base/enums.h"
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010024#include "code_generator.h"
Matthew Gharrity5d6e27d2016-07-18 13:38:44 -070025#include "register_allocation_resolver.h"
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010026#include "ssa_liveness_analysis.h"
27
28namespace art {
29
30static constexpr size_t kMaxLifetimePosition = -1;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010031static constexpr size_t kDefaultNumberOfSpillSlots = 4;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010032
Nicolas Geoffray840e5462015-01-07 16:01:24 +000033// For simplicity, we implement register pairs as (reg, reg + 1).
34// Note that this is a requirement for double registers on ARM, since we
35// allocate SRegister.
36static int GetHighForLowRegister(int reg) { return reg + 1; }
37static bool IsLowRegister(int reg) { return (reg & 1) == 0; }
Nicolas Geoffray234d69d2015-03-09 10:28:50 +000038static bool IsLowOfUnalignedPairInterval(LiveInterval* low) {
39 return GetHighForLowRegister(low->GetRegister()) != low->GetHighInterval()->GetRegister();
40}
Nicolas Geoffray840e5462015-01-07 16:01:24 +000041
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -070042RegisterAllocatorLinearScan::RegisterAllocatorLinearScan(ArenaAllocator* allocator,
43 CodeGenerator* codegen,
44 const SsaLivenessAnalysis& liveness)
45 : RegisterAllocator(allocator, codegen, liveness),
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010046 unhandled_core_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
47 unhandled_fp_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
Nicolas Geoffray39468442014-09-02 15:17:15 +010048 unhandled_(nullptr),
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010049 handled_(allocator->Adapter(kArenaAllocRegisterAllocator)),
50 active_(allocator->Adapter(kArenaAllocRegisterAllocator)),
51 inactive_(allocator->Adapter(kArenaAllocRegisterAllocator)),
52 physical_core_register_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
53 physical_fp_register_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
54 temp_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
55 int_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
56 long_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
57 float_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
58 double_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
David Brazdil77a48ae2015-09-15 12:34:04 +000059 catch_phi_spill_slots_(0),
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010060 safepoints_(allocator->Adapter(kArenaAllocRegisterAllocator)),
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010061 processing_core_registers_(false),
62 number_of_registers_(-1),
63 registers_array_(nullptr),
Nicolas Geoffray102cbed2014-10-15 18:31:05 +010064 blocked_core_registers_(codegen->GetBlockedCoreRegisters()),
65 blocked_fp_registers_(codegen->GetBlockedFloatingPointRegisters()),
Vladimir Marko70e97462016-08-09 11:04:26 +010066 reserved_out_slots_(0) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010067 temp_intervals_.reserve(4);
68 int_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
69 long_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
70 float_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
71 double_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
72
David Brazdil58282f42016-01-14 12:45:10 +000073 codegen->SetupBlockedRegisters();
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010074 physical_core_register_intervals_.resize(codegen->GetNumberOfCoreRegisters(), nullptr);
75 physical_fp_register_intervals_.resize(codegen->GetNumberOfFloatingPointRegisters(), nullptr);
Nicolas Geoffray39468442014-09-02 15:17:15 +010076 // Always reserve for the current method and the graph's max out registers.
77 // TODO: compute it instead.
Mathieu Chartiere401d142015-04-22 13:56:20 -070078 // ArtMethod* takes 2 vregs for 64 bits.
Andreas Gampe542451c2016-07-26 09:02:02 -070079 size_t ptr_size = static_cast<size_t>(InstructionSetPointerSize(codegen->GetInstructionSet()));
80 reserved_out_slots_ = ptr_size / kVRegSize + codegen->GetGraph()->GetMaximumNumberOfOutVRegs();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010081}
82
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010083static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) {
Nicolas Geoffray39468442014-09-02 15:17:15 +010084 if (interval == nullptr) return false;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010085 bool is_core_register = (interval->GetType() != Primitive::kPrimDouble)
86 && (interval->GetType() != Primitive::kPrimFloat);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010087 return processing_core_registers == is_core_register;
88}
89
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -070090void RegisterAllocatorLinearScan::AllocateRegisters() {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010091 AllocateRegistersInternal();
Matthew Gharrity5d6e27d2016-07-18 13:38:44 -070092 RegisterAllocationResolver(allocator_, codegen_, liveness_)
Vladimir Marko70e97462016-08-09 11:04:26 +010093 .Resolve(ArrayRef<HInstruction* const>(safepoints_),
Matthew Gharrity5d6e27d2016-07-18 13:38:44 -070094 reserved_out_slots_,
95 int_spill_slots_.size(),
96 long_spill_slots_.size(),
97 float_spill_slots_.size(),
98 double_spill_slots_.size(),
99 catch_phi_spill_slots_,
100 temp_intervals_);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100101
102 if (kIsDebugBuild) {
103 processing_core_registers_ = true;
104 ValidateInternal(true);
105 processing_core_registers_ = false;
106 ValidateInternal(true);
Nicolas Geoffray59768572014-12-01 09:50:04 +0000107 // Check that the linear order is still correct with regards to lifetime positions.
108 // Since only parallel moves have been inserted during the register allocation,
109 // these checks are mostly for making sure these moves have been added correctly.
110 size_t current_liveness = 0;
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100111 for (HLinearOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
Nicolas Geoffray59768572014-12-01 09:50:04 +0000112 HBasicBlock* block = it.Current();
113 for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
114 HInstruction* instruction = inst_it.Current();
115 DCHECK_LE(current_liveness, instruction->GetLifetimePosition());
116 current_liveness = instruction->GetLifetimePosition();
117 }
118 for (HInstructionIterator inst_it(block->GetInstructions());
119 !inst_it.Done();
120 inst_it.Advance()) {
121 HInstruction* instruction = inst_it.Current();
122 DCHECK_LE(current_liveness, instruction->GetLifetimePosition()) << instruction->DebugName();
123 current_liveness = instruction->GetLifetimePosition();
124 }
125 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100126 }
127}
128
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700129void RegisterAllocatorLinearScan::BlockRegister(Location location, size_t start, size_t end) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100130 int reg = location.reg();
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100131 DCHECK(location.IsRegister() || location.IsFpuRegister());
132 LiveInterval* interval = location.IsRegister()
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100133 ? physical_core_register_intervals_[reg]
134 : physical_fp_register_intervals_[reg];
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100135 Primitive::Type type = location.IsRegister()
136 ? Primitive::kPrimInt
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000137 : Primitive::kPrimFloat;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100138 if (interval == nullptr) {
139 interval = LiveInterval::MakeFixedInterval(allocator_, reg, type);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100140 if (location.IsRegister()) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100141 physical_core_register_intervals_[reg] = interval;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100142 } else {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100143 physical_fp_register_intervals_[reg] = interval;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100144 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100145 }
146 DCHECK(interval->GetRegister() == reg);
147 interval->AddRange(start, end);
148}
149
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700150void RegisterAllocatorLinearScan::BlockRegisters(size_t start, size_t end, bool caller_save_only) {
David Brazdil77a48ae2015-09-15 12:34:04 +0000151 for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) {
152 if (!caller_save_only || !codegen_->IsCoreCalleeSaveRegister(i)) {
153 BlockRegister(Location::RegisterLocation(i), start, end);
154 }
155 }
156 for (size_t i = 0; i < codegen_->GetNumberOfFloatingPointRegisters(); ++i) {
157 if (!caller_save_only || !codegen_->IsFloatingPointCalleeSaveRegister(i)) {
158 BlockRegister(Location::FpuRegisterLocation(i), start, end);
159 }
160 }
161}
162
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700163void RegisterAllocatorLinearScan::AllocateRegistersInternal() {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100164 // Iterate post-order, to ensure the list is sorted, and the last added interval
165 // is the one with the lowest start position.
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100166 for (HLinearPostOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100167 HBasicBlock* block = it.Current();
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800168 for (HBackwardInstructionIterator back_it(block->GetInstructions()); !back_it.Done();
169 back_it.Advance()) {
170 ProcessInstruction(back_it.Current());
Nicolas Geoffray39468442014-09-02 15:17:15 +0100171 }
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800172 for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
173 ProcessInstruction(inst_it.Current());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100174 }
David Brazdil77a48ae2015-09-15 12:34:04 +0000175
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000176 if (block->IsCatchBlock() ||
Nicolas Geoffrayad4ed082016-01-27 14:15:23 +0000177 (block->IsLoopHeader() && block->GetLoopInformation()->IsIrreducible())) {
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000178 // By blocking all registers at the top of each catch block or irreducible loop, we force
179 // intervals belonging to the live-in set of the catch/header block to be spilled.
180 // TODO(ngeoffray): Phis in this block could be allocated in register.
David Brazdil77a48ae2015-09-15 12:34:04 +0000181 size_t position = block->GetLifetimeStart();
182 BlockRegisters(position, position + 1);
183 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100184 }
185
Nicolas Geoffray39468442014-09-02 15:17:15 +0100186 number_of_registers_ = codegen_->GetNumberOfCoreRegisters();
Vladimir Marko5233f932015-09-29 19:01:15 +0100187 registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_,
188 kArenaAllocRegisterAllocator);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100189 processing_core_registers_ = true;
190 unhandled_ = &unhandled_core_intervals_;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100191 for (LiveInterval* fixed : physical_core_register_intervals_) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100192 if (fixed != nullptr) {
Mingyao Yang296bd602014-10-06 16:47:28 -0700193 // Fixed interval is added to inactive_ instead of unhandled_.
194 // It's also the only type of inactive interval whose start position
195 // can be after the current interval during linear scan.
196 // Fixed interval is never split and never moves to unhandled_.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100197 inactive_.push_back(fixed);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100198 }
199 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100200 LinearScan();
Nicolas Geoffray39468442014-09-02 15:17:15 +0100201
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100202 inactive_.clear();
203 active_.clear();
204 handled_.clear();
Nicolas Geoffray39468442014-09-02 15:17:15 +0100205
206 number_of_registers_ = codegen_->GetNumberOfFloatingPointRegisters();
Vladimir Marko5233f932015-09-29 19:01:15 +0100207 registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_,
208 kArenaAllocRegisterAllocator);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100209 processing_core_registers_ = false;
210 unhandled_ = &unhandled_fp_intervals_;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100211 for (LiveInterval* fixed : physical_fp_register_intervals_) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100212 if (fixed != nullptr) {
Mingyao Yang296bd602014-10-06 16:47:28 -0700213 // Fixed interval is added to inactive_ instead of unhandled_.
214 // It's also the only type of inactive interval whose start position
215 // can be after the current interval during linear scan.
216 // Fixed interval is never split and never moves to unhandled_.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100217 inactive_.push_back(fixed);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100218 }
219 }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100220 LinearScan();
221}
222
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700223void RegisterAllocatorLinearScan::ProcessInstruction(HInstruction* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100224 LocationSummary* locations = instruction->GetLocations();
225 size_t position = instruction->GetLifetimePosition();
226
227 if (locations == nullptr) return;
228
229 // Create synthesized intervals for temporaries.
230 for (size_t i = 0; i < locations->GetTempCount(); ++i) {
231 Location temp = locations->GetTemp(i);
Nicolas Geoffray52839d12014-11-07 17:47:25 +0000232 if (temp.IsRegister() || temp.IsFpuRegister()) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100233 BlockRegister(temp, position, position + 1);
Nicolas Geoffray45b83af2015-07-06 15:12:53 +0000234 // Ensure that an explicit temporary register is marked as being allocated.
235 codegen_->AddAllocatedRegister(temp);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100236 } else {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100237 DCHECK(temp.IsUnallocated());
Roland Levillain5368c212014-11-27 15:03:41 +0000238 switch (temp.GetPolicy()) {
239 case Location::kRequiresRegister: {
240 LiveInterval* interval =
241 LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimInt);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100242 temp_intervals_.push_back(interval);
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000243 interval->AddTempUse(instruction, i);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100244 unhandled_core_intervals_.push_back(interval);
Roland Levillain5368c212014-11-27 15:03:41 +0000245 break;
246 }
247
248 case Location::kRequiresFpuRegister: {
249 LiveInterval* interval =
250 LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimDouble);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100251 temp_intervals_.push_back(interval);
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000252 interval->AddTempUse(instruction, i);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000253 if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) {
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100254 interval->AddHighInterval(/* is_temp */ true);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000255 LiveInterval* high = interval->GetHighInterval();
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100256 temp_intervals_.push_back(high);
257 unhandled_fp_intervals_.push_back(high);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000258 }
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100259 unhandled_fp_intervals_.push_back(interval);
Roland Levillain5368c212014-11-27 15:03:41 +0000260 break;
261 }
262
263 default:
264 LOG(FATAL) << "Unexpected policy for temporary location "
265 << temp.GetPolicy();
266 }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100267 }
268 }
269
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100270 bool core_register = (instruction->GetType() != Primitive::kPrimDouble)
271 && (instruction->GetType() != Primitive::kPrimFloat);
272
Alexandre Rames8158f282015-08-07 10:26:17 +0100273 if (locations->NeedsSafepoint()) {
Nicolas Geoffrayc0572a42015-02-06 14:35:25 +0000274 if (codegen_->IsLeafMethod()) {
275 // TODO: We do this here because we do not want the suspend check to artificially
276 // create live registers. We should find another place, but this is currently the
277 // simplest.
278 DCHECK(instruction->IsSuspendCheckEntry());
279 instruction->GetBlock()->RemoveInstruction(instruction);
280 return;
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100281 }
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100282 safepoints_.push_back(instruction);
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100283 }
284
285 if (locations->WillCall()) {
David Brazdil77a48ae2015-09-15 12:34:04 +0000286 BlockRegisters(position, position + 1, /* caller_save_only */ true);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100287 }
288
Vladimir Marko372f10e2016-05-17 16:30:10 +0100289 for (size_t i = 0; i < locations->GetInputCount(); ++i) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100290 Location input = locations->InAt(i);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100291 if (input.IsRegister() || input.IsFpuRegister()) {
292 BlockRegister(input, position, position + 1);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000293 } else if (input.IsPair()) {
294 BlockRegister(input.ToLow(), position, position + 1);
295 BlockRegister(input.ToHigh(), position, position + 1);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100296 }
297 }
298
Nicolas Geoffray39468442014-09-02 15:17:15 +0100299 LiveInterval* current = instruction->GetLiveInterval();
300 if (current == nullptr) return;
301
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100302 ArenaVector<LiveInterval*>& unhandled = core_register
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100303 ? unhandled_core_intervals_
304 : unhandled_fp_intervals_;
305
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100306 DCHECK(unhandled.empty() || current->StartsBeforeOrAt(unhandled.back()));
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000307
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000308 if (codegen_->NeedsTwoRegisters(current->GetType())) {
309 current->AddHighInterval();
310 }
311
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100312 for (size_t safepoint_index = safepoints_.size(); safepoint_index > 0; --safepoint_index) {
313 HInstruction* safepoint = safepoints_[safepoint_index - 1u];
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100314 size_t safepoint_position = safepoint->GetLifetimePosition();
315
316 // Test that safepoints are ordered in the optimal way.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100317 DCHECK(safepoint_index == safepoints_.size() ||
318 safepoints_[safepoint_index]->GetLifetimePosition() < safepoint_position);
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100319
320 if (safepoint_position == current->GetStart()) {
321 // The safepoint is for this instruction, so the location of the instruction
322 // does not need to be saved.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100323 DCHECK_EQ(safepoint_index, safepoints_.size());
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100324 DCHECK_EQ(safepoint, instruction);
325 continue;
326 } else if (current->IsDeadAt(safepoint_position)) {
327 break;
328 } else if (!current->Covers(safepoint_position)) {
329 // Hole in the interval.
330 continue;
331 }
332 current->AddSafepoint(safepoint);
333 }
David Brazdil3fc992f2015-04-16 18:31:55 +0100334 current->ResetSearchCache();
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100335
Nicolas Geoffray39468442014-09-02 15:17:15 +0100336 // Some instructions define their output in fixed register/stack slot. We need
337 // to ensure we know these locations before doing register allocation. For a
338 // given register, we create an interval that covers these locations. The register
339 // will be unavailable at these locations when trying to allocate one for an
340 // interval.
341 //
342 // The backwards walking ensures the ranges are ordered on increasing start positions.
343 Location output = locations->Out();
Calin Juravled0d48522014-11-04 16:40:20 +0000344 if (output.IsUnallocated() && output.GetPolicy() == Location::kSameAsFirstInput) {
345 Location first = locations->InAt(0);
346 if (first.IsRegister() || first.IsFpuRegister()) {
347 current->SetFrom(position + 1);
348 current->SetRegister(first.reg());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000349 } else if (first.IsPair()) {
350 current->SetFrom(position + 1);
351 current->SetRegister(first.low());
352 LiveInterval* high = current->GetHighInterval();
353 high->SetRegister(first.high());
354 high->SetFrom(position + 1);
Calin Juravled0d48522014-11-04 16:40:20 +0000355 }
356 } else if (output.IsRegister() || output.IsFpuRegister()) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100357 // Shift the interval's start by one to account for the blocked register.
358 current->SetFrom(position + 1);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100359 current->SetRegister(output.reg());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100360 BlockRegister(output, position, position + 1);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000361 } else if (output.IsPair()) {
362 current->SetFrom(position + 1);
363 current->SetRegister(output.low());
364 LiveInterval* high = current->GetHighInterval();
365 high->SetRegister(output.high());
366 high->SetFrom(position + 1);
367 BlockRegister(output.ToLow(), position, position + 1);
368 BlockRegister(output.ToHigh(), position, position + 1);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100369 } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) {
370 current->SetSpillSlot(output.GetStackIndex());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000371 } else {
372 DCHECK(output.IsUnallocated() || output.IsConstant());
Nicolas Geoffray39468442014-09-02 15:17:15 +0100373 }
374
David Brazdil77a48ae2015-09-15 12:34:04 +0000375 if (instruction->IsPhi() && instruction->AsPhi()->IsCatchPhi()) {
376 AllocateSpillSlotForCatchPhi(instruction->AsPhi());
377 }
378
Nicolas Geoffray39468442014-09-02 15:17:15 +0100379 // If needed, add interval to the list of unhandled intervals.
380 if (current->HasSpillSlot() || instruction->IsConstant()) {
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +0100381 // Split just before first register use.
Nicolas Geoffray39468442014-09-02 15:17:15 +0100382 size_t first_register_use = current->FirstRegisterUse();
383 if (first_register_use != kNoLifetime) {
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +0100384 LiveInterval* split = SplitBetween(current, current->GetStart(), first_register_use - 1);
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000385 // Don't add directly to `unhandled`, it needs to be sorted and the start
Nicolas Geoffray39468442014-09-02 15:17:15 +0100386 // of this new interval might be after intervals already in the list.
387 AddSorted(&unhandled, split);
388 } else {
389 // Nothing to do, we won't allocate a register for this value.
390 }
391 } else {
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000392 // Don't add directly to `unhandled`, temp or safepoint intervals
393 // for this instruction may have been added, and those can be
394 // processed first.
395 AddSorted(&unhandled, current);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100396 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100397}
398
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100399class AllRangesIterator : public ValueObject {
400 public:
401 explicit AllRangesIterator(LiveInterval* interval)
402 : current_interval_(interval),
403 current_range_(interval->GetFirstRange()) {}
404
405 bool Done() const { return current_interval_ == nullptr; }
406 LiveRange* CurrentRange() const { return current_range_; }
407 LiveInterval* CurrentInterval() const { return current_interval_; }
408
409 void Advance() {
410 current_range_ = current_range_->GetNext();
411 if (current_range_ == nullptr) {
412 current_interval_ = current_interval_->GetNextSibling();
413 if (current_interval_ != nullptr) {
414 current_range_ = current_interval_->GetFirstRange();
415 }
416 }
417 }
418
419 private:
420 LiveInterval* current_interval_;
421 LiveRange* current_range_;
422
423 DISALLOW_COPY_AND_ASSIGN(AllRangesIterator);
424};
425
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700426bool RegisterAllocatorLinearScan::ValidateInternal(bool log_fatal_on_failure) const {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100427 // To simplify unit testing, we eagerly create the array of intervals, and
428 // call the helper method.
Vladimir Markof6a35de2016-03-21 12:01:50 +0000429 ArenaVector<LiveInterval*> intervals(allocator_->Adapter(kArenaAllocRegisterAllocatorValidate));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100430 for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) {
431 HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
432 if (ShouldProcess(processing_core_registers_, instruction->GetLiveInterval())) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100433 intervals.push_back(instruction->GetLiveInterval());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100434 }
435 }
436
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100437 const ArenaVector<LiveInterval*>* physical_register_intervals = processing_core_registers_
438 ? &physical_core_register_intervals_
439 : &physical_fp_register_intervals_;
440 for (LiveInterval* fixed : *physical_register_intervals) {
441 if (fixed != nullptr) {
442 intervals.push_back(fixed);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100443 }
444 }
445
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100446 for (LiveInterval* temp : temp_intervals_) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100447 if (ShouldProcess(processing_core_registers_, temp)) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100448 intervals.push_back(temp);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100449 }
450 }
451
Nicolas Geoffray776b3182015-02-23 14:14:57 +0000452 return ValidateIntervals(intervals, GetNumberOfSpillSlots(), reserved_out_slots_, *codegen_,
Nicolas Geoffray39468442014-09-02 15:17:15 +0100453 allocator_, processing_core_registers_, log_fatal_on_failure);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100454}
455
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700456void RegisterAllocatorLinearScan::DumpInterval(std::ostream& stream, LiveInterval* interval) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100457 interval->Dump(stream);
458 stream << ": ";
459 if (interval->HasRegister()) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100460 if (interval->IsFloatingPoint()) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100461 codegen_->DumpFloatingPointRegister(stream, interval->GetRegister());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100462 } else {
463 codegen_->DumpCoreRegister(stream, interval->GetRegister());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100464 }
465 } else {
466 stream << "spilled";
467 }
468 stream << std::endl;
469}
470
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700471void RegisterAllocatorLinearScan::DumpAllIntervals(std::ostream& stream) const {
Mingyao Yang296bd602014-10-06 16:47:28 -0700472 stream << "inactive: " << std::endl;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100473 for (LiveInterval* inactive_interval : inactive_) {
474 DumpInterval(stream, inactive_interval);
Mingyao Yang296bd602014-10-06 16:47:28 -0700475 }
476 stream << "active: " << std::endl;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100477 for (LiveInterval* active_interval : active_) {
478 DumpInterval(stream, active_interval);
Mingyao Yang296bd602014-10-06 16:47:28 -0700479 }
480 stream << "unhandled: " << std::endl;
481 auto unhandled = (unhandled_ != nullptr) ?
482 unhandled_ : &unhandled_core_intervals_;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100483 for (LiveInterval* unhandled_interval : *unhandled) {
484 DumpInterval(stream, unhandled_interval);
Mingyao Yang296bd602014-10-06 16:47:28 -0700485 }
486 stream << "handled: " << std::endl;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100487 for (LiveInterval* handled_interval : handled_) {
488 DumpInterval(stream, handled_interval);
Mingyao Yang296bd602014-10-06 16:47:28 -0700489 }
490}
491
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100492// By the book implementation of a linear scan register allocator.
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700493void RegisterAllocatorLinearScan::LinearScan() {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100494 while (!unhandled_->empty()) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100495 // (1) Remove interval with the lowest start position from unhandled.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100496 LiveInterval* current = unhandled_->back();
497 unhandled_->pop_back();
Nicolas Geoffray2e92bc22015-08-20 19:52:26 +0100498
499 // Make sure the interval is an expected state.
Nicolas Geoffray39468442014-09-02 15:17:15 +0100500 DCHECK(!current->IsFixed() && !current->HasSpillSlot());
Nicolas Geoffray2e92bc22015-08-20 19:52:26 +0100501 // Make sure we are going in the right order.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100502 DCHECK(unhandled_->empty() || unhandled_->back()->GetStart() >= current->GetStart());
Nicolas Geoffray2e92bc22015-08-20 19:52:26 +0100503 // Make sure a low interval is always with a high.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100504 DCHECK(!current->IsLowInterval() || unhandled_->back()->IsHighInterval());
Nicolas Geoffray2e92bc22015-08-20 19:52:26 +0100505 // Make sure a high interval is always with a low.
506 DCHECK(current->IsLowInterval() ||
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100507 unhandled_->empty() ||
508 !unhandled_->back()->IsHighInterval());
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000509
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100510 size_t position = current->GetStart();
511
Mingyao Yang296bd602014-10-06 16:47:28 -0700512 // Remember the inactive_ size here since the ones moved to inactive_ from
513 // active_ below shouldn't need to be re-checked.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100514 size_t inactive_intervals_to_handle = inactive_.size();
Mingyao Yang296bd602014-10-06 16:47:28 -0700515
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100516 // (2) Remove currently active intervals that are dead at this position.
517 // Move active intervals that have a lifetime hole at this position
518 // to inactive.
Vladimir Markob95fb772015-09-30 13:32:31 +0100519 auto active_kept_end = std::remove_if(
520 active_.begin(),
521 active_.end(),
522 [this, position](LiveInterval* interval) {
523 if (interval->IsDeadAt(position)) {
524 handled_.push_back(interval);
525 return true;
526 } else if (!interval->Covers(position)) {
527 inactive_.push_back(interval);
528 return true;
529 } else {
530 return false; // Keep this interval.
531 }
532 });
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100533 active_.erase(active_kept_end, active_.end());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100534
535 // (3) Remove currently inactive intervals that are dead at this position.
536 // Move inactive intervals that cover this position to active.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100537 auto inactive_to_handle_end = inactive_.begin() + inactive_intervals_to_handle;
Vladimir Markob95fb772015-09-30 13:32:31 +0100538 auto inactive_kept_end = std::remove_if(
539 inactive_.begin(),
540 inactive_to_handle_end,
541 [this, position](LiveInterval* interval) {
542 DCHECK(interval->GetStart() < position || interval->IsFixed());
543 if (interval->IsDeadAt(position)) {
544 handled_.push_back(interval);
545 return true;
546 } else if (interval->Covers(position)) {
547 active_.push_back(interval);
548 return true;
549 } else {
550 return false; // Keep this interval.
551 }
552 });
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100553 inactive_.erase(inactive_kept_end, inactive_to_handle_end);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100554
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000555 if (current->IsHighInterval() && !current->GetLowInterval()->HasRegister()) {
556 DCHECK(!current->HasRegister());
557 // Allocating the low part was unsucessful. The splitted interval for the high part
558 // will be handled next (it is in the `unhandled_` list).
559 continue;
560 }
561
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100562 // (4) Try to find an available register.
563 bool success = TryAllocateFreeReg(current);
564
565 // (5) If no register could be found, we need to spill.
566 if (!success) {
567 success = AllocateBlockedReg(current);
568 }
569
570 // (6) If the interval had a register allocated, add it to the list of active
571 // intervals.
572 if (success) {
Nicolas Geoffray98893962015-01-21 12:32:32 +0000573 codegen_->AddAllocatedRegister(processing_core_registers_
574 ? Location::RegisterLocation(current->GetRegister())
575 : Location::FpuRegisterLocation(current->GetRegister()));
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100576 active_.push_back(current);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000577 if (current->HasHighInterval() && !current->GetHighInterval()->HasRegister()) {
578 current->GetHighInterval()->SetRegister(GetHighForLowRegister(current->GetRegister()));
579 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100580 }
581 }
582}
583
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000584static void FreeIfNotCoverAt(LiveInterval* interval, size_t position, size_t* free_until) {
585 DCHECK(!interval->IsHighInterval());
586 // Note that the same instruction may occur multiple times in the input list,
587 // so `free_until` may have changed already.
David Brazdil3fc992f2015-04-16 18:31:55 +0100588 // Since `position` is not the current scan position, we need to use CoversSlow.
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000589 if (interval->IsDeadAt(position)) {
590 // Set the register to be free. Note that inactive intervals might later
591 // update this.
592 free_until[interval->GetRegister()] = kMaxLifetimePosition;
593 if (interval->HasHighInterval()) {
594 DCHECK(interval->GetHighInterval()->IsDeadAt(position));
595 free_until[interval->GetHighInterval()->GetRegister()] = kMaxLifetimePosition;
596 }
David Brazdil3fc992f2015-04-16 18:31:55 +0100597 } else if (!interval->CoversSlow(position)) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000598 // The interval becomes inactive at `defined_by`. We make its register
599 // available only until the next use strictly after `defined_by`.
600 free_until[interval->GetRegister()] = interval->FirstUseAfter(position);
601 if (interval->HasHighInterval()) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100602 DCHECK(!interval->GetHighInterval()->CoversSlow(position));
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000603 free_until[interval->GetHighInterval()->GetRegister()] = free_until[interval->GetRegister()];
604 }
605 }
606}
607
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100608// Find a free register. If multiple are found, pick the register that
609// is free the longest.
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700610bool RegisterAllocatorLinearScan::TryAllocateFreeReg(LiveInterval* current) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100611 size_t* free_until = registers_array_;
612
613 // First set all registers to be free.
614 for (size_t i = 0; i < number_of_registers_; ++i) {
615 free_until[i] = kMaxLifetimePosition;
616 }
617
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100618 // For each active interval, set its register to not free.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100619 for (LiveInterval* interval : active_) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100620 DCHECK(interval->HasRegister());
621 free_until[interval->GetRegister()] = 0;
622 }
623
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000624 // An interval that starts an instruction (that is, it is not split), may
625 // re-use the registers used by the inputs of that instruciton, based on the
626 // location summary.
627 HInstruction* defined_by = current->GetDefinedBy();
628 if (defined_by != nullptr && !current->IsSplit()) {
629 LocationSummary* locations = defined_by->GetLocations();
630 if (!locations->OutputCanOverlapWithInputs() && locations->Out().IsUnallocated()) {
Vladimir Markoe9004912016-06-16 16:50:52 +0100631 HInputsRef inputs = defined_by->GetInputs();
Vladimir Marko372f10e2016-05-17 16:30:10 +0100632 for (size_t i = 0; i < inputs.size(); ++i) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000633 // Take the last interval of the input. It is the location of that interval
634 // that will be used at `defined_by`.
Vladimir Marko372f10e2016-05-17 16:30:10 +0100635 LiveInterval* interval = inputs[i]->GetLiveInterval()->GetLastSibling();
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000636 // Note that interval may have not been processed yet.
637 // TODO: Handle non-split intervals last in the work list.
Nicolas Geoffray94015b92015-06-04 18:21:04 +0100638 if (locations->InAt(i).IsValid()
639 && interval->HasRegister()
640 && interval->SameRegisterKind(*current)) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000641 // The input must be live until the end of `defined_by`, to comply to
642 // the linear scan algorithm. So we use `defined_by`'s end lifetime
643 // position to check whether the input is dead or is inactive after
644 // `defined_by`.
David Brazdil3fc992f2015-04-16 18:31:55 +0100645 DCHECK(interval->CoversSlow(defined_by->GetLifetimePosition()));
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000646 size_t position = defined_by->GetLifetimePosition() + 1;
647 FreeIfNotCoverAt(interval, position, free_until);
648 }
649 }
650 }
651 }
652
Mingyao Yang296bd602014-10-06 16:47:28 -0700653 // For each inactive interval, set its register to be free until
654 // the next intersection with `current`.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100655 for (LiveInterval* inactive : inactive_) {
Mingyao Yang296bd602014-10-06 16:47:28 -0700656 // Temp/Slow-path-safepoint interval has no holes.
Vladimir Marko70e97462016-08-09 11:04:26 +0100657 DCHECK(!inactive->IsTemp());
Mingyao Yang296bd602014-10-06 16:47:28 -0700658 if (!current->IsSplit() && !inactive->IsFixed()) {
659 // Neither current nor inactive are fixed.
660 // Thanks to SSA, a non-split interval starting in a hole of an
661 // inactive interval should never intersect with that inactive interval.
662 // Only if it's not fixed though, because fixed intervals don't come from SSA.
663 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
664 continue;
665 }
666
667 DCHECK(inactive->HasRegister());
668 if (free_until[inactive->GetRegister()] == 0) {
669 // Already used by some active interval. No need to intersect.
670 continue;
671 }
672 size_t next_intersection = inactive->FirstIntersectionWith(current);
673 if (next_intersection != kNoLifetime) {
674 free_until[inactive->GetRegister()] =
675 std::min(free_until[inactive->GetRegister()], next_intersection);
676 }
677 }
678
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000679 int reg = kNoRegister;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100680 if (current->HasRegister()) {
681 // Some instructions have a fixed register output.
682 reg = current->GetRegister();
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000683 if (free_until[reg] == 0) {
684 DCHECK(current->IsHighInterval());
685 // AllocateBlockedReg will spill the holder of the register.
686 return false;
687 }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100688 } else {
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000689 DCHECK(!current->IsHighInterval());
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +0100690 int hint = current->FindFirstRegisterHint(free_until, liveness_);
Nicolas Geoffrayf2975812015-08-07 18:13:03 -0700691 if ((hint != kNoRegister)
692 // For simplicity, if the hint we are getting for a pair cannot be used,
693 // we are just going to allocate a new pair.
694 && !(current->IsLowInterval() && IsBlocked(GetHighForLowRegister(hint)))) {
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100695 DCHECK(!IsBlocked(hint));
696 reg = hint;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000697 } else if (current->IsLowInterval()) {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000698 reg = FindAvailableRegisterPair(free_until, current->GetStart());
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100699 } else {
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100700 reg = FindAvailableRegister(free_until, current);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100701 }
702 }
703
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000704 DCHECK_NE(reg, kNoRegister);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100705 // If we could not find a register, we need to spill.
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000706 if (free_until[reg] == 0) {
707 return false;
708 }
709
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000710 if (current->IsLowInterval()) {
711 // If the high register of this interval is not available, we need to spill.
712 int high_reg = current->GetHighInterval()->GetRegister();
713 if (high_reg == kNoRegister) {
714 high_reg = GetHighForLowRegister(reg);
715 }
716 if (free_until[high_reg] == 0) {
717 return false;
718 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100719 }
720
721 current->SetRegister(reg);
722 if (!current->IsDeadAt(free_until[reg])) {
723 // If the register is only available for a subset of live ranges
Nicolas Geoffray82726882015-06-01 13:51:57 +0100724 // covered by `current`, split `current` before the position where
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100725 // the register is not available anymore.
Nicolas Geoffray82726882015-06-01 13:51:57 +0100726 LiveInterval* split = SplitBetween(current, current->GetStart(), free_until[reg]);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100727 DCHECK(split != nullptr);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100728 AddSorted(unhandled_, split);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100729 }
730 return true;
731}
732
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700733bool RegisterAllocatorLinearScan::IsBlocked(int reg) const {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100734 return processing_core_registers_
735 ? blocked_core_registers_[reg]
736 : blocked_fp_registers_[reg];
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100737}
738
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700739int RegisterAllocatorLinearScan::FindAvailableRegisterPair(size_t* next_use, size_t starting_at) const {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000740 int reg = kNoRegister;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000741 // Pick the register pair that is used the last.
742 for (size_t i = 0; i < number_of_registers_; ++i) {
743 if (IsBlocked(i)) continue;
744 if (!IsLowRegister(i)) continue;
745 int high_register = GetHighForLowRegister(i);
746 if (IsBlocked(high_register)) continue;
747 int existing_high_register = GetHighForLowRegister(reg);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000748 if ((reg == kNoRegister) || (next_use[i] >= next_use[reg]
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000749 && next_use[high_register] >= next_use[existing_high_register])) {
750 reg = i;
751 if (next_use[i] == kMaxLifetimePosition
752 && next_use[high_register] == kMaxLifetimePosition) {
753 break;
754 }
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000755 } else if (next_use[reg] <= starting_at || next_use[existing_high_register] <= starting_at) {
756 // If one of the current register is known to be unavailable, just unconditionally
757 // try a new one.
758 reg = i;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000759 }
760 }
761 return reg;
762}
763
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700764bool RegisterAllocatorLinearScan::IsCallerSaveRegister(int reg) const {
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100765 return processing_core_registers_
766 ? !codegen_->IsCoreCalleeSaveRegister(reg)
767 : !codegen_->IsFloatingPointCalleeSaveRegister(reg);
768}
769
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700770int RegisterAllocatorLinearScan::FindAvailableRegister(size_t* next_use, LiveInterval* current) const {
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100771 // We special case intervals that do not span a safepoint to try to find a caller-save
772 // register if one is available. We iterate from 0 to the number of registers,
773 // so if there are caller-save registers available at the end, we continue the iteration.
774 bool prefers_caller_save = !current->HasWillCallSafepoint();
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000775 int reg = kNoRegister;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000776 for (size_t i = 0; i < number_of_registers_; ++i) {
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100777 if (IsBlocked(i)) {
778 // Register cannot be used. Continue.
779 continue;
780 }
781
782 // Best case: we found a register fully available.
783 if (next_use[i] == kMaxLifetimePosition) {
784 if (prefers_caller_save && !IsCallerSaveRegister(i)) {
785 // We can get shorter encodings on some platforms by using
786 // small register numbers. So only update the candidate if the previous
787 // one was not available for the whole method.
788 if (reg == kNoRegister || next_use[reg] != kMaxLifetimePosition) {
789 reg = i;
790 }
791 // Continue the iteration in the hope of finding a caller save register.
792 continue;
793 } else {
794 reg = i;
795 // We know the register is good enough. Return it.
796 break;
797 }
798 }
799
800 // If we had no register before, take this one as a reference.
801 if (reg == kNoRegister) {
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000802 reg = i;
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100803 continue;
804 }
805
806 // Pick the register that is used the last.
807 if (next_use[i] > next_use[reg]) {
808 reg = i;
809 continue;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000810 }
811 }
812 return reg;
813}
814
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100815// Remove interval and its other half if any. Return iterator to the following element.
816static ArenaVector<LiveInterval*>::iterator RemoveIntervalAndPotentialOtherHalf(
817 ArenaVector<LiveInterval*>* intervals, ArenaVector<LiveInterval*>::iterator pos) {
818 DCHECK(intervals->begin() <= pos && pos < intervals->end());
819 LiveInterval* interval = *pos;
820 if (interval->IsLowInterval()) {
821 DCHECK(pos + 1 < intervals->end());
822 DCHECK_EQ(*(pos + 1), interval->GetHighInterval());
823 return intervals->erase(pos, pos + 2);
824 } else if (interval->IsHighInterval()) {
825 DCHECK(intervals->begin() < pos);
826 DCHECK_EQ(*(pos - 1), interval->GetLowInterval());
827 return intervals->erase(pos - 1, pos + 1);
828 } else {
829 return intervals->erase(pos);
830 }
831}
832
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700833bool RegisterAllocatorLinearScan::TrySplitNonPairOrUnalignedPairIntervalAt(size_t position,
834 size_t first_register_use,
835 size_t* next_use) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100836 for (auto it = active_.begin(), end = active_.end(); it != end; ++it) {
837 LiveInterval* active = *it;
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000838 DCHECK(active->HasRegister());
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000839 if (active->IsFixed()) continue;
840 if (active->IsHighInterval()) continue;
841 if (first_register_use > next_use[active->GetRegister()]) continue;
842
Nicolas Geoffray2e92bc22015-08-20 19:52:26 +0100843 // Split the first interval found that is either:
844 // 1) A non-pair interval.
845 // 2) A pair interval whose high is not low + 1.
846 // 3) A pair interval whose low is not even.
847 if (!active->IsLowInterval() ||
848 IsLowOfUnalignedPairInterval(active) ||
849 !IsLowRegister(active->GetRegister())) {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000850 LiveInterval* split = Split(active, position);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000851 if (split != active) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100852 handled_.push_back(active);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000853 }
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100854 RemoveIntervalAndPotentialOtherHalf(&active_, it);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000855 AddSorted(unhandled_, split);
856 return true;
857 }
858 }
859 return false;
860}
861
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100862// Find the register that is used the last, and spill the interval
863// that holds it. If the first use of `current` is after that register
864// we spill `current` instead.
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700865bool RegisterAllocatorLinearScan::AllocateBlockedReg(LiveInterval* current) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100866 size_t first_register_use = current->FirstRegisterUse();
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -0700867 if (current->HasRegister()) {
868 DCHECK(current->IsHighInterval());
869 // The low interval has allocated the register for the high interval. In
870 // case the low interval had to split both intervals, we may end up in a
871 // situation where the high interval does not have a register use anymore.
872 // We must still proceed in order to split currently active and inactive
873 // uses of the high interval's register, and put the high interval in the
874 // active set.
875 DCHECK(first_register_use != kNoLifetime || (current->GetNextSibling() != nullptr));
876 } else if (first_register_use == kNoLifetime) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100877 AllocateSpillSlotFor(current);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100878 return false;
879 }
880
881 // First set all registers as not being used.
882 size_t* next_use = registers_array_;
883 for (size_t i = 0; i < number_of_registers_; ++i) {
884 next_use[i] = kMaxLifetimePosition;
885 }
886
887 // For each active interval, find the next use of its register after the
888 // start of current.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100889 for (LiveInterval* active : active_) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100890 DCHECK(active->HasRegister());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100891 if (active->IsFixed()) {
892 next_use[active->GetRegister()] = current->GetStart();
893 } else {
Nicolas Geoffray119a8852016-02-06 17:01:15 +0000894 size_t use = active->FirstRegisterUseAfter(current->GetStart());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100895 if (use != kNoLifetime) {
896 next_use[active->GetRegister()] = use;
897 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100898 }
899 }
900
901 // For each inactive interval, find the next use of its register after the
902 // start of current.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100903 for (LiveInterval* inactive : inactive_) {
Mingyao Yang296bd602014-10-06 16:47:28 -0700904 // Temp/Slow-path-safepoint interval has no holes.
Vladimir Marko70e97462016-08-09 11:04:26 +0100905 DCHECK(!inactive->IsTemp());
Mingyao Yang296bd602014-10-06 16:47:28 -0700906 if (!current->IsSplit() && !inactive->IsFixed()) {
907 // Neither current nor inactive are fixed.
908 // Thanks to SSA, a non-split interval starting in a hole of an
909 // inactive interval should never intersect with that inactive interval.
910 // Only if it's not fixed though, because fixed intervals don't come from SSA.
911 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
912 continue;
913 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100914 DCHECK(inactive->HasRegister());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100915 size_t next_intersection = inactive->FirstIntersectionWith(current);
916 if (next_intersection != kNoLifetime) {
917 if (inactive->IsFixed()) {
918 next_use[inactive->GetRegister()] =
919 std::min(next_intersection, next_use[inactive->GetRegister()]);
920 } else {
Nicolas Geoffray1ba19812015-04-21 09:12:40 +0100921 size_t use = inactive->FirstUseAfter(current->GetStart());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100922 if (use != kNoLifetime) {
923 next_use[inactive->GetRegister()] = std::min(use, next_use[inactive->GetRegister()]);
924 }
925 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100926 }
927 }
928
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000929 int reg = kNoRegister;
930 bool should_spill = false;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000931 if (current->HasRegister()) {
932 DCHECK(current->IsHighInterval());
933 reg = current->GetRegister();
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000934 // When allocating the low part, we made sure the high register was available.
Nicolas Geoffray119a8852016-02-06 17:01:15 +0000935 DCHECK_LT(first_register_use, next_use[reg]);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000936 } else if (current->IsLowInterval()) {
Nicolas Geoffray119a8852016-02-06 17:01:15 +0000937 reg = FindAvailableRegisterPair(next_use, first_register_use);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000938 // We should spill if both registers are not available.
Nicolas Geoffray119a8852016-02-06 17:01:15 +0000939 should_spill = (first_register_use >= next_use[reg])
940 || (first_register_use >= next_use[GetHighForLowRegister(reg)]);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000941 } else {
942 DCHECK(!current->IsHighInterval());
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100943 reg = FindAvailableRegister(next_use, current);
Nicolas Geoffray119a8852016-02-06 17:01:15 +0000944 should_spill = (first_register_use >= next_use[reg]);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100945 }
946
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000947 DCHECK_NE(reg, kNoRegister);
948 if (should_spill) {
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000949 DCHECK(!current->IsHighInterval());
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000950 bool is_allocation_at_use_site = (current->GetStart() >= (first_register_use - 1));
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -0700951 if (is_allocation_at_use_site) {
952 if (!current->IsLowInterval()) {
953 DumpInterval(std::cerr, current);
954 DumpAllIntervals(std::cerr);
955 // This situation has the potential to infinite loop, so we make it a non-debug CHECK.
956 HInstruction* at = liveness_.GetInstructionFromPosition(first_register_use / 2);
957 CHECK(false) << "There is not enough registers available for "
958 << current->GetParent()->GetDefinedBy()->DebugName() << " "
959 << current->GetParent()->GetDefinedBy()->GetId()
960 << " at " << first_register_use - 1 << " "
961 << (at == nullptr ? "" : at->DebugName());
962 }
963
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000964 // If we're allocating a register for `current` because the instruction at
965 // that position requires it, but we think we should spill, then there are
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000966 // non-pair intervals or unaligned pair intervals blocking the allocation.
967 // We split the first interval found, and put ourselves first in the
968 // `unhandled_` list.
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -0700969 bool success = TrySplitNonPairOrUnalignedPairIntervalAt(current->GetStart(),
970 first_register_use,
971 next_use);
972 DCHECK(success);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100973 LiveInterval* existing = unhandled_->back();
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000974 DCHECK(existing->IsHighInterval());
975 DCHECK_EQ(existing->GetLowInterval(), current);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100976 unhandled_->push_back(current);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000977 } else {
978 // If the first use of that instruction is after the last use of the found
979 // register, we split this interval just before its first register use.
980 AllocateSpillSlotFor(current);
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +0100981 LiveInterval* split = SplitBetween(current, current->GetStart(), first_register_use - 1);
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -0700982 DCHECK(current != split);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000983 AddSorted(unhandled_, split);
984 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100985 return false;
986 } else {
987 // Use this register and spill the active and inactives interval that
988 // have that register.
989 current->SetRegister(reg);
990
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100991 for (auto it = active_.begin(), end = active_.end(); it != end; ++it) {
992 LiveInterval* active = *it;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100993 if (active->GetRegister() == reg) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100994 DCHECK(!active->IsFixed());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100995 LiveInterval* split = Split(active, current->GetStart());
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +0000996 if (split != active) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100997 handled_.push_back(active);
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +0000998 }
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100999 RemoveIntervalAndPotentialOtherHalf(&active_, it);
Nicolas Geoffray39468442014-09-02 15:17:15 +01001000 AddSorted(unhandled_, split);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001001 break;
1002 }
1003 }
1004
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001005 // NOTE: Retrieve end() on each iteration because we're removing elements in the loop body.
1006 for (auto it = inactive_.begin(); it != inactive_.end(); ) {
1007 LiveInterval* inactive = *it;
1008 bool erased = false;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001009 if (inactive->GetRegister() == reg) {
Mingyao Yang296bd602014-10-06 16:47:28 -07001010 if (!current->IsSplit() && !inactive->IsFixed()) {
1011 // Neither current nor inactive are fixed.
1012 // Thanks to SSA, a non-split interval starting in a hole of an
1013 // inactive interval should never intersect with that inactive interval.
1014 // Only if it's not fixed though, because fixed intervals don't come from SSA.
1015 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001016 } else {
1017 size_t next_intersection = inactive->FirstIntersectionWith(current);
1018 if (next_intersection != kNoLifetime) {
1019 if (inactive->IsFixed()) {
1020 LiveInterval* split = Split(current, next_intersection);
1021 DCHECK_NE(split, current);
1022 AddSorted(unhandled_, split);
1023 } else {
1024 // Split at the start of `current`, which will lead to splitting
1025 // at the end of the lifetime hole of `inactive`.
1026 LiveInterval* split = Split(inactive, current->GetStart());
1027 // If it's inactive, it must start before the current interval.
1028 DCHECK_NE(split, inactive);
1029 it = RemoveIntervalAndPotentialOtherHalf(&inactive_, it);
1030 erased = true;
1031 handled_.push_back(inactive);
1032 AddSorted(unhandled_, split);
Nicolas Geoffray5b168de2015-03-27 10:27:22 +00001033 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001034 }
1035 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001036 }
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001037 // If we have erased the element, `it` already points to the next element.
1038 // Otherwise we need to move to the next element.
1039 if (!erased) {
1040 ++it;
1041 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001042 }
1043
1044 return true;
1045 }
1046}
1047
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -07001048void RegisterAllocatorLinearScan::AddSorted(ArenaVector<LiveInterval*>* array, LiveInterval* interval) {
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +01001049 DCHECK(!interval->IsFixed() && !interval->HasSpillSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001050 size_t insert_at = 0;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001051 for (size_t i = array->size(); i > 0; --i) {
1052 LiveInterval* current = (*array)[i - 1u];
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001053 // High intervals must be processed right after their low equivalent.
1054 if (current->StartsAfter(interval) && !current->IsHighInterval()) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001055 insert_at = i;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001056 break;
1057 }
1058 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001059
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001060 // Insert the high interval before the low, to ensure the low is processed before.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001061 auto insert_pos = array->begin() + insert_at;
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001062 if (interval->HasHighInterval()) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001063 array->insert(insert_pos, { interval->GetHighInterval(), interval });
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001064 } else if (interval->HasLowInterval()) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001065 array->insert(insert_pos, { interval, interval->GetLowInterval() });
1066 } else {
1067 array->insert(insert_pos, interval);
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001068 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001069}
1070
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -07001071void RegisterAllocatorLinearScan::AllocateSpillSlotFor(LiveInterval* interval) {
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001072 if (interval->IsHighInterval()) {
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -07001073 // The low interval already took care of allocating the spill slot.
1074 DCHECK(!interval->GetLowInterval()->HasRegister());
1075 DCHECK(interval->GetLowInterval()->GetParent()->HasSpillSlot());
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001076 return;
1077 }
1078
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001079 LiveInterval* parent = interval->GetParent();
1080
1081 // An instruction gets a spill slot for its entire lifetime. If the parent
1082 // of this interval already has a spill slot, there is nothing to do.
1083 if (parent->HasSpillSlot()) {
1084 return;
1085 }
1086
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001087 HInstruction* defined_by = parent->GetDefinedBy();
David Brazdil77a48ae2015-09-15 12:34:04 +00001088 DCHECK(!defined_by->IsPhi() || !defined_by->AsPhi()->IsCatchPhi());
1089
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001090 if (defined_by->IsParameterValue()) {
1091 // Parameters have their own stack slot.
1092 parent->SetSpillSlot(codegen_->GetStackSlotOfParameter(defined_by->AsParameterValue()));
1093 return;
1094 }
1095
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001096 if (defined_by->IsCurrentMethod()) {
1097 parent->SetSpillSlot(0);
1098 return;
1099 }
1100
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001101 if (defined_by->IsConstant()) {
1102 // Constants don't need a spill slot.
1103 return;
1104 }
1105
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001106 ArenaVector<size_t>* spill_slots = nullptr;
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001107 switch (interval->GetType()) {
1108 case Primitive::kPrimDouble:
1109 spill_slots = &double_spill_slots_;
1110 break;
1111 case Primitive::kPrimLong:
1112 spill_slots = &long_spill_slots_;
1113 break;
1114 case Primitive::kPrimFloat:
1115 spill_slots = &float_spill_slots_;
1116 break;
1117 case Primitive::kPrimNot:
1118 case Primitive::kPrimInt:
1119 case Primitive::kPrimChar:
1120 case Primitive::kPrimByte:
1121 case Primitive::kPrimBoolean:
1122 case Primitive::kPrimShort:
1123 spill_slots = &int_spill_slots_;
1124 break;
1125 case Primitive::kPrimVoid:
1126 LOG(FATAL) << "Unexpected type for interval " << interval->GetType();
1127 }
1128
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001129 // Find an available spill slot.
1130 size_t slot = 0;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001131 for (size_t e = spill_slots->size(); slot < e; ++slot) {
Matthew Gharrityf64a6ab2016-07-11 14:45:01 -07001132 if ((*spill_slots)[slot] <= parent->GetStart()) {
1133 if (!parent->NeedsTwoSpillSlots()) {
1134 // One spill slot is sufficient.
1135 break;
1136 }
1137 if (slot == e - 1 || (*spill_slots)[slot + 1] <= parent->GetStart()) {
1138 // Two spill slots are available.
1139 break;
1140 }
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001141 }
1142 }
1143
David Brazdil77a48ae2015-09-15 12:34:04 +00001144 size_t end = interval->GetLastSibling()->GetEnd();
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001145 if (parent->NeedsTwoSpillSlots()) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001146 if (slot + 2u > spill_slots->size()) {
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001147 // We need a new spill slot.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001148 spill_slots->resize(slot + 2u, end);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001149 }
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001150 (*spill_slots)[slot] = end;
1151 (*spill_slots)[slot + 1] = end;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001152 } else {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001153 if (slot == spill_slots->size()) {
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001154 // We need a new spill slot.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001155 spill_slots->push_back(end);
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001156 } else {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001157 (*spill_slots)[slot] = end;
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001158 }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001159 }
1160
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001161 // Note that the exact spill slot location will be computed when we resolve,
1162 // that is when we know the number of spill slots for each type.
1163 parent->SetSpillSlot(slot);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001164}
1165
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -07001166void RegisterAllocatorLinearScan::AllocateSpillSlotForCatchPhi(HPhi* phi) {
David Brazdil77a48ae2015-09-15 12:34:04 +00001167 LiveInterval* interval = phi->GetLiveInterval();
1168
1169 HInstruction* previous_phi = phi->GetPrevious();
1170 DCHECK(previous_phi == nullptr ||
1171 previous_phi->AsPhi()->GetRegNumber() <= phi->GetRegNumber())
1172 << "Phis expected to be sorted by vreg number, so that equivalent phis are adjacent.";
1173
1174 if (phi->IsVRegEquivalentOf(previous_phi)) {
1175 // This is an equivalent of the previous phi. We need to assign the same
1176 // catch phi slot.
1177 DCHECK(previous_phi->GetLiveInterval()->HasSpillSlot());
1178 interval->SetSpillSlot(previous_phi->GetLiveInterval()->GetSpillSlot());
1179 } else {
1180 // Allocate a new spill slot for this catch phi.
1181 // TODO: Reuse spill slots when intervals of phis from different catch
1182 // blocks do not overlap.
1183 interval->SetSpillSlot(catch_phi_spill_slots_);
1184 catch_phi_spill_slots_ += interval->NeedsTwoSpillSlots() ? 2 : 1;
1185 }
1186}
1187
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001188} // namespace art