blob: 00848f3d86e69828d994068dce2a2271000df455 [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
17#include "register_allocator.h"
18
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"
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010023#include "code_generator.h"
24#include "ssa_liveness_analysis.h"
25
26namespace art {
27
28static constexpr size_t kMaxLifetimePosition = -1;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010029static constexpr size_t kDefaultNumberOfSpillSlots = 4;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010030
Nicolas Geoffray840e5462015-01-07 16:01:24 +000031// For simplicity, we implement register pairs as (reg, reg + 1).
32// Note that this is a requirement for double registers on ARM, since we
33// allocate SRegister.
34static int GetHighForLowRegister(int reg) { return reg + 1; }
35static bool IsLowRegister(int reg) { return (reg & 1) == 0; }
Nicolas Geoffray234d69d2015-03-09 10:28:50 +000036static bool IsLowOfUnalignedPairInterval(LiveInterval* low) {
37 return GetHighForLowRegister(low->GetRegister()) != low->GetHighInterval()->GetRegister();
38}
Nicolas Geoffray840e5462015-01-07 16:01:24 +000039
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010040RegisterAllocator::RegisterAllocator(ArenaAllocator* allocator,
41 CodeGenerator* codegen,
42 const SsaLivenessAnalysis& liveness)
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010043 : allocator_(allocator),
44 codegen_(codegen),
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010045 liveness_(liveness),
Nicolas Geoffray39468442014-09-02 15:17:15 +010046 unhandled_core_intervals_(allocator, 0),
47 unhandled_fp_intervals_(allocator, 0),
48 unhandled_(nullptr),
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010049 handled_(allocator, 0),
50 active_(allocator, 0),
51 inactive_(allocator, 0),
Nicolas Geoffray102cbed2014-10-15 18:31:05 +010052 physical_core_register_intervals_(allocator, codegen->GetNumberOfCoreRegisters()),
53 physical_fp_register_intervals_(allocator, codegen->GetNumberOfFloatingPointRegisters()),
Nicolas Geoffray39468442014-09-02 15:17:15 +010054 temp_intervals_(allocator, 4),
Nicolas Geoffray776b3182015-02-23 14:14:57 +000055 int_spill_slots_(allocator, kDefaultNumberOfSpillSlots),
56 long_spill_slots_(allocator, kDefaultNumberOfSpillSlots),
57 float_spill_slots_(allocator, kDefaultNumberOfSpillSlots),
58 double_spill_slots_(allocator, kDefaultNumberOfSpillSlots),
Nicolas Geoffray39468442014-09-02 15:17:15 +010059 safepoints_(allocator, 0),
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010060 processing_core_registers_(false),
61 number_of_registers_(-1),
62 registers_array_(nullptr),
Nicolas Geoffray102cbed2014-10-15 18:31:05 +010063 blocked_core_registers_(codegen->GetBlockedCoreRegisters()),
64 blocked_fp_registers_(codegen->GetBlockedFloatingPointRegisters()),
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +010065 reserved_out_slots_(0),
Mark Mendellf85a9ca2015-01-13 09:20:58 -050066 maximum_number_of_live_core_registers_(0),
67 maximum_number_of_live_fp_registers_(0) {
Nicolas Geoffray98893962015-01-21 12:32:32 +000068 static constexpr bool kIsBaseline = false;
69 codegen->SetupBlockedRegisters(kIsBaseline);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +010070 physical_core_register_intervals_.SetSize(codegen->GetNumberOfCoreRegisters());
71 physical_fp_register_intervals_.SetSize(codegen->GetNumberOfFloatingPointRegisters());
Nicolas Geoffray39468442014-09-02 15:17:15 +010072 // Always reserve for the current method and the graph's max out registers.
73 // TODO: compute it instead.
Mathieu Chartiere401d142015-04-22 13:56:20 -070074 // ArtMethod* takes 2 vregs for 64 bits.
75 reserved_out_slots_ = InstructionSetPointerSize(codegen->GetInstructionSet()) / kVRegSize +
76 codegen->GetGraph()->GetMaximumNumberOfOutVRegs();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010077}
78
Nicolas Geoffray234d69d2015-03-09 10:28:50 +000079bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph ATTRIBUTE_UNUSED,
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010080 InstructionSet instruction_set) {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +000081 return instruction_set == kArm64
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +000082 || instruction_set == kX86_64
Alexey Frunze4dda3372015-06-01 18:31:49 -070083 || instruction_set == kMips64
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +000084 || instruction_set == kArm
Nicolas Geoffray234d69d2015-03-09 10:28:50 +000085 || instruction_set == kX86
86 || instruction_set == kThumb2;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010087}
88
89static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) {
Nicolas Geoffray39468442014-09-02 15:17:15 +010090 if (interval == nullptr) return false;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010091 bool is_core_register = (interval->GetType() != Primitive::kPrimDouble)
92 && (interval->GetType() != Primitive::kPrimFloat);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010093 return processing_core_registers == is_core_register;
94}
95
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010096void RegisterAllocator::AllocateRegisters() {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010097 AllocateRegistersInternal();
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010098 Resolve();
99
100 if (kIsDebugBuild) {
101 processing_core_registers_ = true;
102 ValidateInternal(true);
103 processing_core_registers_ = false;
104 ValidateInternal(true);
Nicolas Geoffray59768572014-12-01 09:50:04 +0000105 // Check that the linear order is still correct with regards to lifetime positions.
106 // Since only parallel moves have been inserted during the register allocation,
107 // these checks are mostly for making sure these moves have been added correctly.
108 size_t current_liveness = 0;
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100109 for (HLinearOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
Nicolas Geoffray59768572014-12-01 09:50:04 +0000110 HBasicBlock* block = it.Current();
111 for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
112 HInstruction* instruction = inst_it.Current();
113 DCHECK_LE(current_liveness, instruction->GetLifetimePosition());
114 current_liveness = instruction->GetLifetimePosition();
115 }
116 for (HInstructionIterator inst_it(block->GetInstructions());
117 !inst_it.Done();
118 inst_it.Advance()) {
119 HInstruction* instruction = inst_it.Current();
120 DCHECK_LE(current_liveness, instruction->GetLifetimePosition()) << instruction->DebugName();
121 current_liveness = instruction->GetLifetimePosition();
122 }
123 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100124 }
125}
126
127void RegisterAllocator::BlockRegister(Location location,
128 size_t start,
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100129 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()
133 ? physical_core_register_intervals_.Get(reg)
134 : physical_fp_register_intervals_.Get(reg);
135 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()) {
141 physical_core_register_intervals_.Put(reg, interval);
142 } else {
143 physical_fp_register_intervals_.Put(reg, interval);
144 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100145 }
146 DCHECK(interval->GetRegister() == reg);
147 interval->AddRange(start, end);
148}
149
150void RegisterAllocator::AllocateRegistersInternal() {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100151 // Iterate post-order, to ensure the list is sorted, and the last added interval
152 // is the one with the lowest start position.
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100153 for (HLinearPostOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100154 HBasicBlock* block = it.Current();
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800155 for (HBackwardInstructionIterator back_it(block->GetInstructions()); !back_it.Done();
156 back_it.Advance()) {
157 ProcessInstruction(back_it.Current());
Nicolas Geoffray39468442014-09-02 15:17:15 +0100158 }
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800159 for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
160 ProcessInstruction(inst_it.Current());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100161 }
162 }
163
Nicolas Geoffray39468442014-09-02 15:17:15 +0100164 number_of_registers_ = codegen_->GetNumberOfCoreRegisters();
165 registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
166 processing_core_registers_ = true;
167 unhandled_ = &unhandled_core_intervals_;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100168 for (size_t i = 0, e = physical_core_register_intervals_.Size(); i < e; ++i) {
169 LiveInterval* fixed = physical_core_register_intervals_.Get(i);
170 if (fixed != nullptr) {
Mingyao Yang296bd602014-10-06 16:47:28 -0700171 // Fixed interval is added to inactive_ instead of unhandled_.
172 // It's also the only type of inactive interval whose start position
173 // can be after the current interval during linear scan.
174 // Fixed interval is never split and never moves to unhandled_.
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100175 inactive_.Add(fixed);
176 }
177 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100178 LinearScan();
Nicolas Geoffray39468442014-09-02 15:17:15 +0100179
180 inactive_.Reset();
181 active_.Reset();
182 handled_.Reset();
183
184 number_of_registers_ = codegen_->GetNumberOfFloatingPointRegisters();
185 registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
186 processing_core_registers_ = false;
187 unhandled_ = &unhandled_fp_intervals_;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100188 for (size_t i = 0, e = physical_fp_register_intervals_.Size(); i < e; ++i) {
189 LiveInterval* fixed = physical_fp_register_intervals_.Get(i);
190 if (fixed != nullptr) {
Mingyao Yang296bd602014-10-06 16:47:28 -0700191 // Fixed interval is added to inactive_ instead of unhandled_.
192 // It's also the only type of inactive interval whose start position
193 // can be after the current interval during linear scan.
194 // Fixed interval is never split and never moves to unhandled_.
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100195 inactive_.Add(fixed);
196 }
197 }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100198 LinearScan();
199}
200
201void RegisterAllocator::ProcessInstruction(HInstruction* instruction) {
202 LocationSummary* locations = instruction->GetLocations();
203 size_t position = instruction->GetLifetimePosition();
204
205 if (locations == nullptr) return;
206
207 // Create synthesized intervals for temporaries.
208 for (size_t i = 0; i < locations->GetTempCount(); ++i) {
209 Location temp = locations->GetTemp(i);
Nicolas Geoffray52839d12014-11-07 17:47:25 +0000210 if (temp.IsRegister() || temp.IsFpuRegister()) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100211 BlockRegister(temp, position, position + 1);
Nicolas Geoffray45b83af2015-07-06 15:12:53 +0000212 // Ensure that an explicit temporary register is marked as being allocated.
213 codegen_->AddAllocatedRegister(temp);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100214 } else {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100215 DCHECK(temp.IsUnallocated());
Roland Levillain5368c212014-11-27 15:03:41 +0000216 switch (temp.GetPolicy()) {
217 case Location::kRequiresRegister: {
218 LiveInterval* interval =
219 LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimInt);
220 temp_intervals_.Add(interval);
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000221 interval->AddTempUse(instruction, i);
Roland Levillain5368c212014-11-27 15:03:41 +0000222 unhandled_core_intervals_.Add(interval);
223 break;
224 }
225
226 case Location::kRequiresFpuRegister: {
227 LiveInterval* interval =
228 LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimDouble);
229 temp_intervals_.Add(interval);
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000230 interval->AddTempUse(instruction, i);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000231 if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) {
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100232 interval->AddHighInterval(/* is_temp */ true);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000233 LiveInterval* high = interval->GetHighInterval();
234 temp_intervals_.Add(high);
235 unhandled_fp_intervals_.Add(high);
236 }
Roland Levillain5368c212014-11-27 15:03:41 +0000237 unhandled_fp_intervals_.Add(interval);
238 break;
239 }
240
241 default:
242 LOG(FATAL) << "Unexpected policy for temporary location "
243 << temp.GetPolicy();
244 }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100245 }
246 }
247
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100248 bool core_register = (instruction->GetType() != Primitive::kPrimDouble)
249 && (instruction->GetType() != Primitive::kPrimFloat);
250
Nicolas Geoffray39468442014-09-02 15:17:15 +0100251 if (locations->CanCall()) {
Nicolas Geoffrayc0572a42015-02-06 14:35:25 +0000252 if (codegen_->IsLeafMethod()) {
253 // TODO: We do this here because we do not want the suspend check to artificially
254 // create live registers. We should find another place, but this is currently the
255 // simplest.
256 DCHECK(instruction->IsSuspendCheckEntry());
257 instruction->GetBlock()->RemoveInstruction(instruction);
258 return;
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100259 }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100260 safepoints_.Add(instruction);
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100261 if (locations->OnlyCallsOnSlowPath()) {
262 // We add a synthesized range at this position to record the live registers
263 // at this position. Ideally, we could just update the safepoints when locations
264 // are updated, but we currently need to know the full stack size before updating
265 // locations (because of parameters and the fact that we don't have a frame pointer).
266 // And knowing the full stack size requires to know the maximum number of live
267 // registers at calls in slow paths.
268 // By adding the following interval in the algorithm, we can compute this
269 // maximum before updating locations.
270 LiveInterval* interval = LiveInterval::MakeSlowPathInterval(allocator_, instruction);
Nicolas Geoffrayacd03392014-11-26 15:46:52 +0000271 interval->AddRange(position, position + 1);
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000272 AddSorted(&unhandled_core_intervals_, interval);
273 AddSorted(&unhandled_fp_intervals_, interval);
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100274 }
275 }
276
277 if (locations->WillCall()) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100278 // Block all registers.
279 for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) {
Nicolas Geoffray98893962015-01-21 12:32:32 +0000280 if (!codegen_->IsCoreCalleeSaveRegister(i)) {
281 BlockRegister(Location::RegisterLocation(i),
282 position,
283 position + 1);
284 }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100285 }
286 for (size_t i = 0; i < codegen_->GetNumberOfFloatingPointRegisters(); ++i) {
Nicolas Geoffray98893962015-01-21 12:32:32 +0000287 if (!codegen_->IsFloatingPointCalleeSaveRegister(i)) {
288 BlockRegister(Location::FpuRegisterLocation(i),
289 position,
290 position + 1);
291 }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100292 }
293 }
294
295 for (size_t i = 0; i < instruction->InputCount(); ++i) {
296 Location input = locations->InAt(i);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100297 if (input.IsRegister() || input.IsFpuRegister()) {
298 BlockRegister(input, position, position + 1);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000299 } else if (input.IsPair()) {
300 BlockRegister(input.ToLow(), position, position + 1);
301 BlockRegister(input.ToHigh(), position, position + 1);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100302 }
303 }
304
Nicolas Geoffray39468442014-09-02 15:17:15 +0100305 LiveInterval* current = instruction->GetLiveInterval();
306 if (current == nullptr) return;
307
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100308 GrowableArray<LiveInterval*>& unhandled = core_register
309 ? unhandled_core_intervals_
310 : unhandled_fp_intervals_;
311
Nicolas Geoffray76905622014-09-25 14:39:26 +0100312 DCHECK(unhandled.IsEmpty() || current->StartsBeforeOrAt(unhandled.Peek()));
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000313
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000314 if (codegen_->NeedsTwoRegisters(current->GetType())) {
315 current->AddHighInterval();
316 }
317
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100318 for (size_t safepoint_index = safepoints_.Size(); safepoint_index > 0; --safepoint_index) {
319 HInstruction* safepoint = safepoints_.Get(safepoint_index - 1);
320 size_t safepoint_position = safepoint->GetLifetimePosition();
321
322 // Test that safepoints are ordered in the optimal way.
323 DCHECK(safepoint_index == safepoints_.Size()
324 || safepoints_.Get(safepoint_index)->GetLifetimePosition() < safepoint_position);
325
326 if (safepoint_position == current->GetStart()) {
327 // The safepoint is for this instruction, so the location of the instruction
328 // does not need to be saved.
329 DCHECK_EQ(safepoint_index, safepoints_.Size());
330 DCHECK_EQ(safepoint, instruction);
331 continue;
332 } else if (current->IsDeadAt(safepoint_position)) {
333 break;
334 } else if (!current->Covers(safepoint_position)) {
335 // Hole in the interval.
336 continue;
337 }
338 current->AddSafepoint(safepoint);
339 }
David Brazdil3fc992f2015-04-16 18:31:55 +0100340 current->ResetSearchCache();
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100341
Nicolas Geoffray39468442014-09-02 15:17:15 +0100342 // Some instructions define their output in fixed register/stack slot. We need
343 // to ensure we know these locations before doing register allocation. For a
344 // given register, we create an interval that covers these locations. The register
345 // will be unavailable at these locations when trying to allocate one for an
346 // interval.
347 //
348 // The backwards walking ensures the ranges are ordered on increasing start positions.
349 Location output = locations->Out();
Calin Juravled0d48522014-11-04 16:40:20 +0000350 if (output.IsUnallocated() && output.GetPolicy() == Location::kSameAsFirstInput) {
351 Location first = locations->InAt(0);
352 if (first.IsRegister() || first.IsFpuRegister()) {
353 current->SetFrom(position + 1);
354 current->SetRegister(first.reg());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000355 } else if (first.IsPair()) {
356 current->SetFrom(position + 1);
357 current->SetRegister(first.low());
358 LiveInterval* high = current->GetHighInterval();
359 high->SetRegister(first.high());
360 high->SetFrom(position + 1);
Calin Juravled0d48522014-11-04 16:40:20 +0000361 }
362 } else if (output.IsRegister() || output.IsFpuRegister()) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100363 // Shift the interval's start by one to account for the blocked register.
364 current->SetFrom(position + 1);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100365 current->SetRegister(output.reg());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100366 BlockRegister(output, position, position + 1);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000367 } else if (output.IsPair()) {
368 current->SetFrom(position + 1);
369 current->SetRegister(output.low());
370 LiveInterval* high = current->GetHighInterval();
371 high->SetRegister(output.high());
372 high->SetFrom(position + 1);
373 BlockRegister(output.ToLow(), position, position + 1);
374 BlockRegister(output.ToHigh(), position, position + 1);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100375 } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) {
376 current->SetSpillSlot(output.GetStackIndex());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000377 } else {
378 DCHECK(output.IsUnallocated() || output.IsConstant());
Nicolas Geoffray39468442014-09-02 15:17:15 +0100379 }
380
381 // If needed, add interval to the list of unhandled intervals.
382 if (current->HasSpillSlot() || instruction->IsConstant()) {
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +0100383 // Split just before first register use.
Nicolas Geoffray39468442014-09-02 15:17:15 +0100384 size_t first_register_use = current->FirstRegisterUse();
385 if (first_register_use != kNoLifetime) {
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +0100386 LiveInterval* split = SplitBetween(current, current->GetStart(), first_register_use - 1);
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000387 // Don't add directly to `unhandled`, it needs to be sorted and the start
Nicolas Geoffray39468442014-09-02 15:17:15 +0100388 // of this new interval might be after intervals already in the list.
389 AddSorted(&unhandled, split);
390 } else {
391 // Nothing to do, we won't allocate a register for this value.
392 }
393 } else {
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000394 // Don't add directly to `unhandled`, temp or safepoint intervals
395 // for this instruction may have been added, and those can be
396 // processed first.
397 AddSorted(&unhandled, current);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100398 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100399}
400
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100401class AllRangesIterator : public ValueObject {
402 public:
403 explicit AllRangesIterator(LiveInterval* interval)
404 : current_interval_(interval),
405 current_range_(interval->GetFirstRange()) {}
406
407 bool Done() const { return current_interval_ == nullptr; }
408 LiveRange* CurrentRange() const { return current_range_; }
409 LiveInterval* CurrentInterval() const { return current_interval_; }
410
411 void Advance() {
412 current_range_ = current_range_->GetNext();
413 if (current_range_ == nullptr) {
414 current_interval_ = current_interval_->GetNextSibling();
415 if (current_interval_ != nullptr) {
416 current_range_ = current_interval_->GetFirstRange();
417 }
418 }
419 }
420
421 private:
422 LiveInterval* current_interval_;
423 LiveRange* current_range_;
424
425 DISALLOW_COPY_AND_ASSIGN(AllRangesIterator);
426};
427
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100428bool RegisterAllocator::ValidateInternal(bool log_fatal_on_failure) const {
429 // To simplify unit testing, we eagerly create the array of intervals, and
430 // call the helper method.
431 GrowableArray<LiveInterval*> intervals(allocator_, 0);
432 for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) {
433 HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
434 if (ShouldProcess(processing_core_registers_, instruction->GetLiveInterval())) {
435 intervals.Add(instruction->GetLiveInterval());
436 }
437 }
438
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100439 if (processing_core_registers_) {
440 for (size_t i = 0, e = physical_core_register_intervals_.Size(); i < e; ++i) {
441 LiveInterval* fixed = physical_core_register_intervals_.Get(i);
442 if (fixed != nullptr) {
443 intervals.Add(fixed);
444 }
445 }
446 } else {
447 for (size_t i = 0, e = physical_fp_register_intervals_.Size(); i < e; ++i) {
448 LiveInterval* fixed = physical_fp_register_intervals_.Get(i);
449 if (fixed != nullptr) {
450 intervals.Add(fixed);
451 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100452 }
453 }
454
Nicolas Geoffray39468442014-09-02 15:17:15 +0100455 for (size_t i = 0, e = temp_intervals_.Size(); i < e; ++i) {
456 LiveInterval* temp = temp_intervals_.Get(i);
457 if (ShouldProcess(processing_core_registers_, temp)) {
458 intervals.Add(temp);
459 }
460 }
461
Nicolas Geoffray776b3182015-02-23 14:14:57 +0000462 return ValidateIntervals(intervals, GetNumberOfSpillSlots(), reserved_out_slots_, *codegen_,
Nicolas Geoffray39468442014-09-02 15:17:15 +0100463 allocator_, processing_core_registers_, log_fatal_on_failure);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100464}
465
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100466bool RegisterAllocator::ValidateIntervals(const GrowableArray<LiveInterval*>& intervals,
467 size_t number_of_spill_slots,
Nicolas Geoffray39468442014-09-02 15:17:15 +0100468 size_t number_of_out_slots,
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100469 const CodeGenerator& codegen,
470 ArenaAllocator* allocator,
471 bool processing_core_registers,
472 bool log_fatal_on_failure) {
473 size_t number_of_registers = processing_core_registers
474 ? codegen.GetNumberOfCoreRegisters()
475 : codegen.GetNumberOfFloatingPointRegisters();
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100476 GrowableArray<ArenaBitVector*> liveness_of_values(
477 allocator, number_of_registers + number_of_spill_slots);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100478
479 // Allocate a bit vector per register. A live interval that has a register
480 // allocated will populate the associated bit vector based on its live ranges.
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100481 for (size_t i = 0; i < number_of_registers + number_of_spill_slots; ++i) {
482 liveness_of_values.Add(new (allocator) ArenaBitVector(allocator, 0, true));
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100483 }
484
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100485 for (size_t i = 0, e = intervals.Size(); i < e; ++i) {
486 for (AllRangesIterator it(intervals.Get(i)); !it.Done(); it.Advance()) {
487 LiveInterval* current = it.CurrentInterval();
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100488 HInstruction* defined_by = current->GetParent()->GetDefinedBy();
489 if (current->GetParent()->HasSpillSlot()
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100490 // Parameters and current method have their own stack slot.
491 && !(defined_by != nullptr && (defined_by->IsParameterValue()
492 || defined_by->IsCurrentMethod()))) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100493 BitVector* liveness_of_spill_slot = liveness_of_values.Get(number_of_registers
494 + current->GetParent()->GetSpillSlot() / kVRegSize
495 - number_of_out_slots);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100496 for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
497 if (liveness_of_spill_slot->IsBitSet(j)) {
498 if (log_fatal_on_failure) {
499 std::ostringstream message;
500 message << "Spill slot conflict at " << j;
501 LOG(FATAL) << message.str();
502 } else {
503 return false;
504 }
505 } else {
506 liveness_of_spill_slot->SetBit(j);
507 }
508 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100509 }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100510
511 if (current->HasRegister()) {
Nicolas Geoffray45b83af2015-07-06 15:12:53 +0000512 if (kIsDebugBuild && log_fatal_on_failure && !current->IsFixed()) {
513 // Only check when an error is fatal. Only tests code ask for non-fatal failures
514 // and test code may not properly fill the right information to the code generator.
515 CHECK(codegen.HasAllocatedRegister(processing_core_registers, current->GetRegister()));
516 }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100517 BitVector* liveness_of_register = liveness_of_values.Get(current->GetRegister());
518 for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
519 if (liveness_of_register->IsBitSet(j)) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000520 if (current->IsUsingInputRegister() && current->CanUseInputRegister()) {
521 continue;
522 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100523 if (log_fatal_on_failure) {
524 std::ostringstream message;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100525 message << "Register conflict at " << j << " ";
526 if (defined_by != nullptr) {
527 message << "(" << defined_by->DebugName() << ")";
528 }
529 message << "for ";
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100530 if (processing_core_registers) {
531 codegen.DumpCoreRegister(message, current->GetRegister());
532 } else {
533 codegen.DumpFloatingPointRegister(message, current->GetRegister());
534 }
535 LOG(FATAL) << message.str();
536 } else {
537 return false;
538 }
539 } else {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100540 liveness_of_register->SetBit(j);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100541 }
542 }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100543 }
544 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100545 }
546 return true;
547}
548
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100549void RegisterAllocator::DumpInterval(std::ostream& stream, LiveInterval* interval) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100550 interval->Dump(stream);
551 stream << ": ";
552 if (interval->HasRegister()) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100553 if (interval->IsFloatingPoint()) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100554 codegen_->DumpFloatingPointRegister(stream, interval->GetRegister());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100555 } else {
556 codegen_->DumpCoreRegister(stream, interval->GetRegister());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100557 }
558 } else {
559 stream << "spilled";
560 }
561 stream << std::endl;
562}
563
Mingyao Yang296bd602014-10-06 16:47:28 -0700564void RegisterAllocator::DumpAllIntervals(std::ostream& stream) const {
565 stream << "inactive: " << std::endl;
566 for (size_t i = 0; i < inactive_.Size(); i ++) {
567 DumpInterval(stream, inactive_.Get(i));
568 }
569 stream << "active: " << std::endl;
570 for (size_t i = 0; i < active_.Size(); i ++) {
571 DumpInterval(stream, active_.Get(i));
572 }
573 stream << "unhandled: " << std::endl;
574 auto unhandled = (unhandled_ != nullptr) ?
575 unhandled_ : &unhandled_core_intervals_;
576 for (size_t i = 0; i < unhandled->Size(); i ++) {
577 DumpInterval(stream, unhandled->Get(i));
578 }
579 stream << "handled: " << std::endl;
580 for (size_t i = 0; i < handled_.Size(); i ++) {
581 DumpInterval(stream, handled_.Get(i));
582 }
583}
584
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100585// By the book implementation of a linear scan register allocator.
586void RegisterAllocator::LinearScan() {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100587 while (!unhandled_->IsEmpty()) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100588 // (1) Remove interval with the lowest start position from unhandled.
Nicolas Geoffray39468442014-09-02 15:17:15 +0100589 LiveInterval* current = unhandled_->Pop();
590 DCHECK(!current->IsFixed() && !current->HasSpillSlot());
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +0100591 DCHECK(unhandled_->IsEmpty() || unhandled_->Peek()->GetStart() >= current->GetStart());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000592 DCHECK(!current->IsLowInterval() || unhandled_->Peek()->IsHighInterval());
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000593
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100594 size_t position = current->GetStart();
595
Mingyao Yang296bd602014-10-06 16:47:28 -0700596 // Remember the inactive_ size here since the ones moved to inactive_ from
597 // active_ below shouldn't need to be re-checked.
598 size_t inactive_intervals_to_handle = inactive_.Size();
599
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100600 // (2) Remove currently active intervals that are dead at this position.
601 // Move active intervals that have a lifetime hole at this position
602 // to inactive.
603 for (size_t i = 0; i < active_.Size(); ++i) {
604 LiveInterval* interval = active_.Get(i);
605 if (interval->IsDeadAt(position)) {
606 active_.Delete(interval);
607 --i;
608 handled_.Add(interval);
609 } else if (!interval->Covers(position)) {
610 active_.Delete(interval);
611 --i;
612 inactive_.Add(interval);
613 }
614 }
615
616 // (3) Remove currently inactive intervals that are dead at this position.
617 // Move inactive intervals that cover this position to active.
Mingyao Yang296bd602014-10-06 16:47:28 -0700618 for (size_t i = 0; i < inactive_intervals_to_handle; ++i) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100619 LiveInterval* interval = inactive_.Get(i);
Mingyao Yang296bd602014-10-06 16:47:28 -0700620 DCHECK(interval->GetStart() < position || interval->IsFixed());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100621 if (interval->IsDeadAt(position)) {
622 inactive_.Delete(interval);
623 --i;
Mingyao Yang296bd602014-10-06 16:47:28 -0700624 --inactive_intervals_to_handle;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100625 handled_.Add(interval);
626 } else if (interval->Covers(position)) {
627 inactive_.Delete(interval);
628 --i;
Mingyao Yang296bd602014-10-06 16:47:28 -0700629 --inactive_intervals_to_handle;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100630 active_.Add(interval);
631 }
632 }
633
Nicolas Geoffrayacd03392014-11-26 15:46:52 +0000634 if (current->IsSlowPathSafepoint()) {
635 // Synthesized interval to record the maximum number of live registers
636 // at safepoints. No need to allocate a register for it.
Mark Mendellf85a9ca2015-01-13 09:20:58 -0500637 if (processing_core_registers_) {
638 maximum_number_of_live_core_registers_ =
639 std::max(maximum_number_of_live_core_registers_, active_.Size());
640 } else {
641 maximum_number_of_live_fp_registers_ =
642 std::max(maximum_number_of_live_fp_registers_, active_.Size());
643 }
Nicolas Geoffrayacd03392014-11-26 15:46:52 +0000644 DCHECK(unhandled_->IsEmpty() || unhandled_->Peek()->GetStart() > current->GetStart());
645 continue;
646 }
647
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000648 if (current->IsHighInterval() && !current->GetLowInterval()->HasRegister()) {
649 DCHECK(!current->HasRegister());
650 // Allocating the low part was unsucessful. The splitted interval for the high part
651 // will be handled next (it is in the `unhandled_` list).
652 continue;
653 }
654
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100655 // (4) Try to find an available register.
656 bool success = TryAllocateFreeReg(current);
657
658 // (5) If no register could be found, we need to spill.
659 if (!success) {
660 success = AllocateBlockedReg(current);
661 }
662
663 // (6) If the interval had a register allocated, add it to the list of active
664 // intervals.
665 if (success) {
Nicolas Geoffray98893962015-01-21 12:32:32 +0000666 codegen_->AddAllocatedRegister(processing_core_registers_
667 ? Location::RegisterLocation(current->GetRegister())
668 : Location::FpuRegisterLocation(current->GetRegister()));
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100669 active_.Add(current);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000670 if (current->HasHighInterval() && !current->GetHighInterval()->HasRegister()) {
671 current->GetHighInterval()->SetRegister(GetHighForLowRegister(current->GetRegister()));
672 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100673 }
674 }
675}
676
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000677static void FreeIfNotCoverAt(LiveInterval* interval, size_t position, size_t* free_until) {
678 DCHECK(!interval->IsHighInterval());
679 // Note that the same instruction may occur multiple times in the input list,
680 // so `free_until` may have changed already.
David Brazdil3fc992f2015-04-16 18:31:55 +0100681 // Since `position` is not the current scan position, we need to use CoversSlow.
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000682 if (interval->IsDeadAt(position)) {
683 // Set the register to be free. Note that inactive intervals might later
684 // update this.
685 free_until[interval->GetRegister()] = kMaxLifetimePosition;
686 if (interval->HasHighInterval()) {
687 DCHECK(interval->GetHighInterval()->IsDeadAt(position));
688 free_until[interval->GetHighInterval()->GetRegister()] = kMaxLifetimePosition;
689 }
David Brazdil3fc992f2015-04-16 18:31:55 +0100690 } else if (!interval->CoversSlow(position)) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000691 // The interval becomes inactive at `defined_by`. We make its register
692 // available only until the next use strictly after `defined_by`.
693 free_until[interval->GetRegister()] = interval->FirstUseAfter(position);
694 if (interval->HasHighInterval()) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100695 DCHECK(!interval->GetHighInterval()->CoversSlow(position));
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000696 free_until[interval->GetHighInterval()->GetRegister()] = free_until[interval->GetRegister()];
697 }
698 }
699}
700
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100701// Find a free register. If multiple are found, pick the register that
702// is free the longest.
703bool RegisterAllocator::TryAllocateFreeReg(LiveInterval* current) {
704 size_t* free_until = registers_array_;
705
706 // First set all registers to be free.
707 for (size_t i = 0; i < number_of_registers_; ++i) {
708 free_until[i] = kMaxLifetimePosition;
709 }
710
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100711 // For each active interval, set its register to not free.
712 for (size_t i = 0, e = active_.Size(); i < e; ++i) {
713 LiveInterval* interval = active_.Get(i);
714 DCHECK(interval->HasRegister());
715 free_until[interval->GetRegister()] = 0;
716 }
717
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000718 // An interval that starts an instruction (that is, it is not split), may
719 // re-use the registers used by the inputs of that instruciton, based on the
720 // location summary.
721 HInstruction* defined_by = current->GetDefinedBy();
722 if (defined_by != nullptr && !current->IsSplit()) {
723 LocationSummary* locations = defined_by->GetLocations();
724 if (!locations->OutputCanOverlapWithInputs() && locations->Out().IsUnallocated()) {
Nicolas Geoffray94015b92015-06-04 18:21:04 +0100725 for (size_t i = 0, e = defined_by->InputCount(); i < e; ++i) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000726 // Take the last interval of the input. It is the location of that interval
727 // that will be used at `defined_by`.
Nicolas Geoffray94015b92015-06-04 18:21:04 +0100728 LiveInterval* interval = defined_by->InputAt(i)->GetLiveInterval()->GetLastSibling();
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000729 // Note that interval may have not been processed yet.
730 // TODO: Handle non-split intervals last in the work list.
Nicolas Geoffray94015b92015-06-04 18:21:04 +0100731 if (locations->InAt(i).IsValid()
732 && interval->HasRegister()
733 && interval->SameRegisterKind(*current)) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000734 // The input must be live until the end of `defined_by`, to comply to
735 // the linear scan algorithm. So we use `defined_by`'s end lifetime
736 // position to check whether the input is dead or is inactive after
737 // `defined_by`.
David Brazdil3fc992f2015-04-16 18:31:55 +0100738 DCHECK(interval->CoversSlow(defined_by->GetLifetimePosition()));
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000739 size_t position = defined_by->GetLifetimePosition() + 1;
740 FreeIfNotCoverAt(interval, position, free_until);
741 }
742 }
743 }
744 }
745
Mingyao Yang296bd602014-10-06 16:47:28 -0700746 // For each inactive interval, set its register to be free until
747 // the next intersection with `current`.
748 for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
749 LiveInterval* inactive = inactive_.Get(i);
750 // Temp/Slow-path-safepoint interval has no holes.
751 DCHECK(!inactive->IsTemp() && !inactive->IsSlowPathSafepoint());
752 if (!current->IsSplit() && !inactive->IsFixed()) {
753 // Neither current nor inactive are fixed.
754 // Thanks to SSA, a non-split interval starting in a hole of an
755 // inactive interval should never intersect with that inactive interval.
756 // Only if it's not fixed though, because fixed intervals don't come from SSA.
757 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
758 continue;
759 }
760
761 DCHECK(inactive->HasRegister());
762 if (free_until[inactive->GetRegister()] == 0) {
763 // Already used by some active interval. No need to intersect.
764 continue;
765 }
766 size_t next_intersection = inactive->FirstIntersectionWith(current);
767 if (next_intersection != kNoLifetime) {
768 free_until[inactive->GetRegister()] =
769 std::min(free_until[inactive->GetRegister()], next_intersection);
770 }
771 }
772
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000773 int reg = kNoRegister;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100774 if (current->HasRegister()) {
775 // Some instructions have a fixed register output.
776 reg = current->GetRegister();
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000777 if (free_until[reg] == 0) {
778 DCHECK(current->IsHighInterval());
779 // AllocateBlockedReg will spill the holder of the register.
780 return false;
781 }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100782 } else {
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000783 DCHECK(!current->IsHighInterval());
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +0100784 int hint = current->FindFirstRegisterHint(free_until, liveness_);
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100785 if (hint != kNoRegister) {
786 DCHECK(!IsBlocked(hint));
787 reg = hint;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000788 } else if (current->IsLowInterval()) {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000789 reg = FindAvailableRegisterPair(free_until, current->GetStart());
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100790 } else {
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100791 reg = FindAvailableRegister(free_until, current);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100792 }
793 }
794
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000795 DCHECK_NE(reg, kNoRegister);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100796 // If we could not find a register, we need to spill.
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000797 if (free_until[reg] == 0) {
798 return false;
799 }
800
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000801 if (current->IsLowInterval()) {
802 // If the high register of this interval is not available, we need to spill.
803 int high_reg = current->GetHighInterval()->GetRegister();
804 if (high_reg == kNoRegister) {
805 high_reg = GetHighForLowRegister(reg);
806 }
807 if (free_until[high_reg] == 0) {
808 return false;
809 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100810 }
811
812 current->SetRegister(reg);
813 if (!current->IsDeadAt(free_until[reg])) {
814 // If the register is only available for a subset of live ranges
Nicolas Geoffray82726882015-06-01 13:51:57 +0100815 // covered by `current`, split `current` before the position where
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100816 // the register is not available anymore.
Nicolas Geoffray82726882015-06-01 13:51:57 +0100817 LiveInterval* split = SplitBetween(current, current->GetStart(), free_until[reg]);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100818 DCHECK(split != nullptr);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100819 AddSorted(unhandled_, split);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100820 }
821 return true;
822}
823
824bool RegisterAllocator::IsBlocked(int reg) const {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100825 return processing_core_registers_
826 ? blocked_core_registers_[reg]
827 : blocked_fp_registers_[reg];
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100828}
829
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000830int RegisterAllocator::FindAvailableRegisterPair(size_t* next_use, size_t starting_at) const {
831 int reg = kNoRegister;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000832 // Pick the register pair that is used the last.
833 for (size_t i = 0; i < number_of_registers_; ++i) {
834 if (IsBlocked(i)) continue;
835 if (!IsLowRegister(i)) continue;
836 int high_register = GetHighForLowRegister(i);
837 if (IsBlocked(high_register)) continue;
838 int existing_high_register = GetHighForLowRegister(reg);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000839 if ((reg == kNoRegister) || (next_use[i] >= next_use[reg]
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000840 && next_use[high_register] >= next_use[existing_high_register])) {
841 reg = i;
842 if (next_use[i] == kMaxLifetimePosition
843 && next_use[high_register] == kMaxLifetimePosition) {
844 break;
845 }
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000846 } else if (next_use[reg] <= starting_at || next_use[existing_high_register] <= starting_at) {
847 // If one of the current register is known to be unavailable, just unconditionally
848 // try a new one.
849 reg = i;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000850 }
851 }
852 return reg;
853}
854
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100855bool RegisterAllocator::IsCallerSaveRegister(int reg) const {
856 return processing_core_registers_
857 ? !codegen_->IsCoreCalleeSaveRegister(reg)
858 : !codegen_->IsFloatingPointCalleeSaveRegister(reg);
859}
860
861int RegisterAllocator::FindAvailableRegister(size_t* next_use, LiveInterval* current) const {
862 // We special case intervals that do not span a safepoint to try to find a caller-save
863 // register if one is available. We iterate from 0 to the number of registers,
864 // so if there are caller-save registers available at the end, we continue the iteration.
865 bool prefers_caller_save = !current->HasWillCallSafepoint();
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000866 int reg = kNoRegister;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000867 for (size_t i = 0; i < number_of_registers_; ++i) {
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100868 if (IsBlocked(i)) {
869 // Register cannot be used. Continue.
870 continue;
871 }
872
873 // Best case: we found a register fully available.
874 if (next_use[i] == kMaxLifetimePosition) {
875 if (prefers_caller_save && !IsCallerSaveRegister(i)) {
876 // We can get shorter encodings on some platforms by using
877 // small register numbers. So only update the candidate if the previous
878 // one was not available for the whole method.
879 if (reg == kNoRegister || next_use[reg] != kMaxLifetimePosition) {
880 reg = i;
881 }
882 // Continue the iteration in the hope of finding a caller save register.
883 continue;
884 } else {
885 reg = i;
886 // We know the register is good enough. Return it.
887 break;
888 }
889 }
890
891 // If we had no register before, take this one as a reference.
892 if (reg == kNoRegister) {
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000893 reg = i;
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100894 continue;
895 }
896
897 // Pick the register that is used the last.
898 if (next_use[i] > next_use[reg]) {
899 reg = i;
900 continue;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000901 }
902 }
903 return reg;
904}
905
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000906bool RegisterAllocator::TrySplitNonPairOrUnalignedPairIntervalAt(size_t position,
907 size_t first_register_use,
908 size_t* next_use) {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000909 for (size_t i = 0, e = active_.Size(); i < e; ++i) {
910 LiveInterval* active = active_.Get(i);
911 DCHECK(active->HasRegister());
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000912 if (active->IsFixed()) continue;
913 if (active->IsHighInterval()) continue;
914 if (first_register_use > next_use[active->GetRegister()]) continue;
915
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000916 // Split the first interval found.
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000917 if (!active->IsLowInterval() || IsLowOfUnalignedPairInterval(active)) {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000918 LiveInterval* split = Split(active, position);
919 active_.DeleteAt(i);
920 if (split != active) {
921 handled_.Add(active);
922 }
923 AddSorted(unhandled_, split);
924 return true;
925 }
926 }
927 return false;
928}
929
Nicolas Geoffray5b168de2015-03-27 10:27:22 +0000930bool RegisterAllocator::PotentiallyRemoveOtherHalf(LiveInterval* interval,
931 GrowableArray<LiveInterval*>* intervals,
932 size_t index) {
933 if (interval->IsLowInterval()) {
934 DCHECK_EQ(intervals->Get(index), interval->GetHighInterval());
935 intervals->DeleteAt(index);
936 return true;
937 } else if (interval->IsHighInterval()) {
938 DCHECK_GT(index, 0u);
939 DCHECK_EQ(intervals->Get(index - 1), interval->GetLowInterval());
940 intervals->DeleteAt(index - 1);
941 return true;
942 } else {
943 return false;
944 }
945}
946
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100947// Find the register that is used the last, and spill the interval
948// that holds it. If the first use of `current` is after that register
949// we spill `current` instead.
950bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
951 size_t first_register_use = current->FirstRegisterUse();
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -0700952 if (current->HasRegister()) {
953 DCHECK(current->IsHighInterval());
954 // The low interval has allocated the register for the high interval. In
955 // case the low interval had to split both intervals, we may end up in a
956 // situation where the high interval does not have a register use anymore.
957 // We must still proceed in order to split currently active and inactive
958 // uses of the high interval's register, and put the high interval in the
959 // active set.
960 DCHECK(first_register_use != kNoLifetime || (current->GetNextSibling() != nullptr));
961 } else if (first_register_use == kNoLifetime) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100962 AllocateSpillSlotFor(current);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100963 return false;
964 }
965
Nicolas Geoffray1ba19812015-04-21 09:12:40 +0100966 // We use the first use to compare with other intervals. If this interval
967 // is used after any active intervals, we will spill this interval.
968 size_t first_use = current->FirstUseAfter(current->GetStart());
969
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100970 // First set all registers as not being used.
971 size_t* next_use = registers_array_;
972 for (size_t i = 0; i < number_of_registers_; ++i) {
973 next_use[i] = kMaxLifetimePosition;
974 }
975
976 // For each active interval, find the next use of its register after the
977 // start of current.
978 for (size_t i = 0, e = active_.Size(); i < e; ++i) {
979 LiveInterval* active = active_.Get(i);
980 DCHECK(active->HasRegister());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100981 if (active->IsFixed()) {
982 next_use[active->GetRegister()] = current->GetStart();
983 } else {
Nicolas Geoffray1ba19812015-04-21 09:12:40 +0100984 size_t use = active->FirstUseAfter(current->GetStart());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100985 if (use != kNoLifetime) {
986 next_use[active->GetRegister()] = use;
987 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100988 }
989 }
990
991 // For each inactive interval, find the next use of its register after the
992 // start of current.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100993 for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
994 LiveInterval* inactive = inactive_.Get(i);
Mingyao Yang296bd602014-10-06 16:47:28 -0700995 // Temp/Slow-path-safepoint interval has no holes.
996 DCHECK(!inactive->IsTemp() && !inactive->IsSlowPathSafepoint());
997 if (!current->IsSplit() && !inactive->IsFixed()) {
998 // Neither current nor inactive are fixed.
999 // Thanks to SSA, a non-split interval starting in a hole of an
1000 // inactive interval should never intersect with that inactive interval.
1001 // Only if it's not fixed though, because fixed intervals don't come from SSA.
1002 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
1003 continue;
1004 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001005 DCHECK(inactive->HasRegister());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001006 size_t next_intersection = inactive->FirstIntersectionWith(current);
1007 if (next_intersection != kNoLifetime) {
1008 if (inactive->IsFixed()) {
1009 next_use[inactive->GetRegister()] =
1010 std::min(next_intersection, next_use[inactive->GetRegister()]);
1011 } else {
Nicolas Geoffray1ba19812015-04-21 09:12:40 +01001012 size_t use = inactive->FirstUseAfter(current->GetStart());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001013 if (use != kNoLifetime) {
1014 next_use[inactive->GetRegister()] = std::min(use, next_use[inactive->GetRegister()]);
1015 }
1016 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001017 }
1018 }
1019
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001020 int reg = kNoRegister;
1021 bool should_spill = false;
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001022 if (current->HasRegister()) {
1023 DCHECK(current->IsHighInterval());
1024 reg = current->GetRegister();
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001025 // When allocating the low part, we made sure the high register was available.
Nicolas Geoffray1ba19812015-04-21 09:12:40 +01001026 DCHECK_LT(first_use, next_use[reg]);
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001027 } else if (current->IsLowInterval()) {
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -07001028 reg = FindAvailableRegisterPair(next_use, first_use);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001029 // We should spill if both registers are not available.
Nicolas Geoffray1ba19812015-04-21 09:12:40 +01001030 should_spill = (first_use >= next_use[reg])
1031 || (first_use >= next_use[GetHighForLowRegister(reg)]);
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001032 } else {
1033 DCHECK(!current->IsHighInterval());
Nicolas Geoffray8826f672015-04-17 09:15:11 +01001034 reg = FindAvailableRegister(next_use, current);
Nicolas Geoffray1ba19812015-04-21 09:12:40 +01001035 should_spill = (first_use >= next_use[reg]);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001036 }
1037
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001038 DCHECK_NE(reg, kNoRegister);
1039 if (should_spill) {
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001040 DCHECK(!current->IsHighInterval());
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001041 bool is_allocation_at_use_site = (current->GetStart() >= (first_register_use - 1));
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -07001042 if (is_allocation_at_use_site) {
1043 if (!current->IsLowInterval()) {
1044 DumpInterval(std::cerr, current);
1045 DumpAllIntervals(std::cerr);
1046 // This situation has the potential to infinite loop, so we make it a non-debug CHECK.
1047 HInstruction* at = liveness_.GetInstructionFromPosition(first_register_use / 2);
1048 CHECK(false) << "There is not enough registers available for "
1049 << current->GetParent()->GetDefinedBy()->DebugName() << " "
1050 << current->GetParent()->GetDefinedBy()->GetId()
1051 << " at " << first_register_use - 1 << " "
1052 << (at == nullptr ? "" : at->DebugName());
1053 }
1054
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001055 // If we're allocating a register for `current` because the instruction at
1056 // that position requires it, but we think we should spill, then there are
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001057 // non-pair intervals or unaligned pair intervals blocking the allocation.
1058 // We split the first interval found, and put ourselves first in the
1059 // `unhandled_` list.
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -07001060 bool success = TrySplitNonPairOrUnalignedPairIntervalAt(current->GetStart(),
1061 first_register_use,
1062 next_use);
1063 DCHECK(success);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001064 LiveInterval* existing = unhandled_->Peek();
1065 DCHECK(existing->IsHighInterval());
1066 DCHECK_EQ(existing->GetLowInterval(), current);
1067 unhandled_->Add(current);
1068 } else {
1069 // If the first use of that instruction is after the last use of the found
1070 // register, we split this interval just before its first register use.
1071 AllocateSpillSlotFor(current);
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001072 LiveInterval* split = SplitBetween(current, current->GetStart(), first_register_use - 1);
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -07001073 DCHECK(current != split);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001074 AddSorted(unhandled_, split);
1075 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001076 return false;
1077 } else {
1078 // Use this register and spill the active and inactives interval that
1079 // have that register.
1080 current->SetRegister(reg);
1081
1082 for (size_t i = 0, e = active_.Size(); i < e; ++i) {
1083 LiveInterval* active = active_.Get(i);
1084 if (active->GetRegister() == reg) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001085 DCHECK(!active->IsFixed());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001086 LiveInterval* split = Split(active, current->GetStart());
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00001087 if (split != active) {
1088 handled_.Add(active);
1089 }
Nicolas Geoffray5b168de2015-03-27 10:27:22 +00001090 active_.DeleteAt(i);
1091 PotentiallyRemoveOtherHalf(active, &active_, i);
Nicolas Geoffray39468442014-09-02 15:17:15 +01001092 AddSorted(unhandled_, split);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001093 break;
1094 }
1095 }
1096
Nicolas Geoffray5b168de2015-03-27 10:27:22 +00001097 for (size_t i = 0; i < inactive_.Size(); ++i) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001098 LiveInterval* inactive = inactive_.Get(i);
1099 if (inactive->GetRegister() == reg) {
Mingyao Yang296bd602014-10-06 16:47:28 -07001100 if (!current->IsSplit() && !inactive->IsFixed()) {
1101 // Neither current nor inactive are fixed.
1102 // Thanks to SSA, a non-split interval starting in a hole of an
1103 // inactive interval should never intersect with that inactive interval.
1104 // Only if it's not fixed though, because fixed intervals don't come from SSA.
1105 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
1106 continue;
1107 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001108 size_t next_intersection = inactive->FirstIntersectionWith(current);
1109 if (next_intersection != kNoLifetime) {
1110 if (inactive->IsFixed()) {
1111 LiveInterval* split = Split(current, next_intersection);
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00001112 DCHECK_NE(split, current);
Nicolas Geoffray39468442014-09-02 15:17:15 +01001113 AddSorted(unhandled_, split);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001114 } else {
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00001115 // Split at the start of `current`, which will lead to splitting
1116 // at the end of the lifetime hole of `inactive`.
1117 LiveInterval* split = Split(inactive, current->GetStart());
1118 // If it's inactive, it must start before the current interval.
1119 DCHECK_NE(split, inactive);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001120 inactive_.DeleteAt(i);
Nicolas Geoffray5b168de2015-03-27 10:27:22 +00001121 if (PotentiallyRemoveOtherHalf(inactive, &inactive_, i) && inactive->IsHighInterval()) {
1122 // We have removed an entry prior to `inactive`. So we need to decrement.
1123 --i;
1124 }
1125 // Decrement because we have removed `inactive` from the list.
Mingyao Yang296bd602014-10-06 16:47:28 -07001126 --i;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001127 handled_.Add(inactive);
Nicolas Geoffray39468442014-09-02 15:17:15 +01001128 AddSorted(unhandled_, split);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001129 }
1130 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001131 }
1132 }
1133
1134 return true;
1135 }
1136}
1137
Nicolas Geoffray39468442014-09-02 15:17:15 +01001138void RegisterAllocator::AddSorted(GrowableArray<LiveInterval*>* array, LiveInterval* interval) {
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +01001139 DCHECK(!interval->IsFixed() && !interval->HasSpillSlot());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001140 size_t insert_at = 0;
Nicolas Geoffray39468442014-09-02 15:17:15 +01001141 for (size_t i = array->Size(); i > 0; --i) {
1142 LiveInterval* current = array->Get(i - 1);
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001143 // High intervals must be processed right after their low equivalent.
1144 if (current->StartsAfter(interval) && !current->IsHighInterval()) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001145 insert_at = i;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001146 break;
Nicolas Geoffrayacd03392014-11-26 15:46:52 +00001147 } else if ((current->GetStart() == interval->GetStart()) && current->IsSlowPathSafepoint()) {
1148 // Ensure the slow path interval is the last to be processed at its location: we want the
1149 // interval to know all live registers at this location.
1150 DCHECK(i == 1 || array->Get(i - 2)->StartsAfter(current));
1151 insert_at = i;
1152 break;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001153 }
1154 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001155
Nicolas Geoffray39468442014-09-02 15:17:15 +01001156 array->InsertAt(insert_at, interval);
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001157 // Insert the high interval before the low, to ensure the low is processed before.
1158 if (interval->HasHighInterval()) {
1159 array->InsertAt(insert_at, interval->GetHighInterval());
1160 } else if (interval->HasLowInterval()) {
1161 array->InsertAt(insert_at + 1, interval->GetLowInterval());
1162 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001163}
1164
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001165LiveInterval* RegisterAllocator::SplitBetween(LiveInterval* interval, size_t from, size_t to) {
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +01001166 HBasicBlock* block_from = liveness_.GetBlockFromPosition(from / 2);
1167 HBasicBlock* block_to = liveness_.GetBlockFromPosition(to / 2);
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001168 DCHECK(block_from != nullptr);
1169 DCHECK(block_to != nullptr);
1170
1171 // Both locations are in the same block. We split at the given location.
1172 if (block_from == block_to) {
1173 return Split(interval, to);
1174 }
1175
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +01001176 /*
1177 * Non-linear control flow will force moves at every branch instruction to the new location.
1178 * To avoid having all branches doing the moves, we find the next non-linear position and
1179 * split the interval at this position. Take the following example (block number is the linear
1180 * order position):
1181 *
1182 * B1
1183 * / \
1184 * B2 B3
1185 * \ /
1186 * B4
1187 *
1188 * B2 needs to split an interval, whose next use is in B4. If we were to split at the
1189 * beginning of B4, B3 would need to do a move between B3 and B4 to ensure the interval
1190 * is now in the correct location. It makes performance worst if the interval is spilled
1191 * and both B2 and B3 need to reload it before entering B4.
1192 *
1193 * By splitting at B3, we give a chance to the register allocator to allocate the
1194 * interval to the same register as in B1, and therefore avoid doing any
1195 * moves in B3.
1196 */
1197 if (block_from->GetDominator() != nullptr) {
1198 const GrowableArray<HBasicBlock*>& dominated = block_from->GetDominator()->GetDominatedBlocks();
1199 for (size_t i = 0; i < dominated.Size(); ++i) {
1200 size_t position = dominated.Get(i)->GetLifetimeStart();
1201 if ((position > from) && (block_to->GetLifetimeStart() > position)) {
1202 // Even if we found a better block, we continue iterating in case
1203 // a dominated block is closer.
1204 // Note that dominated blocks are not sorted in liveness order.
1205 block_to = dominated.Get(i);
1206 DCHECK_NE(block_to, block_from);
1207 }
1208 }
1209 }
1210
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001211 // If `to` is in a loop, find the outermost loop header which does not contain `from`.
1212 for (HLoopInformationOutwardIterator it(*block_to); !it.Done(); it.Advance()) {
1213 HBasicBlock* header = it.Current()->GetHeader();
1214 if (block_from->GetLifetimeStart() >= header->GetLifetimeStart()) {
1215 break;
1216 }
1217 block_to = header;
1218 }
1219
1220 // Split at the start of the found block, to piggy back on existing moves
1221 // due to resolution if non-linear control flow (see `ConnectSplitSiblings`).
1222 return Split(interval, block_to->GetLifetimeStart());
1223}
1224
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001225LiveInterval* RegisterAllocator::Split(LiveInterval* interval, size_t position) {
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001226 DCHECK_GE(position, interval->GetStart());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001227 DCHECK(!interval->IsDeadAt(position));
1228 if (position == interval->GetStart()) {
1229 // Spill slot will be allocated when handling `interval` again.
1230 interval->ClearRegister();
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001231 if (interval->HasHighInterval()) {
1232 interval->GetHighInterval()->ClearRegister();
1233 } else if (interval->HasLowInterval()) {
1234 interval->GetLowInterval()->ClearRegister();
1235 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001236 return interval;
1237 } else {
1238 LiveInterval* new_interval = interval->SplitAt(position);
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001239 if (interval->HasHighInterval()) {
1240 LiveInterval* high = interval->GetHighInterval()->SplitAt(position);
1241 new_interval->SetHighInterval(high);
1242 high->SetLowInterval(new_interval);
1243 } else if (interval->HasLowInterval()) {
1244 LiveInterval* low = interval->GetLowInterval()->SplitAt(position);
1245 new_interval->SetLowInterval(low);
1246 low->SetHighInterval(new_interval);
1247 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001248 return new_interval;
1249 }
1250}
1251
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001252void RegisterAllocator::AllocateSpillSlotFor(LiveInterval* interval) {
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001253 if (interval->IsHighInterval()) {
Nicolas Geoffrayda2b2542015-08-06 19:56:45 -07001254 // The low interval already took care of allocating the spill slot.
1255 DCHECK(!interval->GetLowInterval()->HasRegister());
1256 DCHECK(interval->GetLowInterval()->GetParent()->HasSpillSlot());
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001257 return;
1258 }
1259
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001260 LiveInterval* parent = interval->GetParent();
1261
1262 // An instruction gets a spill slot for its entire lifetime. If the parent
1263 // of this interval already has a spill slot, there is nothing to do.
1264 if (parent->HasSpillSlot()) {
1265 return;
1266 }
1267
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001268 HInstruction* defined_by = parent->GetDefinedBy();
1269 if (defined_by->IsParameterValue()) {
1270 // Parameters have their own stack slot.
1271 parent->SetSpillSlot(codegen_->GetStackSlotOfParameter(defined_by->AsParameterValue()));
1272 return;
1273 }
1274
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001275 if (defined_by->IsCurrentMethod()) {
1276 parent->SetSpillSlot(0);
1277 return;
1278 }
1279
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001280 if (defined_by->IsConstant()) {
1281 // Constants don't need a spill slot.
1282 return;
1283 }
1284
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001285 LiveInterval* last_sibling = interval;
1286 while (last_sibling->GetNextSibling() != nullptr) {
1287 last_sibling = last_sibling->GetNextSibling();
1288 }
1289 size_t end = last_sibling->GetEnd();
1290
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001291 GrowableArray<size_t>* spill_slots = nullptr;
1292 switch (interval->GetType()) {
1293 case Primitive::kPrimDouble:
1294 spill_slots = &double_spill_slots_;
1295 break;
1296 case Primitive::kPrimLong:
1297 spill_slots = &long_spill_slots_;
1298 break;
1299 case Primitive::kPrimFloat:
1300 spill_slots = &float_spill_slots_;
1301 break;
1302 case Primitive::kPrimNot:
1303 case Primitive::kPrimInt:
1304 case Primitive::kPrimChar:
1305 case Primitive::kPrimByte:
1306 case Primitive::kPrimBoolean:
1307 case Primitive::kPrimShort:
1308 spill_slots = &int_spill_slots_;
1309 break;
1310 case Primitive::kPrimVoid:
1311 LOG(FATAL) << "Unexpected type for interval " << interval->GetType();
1312 }
1313
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001314 // Find an available spill slot.
1315 size_t slot = 0;
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001316 for (size_t e = spill_slots->Size(); slot < e; ++slot) {
1317 if (spill_slots->Get(slot) <= parent->GetStart()
1318 && (slot == (e - 1) || spill_slots->Get(slot + 1) <= parent->GetStart())) {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001319 break;
1320 }
1321 }
1322
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001323 if (parent->NeedsTwoSpillSlots()) {
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001324 if (slot == spill_slots->Size()) {
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001325 // We need a new spill slot.
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001326 spill_slots->Add(end);
1327 spill_slots->Add(end);
1328 } else if (slot == spill_slots->Size() - 1) {
1329 spill_slots->Put(slot, end);
1330 spill_slots->Add(end);
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001331 } else {
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001332 spill_slots->Put(slot, end);
1333 spill_slots->Put(slot + 1, end);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001334 }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001335 } else {
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001336 if (slot == spill_slots->Size()) {
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001337 // We need a new spill slot.
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001338 spill_slots->Add(end);
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001339 } else {
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001340 spill_slots->Put(slot, end);
Nicolas Geoffray3c049742014-09-24 18:10:46 +01001341 }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001342 }
1343
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001344 // Note that the exact spill slot location will be computed when we resolve,
1345 // that is when we know the number of spill slots for each type.
1346 parent->SetSpillSlot(slot);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001347}
1348
Nicolas Geoffray2a877f32014-09-10 10:49:34 +01001349static bool IsValidDestination(Location destination) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001350 return destination.IsRegister()
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001351 || destination.IsRegisterPair()
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001352 || destination.IsFpuRegister()
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001353 || destination.IsFpuRegisterPair()
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001354 || destination.IsStackSlot()
1355 || destination.IsDoubleStackSlot();
Nicolas Geoffray2a877f32014-09-10 10:49:34 +01001356}
1357
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001358void RegisterAllocator::AddMove(HParallelMove* move,
1359 Location source,
1360 Location destination,
1361 HInstruction* instruction,
1362 Primitive::Type type) const {
1363 if (type == Primitive::kPrimLong
1364 && codegen_->ShouldSplitLongMoves()
1365 // The parallel move resolver knows how to deal with long constants.
1366 && !source.IsConstant()) {
Nicolas Geoffray90218252015-04-15 11:56:51 +01001367 move->AddMove(source.ToLow(), destination.ToLow(), Primitive::kPrimInt, instruction);
1368 move->AddMove(source.ToHigh(), destination.ToHigh(), Primitive::kPrimInt, nullptr);
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001369 } else {
Nicolas Geoffray90218252015-04-15 11:56:51 +01001370 move->AddMove(source, destination, type, instruction);
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001371 }
1372}
1373
1374void RegisterAllocator::AddInputMoveFor(HInstruction* input,
1375 HInstruction* user,
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001376 Location source,
1377 Location destination) const {
1378 if (source.Equals(destination)) return;
1379
Roland Levillain476df552014-10-09 17:51:36 +01001380 DCHECK(!user->IsPhi());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001381
Nicolas Geoffray740475d2014-09-29 10:33:25 +01001382 HInstruction* previous = user->GetPrevious();
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001383 HParallelMove* move = nullptr;
1384 if (previous == nullptr
Roland Levillain476df552014-10-09 17:51:36 +01001385 || !previous->IsParallelMove()
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001386 || previous->GetLifetimePosition() < user->GetLifetimePosition()) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001387 move = new (allocator_) HParallelMove(allocator_);
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001388 move->SetLifetimePosition(user->GetLifetimePosition());
Nicolas Geoffray740475d2014-09-29 10:33:25 +01001389 user->GetBlock()->InsertInstructionBefore(move, user);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001390 } else {
1391 move = previous->AsParallelMove();
1392 }
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001393 DCHECK_EQ(move->GetLifetimePosition(), user->GetLifetimePosition());
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001394 AddMove(move, source, destination, nullptr, input->GetType());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001395}
1396
Nicolas Geoffray46fbaab2014-11-26 18:30:23 +00001397static bool IsInstructionStart(size_t position) {
1398 return (position & 1) == 0;
1399}
1400
1401static bool IsInstructionEnd(size_t position) {
1402 return (position & 1) == 1;
1403}
1404
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001405void RegisterAllocator::InsertParallelMoveAt(size_t position,
Nicolas Geoffray740475d2014-09-29 10:33:25 +01001406 HInstruction* instruction,
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001407 Location source,
1408 Location destination) const {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001409 DCHECK(IsValidDestination(destination)) << destination;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001410 if (source.Equals(destination)) return;
1411
1412 HInstruction* at = liveness_.GetInstructionFromPosition(position / 2);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001413 HParallelMove* move;
Nicolas Geoffray46fbaab2014-11-26 18:30:23 +00001414 if (at == nullptr) {
1415 if (IsInstructionStart(position)) {
1416 // Block boundary, don't do anything the connection of split siblings will handle it.
1417 return;
1418 } else {
1419 // Move must happen before the first instruction of the block.
1420 at = liveness_.GetInstructionFromPosition((position + 1) / 2);
Nicolas Geoffray59768572014-12-01 09:50:04 +00001421 // Note that parallel moves may have already been inserted, so we explicitly
1422 // ask for the first instruction of the block: `GetInstructionFromPosition` does
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001423 // not contain the `HParallelMove` instructions.
Nicolas Geoffray59768572014-12-01 09:50:04 +00001424 at = at->GetBlock()->GetFirstInstruction();
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001425
1426 if (at->GetLifetimePosition() < position) {
1427 // We may insert moves for split siblings and phi spills at the beginning of the block.
1428 // Since this is a different lifetime position, we need to go to the next instruction.
1429 DCHECK(at->IsParallelMove());
1430 at = at->GetNext();
1431 }
1432
Nicolas Geoffray59768572014-12-01 09:50:04 +00001433 if (at->GetLifetimePosition() != position) {
1434 DCHECK_GT(at->GetLifetimePosition(), position);
Nicolas Geoffray46fbaab2014-11-26 18:30:23 +00001435 move = new (allocator_) HParallelMove(allocator_);
1436 move->SetLifetimePosition(position);
1437 at->GetBlock()->InsertInstructionBefore(move, at);
Nicolas Geoffray59768572014-12-01 09:50:04 +00001438 } else {
1439 DCHECK(at->IsParallelMove());
1440 move = at->AsParallelMove();
Nicolas Geoffray46fbaab2014-11-26 18:30:23 +00001441 }
1442 }
1443 } else if (IsInstructionEnd(position)) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001444 // Move must happen after the instruction.
1445 DCHECK(!at->IsControlFlow());
1446 move = at->GetNext()->AsParallelMove();
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001447 // This is a parallel move for connecting siblings in a same block. We need to
1448 // differentiate it with moves for connecting blocks, and input moves.
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +01001449 if (move == nullptr || move->GetLifetimePosition() > position) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001450 move = new (allocator_) HParallelMove(allocator_);
1451 move->SetLifetimePosition(position);
1452 at->GetBlock()->InsertInstructionBefore(move, at->GetNext());
1453 }
1454 } else {
1455 // Move must happen before the instruction.
1456 HInstruction* previous = at->GetPrevious();
Nicolas Geoffray740475d2014-09-29 10:33:25 +01001457 if (previous == nullptr
1458 || !previous->IsParallelMove()
1459 || previous->GetLifetimePosition() != position) {
1460 // If the previous is a parallel move, then its position must be lower
1461 // than the given `position`: it was added just after the non-parallel
1462 // move instruction that precedes `instruction`.
1463 DCHECK(previous == nullptr
1464 || !previous->IsParallelMove()
1465 || previous->GetLifetimePosition() < position);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001466 move = new (allocator_) HParallelMove(allocator_);
1467 move->SetLifetimePosition(position);
1468 at->GetBlock()->InsertInstructionBefore(move, at);
1469 } else {
1470 move = previous->AsParallelMove();
1471 }
1472 }
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001473 DCHECK_EQ(move->GetLifetimePosition(), position);
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001474 AddMove(move, source, destination, instruction, instruction->GetType());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001475}
1476
1477void RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block,
Nicolas Geoffray740475d2014-09-29 10:33:25 +01001478 HInstruction* instruction,
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001479 Location source,
1480 Location destination) const {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001481 DCHECK(IsValidDestination(destination)) << destination;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001482 if (source.Equals(destination)) return;
1483
1484 DCHECK_EQ(block->GetSuccessors().Size(), 1u);
1485 HInstruction* last = block->GetLastInstruction();
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001486 // We insert moves at exit for phi predecessors and connecting blocks.
1487 // A block ending with an if cannot branch to a block with phis because
1488 // we do not allow critical edges. It can also not connect
1489 // a split interval between two blocks: the move has to happen in the successor.
1490 DCHECK(!last->IsIf());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001491 HInstruction* previous = last->GetPrevious();
1492 HParallelMove* move;
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001493 // This is a parallel move for connecting blocks. We need to differentiate
1494 // it with moves for connecting siblings in a same block, and output moves.
Nicolas Geoffray59768572014-12-01 09:50:04 +00001495 size_t position = last->GetLifetimePosition();
Nicolas Geoffray740475d2014-09-29 10:33:25 +01001496 if (previous == nullptr || !previous->IsParallelMove()
Nicolas Geoffray59768572014-12-01 09:50:04 +00001497 || previous->AsParallelMove()->GetLifetimePosition() != position) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001498 move = new (allocator_) HParallelMove(allocator_);
Nicolas Geoffray59768572014-12-01 09:50:04 +00001499 move->SetLifetimePosition(position);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001500 block->InsertInstructionBefore(move, last);
1501 } else {
1502 move = previous->AsParallelMove();
1503 }
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001504 AddMove(move, source, destination, instruction, instruction->GetType());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001505}
1506
1507void RegisterAllocator::InsertParallelMoveAtEntryOf(HBasicBlock* block,
Nicolas Geoffray740475d2014-09-29 10:33:25 +01001508 HInstruction* instruction,
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001509 Location source,
1510 Location destination) const {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001511 DCHECK(IsValidDestination(destination)) << destination;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001512 if (source.Equals(destination)) return;
1513
1514 HInstruction* first = block->GetFirstInstruction();
1515 HParallelMove* move = first->AsParallelMove();
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001516 size_t position = block->GetLifetimeStart();
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001517 // This is a parallel move for connecting blocks. We need to differentiate
1518 // it with moves for connecting siblings in a same block, and input moves.
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001519 if (move == nullptr || move->GetLifetimePosition() != position) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001520 move = new (allocator_) HParallelMove(allocator_);
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001521 move->SetLifetimePosition(position);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001522 block->InsertInstructionBefore(move, first);
1523 }
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001524 AddMove(move, source, destination, instruction, instruction->GetType());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001525}
1526
1527void RegisterAllocator::InsertMoveAfter(HInstruction* instruction,
1528 Location source,
1529 Location destination) const {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001530 DCHECK(IsValidDestination(destination)) << destination;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001531 if (source.Equals(destination)) return;
1532
Roland Levillain476df552014-10-09 17:51:36 +01001533 if (instruction->IsPhi()) {
Nicolas Geoffray740475d2014-09-29 10:33:25 +01001534 InsertParallelMoveAtEntryOf(instruction->GetBlock(), instruction, source, destination);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001535 return;
1536 }
1537
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001538 size_t position = instruction->GetLifetimePosition() + 1;
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001539 HParallelMove* move = instruction->GetNext()->AsParallelMove();
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001540 // This is a parallel move for moving the output of an instruction. We need
1541 // to differentiate with input moves, moves for connecting siblings in a
1542 // and moves for connecting blocks.
1543 if (move == nullptr || move->GetLifetimePosition() != position) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001544 move = new (allocator_) HParallelMove(allocator_);
Nicolas Geoffraye27f31a2014-06-12 17:53:14 +01001545 move->SetLifetimePosition(position);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001546 instruction->GetBlock()->InsertInstructionBefore(move, instruction->GetNext());
1547 }
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001548 AddMove(move, source, destination, instruction, instruction->GetType());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001549}
1550
1551void RegisterAllocator::ConnectSiblings(LiveInterval* interval) {
1552 LiveInterval* current = interval;
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001553 if (current->HasSpillSlot()
1554 && current->HasRegister()
1555 // Currently, we spill unconditionnally the current method in the code generators.
1556 && !interval->GetDefinedBy()->IsCurrentMethod()) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001557 // We spill eagerly, so move must be at definition.
1558 InsertMoveAfter(interval->GetDefinedBy(),
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001559 interval->ToLocation(),
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001560 interval->NeedsTwoSpillSlots()
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001561 ? Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot())
1562 : Location::StackSlot(interval->GetParent()->GetSpillSlot()));
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001563 }
1564 UsePosition* use = current->GetFirstUse();
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +01001565 UsePosition* env_use = current->GetFirstEnvironmentUse();
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001566
1567 // Walk over all siblings, updating locations of use positions, and
1568 // connecting them when they are adjacent.
1569 do {
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001570 Location source = current->ToLocation();
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001571
1572 // Walk over all uses covered by this interval, and update the location
1573 // information.
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +00001574
1575 LiveRange* range = current->GetFirstRange();
1576 while (range != nullptr) {
Nicolas Geoffray57902602015-04-21 14:28:41 +01001577 while (use != nullptr && use->GetPosition() < range->GetStart()) {
1578 DCHECK(use->IsSynthesized());
1579 use = use->GetNext();
1580 }
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +00001581 while (use != nullptr && use->GetPosition() <= range->GetEnd()) {
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +01001582 DCHECK(!use->GetIsEnvironment());
David Brazdil3fc992f2015-04-16 18:31:55 +01001583 DCHECK(current->CoversSlow(use->GetPosition()) || (use->GetPosition() == range->GetEnd()));
Nicolas Geoffray57902602015-04-21 14:28:41 +01001584 if (!use->IsSynthesized()) {
1585 LocationSummary* locations = use->GetUser()->GetLocations();
1586 Location expected_location = locations->InAt(use->GetInputIndex());
1587 // The expected (actual) location may be invalid in case the input is unused. Currently
1588 // this only happens for intrinsics.
1589 if (expected_location.IsValid()) {
1590 if (expected_location.IsUnallocated()) {
1591 locations->SetInAt(use->GetInputIndex(), source);
1592 } else if (!expected_location.IsConstant()) {
1593 AddInputMoveFor(interval->GetDefinedBy(), use->GetUser(), source, expected_location);
1594 }
1595 } else {
1596 DCHECK(use->GetUser()->IsInvoke());
1597 DCHECK(use->GetUser()->AsInvoke()->GetIntrinsic() != Intrinsics::kNone);
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +00001598 }
1599 }
1600 use = use->GetNext();
1601 }
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +01001602
1603 // Walk over the environment uses, and update their locations.
1604 while (env_use != nullptr && env_use->GetPosition() < range->GetStart()) {
1605 env_use = env_use->GetNext();
1606 }
1607
1608 while (env_use != nullptr && env_use->GetPosition() <= range->GetEnd()) {
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001609 DCHECK(current->CoversSlow(env_use->GetPosition())
1610 || (env_use->GetPosition() == range->GetEnd()));
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001611 HEnvironment* environment = env_use->GetEnvironment();
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001612 environment->SetLocationAt(env_use->GetInputIndex(), source);
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +01001613 env_use = env_use->GetNext();
1614 }
1615
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +00001616 range = range->GetNext();
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001617 }
1618
1619 // If the next interval starts just after this one, and has a register,
1620 // insert a move.
1621 LiveInterval* next_sibling = current->GetNextSibling();
1622 if (next_sibling != nullptr
1623 && next_sibling->HasRegister()
1624 && current->GetEnd() == next_sibling->GetStart()) {
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001625 Location destination = next_sibling->ToLocation();
Nicolas Geoffray740475d2014-09-29 10:33:25 +01001626 InsertParallelMoveAt(current->GetEnd(), interval->GetDefinedBy(), source, destination);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001627 }
Nicolas Geoffray39468442014-09-02 15:17:15 +01001628
Nicolas Geoffray43af7282015-04-16 13:01:01 +01001629 for (SafepointPosition* safepoint_position = current->GetFirstSafepoint();
1630 safepoint_position != nullptr;
1631 safepoint_position = safepoint_position->GetNext()) {
David Brazdil3fc992f2015-04-16 18:31:55 +01001632 DCHECK(current->CoversSlow(safepoint_position->GetPosition()));
Nicolas Geoffray39468442014-09-02 15:17:15 +01001633
Nicolas Geoffray5588e582015-04-14 14:10:59 +01001634 LocationSummary* locations = safepoint_position->GetLocations();
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +01001635 if ((current->GetType() == Primitive::kPrimNot) && current->GetParent()->HasSpillSlot()) {
Nicolas Geoffray39468442014-09-02 15:17:15 +01001636 locations->SetStackBit(current->GetParent()->GetSpillSlot() / kVRegSize);
1637 }
1638
1639 switch (source.GetKind()) {
1640 case Location::kRegister: {
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +01001641 locations->AddLiveRegister(source);
Nicolas Geoffray98893962015-01-21 12:32:32 +00001642 if (kIsDebugBuild && locations->OnlyCallsOnSlowPath()) {
1643 DCHECK_LE(locations->GetNumberOfLiveRegisters(),
1644 maximum_number_of_live_core_registers_ +
1645 maximum_number_of_live_fp_registers_);
1646 }
Nicolas Geoffray39468442014-09-02 15:17:15 +01001647 if (current->GetType() == Primitive::kPrimNot) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +01001648 locations->SetRegisterBit(source.reg());
Nicolas Geoffray39468442014-09-02 15:17:15 +01001649 }
1650 break;
1651 }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001652 case Location::kFpuRegister: {
1653 locations->AddLiveRegister(source);
1654 break;
1655 }
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +00001656
1657 case Location::kRegisterPair:
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001658 case Location::kFpuRegisterPair: {
1659 locations->AddLiveRegister(source.ToLow());
1660 locations->AddLiveRegister(source.ToHigh());
1661 break;
1662 }
Nicolas Geoffray39468442014-09-02 15:17:15 +01001663 case Location::kStackSlot: // Fall-through
1664 case Location::kDoubleStackSlot: // Fall-through
1665 case Location::kConstant: {
1666 // Nothing to do.
1667 break;
1668 }
1669 default: {
1670 LOG(FATAL) << "Unexpected location for object";
1671 }
1672 }
1673 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001674 current = next_sibling;
1675 } while (current != nullptr);
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +00001676
Nicolas Geoffray57902602015-04-21 14:28:41 +01001677 if (kIsDebugBuild) {
1678 // Following uses can only be synthesized uses.
1679 while (use != nullptr) {
1680 DCHECK(use->IsSynthesized());
1681 use = use->GetNext();
1682 }
1683 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001684}
1685
1686void RegisterAllocator::ConnectSplitSiblings(LiveInterval* interval,
1687 HBasicBlock* from,
1688 HBasicBlock* to) const {
1689 if (interval->GetNextSibling() == nullptr) {
1690 // Nothing to connect. The whole range was allocated to the same location.
1691 return;
1692 }
1693
David Brazdil241a4862015-04-16 17:59:03 +01001694 // Find the intervals that cover `from` and `to`.
1695 LiveInterval* destination = interval->GetSiblingAt(to->GetLifetimeStart());
1696 LiveInterval* source = interval->GetSiblingAt(from->GetLifetimeEnd() - 1);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001697
1698 if (destination == source) {
1699 // Interval was not split.
1700 return;
1701 }
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +01001702 DCHECK(destination != nullptr && source != nullptr);
1703
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001704 if (!destination->HasRegister()) {
1705 // Values are eagerly spilled. Spill slot already contains appropriate value.
1706 return;
1707 }
1708
1709 // If `from` has only one successor, we can put the moves at the exit of it. Otherwise
1710 // we need to put the moves at the entry of `to`.
1711 if (from->GetSuccessors().Size() == 1) {
Nicolas Geoffray740475d2014-09-29 10:33:25 +01001712 InsertParallelMoveAtExitOf(from,
1713 interval->GetParent()->GetDefinedBy(),
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001714 source->ToLocation(),
1715 destination->ToLocation());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001716 } else {
1717 DCHECK_EQ(to->GetPredecessors().Size(), 1u);
Nicolas Geoffray740475d2014-09-29 10:33:25 +01001718 InsertParallelMoveAtEntryOf(to,
1719 interval->GetParent()->GetDefinedBy(),
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001720 source->ToLocation(),
1721 destination->ToLocation());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001722 }
1723}
1724
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001725void RegisterAllocator::Resolve() {
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001726 codegen_->InitializeCodeGeneration(GetNumberOfSpillSlots(),
Nicolas Geoffray4c204ba2015-02-03 15:12:35 +00001727 maximum_number_of_live_core_registers_,
1728 maximum_number_of_live_fp_registers_,
1729 reserved_out_slots_,
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01001730 codegen_->GetGraph()->GetLinearOrder());
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001731
1732 // Adjust the Out Location of instructions.
1733 // TODO: Use pointers of Location inside LiveInterval to avoid doing another iteration.
1734 for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) {
1735 HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
1736 LiveInterval* current = instruction->GetLiveInterval();
1737 LocationSummary* locations = instruction->GetLocations();
1738 Location location = locations->Out();
Roland Levillain476df552014-10-09 17:51:36 +01001739 if (instruction->IsParameterValue()) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001740 // Now that we know the frame size, adjust the parameter's location.
1741 if (location.IsStackSlot()) {
1742 location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
1743 current->SetSpillSlot(location.GetStackIndex());
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +00001744 locations->UpdateOut(location);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001745 } else if (location.IsDoubleStackSlot()) {
1746 location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
1747 current->SetSpillSlot(location.GetStackIndex());
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +00001748 locations->UpdateOut(location);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001749 } else if (current->HasSpillSlot()) {
1750 current->SetSpillSlot(current->GetSpillSlot() + codegen_->GetFrameSize());
1751 }
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001752 } else if (instruction->IsCurrentMethod()) {
1753 // The current method is always at offset 0.
1754 DCHECK(!current->HasSpillSlot() || (current->GetSpillSlot() == 0));
Nicolas Geoffray776b3182015-02-23 14:14:57 +00001755 } else if (current->HasSpillSlot()) {
1756 // Adjust the stack slot, now that we know the number of them for each type.
1757 // The way this implementation lays out the stack is the following:
1758 // [parameter slots ]
1759 // [double spill slots ]
1760 // [long spill slots ]
1761 // [float spill slots ]
1762 // [int/ref values ]
1763 // [maximum out values ] (number of arguments for calls)
1764 // [art method ].
1765 uint32_t slot = current->GetSpillSlot();
1766 switch (current->GetType()) {
1767 case Primitive::kPrimDouble:
1768 slot += long_spill_slots_.Size();
1769 FALLTHROUGH_INTENDED;
1770 case Primitive::kPrimLong:
1771 slot += float_spill_slots_.Size();
1772 FALLTHROUGH_INTENDED;
1773 case Primitive::kPrimFloat:
1774 slot += int_spill_slots_.Size();
1775 FALLTHROUGH_INTENDED;
1776 case Primitive::kPrimNot:
1777 case Primitive::kPrimInt:
1778 case Primitive::kPrimChar:
1779 case Primitive::kPrimByte:
1780 case Primitive::kPrimBoolean:
1781 case Primitive::kPrimShort:
1782 slot += reserved_out_slots_;
1783 break;
1784 case Primitive::kPrimVoid:
1785 LOG(FATAL) << "Unexpected type for interval " << current->GetType();
1786 }
1787 current->SetSpillSlot(slot * kVRegSize);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001788 }
1789
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001790 Location source = current->ToLocation();
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001791
1792 if (location.IsUnallocated()) {
1793 if (location.GetPolicy() == Location::kSameAsFirstInput) {
Calin Juravled0d48522014-11-04 16:40:20 +00001794 if (locations->InAt(0).IsUnallocated()) {
1795 locations->SetInAt(0, source);
1796 } else {
1797 DCHECK(locations->InAt(0).Equals(source));
1798 }
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001799 }
Nicolas Geoffray829280c2015-01-28 10:20:37 +00001800 locations->UpdateOut(source);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001801 } else {
1802 DCHECK(source.Equals(location));
1803 }
1804 }
1805
1806 // Connect siblings.
1807 for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) {
1808 HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
1809 ConnectSiblings(instruction->GetLiveInterval());
1810 }
1811
1812 // Resolve non-linear control flow across branches. Order does not matter.
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01001813 for (HLinearOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001814 HBasicBlock* block = it.Current();
1815 BitVector* live = liveness_.GetLiveInSet(*block);
1816 for (uint32_t idx : live->Indexes()) {
1817 HInstruction* current = liveness_.GetInstructionFromSsaIndex(idx);
1818 LiveInterval* interval = current->GetLiveInterval();
1819 for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
1820 ConnectSplitSiblings(interval, block->GetPredecessors().Get(i), block);
1821 }
1822 }
1823 }
1824
1825 // Resolve phi inputs. Order does not matter.
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01001826 for (HLinearOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001827 HBasicBlock* current = it.Current();
Andreas Gampe277ccbd2014-11-03 21:36:10 -08001828 for (HInstructionIterator inst_it(current->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
1829 HInstruction* phi = inst_it.Current();
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001830 for (size_t i = 0, e = current->GetPredecessors().Size(); i < e; ++i) {
1831 HBasicBlock* predecessor = current->GetPredecessors().Get(i);
1832 DCHECK_EQ(predecessor->GetSuccessors().Size(), 1u);
1833 HInstruction* input = phi->InputAt(i);
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001834 Location source = input->GetLiveInterval()->GetLocationAt(
1835 predecessor->GetLifetimeEnd() - 1);
1836 Location destination = phi->GetLiveInterval()->ToLocation();
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00001837 InsertParallelMoveAtExitOf(predecessor, phi, source, destination);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +01001838 }
1839 }
1840 }
Nicolas Geoffray39468442014-09-02 15:17:15 +01001841
1842 // Assign temp locations.
Nicolas Geoffray39468442014-09-02 15:17:15 +01001843 for (size_t i = 0; i < temp_intervals_.Size(); ++i) {
1844 LiveInterval* temp = temp_intervals_.Get(i);
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001845 if (temp->IsHighInterval()) {
1846 // High intervals can be skipped, they are already handled by the low interval.
1847 continue;
1848 }
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001849 HInstruction* at = liveness_.GetTempUser(temp);
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +00001850 size_t temp_index = liveness_.GetTempIndex(temp);
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001851 LocationSummary* locations = at->GetLocations();
Roland Levillain5368c212014-11-27 15:03:41 +00001852 switch (temp->GetType()) {
1853 case Primitive::kPrimInt:
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +00001854 locations->SetTempAt(temp_index, Location::RegisterLocation(temp->GetRegister()));
Roland Levillain5368c212014-11-27 15:03:41 +00001855 break;
1856
1857 case Primitive::kPrimDouble:
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001858 if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) {
1859 Location location = Location::FpuRegisterPairLocation(
1860 temp->GetRegister(), temp->GetHighInterval()->GetRegister());
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +00001861 locations->SetTempAt(temp_index, location);
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001862 } else {
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +00001863 locations->SetTempAt(temp_index, Location::FpuRegisterLocation(temp->GetRegister()));
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001864 }
Roland Levillain5368c212014-11-27 15:03:41 +00001865 break;
1866
1867 default:
1868 LOG(FATAL) << "Unexpected type for temporary location "
1869 << temp->GetType();
1870 }
Nicolas Geoffray39468442014-09-02 15:17:15 +01001871 }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001872}
1873
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001874} // namespace art