blob: 0d6c5a3eff20cd9e7078816047f8a0c5aea82983 [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"
Aart Bik96202302016-10-04 17:33:56 -070025#include "linear_order.h"
Matthew Gharrity5d6e27d2016-07-18 13:38:44 -070026#include "register_allocation_resolver.h"
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010027#include "ssa_liveness_analysis.h"
28
29namespace art {
30
31static constexpr size_t kMaxLifetimePosition = -1;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010032static constexpr size_t kDefaultNumberOfSpillSlots = 4;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010033
Nicolas Geoffray840e5462015-01-07 16:01:24 +000034// For simplicity, we implement register pairs as (reg, reg + 1).
35// Note that this is a requirement for double registers on ARM, since we
36// allocate SRegister.
37static int GetHighForLowRegister(int reg) { return reg + 1; }
38static bool IsLowRegister(int reg) { return (reg & 1) == 0; }
Nicolas Geoffray234d69d2015-03-09 10:28:50 +000039static bool IsLowOfUnalignedPairInterval(LiveInterval* low) {
40 return GetHighForLowRegister(low->GetRegister()) != low->GetHighInterval()->GetRegister();
41}
Nicolas Geoffray840e5462015-01-07 16:01:24 +000042
Vladimir Markoe764d2e2017-10-05 14:35:55 +010043RegisterAllocatorLinearScan::RegisterAllocatorLinearScan(ScopedArenaAllocator* allocator,
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -070044 CodeGenerator* codegen,
45 const SsaLivenessAnalysis& liveness)
46 : RegisterAllocator(allocator, codegen, liveness),
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010047 unhandled_core_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
48 unhandled_fp_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
Nicolas Geoffray39468442014-09-02 15:17:15 +010049 unhandled_(nullptr),
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010050 handled_(allocator->Adapter(kArenaAllocRegisterAllocator)),
51 active_(allocator->Adapter(kArenaAllocRegisterAllocator)),
52 inactive_(allocator->Adapter(kArenaAllocRegisterAllocator)),
53 physical_core_register_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
54 physical_fp_register_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
55 temp_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
56 int_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
57 long_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
58 float_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
59 double_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
David Brazdil77a48ae2015-09-15 12:34:04 +000060 catch_phi_spill_slots_(0),
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010061 safepoints_(allocator->Adapter(kArenaAllocRegisterAllocator)),
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010062 processing_core_registers_(false),
63 number_of_registers_(-1),
64 registers_array_(nullptr),
Nicolas Geoffray102cbed2014-10-15 18:31:05 +010065 blocked_core_registers_(codegen->GetBlockedCoreRegisters()),
66 blocked_fp_registers_(codegen->GetBlockedFloatingPointRegisters()),
Vladimir Marko70e97462016-08-09 11:04:26 +010067 reserved_out_slots_(0) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010068 temp_intervals_.reserve(4);
69 int_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
70 long_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
71 float_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
72 double_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
73
David Brazdil58282f42016-01-14 12:45:10 +000074 codegen->SetupBlockedRegisters();
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010075 physical_core_register_intervals_.resize(codegen->GetNumberOfCoreRegisters(), nullptr);
76 physical_fp_register_intervals_.resize(codegen->GetNumberOfFloatingPointRegisters(), nullptr);
Nicolas Geoffray39468442014-09-02 15:17:15 +010077 // Always reserve for the current method and the graph's max out registers.
78 // TODO: compute it instead.
Mathieu Chartiere401d142015-04-22 13:56:20 -070079 // ArtMethod* takes 2 vregs for 64 bits.
Andreas Gampe542451c2016-07-26 09:02:02 -070080 size_t ptr_size = static_cast<size_t>(InstructionSetPointerSize(codegen->GetInstructionSet()));
81 reserved_out_slots_ = ptr_size / kVRegSize + codegen->GetGraph()->GetMaximumNumberOfOutVRegs();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010082}
83
Vladimir Markoe764d2e2017-10-05 14:35:55 +010084RegisterAllocatorLinearScan::~RegisterAllocatorLinearScan() {}
85
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010086static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) {
Nicolas Geoffray39468442014-09-02 15:17:15 +010087 if (interval == nullptr) return false;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010088 bool is_core_register = (interval->GetType() != DataType::Type::kFloat64)
89 && (interval->GetType() != DataType::Type::kFloat32);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010090 return processing_core_registers == is_core_register;
91}
92
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -070093void RegisterAllocatorLinearScan::AllocateRegisters() {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010094 AllocateRegistersInternal();
Vladimir Markoe764d2e2017-10-05 14:35:55 +010095 RegisterAllocationResolver(codegen_, liveness_)
Vladimir Marko70e97462016-08-09 11:04:26 +010096 .Resolve(ArrayRef<HInstruction* const>(safepoints_),
Matthew Gharrity5d6e27d2016-07-18 13:38:44 -070097 reserved_out_slots_,
98 int_spill_slots_.size(),
99 long_spill_slots_.size(),
100 float_spill_slots_.size(),
101 double_spill_slots_.size(),
102 catch_phi_spill_slots_,
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100103 ArrayRef<LiveInterval* const>(temp_intervals_));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100104
105 if (kIsDebugBuild) {
106 processing_core_registers_ = true;
107 ValidateInternal(true);
108 processing_core_registers_ = false;
109 ValidateInternal(true);
Nicolas Geoffray59768572014-12-01 09:50:04 +0000110 // Check that the linear order is still correct with regards to lifetime positions.
111 // Since only parallel moves have been inserted during the register allocation,
112 // these checks are mostly for making sure these moves have been added correctly.
113 size_t current_liveness = 0;
Aart Bik96202302016-10-04 17:33:56 -0700114 for (HBasicBlock* block : codegen_->GetGraph()->GetLinearOrder()) {
Nicolas Geoffray59768572014-12-01 09:50:04 +0000115 for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
116 HInstruction* instruction = inst_it.Current();
117 DCHECK_LE(current_liveness, instruction->GetLifetimePosition());
118 current_liveness = instruction->GetLifetimePosition();
119 }
120 for (HInstructionIterator inst_it(block->GetInstructions());
121 !inst_it.Done();
122 inst_it.Advance()) {
123 HInstruction* instruction = inst_it.Current();
124 DCHECK_LE(current_liveness, instruction->GetLifetimePosition()) << instruction->DebugName();
125 current_liveness = instruction->GetLifetimePosition();
126 }
127 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100128 }
129}
130
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700131void RegisterAllocatorLinearScan::BlockRegister(Location location, size_t start, size_t end) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100132 int reg = location.reg();
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100133 DCHECK(location.IsRegister() || location.IsFpuRegister());
134 LiveInterval* interval = location.IsRegister()
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100135 ? physical_core_register_intervals_[reg]
136 : physical_fp_register_intervals_[reg];
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100137 DataType::Type type = location.IsRegister()
138 ? DataType::Type::kInt32
139 : DataType::Type::kFloat32;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100140 if (interval == nullptr) {
141 interval = LiveInterval::MakeFixedInterval(allocator_, reg, type);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100142 if (location.IsRegister()) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100143 physical_core_register_intervals_[reg] = interval;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100144 } else {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100145 physical_fp_register_intervals_[reg] = interval;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100146 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100147 }
148 DCHECK(interval->GetRegister() == reg);
149 interval->AddRange(start, end);
150}
151
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700152void RegisterAllocatorLinearScan::BlockRegisters(size_t start, size_t end, bool caller_save_only) {
David Brazdil77a48ae2015-09-15 12:34:04 +0000153 for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) {
154 if (!caller_save_only || !codegen_->IsCoreCalleeSaveRegister(i)) {
155 BlockRegister(Location::RegisterLocation(i), start, end);
156 }
157 }
158 for (size_t i = 0; i < codegen_->GetNumberOfFloatingPointRegisters(); ++i) {
159 if (!caller_save_only || !codegen_->IsFloatingPointCalleeSaveRegister(i)) {
160 BlockRegister(Location::FpuRegisterLocation(i), start, end);
161 }
162 }
163}
164
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700165void RegisterAllocatorLinearScan::AllocateRegistersInternal() {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100166 // Iterate post-order, to ensure the list is sorted, and the last added interval
167 // is the one with the lowest start position.
Vladimir Marko2c45bc92016-10-25 16:54:12 +0100168 for (HBasicBlock* block : codegen_->GetGraph()->GetLinearPostOrder()) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800169 for (HBackwardInstructionIterator back_it(block->GetInstructions()); !back_it.Done();
170 back_it.Advance()) {
171 ProcessInstruction(back_it.Current());
Nicolas Geoffray39468442014-09-02 15:17:15 +0100172 }
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800173 for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
174 ProcessInstruction(inst_it.Current());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100175 }
David Brazdil77a48ae2015-09-15 12:34:04 +0000176
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000177 if (block->IsCatchBlock() ||
Nicolas Geoffrayad4ed082016-01-27 14:15:23 +0000178 (block->IsLoopHeader() && block->GetLoopInformation()->IsIrreducible())) {
Nicolas Geoffray15bd2282016-01-05 15:55:41 +0000179 // By blocking all registers at the top of each catch block or irreducible loop, we force
180 // intervals belonging to the live-in set of the catch/header block to be spilled.
181 // TODO(ngeoffray): Phis in this block could be allocated in register.
David Brazdil77a48ae2015-09-15 12:34:04 +0000182 size_t position = block->GetLifetimeStart();
183 BlockRegisters(position, position + 1);
184 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100185 }
186
Nicolas Geoffray39468442014-09-02 15:17:15 +0100187 number_of_registers_ = codegen_->GetNumberOfCoreRegisters();
Vladimir Marko5233f932015-09-29 19:01:15 +0100188 registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_,
189 kArenaAllocRegisterAllocator);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100190 processing_core_registers_ = true;
191 unhandled_ = &unhandled_core_intervals_;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100192 for (LiveInterval* fixed : physical_core_register_intervals_) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100193 if (fixed != nullptr) {
Mingyao Yang296bd602014-10-06 16:47:28 -0700194 // Fixed interval is added to inactive_ instead of unhandled_.
195 // It's also the only type of inactive interval whose start position
196 // can be after the current interval during linear scan.
197 // Fixed interval is never split and never moves to unhandled_.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100198 inactive_.push_back(fixed);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100199 }
200 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100201 LinearScan();
Nicolas Geoffray39468442014-09-02 15:17:15 +0100202
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100203 inactive_.clear();
204 active_.clear();
205 handled_.clear();
Nicolas Geoffray39468442014-09-02 15:17:15 +0100206
207 number_of_registers_ = codegen_->GetNumberOfFloatingPointRegisters();
Vladimir Marko5233f932015-09-29 19:01:15 +0100208 registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_,
209 kArenaAllocRegisterAllocator);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100210 processing_core_registers_ = false;
211 unhandled_ = &unhandled_fp_intervals_;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100212 for (LiveInterval* fixed : physical_fp_register_intervals_) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100213 if (fixed != nullptr) {
Mingyao Yang296bd602014-10-06 16:47:28 -0700214 // Fixed interval is added to inactive_ instead of unhandled_.
215 // It's also the only type of inactive interval whose start position
216 // can be after the current interval during linear scan.
217 // Fixed interval is never split and never moves to unhandled_.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100218 inactive_.push_back(fixed);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100219 }
220 }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100221 LinearScan();
222}
223
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700224void RegisterAllocatorLinearScan::ProcessInstruction(HInstruction* instruction) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100225 LocationSummary* locations = instruction->GetLocations();
226 size_t position = instruction->GetLifetimePosition();
227
228 if (locations == nullptr) return;
229
230 // Create synthesized intervals for temporaries.
231 for (size_t i = 0; i < locations->GetTempCount(); ++i) {
232 Location temp = locations->GetTemp(i);
Nicolas Geoffray52839d12014-11-07 17:47:25 +0000233 if (temp.IsRegister() || temp.IsFpuRegister()) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100234 BlockRegister(temp, position, position + 1);
Nicolas Geoffray45b83af2015-07-06 15:12:53 +0000235 // Ensure that an explicit temporary register is marked as being allocated.
236 codegen_->AddAllocatedRegister(temp);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100237 } else {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100238 DCHECK(temp.IsUnallocated());
Roland Levillain5368c212014-11-27 15:03:41 +0000239 switch (temp.GetPolicy()) {
240 case Location::kRequiresRegister: {
241 LiveInterval* interval =
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100242 LiveInterval::MakeTempInterval(allocator_, DataType::Type::kInt32);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100243 temp_intervals_.push_back(interval);
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000244 interval->AddTempUse(instruction, i);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100245 unhandled_core_intervals_.push_back(interval);
Roland Levillain5368c212014-11-27 15:03:41 +0000246 break;
247 }
248
249 case Location::kRequiresFpuRegister: {
250 LiveInterval* interval =
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100251 LiveInterval::MakeTempInterval(allocator_, DataType::Type::kFloat64);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100252 temp_intervals_.push_back(interval);
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000253 interval->AddTempUse(instruction, i);
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100254 if (codegen_->NeedsTwoRegisters(DataType::Type::kFloat64)) {
Andreas Gampe3db70682018-12-26 15:12:03 -0800255 interval->AddHighInterval(/* is_temp= */ true);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000256 LiveInterval* high = interval->GetHighInterval();
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100257 temp_intervals_.push_back(high);
258 unhandled_fp_intervals_.push_back(high);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000259 }
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100260 unhandled_fp_intervals_.push_back(interval);
Roland Levillain5368c212014-11-27 15:03:41 +0000261 break;
262 }
263
264 default:
265 LOG(FATAL) << "Unexpected policy for temporary location "
266 << temp.GetPolicy();
267 }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100268 }
269 }
270
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100271 bool core_register = (instruction->GetType() != DataType::Type::kFloat64)
272 && (instruction->GetType() != DataType::Type::kFloat32);
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100273
Alexandre Rames8158f282015-08-07 10:26:17 +0100274 if (locations->NeedsSafepoint()) {
Nicolas Geoffrayc0572a42015-02-06 14:35:25 +0000275 if (codegen_->IsLeafMethod()) {
276 // TODO: We do this here because we do not want the suspend check to artificially
277 // create live registers. We should find another place, but this is currently the
278 // simplest.
279 DCHECK(instruction->IsSuspendCheckEntry());
280 instruction->GetBlock()->RemoveInstruction(instruction);
281 return;
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100282 }
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100283 safepoints_.push_back(instruction);
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100284 }
285
286 if (locations->WillCall()) {
Andreas Gampe3db70682018-12-26 15:12:03 -0800287 BlockRegisters(position, position + 1, /* caller_save_only= */ true);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100288 }
289
Vladimir Marko372f10e2016-05-17 16:30:10 +0100290 for (size_t i = 0; i < locations->GetInputCount(); ++i) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100291 Location input = locations->InAt(i);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100292 if (input.IsRegister() || input.IsFpuRegister()) {
293 BlockRegister(input, position, position + 1);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000294 } else if (input.IsPair()) {
295 BlockRegister(input.ToLow(), position, position + 1);
296 BlockRegister(input.ToHigh(), position, position + 1);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100297 }
298 }
299
Nicolas Geoffray39468442014-09-02 15:17:15 +0100300 LiveInterval* current = instruction->GetLiveInterval();
301 if (current == nullptr) return;
302
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100303 ScopedArenaVector<LiveInterval*>& unhandled = core_register
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100304 ? unhandled_core_intervals_
305 : unhandled_fp_intervals_;
306
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100307 DCHECK(unhandled.empty() || current->StartsBeforeOrAt(unhandled.back()));
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000308
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000309 if (codegen_->NeedsTwoRegisters(current->GetType())) {
310 current->AddHighInterval();
311 }
312
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100313 for (size_t safepoint_index = safepoints_.size(); safepoint_index > 0; --safepoint_index) {
314 HInstruction* safepoint = safepoints_[safepoint_index - 1u];
Nicolas Geoffray2aee3af2018-08-27 20:56:45 +0100315 size_t safepoint_position = SafepointPosition::ComputePosition(safepoint);
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100316
317 // Test that safepoints are ordered in the optimal way.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100318 DCHECK(safepoint_index == safepoints_.size() ||
319 safepoints_[safepoint_index]->GetLifetimePosition() < safepoint_position);
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100320
321 if (safepoint_position == current->GetStart()) {
322 // The safepoint is for this instruction, so the location of the instruction
323 // does not need to be saved.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100324 DCHECK_EQ(safepoint_index, safepoints_.size());
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100325 DCHECK_EQ(safepoint, instruction);
326 continue;
327 } else if (current->IsDeadAt(safepoint_position)) {
328 break;
329 } else if (!current->Covers(safepoint_position)) {
330 // Hole in the interval.
331 continue;
332 }
333 current->AddSafepoint(safepoint);
334 }
David Brazdil3fc992f2015-04-16 18:31:55 +0100335 current->ResetSearchCache();
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100336
Nicolas Geoffray39468442014-09-02 15:17:15 +0100337 // Some instructions define their output in fixed register/stack slot. We need
338 // to ensure we know these locations before doing register allocation. For a
339 // given register, we create an interval that covers these locations. The register
340 // will be unavailable at these locations when trying to allocate one for an
341 // interval.
342 //
343 // The backwards walking ensures the ranges are ordered on increasing start positions.
344 Location output = locations->Out();
Calin Juravled0d48522014-11-04 16:40:20 +0000345 if (output.IsUnallocated() && output.GetPolicy() == Location::kSameAsFirstInput) {
346 Location first = locations->InAt(0);
347 if (first.IsRegister() || first.IsFpuRegister()) {
348 current->SetFrom(position + 1);
349 current->SetRegister(first.reg());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000350 } else if (first.IsPair()) {
351 current->SetFrom(position + 1);
352 current->SetRegister(first.low());
353 LiveInterval* high = current->GetHighInterval();
354 high->SetRegister(first.high());
355 high->SetFrom(position + 1);
Calin Juravled0d48522014-11-04 16:40:20 +0000356 }
357 } else if (output.IsRegister() || output.IsFpuRegister()) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100358 // Shift the interval's start by one to account for the blocked register.
359 current->SetFrom(position + 1);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100360 current->SetRegister(output.reg());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100361 BlockRegister(output, position, position + 1);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000362 } else if (output.IsPair()) {
363 current->SetFrom(position + 1);
364 current->SetRegister(output.low());
365 LiveInterval* high = current->GetHighInterval();
366 high->SetRegister(output.high());
367 high->SetFrom(position + 1);
368 BlockRegister(output.ToLow(), position, position + 1);
369 BlockRegister(output.ToHigh(), position, position + 1);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100370 } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) {
371 current->SetSpillSlot(output.GetStackIndex());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000372 } else {
373 DCHECK(output.IsUnallocated() || output.IsConstant());
Nicolas Geoffray39468442014-09-02 15:17:15 +0100374 }
375
David Brazdil77a48ae2015-09-15 12:34:04 +0000376 if (instruction->IsPhi() && instruction->AsPhi()->IsCatchPhi()) {
377 AllocateSpillSlotForCatchPhi(instruction->AsPhi());
378 }
379
Nicolas Geoffray39468442014-09-02 15:17:15 +0100380 // If needed, add interval to the list of unhandled intervals.
381 if (current->HasSpillSlot() || instruction->IsConstant()) {
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +0100382 // Split just before first register use.
Nicolas Geoffray39468442014-09-02 15:17:15 +0100383 size_t first_register_use = current->FirstRegisterUse();
384 if (first_register_use != kNoLifetime) {
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +0100385 LiveInterval* split = SplitBetween(current, current->GetStart(), first_register_use - 1);
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000386 // Don't add directly to `unhandled`, it needs to be sorted and the start
Nicolas Geoffray39468442014-09-02 15:17:15 +0100387 // of this new interval might be after intervals already in the list.
388 AddSorted(&unhandled, split);
389 } else {
390 // Nothing to do, we won't allocate a register for this value.
391 }
392 } else {
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000393 // Don't add directly to `unhandled`, temp or safepoint intervals
394 // for this instruction may have been added, and those can be
395 // processed first.
396 AddSorted(&unhandled, current);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100397 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100398}
399
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100400class AllRangesIterator : public ValueObject {
401 public:
402 explicit AllRangesIterator(LiveInterval* interval)
403 : current_interval_(interval),
404 current_range_(interval->GetFirstRange()) {}
405
406 bool Done() const { return current_interval_ == nullptr; }
407 LiveRange* CurrentRange() const { return current_range_; }
408 LiveInterval* CurrentInterval() const { return current_interval_; }
409
410 void Advance() {
411 current_range_ = current_range_->GetNext();
412 if (current_range_ == nullptr) {
413 current_interval_ = current_interval_->GetNextSibling();
414 if (current_interval_ != nullptr) {
415 current_range_ = current_interval_->GetFirstRange();
416 }
417 }
418 }
419
420 private:
421 LiveInterval* current_interval_;
422 LiveRange* current_range_;
423
424 DISALLOW_COPY_AND_ASSIGN(AllRangesIterator);
425};
426
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700427bool RegisterAllocatorLinearScan::ValidateInternal(bool log_fatal_on_failure) const {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100428 // To simplify unit testing, we eagerly create the array of intervals, and
429 // call the helper method.
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100430 ScopedArenaAllocator allocator(allocator_->GetArenaStack());
431 ScopedArenaVector<LiveInterval*> intervals(
432 allocator.Adapter(kArenaAllocRegisterAllocatorValidate));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100433 for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) {
434 HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
435 if (ShouldProcess(processing_core_registers_, instruction->GetLiveInterval())) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100436 intervals.push_back(instruction->GetLiveInterval());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100437 }
438 }
439
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100440 const ScopedArenaVector<LiveInterval*>* physical_register_intervals = processing_core_registers_
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100441 ? &physical_core_register_intervals_
442 : &physical_fp_register_intervals_;
443 for (LiveInterval* fixed : *physical_register_intervals) {
444 if (fixed != nullptr) {
445 intervals.push_back(fixed);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100446 }
447 }
448
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100449 for (LiveInterval* temp : temp_intervals_) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100450 if (ShouldProcess(processing_core_registers_, temp)) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100451 intervals.push_back(temp);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100452 }
453 }
454
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100455 return ValidateIntervals(ArrayRef<LiveInterval* const>(intervals),
456 GetNumberOfSpillSlots(),
457 reserved_out_slots_,
458 *codegen_,
459 processing_core_registers_,
460 log_fatal_on_failure);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100461}
462
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700463void RegisterAllocatorLinearScan::DumpInterval(std::ostream& stream, LiveInterval* interval) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100464 interval->Dump(stream);
465 stream << ": ";
466 if (interval->HasRegister()) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100467 if (interval->IsFloatingPoint()) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100468 codegen_->DumpFloatingPointRegister(stream, interval->GetRegister());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100469 } else {
470 codegen_->DumpCoreRegister(stream, interval->GetRegister());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100471 }
472 } else {
473 stream << "spilled";
474 }
475 stream << std::endl;
476}
477
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700478void RegisterAllocatorLinearScan::DumpAllIntervals(std::ostream& stream) const {
Mingyao Yang296bd602014-10-06 16:47:28 -0700479 stream << "inactive: " << std::endl;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100480 for (LiveInterval* inactive_interval : inactive_) {
481 DumpInterval(stream, inactive_interval);
Mingyao Yang296bd602014-10-06 16:47:28 -0700482 }
483 stream << "active: " << std::endl;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100484 for (LiveInterval* active_interval : active_) {
485 DumpInterval(stream, active_interval);
Mingyao Yang296bd602014-10-06 16:47:28 -0700486 }
487 stream << "unhandled: " << std::endl;
488 auto unhandled = (unhandled_ != nullptr) ?
489 unhandled_ : &unhandled_core_intervals_;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100490 for (LiveInterval* unhandled_interval : *unhandled) {
491 DumpInterval(stream, unhandled_interval);
Mingyao Yang296bd602014-10-06 16:47:28 -0700492 }
493 stream << "handled: " << std::endl;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100494 for (LiveInterval* handled_interval : handled_) {
495 DumpInterval(stream, handled_interval);
Mingyao Yang296bd602014-10-06 16:47:28 -0700496 }
497}
498
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100499// By the book implementation of a linear scan register allocator.
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700500void RegisterAllocatorLinearScan::LinearScan() {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100501 while (!unhandled_->empty()) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100502 // (1) Remove interval with the lowest start position from unhandled.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100503 LiveInterval* current = unhandled_->back();
504 unhandled_->pop_back();
Nicolas Geoffray2e92bc22015-08-20 19:52:26 +0100505
506 // Make sure the interval is an expected state.
Nicolas Geoffray39468442014-09-02 15:17:15 +0100507 DCHECK(!current->IsFixed() && !current->HasSpillSlot());
Nicolas Geoffray2e92bc22015-08-20 19:52:26 +0100508 // Make sure we are going in the right order.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100509 DCHECK(unhandled_->empty() || unhandled_->back()->GetStart() >= current->GetStart());
Nicolas Geoffray2e92bc22015-08-20 19:52:26 +0100510 // Make sure a low interval is always with a high.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100511 DCHECK(!current->IsLowInterval() || unhandled_->back()->IsHighInterval());
Nicolas Geoffray2e92bc22015-08-20 19:52:26 +0100512 // Make sure a high interval is always with a low.
513 DCHECK(current->IsLowInterval() ||
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100514 unhandled_->empty() ||
515 !unhandled_->back()->IsHighInterval());
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000516
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100517 size_t position = current->GetStart();
518
Mingyao Yang296bd602014-10-06 16:47:28 -0700519 // Remember the inactive_ size here since the ones moved to inactive_ from
520 // active_ below shouldn't need to be re-checked.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100521 size_t inactive_intervals_to_handle = inactive_.size();
Mingyao Yang296bd602014-10-06 16:47:28 -0700522
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100523 // (2) Remove currently active intervals that are dead at this position.
524 // Move active intervals that have a lifetime hole at this position
525 // to inactive.
Vladimir Markob95fb772015-09-30 13:32:31 +0100526 auto active_kept_end = std::remove_if(
527 active_.begin(),
528 active_.end(),
529 [this, position](LiveInterval* interval) {
530 if (interval->IsDeadAt(position)) {
531 handled_.push_back(interval);
532 return true;
533 } else if (!interval->Covers(position)) {
534 inactive_.push_back(interval);
535 return true;
536 } else {
537 return false; // Keep this interval.
538 }
539 });
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100540 active_.erase(active_kept_end, active_.end());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100541
542 // (3) Remove currently inactive intervals that are dead at this position.
543 // Move inactive intervals that cover this position to active.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100544 auto inactive_to_handle_end = inactive_.begin() + inactive_intervals_to_handle;
Vladimir Markob95fb772015-09-30 13:32:31 +0100545 auto inactive_kept_end = std::remove_if(
546 inactive_.begin(),
547 inactive_to_handle_end,
548 [this, position](LiveInterval* interval) {
549 DCHECK(interval->GetStart() < position || interval->IsFixed());
550 if (interval->IsDeadAt(position)) {
551 handled_.push_back(interval);
552 return true;
553 } else if (interval->Covers(position)) {
554 active_.push_back(interval);
555 return true;
556 } else {
557 return false; // Keep this interval.
558 }
559 });
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100560 inactive_.erase(inactive_kept_end, inactive_to_handle_end);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100561
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000562 if (current->IsHighInterval() && !current->GetLowInterval()->HasRegister()) {
563 DCHECK(!current->HasRegister());
564 // Allocating the low part was unsucessful. The splitted interval for the high part
565 // will be handled next (it is in the `unhandled_` list).
566 continue;
567 }
568
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100569 // (4) Try to find an available register.
570 bool success = TryAllocateFreeReg(current);
571
572 // (5) If no register could be found, we need to spill.
573 if (!success) {
574 success = AllocateBlockedReg(current);
575 }
576
577 // (6) If the interval had a register allocated, add it to the list of active
578 // intervals.
579 if (success) {
Nicolas Geoffray98893962015-01-21 12:32:32 +0000580 codegen_->AddAllocatedRegister(processing_core_registers_
581 ? Location::RegisterLocation(current->GetRegister())
582 : Location::FpuRegisterLocation(current->GetRegister()));
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100583 active_.push_back(current);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000584 if (current->HasHighInterval() && !current->GetHighInterval()->HasRegister()) {
585 current->GetHighInterval()->SetRegister(GetHighForLowRegister(current->GetRegister()));
586 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100587 }
588 }
589}
590
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000591static void FreeIfNotCoverAt(LiveInterval* interval, size_t position, size_t* free_until) {
592 DCHECK(!interval->IsHighInterval());
593 // Note that the same instruction may occur multiple times in the input list,
594 // so `free_until` may have changed already.
David Brazdil3fc992f2015-04-16 18:31:55 +0100595 // Since `position` is not the current scan position, we need to use CoversSlow.
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000596 if (interval->IsDeadAt(position)) {
597 // Set the register to be free. Note that inactive intervals might later
598 // update this.
599 free_until[interval->GetRegister()] = kMaxLifetimePosition;
600 if (interval->HasHighInterval()) {
601 DCHECK(interval->GetHighInterval()->IsDeadAt(position));
602 free_until[interval->GetHighInterval()->GetRegister()] = kMaxLifetimePosition;
603 }
David Brazdil3fc992f2015-04-16 18:31:55 +0100604 } else if (!interval->CoversSlow(position)) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000605 // The interval becomes inactive at `defined_by`. We make its register
606 // available only until the next use strictly after `defined_by`.
607 free_until[interval->GetRegister()] = interval->FirstUseAfter(position);
608 if (interval->HasHighInterval()) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100609 DCHECK(!interval->GetHighInterval()->CoversSlow(position));
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000610 free_until[interval->GetHighInterval()->GetRegister()] = free_until[interval->GetRegister()];
611 }
612 }
613}
614
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100615// Find a free register. If multiple are found, pick the register that
616// is free the longest.
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700617bool RegisterAllocatorLinearScan::TryAllocateFreeReg(LiveInterval* current) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100618 size_t* free_until = registers_array_;
619
620 // First set all registers to be free.
621 for (size_t i = 0; i < number_of_registers_; ++i) {
622 free_until[i] = kMaxLifetimePosition;
623 }
624
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100625 // For each active interval, set its register to not free.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100626 for (LiveInterval* interval : active_) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100627 DCHECK(interval->HasRegister());
628 free_until[interval->GetRegister()] = 0;
629 }
630
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000631 // An interval that starts an instruction (that is, it is not split), may
632 // re-use the registers used by the inputs of that instruciton, based on the
633 // location summary.
634 HInstruction* defined_by = current->GetDefinedBy();
635 if (defined_by != nullptr && !current->IsSplit()) {
636 LocationSummary* locations = defined_by->GetLocations();
637 if (!locations->OutputCanOverlapWithInputs() && locations->Out().IsUnallocated()) {
Vladimir Markoe9004912016-06-16 16:50:52 +0100638 HInputsRef inputs = defined_by->GetInputs();
Vladimir Marko372f10e2016-05-17 16:30:10 +0100639 for (size_t i = 0; i < inputs.size(); ++i) {
Donghui Bai426b49c2016-11-08 14:55:38 +0800640 if (locations->InAt(i).IsValid()) {
641 // Take the last interval of the input. It is the location of that interval
642 // that will be used at `defined_by`.
643 LiveInterval* interval = inputs[i]->GetLiveInterval()->GetLastSibling();
644 // Note that interval may have not been processed yet.
645 // TODO: Handle non-split intervals last in the work list.
646 if (interval->HasRegister() && interval->SameRegisterKind(*current)) {
647 // The input must be live until the end of `defined_by`, to comply to
648 // the linear scan algorithm. So we use `defined_by`'s end lifetime
649 // position to check whether the input is dead or is inactive after
650 // `defined_by`.
651 DCHECK(interval->CoversSlow(defined_by->GetLifetimePosition()));
652 size_t position = defined_by->GetLifetimePosition() + 1;
653 FreeIfNotCoverAt(interval, position, free_until);
654 }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000655 }
656 }
657 }
658 }
659
Mingyao Yang296bd602014-10-06 16:47:28 -0700660 // For each inactive interval, set its register to be free until
661 // the next intersection with `current`.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100662 for (LiveInterval* inactive : inactive_) {
Mingyao Yang296bd602014-10-06 16:47:28 -0700663 // Temp/Slow-path-safepoint interval has no holes.
Vladimir Marko70e97462016-08-09 11:04:26 +0100664 DCHECK(!inactive->IsTemp());
Mingyao Yang296bd602014-10-06 16:47:28 -0700665 if (!current->IsSplit() && !inactive->IsFixed()) {
666 // Neither current nor inactive are fixed.
667 // Thanks to SSA, a non-split interval starting in a hole of an
668 // inactive interval should never intersect with that inactive interval.
669 // Only if it's not fixed though, because fixed intervals don't come from SSA.
670 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
671 continue;
672 }
673
674 DCHECK(inactive->HasRegister());
675 if (free_until[inactive->GetRegister()] == 0) {
676 // Already used by some active interval. No need to intersect.
677 continue;
678 }
679 size_t next_intersection = inactive->FirstIntersectionWith(current);
680 if (next_intersection != kNoLifetime) {
681 free_until[inactive->GetRegister()] =
682 std::min(free_until[inactive->GetRegister()], next_intersection);
683 }
684 }
685
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000686 int reg = kNoRegister;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100687 if (current->HasRegister()) {
688 // Some instructions have a fixed register output.
689 reg = current->GetRegister();
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000690 if (free_until[reg] == 0) {
691 DCHECK(current->IsHighInterval());
692 // AllocateBlockedReg will spill the holder of the register.
693 return false;
694 }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100695 } else {
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000696 DCHECK(!current->IsHighInterval());
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +0100697 int hint = current->FindFirstRegisterHint(free_until, liveness_);
Nicolas Geoffrayf2975812015-08-07 18:13:03 -0700698 if ((hint != kNoRegister)
699 // For simplicity, if the hint we are getting for a pair cannot be used,
700 // we are just going to allocate a new pair.
701 && !(current->IsLowInterval() && IsBlocked(GetHighForLowRegister(hint)))) {
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100702 DCHECK(!IsBlocked(hint));
703 reg = hint;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000704 } else if (current->IsLowInterval()) {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000705 reg = FindAvailableRegisterPair(free_until, current->GetStart());
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100706 } else {
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100707 reg = FindAvailableRegister(free_until, current);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100708 }
709 }
710
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000711 DCHECK_NE(reg, kNoRegister);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100712 // If we could not find a register, we need to spill.
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000713 if (free_until[reg] == 0) {
714 return false;
715 }
716
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000717 if (current->IsLowInterval()) {
718 // If the high register of this interval is not available, we need to spill.
719 int high_reg = current->GetHighInterval()->GetRegister();
720 if (high_reg == kNoRegister) {
721 high_reg = GetHighForLowRegister(reg);
722 }
723 if (free_until[high_reg] == 0) {
724 return false;
725 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100726 }
727
728 current->SetRegister(reg);
729 if (!current->IsDeadAt(free_until[reg])) {
730 // If the register is only available for a subset of live ranges
Nicolas Geoffray82726882015-06-01 13:51:57 +0100731 // covered by `current`, split `current` before the position where
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100732 // the register is not available anymore.
Nicolas Geoffray82726882015-06-01 13:51:57 +0100733 LiveInterval* split = SplitBetween(current, current->GetStart(), free_until[reg]);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100734 DCHECK(split != nullptr);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100735 AddSorted(unhandled_, split);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100736 }
737 return true;
738}
739
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700740bool RegisterAllocatorLinearScan::IsBlocked(int reg) const {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100741 return processing_core_registers_
742 ? blocked_core_registers_[reg]
743 : blocked_fp_registers_[reg];
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100744}
745
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700746int RegisterAllocatorLinearScan::FindAvailableRegisterPair(size_t* next_use, size_t starting_at) const {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000747 int reg = kNoRegister;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000748 // Pick the register pair that is used the last.
749 for (size_t i = 0; i < number_of_registers_; ++i) {
750 if (IsBlocked(i)) continue;
751 if (!IsLowRegister(i)) continue;
752 int high_register = GetHighForLowRegister(i);
753 if (IsBlocked(high_register)) continue;
754 int existing_high_register = GetHighForLowRegister(reg);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000755 if ((reg == kNoRegister) || (next_use[i] >= next_use[reg]
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000756 && next_use[high_register] >= next_use[existing_high_register])) {
757 reg = i;
758 if (next_use[i] == kMaxLifetimePosition
759 && next_use[high_register] == kMaxLifetimePosition) {
760 break;
761 }
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000762 } else if (next_use[reg] <= starting_at || next_use[existing_high_register] <= starting_at) {
763 // If one of the current register is known to be unavailable, just unconditionally
764 // try a new one.
765 reg = i;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000766 }
767 }
768 return reg;
769}
770
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700771bool RegisterAllocatorLinearScan::IsCallerSaveRegister(int reg) const {
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100772 return processing_core_registers_
773 ? !codegen_->IsCoreCalleeSaveRegister(reg)
774 : !codegen_->IsFloatingPointCalleeSaveRegister(reg);
775}
776
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700777int RegisterAllocatorLinearScan::FindAvailableRegister(size_t* next_use, LiveInterval* current) const {
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100778 // We special case intervals that do not span a safepoint to try to find a caller-save
779 // register if one is available. We iterate from 0 to the number of registers,
780 // so if there are caller-save registers available at the end, we continue the iteration.
781 bool prefers_caller_save = !current->HasWillCallSafepoint();
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000782 int reg = kNoRegister;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000783 for (size_t i = 0; i < number_of_registers_; ++i) {
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100784 if (IsBlocked(i)) {
785 // Register cannot be used. Continue.
786 continue;
787 }
788
789 // Best case: we found a register fully available.
790 if (next_use[i] == kMaxLifetimePosition) {
791 if (prefers_caller_save && !IsCallerSaveRegister(i)) {
792 // We can get shorter encodings on some platforms by using
793 // small register numbers. So only update the candidate if the previous
794 // one was not available for the whole method.
795 if (reg == kNoRegister || next_use[reg] != kMaxLifetimePosition) {
796 reg = i;
797 }
798 // Continue the iteration in the hope of finding a caller save register.
799 continue;
800 } else {
801 reg = i;
802 // We know the register is good enough. Return it.
803 break;
804 }
805 }
806
807 // If we had no register before, take this one as a reference.
808 if (reg == kNoRegister) {
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000809 reg = i;
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100810 continue;
811 }
812
813 // Pick the register that is used the last.
814 if (next_use[i] > next_use[reg]) {
815 reg = i;
816 continue;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000817 }
818 }
819 return reg;
820}
821
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100822// Remove interval and its other half if any. Return iterator to the following element.
823static ArenaVector<LiveInterval*>::iterator RemoveIntervalAndPotentialOtherHalf(
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100824 ScopedArenaVector<LiveInterval*>* intervals, ScopedArenaVector<LiveInterval*>::iterator pos) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100825 DCHECK(intervals->begin() <= pos && pos < intervals->end());
826 LiveInterval* interval = *pos;
827 if (interval->IsLowInterval()) {
828 DCHECK(pos + 1 < intervals->end());
829 DCHECK_EQ(*(pos + 1), interval->GetHighInterval());
830 return intervals->erase(pos, pos + 2);
831 } else if (interval->IsHighInterval()) {
832 DCHECK(intervals->begin() < pos);
833 DCHECK_EQ(*(pos - 1), interval->GetLowInterval());
834 return intervals->erase(pos - 1, pos + 1);
835 } else {
836 return intervals->erase(pos);
837 }
838}
839
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700840bool RegisterAllocatorLinearScan::TrySplitNonPairOrUnalignedPairIntervalAt(size_t position,
841 size_t first_register_use,
842 size_t* next_use) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100843 for (auto it = active_.begin(), end = active_.end(); it != end; ++it) {
844 LiveInterval* active = *it;
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000845 DCHECK(active->HasRegister());
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000846 if (active->IsFixed()) continue;
847 if (active->IsHighInterval()) continue;
848 if (first_register_use > next_use[active->GetRegister()]) continue;
849
Nicolas Geoffray2e92bc22015-08-20 19:52:26 +0100850 // Split the first interval found that is either:
851 // 1) A non-pair interval.
852 // 2) A pair interval whose high is not low + 1.
853 // 3) A pair interval whose low is not even.
854 if (!active->IsLowInterval() ||
855 IsLowOfUnalignedPairInterval(active) ||
856 !IsLowRegister(active->GetRegister())) {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000857 LiveInterval* split = Split(active, position);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000858 if (split != active) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100859 handled_.push_back(active);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000860 }
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100861 RemoveIntervalAndPotentialOtherHalf(&active_, it);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000862 AddSorted(unhandled_, split);
863 return true;
864 }
865 }
866 return false;
867}
868
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100869// Find the register that is used the last, and spill the interval
870// that holds it. If the first use of `current` is after that register
871// we spill `current` instead.
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -0700872bool RegisterAllocatorLinearScan::AllocateBlockedReg(LiveInterval* current) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100873 size_t first_register_use = current->FirstRegisterUse();
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -0700874 if (current->HasRegister()) {
875 DCHECK(current->IsHighInterval());
876 // The low interval has allocated the register for the high interval. In
877 // case the low interval had to split both intervals, we may end up in a
878 // situation where the high interval does not have a register use anymore.
879 // We must still proceed in order to split currently active and inactive
880 // uses of the high interval's register, and put the high interval in the
881 // active set.
882 DCHECK(first_register_use != kNoLifetime || (current->GetNextSibling() != nullptr));
883 } else if (first_register_use == kNoLifetime) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100884 AllocateSpillSlotFor(current);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100885 return false;
886 }
887
888 // First set all registers as not being used.
889 size_t* next_use = registers_array_;
890 for (size_t i = 0; i < number_of_registers_; ++i) {
891 next_use[i] = kMaxLifetimePosition;
892 }
893
894 // For each active interval, find the next use of its register after the
895 // start of current.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100896 for (LiveInterval* active : active_) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100897 DCHECK(active->HasRegister());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100898 if (active->IsFixed()) {
899 next_use[active->GetRegister()] = current->GetStart();
900 } else {
Nicolas Geoffray119a8852016-02-06 17:01:15 +0000901 size_t use = active->FirstRegisterUseAfter(current->GetStart());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100902 if (use != kNoLifetime) {
903 next_use[active->GetRegister()] = use;
904 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100905 }
906 }
907
908 // For each inactive interval, find the next use of its register after the
909 // start of current.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100910 for (LiveInterval* inactive : inactive_) {
Mingyao Yang296bd602014-10-06 16:47:28 -0700911 // Temp/Slow-path-safepoint interval has no holes.
Vladimir Marko70e97462016-08-09 11:04:26 +0100912 DCHECK(!inactive->IsTemp());
Mingyao Yang296bd602014-10-06 16:47:28 -0700913 if (!current->IsSplit() && !inactive->IsFixed()) {
914 // Neither current nor inactive are fixed.
915 // Thanks to SSA, a non-split interval starting in a hole of an
916 // inactive interval should never intersect with that inactive interval.
917 // Only if it's not fixed though, because fixed intervals don't come from SSA.
918 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
919 continue;
920 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100921 DCHECK(inactive->HasRegister());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100922 size_t next_intersection = inactive->FirstIntersectionWith(current);
923 if (next_intersection != kNoLifetime) {
924 if (inactive->IsFixed()) {
925 next_use[inactive->GetRegister()] =
926 std::min(next_intersection, next_use[inactive->GetRegister()]);
927 } else {
Nicolas Geoffray1ba19812015-04-21 09:12:40 +0100928 size_t use = inactive->FirstUseAfter(current->GetStart());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100929 if (use != kNoLifetime) {
930 next_use[inactive->GetRegister()] = std::min(use, next_use[inactive->GetRegister()]);
931 }
932 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100933 }
934 }
935
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000936 int reg = kNoRegister;
937 bool should_spill = false;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000938 if (current->HasRegister()) {
939 DCHECK(current->IsHighInterval());
940 reg = current->GetRegister();
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000941 // When allocating the low part, we made sure the high register was available.
Nicolas Geoffray119a8852016-02-06 17:01:15 +0000942 DCHECK_LT(first_register_use, next_use[reg]);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000943 } else if (current->IsLowInterval()) {
Nicolas Geoffray119a8852016-02-06 17:01:15 +0000944 reg = FindAvailableRegisterPair(next_use, first_register_use);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000945 // We should spill if both registers are not available.
Nicolas Geoffray119a8852016-02-06 17:01:15 +0000946 should_spill = (first_register_use >= next_use[reg])
947 || (first_register_use >= next_use[GetHighForLowRegister(reg)]);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000948 } else {
949 DCHECK(!current->IsHighInterval());
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100950 reg = FindAvailableRegister(next_use, current);
Nicolas Geoffray119a8852016-02-06 17:01:15 +0000951 should_spill = (first_register_use >= next_use[reg]);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100952 }
953
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000954 DCHECK_NE(reg, kNoRegister);
955 if (should_spill) {
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000956 DCHECK(!current->IsHighInterval());
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000957 bool is_allocation_at_use_site = (current->GetStart() >= (first_register_use - 1));
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -0700958 if (is_allocation_at_use_site) {
959 if (!current->IsLowInterval()) {
960 DumpInterval(std::cerr, current);
961 DumpAllIntervals(std::cerr);
962 // This situation has the potential to infinite loop, so we make it a non-debug CHECK.
963 HInstruction* at = liveness_.GetInstructionFromPosition(first_register_use / 2);
964 CHECK(false) << "There is not enough registers available for "
965 << current->GetParent()->GetDefinedBy()->DebugName() << " "
966 << current->GetParent()->GetDefinedBy()->GetId()
967 << " at " << first_register_use - 1 << " "
968 << (at == nullptr ? "" : at->DebugName());
969 }
970
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000971 // If we're allocating a register for `current` because the instruction at
972 // that position requires it, but we think we should spill, then there are
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000973 // non-pair intervals or unaligned pair intervals blocking the allocation.
974 // We split the first interval found, and put ourselves first in the
975 // `unhandled_` list.
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -0700976 bool success = TrySplitNonPairOrUnalignedPairIntervalAt(current->GetStart(),
977 first_register_use,
978 next_use);
979 DCHECK(success);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100980 LiveInterval* existing = unhandled_->back();
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000981 DCHECK(existing->IsHighInterval());
982 DCHECK_EQ(existing->GetLowInterval(), current);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100983 unhandled_->push_back(current);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000984 } else {
985 // If the first use of that instruction is after the last use of the found
986 // register, we split this interval just before its first register use.
987 AllocateSpillSlotFor(current);
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +0100988 LiveInterval* split = SplitBetween(current, current->GetStart(), first_register_use - 1);
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -0700989 DCHECK(current != split);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000990 AddSorted(unhandled_, split);
991 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100992 return false;
993 } else {
994 // Use this register and spill the active and inactives interval that
995 // have that register.
996 current->SetRegister(reg);
997
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100998 for (auto it = active_.begin(), end = active_.end(); it != end; ++it) {
999 LiveInterval* active = *it;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001000 if (active->GetRegister() == reg) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001001 DCHECK(!active->IsFixed());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001002 LiveInterval* split = Split(active, current->GetStart());
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00001003 if (split != active) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001004 handled_.push_back(active);
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00001005 }
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001006 RemoveIntervalAndPotentialOtherHalf(&active_, it);
Nicolas Geoffray39468442014-09-02 15:17:15 +01001007 AddSorted(unhandled_, split);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001008 break;
1009 }
1010 }
1011
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001012 // NOTE: Retrieve end() on each iteration because we're removing elements in the loop body.
1013 for (auto it = inactive_.begin(); it != inactive_.end(); ) {
1014 LiveInterval* inactive = *it;
1015 bool erased = false;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001016 if (inactive->GetRegister() == reg) {
Mingyao Yang296bd602014-10-06 16:47:28 -07001017 if (!current->IsSplit() && !inactive->IsFixed()) {
1018 // Neither current nor inactive are fixed.
1019 // Thanks to SSA, a non-split interval starting in a hole of an
1020 // inactive interval should never intersect with that inactive interval.
1021 // Only if it's not fixed though, because fixed intervals don't come from SSA.
1022 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001023 } else {
1024 size_t next_intersection = inactive->FirstIntersectionWith(current);
1025 if (next_intersection != kNoLifetime) {
1026 if (inactive->IsFixed()) {
1027 LiveInterval* split = Split(current, next_intersection);
1028 DCHECK_NE(split, current);
1029 AddSorted(unhandled_, split);
1030 } else {
1031 // Split at the start of `current`, which will lead to splitting
1032 // at the end of the lifetime hole of `inactive`.
1033 LiveInterval* split = Split(inactive, current->GetStart());
1034 // If it's inactive, it must start before the current interval.
1035 DCHECK_NE(split, inactive);
1036 it = RemoveIntervalAndPotentialOtherHalf(&inactive_, it);
1037 erased = true;
1038 handled_.push_back(inactive);
1039 AddSorted(unhandled_, split);
Nicolas Geoffray5b168de2015-03-27 10:27:22 +00001040 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001041 }
1042 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001043 }
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001044 // If we have erased the element, `it` already points to the next element.
1045 // Otherwise we need to move to the next element.
1046 if (!erased) {
1047 ++it;
1048 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001049 }
1050
1051 return true;
1052 }
1053}
1054
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001055void RegisterAllocatorLinearScan::AddSorted(ScopedArenaVector<LiveInterval*>* array,
1056 LiveInterval* interval) {
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +01001057 DCHECK(!interval->IsFixed() && !interval->HasSpillSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001058 size_t insert_at = 0;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001059 for (size_t i = array->size(); i > 0; --i) {
1060 LiveInterval* current = (*array)[i - 1u];
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001061 // High intervals must be processed right after their low equivalent.
1062 if (current->StartsAfter(interval) && !current->IsHighInterval()) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001063 insert_at = i;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001064 break;
1065 }
1066 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001067
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001068 // Insert the high interval before the low, to ensure the low is processed before.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001069 auto insert_pos = array->begin() + insert_at;
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001070 if (interval->HasHighInterval()) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001071 array->insert(insert_pos, { interval->GetHighInterval(), interval });
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001072 } else if (interval->HasLowInterval()) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001073 array->insert(insert_pos, { interval, interval->GetLowInterval() });
1074 } else {
1075 array->insert(insert_pos, interval);
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001076 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001077}
1078
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -07001079void RegisterAllocatorLinearScan::AllocateSpillSlotFor(LiveInterval* interval) {
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001080 if (interval->IsHighInterval()) {
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -07001081 // The low interval already took care of allocating the spill slot.
1082 DCHECK(!interval->GetLowInterval()->HasRegister());
1083 DCHECK(interval->GetLowInterval()->GetParent()->HasSpillSlot());
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001084 return;
1085 }
1086
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001087 LiveInterval* parent = interval->GetParent();
1088
1089 // An instruction gets a spill slot for its entire lifetime. If the parent
1090 // of this interval already has a spill slot, there is nothing to do.
1091 if (parent->HasSpillSlot()) {
1092 return;
1093 }
1094
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001095 HInstruction* defined_by = parent->GetDefinedBy();
David Brazdil77a48ae2015-09-15 12:34:04 +00001096 DCHECK(!defined_by->IsPhi() || !defined_by->AsPhi()->IsCatchPhi());
1097
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001098 if (defined_by->IsParameterValue()) {
1099 // Parameters have their own stack slot.
1100 parent->SetSpillSlot(codegen_->GetStackSlotOfParameter(defined_by->AsParameterValue()));
1101 return;
1102 }
1103
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001104 if (defined_by->IsCurrentMethod()) {
1105 parent->SetSpillSlot(0);
1106 return;
1107 }
1108
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001109 if (defined_by->IsConstant()) {
1110 // Constants don't need a spill slot.
1111 return;
1112 }
1113
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001114 ScopedArenaVector<size_t>* spill_slots = nullptr;
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001115 switch (interval->GetType()) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001116 case DataType::Type::kFloat64:
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001117 spill_slots = &double_spill_slots_;
1118 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001119 case DataType::Type::kInt64:
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001120 spill_slots = &long_spill_slots_;
1121 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001122 case DataType::Type::kFloat32:
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001123 spill_slots = &float_spill_slots_;
1124 break;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001125 case DataType::Type::kReference:
1126 case DataType::Type::kInt32:
1127 case DataType::Type::kUint16:
Vladimir Markod5d2f2c2017-09-26 12:37:26 +01001128 case DataType::Type::kUint8:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001129 case DataType::Type::kInt8:
1130 case DataType::Type::kBool:
1131 case DataType::Type::kInt16:
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001132 spill_slots = &int_spill_slots_;
1133 break;
Aart Bik66c158e2018-01-31 12:55:04 -08001134 case DataType::Type::kUint32:
1135 case DataType::Type::kUint64:
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001136 case DataType::Type::kVoid:
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001137 LOG(FATAL) << "Unexpected type for interval " << interval->GetType();
1138 }
1139
Aart Bikcc895252017-03-21 10:55:15 -07001140 // Find first available spill slots.
1141 size_t number_of_spill_slots_needed = parent->NumberOfSpillSlotsNeeded();
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001142 size_t slot = 0;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001143 for (size_t e = spill_slots->size(); slot < e; ++slot) {
Aart Bikcc895252017-03-21 10:55:15 -07001144 bool found = true;
1145 for (size_t s = slot, u = std::min(slot + number_of_spill_slots_needed, e); s < u; s++) {
1146 if ((*spill_slots)[s] > parent->GetStart()) {
1147 found = false; // failure
Matthew Gharrityf64a6ab2016-07-11 14:45:01 -07001148 break;
1149 }
Aart Bikcc895252017-03-21 10:55:15 -07001150 }
1151 if (found) {
1152 break; // success
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001153 }
1154 }
1155
Aart Bikcc895252017-03-21 10:55:15 -07001156 // Need new spill slots?
1157 size_t upper = slot + number_of_spill_slots_needed;
1158 if (upper > spill_slots->size()) {
1159 spill_slots->resize(upper);
1160 }
1161 // Set slots to end.
David Brazdil77a48ae2015-09-15 12:34:04 +00001162 size_t end = interval->GetLastSibling()->GetEnd();
Aart Bikcc895252017-03-21 10:55:15 -07001163 for (size_t s = slot; s < upper; s++) {
1164 (*spill_slots)[s] = end;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001165 }
1166
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001167 // Note that the exact spill slot location will be computed when we resolve,
1168 // that is when we know the number of spill slots for each type.
1169 parent->SetSpillSlot(slot);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001170}
1171
Matthew Gharrity8f49d4b2016-07-14 13:24:00 -07001172void RegisterAllocatorLinearScan::AllocateSpillSlotForCatchPhi(HPhi* phi) {
David Brazdil77a48ae2015-09-15 12:34:04 +00001173 LiveInterval* interval = phi->GetLiveInterval();
1174
1175 HInstruction* previous_phi = phi->GetPrevious();
1176 DCHECK(previous_phi == nullptr ||
1177 previous_phi->AsPhi()->GetRegNumber() <= phi->GetRegNumber())
1178 << "Phis expected to be sorted by vreg number, so that equivalent phis are adjacent.";
1179
1180 if (phi->IsVRegEquivalentOf(previous_phi)) {
1181 // This is an equivalent of the previous phi. We need to assign the same
1182 // catch phi slot.
1183 DCHECK(previous_phi->GetLiveInterval()->HasSpillSlot());
1184 interval->SetSpillSlot(previous_phi->GetLiveInterval()->GetSpillSlot());
1185 } else {
1186 // Allocate a new spill slot for this catch phi.
1187 // TODO: Reuse spill slots when intervals of phis from different catch
1188 // blocks do not overlap.
1189 interval->SetSpillSlot(catch_phi_spill_slots_);
Aart Bikcc895252017-03-21 10:55:15 -07001190 catch_phi_spill_slots_ += interval->NumberOfSpillSlotsNeeded();
David Brazdil77a48ae2015-09-15 12:34:04 +00001191 }
1192}
1193
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001194} // namespace art