1 /*
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_linear_scan.h"
18
19 #include <iostream>
20 #include <sstream>
21
22 #include "base/bit_utils_iterator.h"
23 #include "base/bit_vector-inl.h"
24 #include "base/pointer_size.h"
25 #include "code_generator.h"
26 #include "linear_order.h"
27 #include "register_allocation_resolver.h"
28 #include "ssa_liveness_analysis.h"
29
30 namespace art HIDDEN {
31
32 static constexpr size_t kMaxLifetimePosition = -1;
33 static constexpr size_t kDefaultNumberOfSpillSlots = 4;
34
35 // For simplicity, we implement register pairs as (reg, reg + 1).
36 // Note that this is a requirement for double registers on ARM, since we
37 // allocate SRegister.
GetHighForLowRegister(int reg)38 static int GetHighForLowRegister(int reg) { return reg + 1; }
IsLowRegister(int reg)39 static bool IsLowRegister(int reg) { return (reg & 1) == 0; }
IsLowOfUnalignedPairInterval(LiveInterval * low)40 static bool IsLowOfUnalignedPairInterval(LiveInterval* low) {
41 return GetHighForLowRegister(low->GetRegister()) != low->GetHighInterval()->GetRegister();
42 }
43
RegisterAllocatorLinearScan(ScopedArenaAllocator * allocator,CodeGenerator * codegen,const SsaLivenessAnalysis & liveness)44 RegisterAllocatorLinearScan::RegisterAllocatorLinearScan(ScopedArenaAllocator* allocator,
45 CodeGenerator* codegen,
46 const SsaLivenessAnalysis& liveness)
47 : RegisterAllocator(allocator, codegen, liveness),
48 unhandled_core_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
49 unhandled_fp_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
50 unhandled_(nullptr),
51 handled_(allocator->Adapter(kArenaAllocRegisterAllocator)),
52 active_(allocator->Adapter(kArenaAllocRegisterAllocator)),
53 inactive_(allocator->Adapter(kArenaAllocRegisterAllocator)),
54 physical_core_register_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
55 physical_fp_register_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
56 block_registers_for_call_interval_(
57 LiveInterval::MakeFixedInterval(allocator, kNoRegister, DataType::Type::kVoid)),
58 block_registers_special_interval_(
59 LiveInterval::MakeFixedInterval(allocator, kNoRegister, DataType::Type::kVoid)),
60 temp_intervals_(allocator->Adapter(kArenaAllocRegisterAllocator)),
61 int_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
62 long_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
63 float_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
64 double_spill_slots_(allocator->Adapter(kArenaAllocRegisterAllocator)),
65 catch_phi_spill_slots_(0),
66 safepoints_(allocator->Adapter(kArenaAllocRegisterAllocator)),
67 current_register_type_(RegisterType::kCoreRegister),
68 number_of_registers_(-1),
69 registers_array_(nullptr),
70 blocked_core_registers_(codegen->GetBlockedCoreRegisters()),
71 blocked_fp_registers_(codegen->GetBlockedFloatingPointRegisters()),
72 reserved_out_slots_(0) {
73 temp_intervals_.reserve(4);
74 int_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
75 long_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
76 float_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
77 double_spill_slots_.reserve(kDefaultNumberOfSpillSlots);
78
79 codegen->SetupBlockedRegisters();
80 physical_core_register_intervals_.resize(codegen->GetNumberOfCoreRegisters(), nullptr);
81 physical_fp_register_intervals_.resize(codegen->GetNumberOfFloatingPointRegisters(), nullptr);
82 // Always reserve for the current method and the graph's max out registers.
83 // TODO: compute it instead.
84 // ArtMethod* takes 2 vregs for 64 bits.
85 size_t ptr_size = static_cast<size_t>(InstructionSetPointerSize(codegen->GetInstructionSet()));
86 reserved_out_slots_ = ptr_size / kVRegSize + codegen->GetGraph()->GetMaximumNumberOfOutVRegs();
87 }
88
~RegisterAllocatorLinearScan()89 RegisterAllocatorLinearScan::~RegisterAllocatorLinearScan() {}
90
AllocateRegisters()91 void RegisterAllocatorLinearScan::AllocateRegisters() {
92 AllocateRegistersInternal();
93 RegisterAllocationResolver(codegen_, liveness_)
94 .Resolve(ArrayRef<HInstruction* const>(safepoints_),
95 reserved_out_slots_,
96 int_spill_slots_.size(),
97 long_spill_slots_.size(),
98 float_spill_slots_.size(),
99 double_spill_slots_.size(),
100 catch_phi_spill_slots_,
101 ArrayRef<LiveInterval* const>(temp_intervals_));
102
103 if (kIsDebugBuild) {
104 current_register_type_ = RegisterType::kCoreRegister;
105 ValidateInternal(true);
106 current_register_type_ = RegisterType::kFpRegister;
107 ValidateInternal(true);
108 // Check that the linear order is still correct with regards to lifetime positions.
109 // Since only parallel moves have been inserted during the register allocation,
110 // these checks are mostly for making sure these moves have been added correctly.
111 size_t current_liveness = 0;
112 for (HBasicBlock* block : codegen_->GetGraph()->GetLinearOrder()) {
113 for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
114 HInstruction* instruction = inst_it.Current();
115 DCHECK_LE(current_liveness, instruction->GetLifetimePosition());
116 current_liveness = instruction->GetLifetimePosition();
117 }
118 for (HInstructionIterator inst_it(block->GetInstructions());
119 !inst_it.Done();
120 inst_it.Advance()) {
121 HInstruction* instruction = inst_it.Current();
122 DCHECK_LE(current_liveness, instruction->GetLifetimePosition()) << instruction->DebugName();
123 current_liveness = instruction->GetLifetimePosition();
124 }
125 }
126 }
127 }
128
BlockRegister(Location location,size_t position,bool will_call)129 void RegisterAllocatorLinearScan::BlockRegister(Location location,
130 size_t position,
131 bool will_call) {
132 DCHECK(location.IsRegister() || location.IsFpuRegister());
133 int reg = location.reg();
134 if (will_call) {
135 uint32_t registers_blocked_for_call =
136 location.IsRegister() ? core_registers_blocked_for_call_ : fp_registers_blocked_for_call_;
137 if ((registers_blocked_for_call & (1u << reg)) != 0u) {
138 // Register is already marked as blocked by the `block_registers_for_call_interval_`.
139 return;
140 }
141 }
142 DCHECK(location.IsRegister() || location.IsFpuRegister());
143 LiveInterval* interval = location.IsRegister()
144 ? physical_core_register_intervals_[reg]
145 : physical_fp_register_intervals_[reg];
146 DataType::Type type = location.IsRegister()
147 ? DataType::Type::kInt32
148 : DataType::Type::kFloat32;
149 if (interval == nullptr) {
150 interval = LiveInterval::MakeFixedInterval(allocator_, reg, type);
151 if (location.IsRegister()) {
152 physical_core_register_intervals_[reg] = interval;
153 } else {
154 physical_fp_register_intervals_[reg] = interval;
155 }
156 }
157 DCHECK(interval->GetRegister() == reg);
158 interval->AddRange(position, position + 1u);
159 }
160
AllocateRegistersInternal()161 void RegisterAllocatorLinearScan::AllocateRegistersInternal() {
162 // Iterate post-order, to ensure the list is sorted, and the last added interval
163 // is the one with the lowest start position.
164 for (HBasicBlock* block : codegen_->GetGraph()->GetLinearPostOrder()) {
165 for (HBackwardInstructionIterator back_it(block->GetInstructions()); !back_it.Done();
166 back_it.Advance()) {
167 ProcessInstruction(back_it.Current());
168 }
169 for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
170 ProcessInstruction(inst_it.Current());
171 }
172
173 if (block->IsCatchBlock() ||
174 (block->IsLoopHeader() && block->GetLoopInformation()->IsIrreducible())) {
175 // By blocking all registers at the top of each catch block or irreducible loop, we force
176 // intervals belonging to the live-in set of the catch/header block to be spilled.
177 // TODO(ngeoffray): Phis in this block could be allocated in register.
178 size_t position = block->GetLifetimeStart();
179 DCHECK_EQ(liveness_.GetInstructionFromPosition(position / 2u), nullptr);
180 block_registers_special_interval_->AddRange(position, position + 1u);
181 }
182 }
183
184 number_of_registers_ = codegen_->GetNumberOfCoreRegisters();
185 registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_,
186 kArenaAllocRegisterAllocator);
187 current_register_type_ = RegisterType::kCoreRegister;
188 unhandled_ = &unhandled_core_intervals_;
189 // Add intervals representing groups of physical registers blocked for calls,
190 // catch blocks and irreducible loop headers.
191 for (LiveInterval* block_registers_interval : { block_registers_for_call_interval_,
192 block_registers_special_interval_ }) {
193 if (block_registers_interval->GetFirstRange() != nullptr) {
194 block_registers_interval->ResetSearchCache();
195 inactive_.push_back(block_registers_interval);
196 }
197 }
198 for (LiveInterval* fixed : physical_core_register_intervals_) {
199 if (fixed != nullptr) {
200 // Fixed interval is added to inactive_ instead of unhandled_.
201 // It's also the only type of inactive interval whose start position
202 // can be after the current interval during linear scan.
203 // Fixed interval is never split and never moves to unhandled_.
204 inactive_.push_back(fixed);
205 }
206 }
207 LinearScan();
208
209 inactive_.clear();
210 active_.clear();
211 handled_.clear();
212
213 number_of_registers_ = codegen_->GetNumberOfFloatingPointRegisters();
214 registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_,
215 kArenaAllocRegisterAllocator);
216 current_register_type_ = RegisterType::kFpRegister;
217 unhandled_ = &unhandled_fp_intervals_;
218 // Add intervals representing groups of physical registers blocked for calls,
219 // catch blocks and irreducible loop headers.
220 for (LiveInterval* block_registers_interval : { block_registers_for_call_interval_,
221 block_registers_special_interval_ }) {
222 if (block_registers_interval->GetFirstRange() != nullptr) {
223 block_registers_interval->ResetSearchCache();
224 inactive_.push_back(block_registers_interval);
225 }
226 }
227 for (LiveInterval* fixed : physical_fp_register_intervals_) {
228 if (fixed != nullptr) {
229 // Fixed interval is added to inactive_ instead of unhandled_.
230 // It's also the only type of inactive interval whose start position
231 // can be after the current interval during linear scan.
232 // Fixed interval is never split and never moves to unhandled_.
233 inactive_.push_back(fixed);
234 }
235 }
236 LinearScan();
237 }
238
ProcessInstruction(HInstruction * instruction)239 void RegisterAllocatorLinearScan::ProcessInstruction(HInstruction* instruction) {
240 LocationSummary* locations = instruction->GetLocations();
241
242 // Check for early returns.
243 if (locations == nullptr) {
244 return;
245 }
246 if (TryRemoveSuspendCheckEntry(instruction)) {
247 return;
248 }
249
250 bool will_call = locations->WillCall();
251 if (will_call) {
252 // If a call will happen, add the range to a fixed interval that represents all the
253 // caller-save registers blocked at call sites.
254 const size_t position = instruction->GetLifetimePosition();
255 DCHECK_NE(liveness_.GetInstructionFromPosition(position / 2u), nullptr);
256 block_registers_for_call_interval_->AddRange(position, position + 1u);
257 }
258 CheckForTempLiveIntervals(instruction, will_call);
259 CheckForSafepoint(instruction);
260 CheckForFixedInputs(instruction, will_call);
261
262 LiveInterval* current = instruction->GetLiveInterval();
263 if (current == nullptr)
264 return;
265
266 const bool core_register = !DataType::IsFloatingPointType(instruction->GetType());
267 ScopedArenaVector<LiveInterval*>& unhandled =
268 core_register ? unhandled_core_intervals_ : unhandled_fp_intervals_;
269
270 DCHECK(unhandled.empty() || current->StartsBeforeOrAt(unhandled.back()));
271
272 if (codegen_->NeedsTwoRegisters(current->GetType())) {
273 current->AddHighInterval();
274 }
275
276 AddSafepointsFor(instruction);
277 current->ResetSearchCache();
278 CheckForFixedOutput(instruction, will_call);
279
280 if (instruction->IsPhi() && instruction->AsPhi()->IsCatchPhi()) {
281 AllocateSpillSlotForCatchPhi(instruction->AsPhi());
282 }
283
284 // If needed, add interval to the list of unhandled intervals.
285 if (current->HasSpillSlot() || instruction->IsConstant()) {
286 // Split just before first register use.
287 size_t first_register_use = current->FirstRegisterUse();
288 if (first_register_use != kNoLifetime) {
289 LiveInterval* split = SplitBetween(current, current->GetStart(), first_register_use - 1);
290 // Don't add directly to `unhandled`, it needs to be sorted and the start
291 // of this new interval might be after intervals already in the list.
292 AddSorted(&unhandled, split);
293 } else {
294 // Nothing to do, we won't allocate a register for this value.
295 }
296 } else {
297 // Don't add directly to `unhandled`, temp or safepoint intervals
298 // for this instruction may have been added, and those can be
299 // processed first.
300 AddSorted(&unhandled, current);
301 }
302 }
303
TryRemoveSuspendCheckEntry(HInstruction * instruction)304 bool RegisterAllocatorLinearScan::TryRemoveSuspendCheckEntry(HInstruction* instruction) {
305 LocationSummary* locations = instruction->GetLocations();
306 if (instruction->IsSuspendCheckEntry() && !codegen_->NeedsSuspendCheckEntry()) {
307 // TODO: We do this here because we do not want the suspend check to artificially
308 // create live registers. We should find another place, but this is currently the
309 // simplest.
310 DCHECK_EQ(locations->GetTempCount(), 0u);
311 instruction->GetBlock()->RemoveInstruction(instruction);
312 return true;
313 }
314 return false;
315 }
316
CheckForTempLiveIntervals(HInstruction * instruction,bool will_call)317 void RegisterAllocatorLinearScan::CheckForTempLiveIntervals(HInstruction* instruction,
318 bool will_call) {
319 LocationSummary* locations = instruction->GetLocations();
320 size_t position = instruction->GetLifetimePosition();
321
322 // Create synthesized intervals for temporaries.
323 for (size_t i = 0; i < locations->GetTempCount(); ++i) {
324 Location temp = locations->GetTemp(i);
325 if (temp.IsRegister() || temp.IsFpuRegister()) {
326 BlockRegister(temp, position, will_call);
327 // Ensure that an explicit temporary register is marked as being allocated.
328 codegen_->AddAllocatedRegister(temp);
329 } else {
330 DCHECK(temp.IsUnallocated());
331 switch (temp.GetPolicy()) {
332 case Location::kRequiresRegister: {
333 LiveInterval* interval =
334 LiveInterval::MakeTempInterval(allocator_, DataType::Type::kInt32);
335 temp_intervals_.push_back(interval);
336 interval->AddTempUse(instruction, i);
337 unhandled_core_intervals_.push_back(interval);
338 break;
339 }
340
341 case Location::kRequiresFpuRegister: {
342 LiveInterval* interval =
343 LiveInterval::MakeTempInterval(allocator_, DataType::Type::kFloat64);
344 temp_intervals_.push_back(interval);
345 interval->AddTempUse(instruction, i);
346 if (codegen_->NeedsTwoRegisters(DataType::Type::kFloat64)) {
347 interval->AddHighInterval(/* is_temp= */ true);
348 LiveInterval* high = interval->GetHighInterval();
349 temp_intervals_.push_back(high);
350 unhandled_fp_intervals_.push_back(high);
351 }
352 unhandled_fp_intervals_.push_back(interval);
353 break;
354 }
355
356 default:
357 LOG(FATAL) << "Unexpected policy for temporary location " << temp.GetPolicy();
358 }
359 }
360 }
361 }
362
CheckForSafepoint(HInstruction * instruction)363 void RegisterAllocatorLinearScan::CheckForSafepoint(HInstruction* instruction) {
364 LocationSummary* locations = instruction->GetLocations();
365 if (locations->NeedsSafepoint()) {
366 safepoints_.push_back(instruction);
367 }
368 }
369
CheckForFixedInputs(HInstruction * instruction,bool will_call)370 void RegisterAllocatorLinearScan::CheckForFixedInputs(HInstruction* instruction, bool will_call) {
371 LocationSummary* locations = instruction->GetLocations();
372 size_t position = instruction->GetLifetimePosition();
373 for (size_t i = 0; i < locations->GetInputCount(); ++i) {
374 Location input = locations->InAt(i);
375 if (input.IsRegister() || input.IsFpuRegister()) {
376 BlockRegister(input, position, will_call);
377 // Ensure that an explicit input register is marked as being allocated.
378 codegen_->AddAllocatedRegister(input);
379 } else if (input.IsPair()) {
380 BlockRegister(input.ToLow(), position, will_call);
381 BlockRegister(input.ToHigh(), position, will_call);
382 // Ensure that an explicit input register pair is marked as being allocated.
383 codegen_->AddAllocatedRegister(input.ToLow());
384 codegen_->AddAllocatedRegister(input.ToHigh());
385 }
386 }
387 }
388
AddSafepointsFor(HInstruction * instruction)389 void RegisterAllocatorLinearScan::AddSafepointsFor(HInstruction* instruction) {
390 LiveInterval* current = instruction->GetLiveInterval();
391 for (size_t safepoint_index = safepoints_.size(); safepoint_index > 0; --safepoint_index) {
392 HInstruction* safepoint = safepoints_[safepoint_index - 1u];
393 size_t safepoint_position = SafepointPosition::ComputePosition(safepoint);
394
395 // Test that safepoints are ordered in the optimal way.
396 DCHECK(safepoint_index == safepoints_.size() ||
397 safepoints_[safepoint_index]->GetLifetimePosition() < safepoint_position);
398
399 if (safepoint_position == current->GetStart()) {
400 // The safepoint is for this instruction, so the location of the instruction
401 // does not need to be saved.
402 DCHECK_EQ(safepoint_index, safepoints_.size());
403 DCHECK_EQ(safepoint, instruction);
404 continue;
405 } else if (current->IsDeadAt(safepoint_position)) {
406 break;
407 } else if (!current->Covers(safepoint_position)) {
408 // Hole in the interval.
409 continue;
410 }
411 current->AddSafepoint(safepoint);
412 }
413 }
414
CheckForFixedOutput(HInstruction * instruction,bool will_call)415 void RegisterAllocatorLinearScan::CheckForFixedOutput(HInstruction* instruction, bool will_call) {
416 LocationSummary* locations = instruction->GetLocations();
417 size_t position = instruction->GetLifetimePosition();
418 LiveInterval* current = instruction->GetLiveInterval();
419 // Some instructions define their output in fixed register/stack slot. We need
420 // to ensure we know these locations before doing register allocation. For a
421 // given register, we create an interval that covers these locations. The register
422 // will be unavailable at these locations when trying to allocate one for an
423 // interval.
424 //
425 // The backwards walking ensures the ranges are ordered on increasing start positions.
426 Location output = locations->Out();
427 if (output.IsUnallocated() && output.GetPolicy() == Location::kSameAsFirstInput) {
428 Location first = locations->InAt(0);
429 if (first.IsRegister() || first.IsFpuRegister()) {
430 current->SetFrom(position + 1u);
431 current->SetRegister(first.reg());
432 } else if (first.IsPair()) {
433 current->SetFrom(position + 1u);
434 current->SetRegister(first.low());
435 LiveInterval* high = current->GetHighInterval();
436 high->SetRegister(first.high());
437 high->SetFrom(position + 1u);
438 }
439 } else if (output.IsRegister() || output.IsFpuRegister()) {
440 // Shift the interval's start by one to account for the blocked register.
441 current->SetFrom(position + 1u);
442 current->SetRegister(output.reg());
443 BlockRegister(output, position, will_call);
444 // Ensure that an explicit output register is marked as being allocated.
445 codegen_->AddAllocatedRegister(output);
446 } else if (output.IsPair()) {
447 current->SetFrom(position + 1u);
448 current->SetRegister(output.low());
449 LiveInterval* high = current->GetHighInterval();
450 high->SetRegister(output.high());
451 high->SetFrom(position + 1u);
452 BlockRegister(output.ToLow(), position, will_call);
453 BlockRegister(output.ToHigh(), position, will_call);
454 // Ensure that an explicit output register pair is marked as being allocated.
455 codegen_->AddAllocatedRegister(output.ToLow());
456 codegen_->AddAllocatedRegister(output.ToHigh());
457 } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) {
458 current->SetSpillSlot(output.GetStackIndex());
459 } else {
460 DCHECK(output.IsUnallocated() || output.IsConstant());
461 }
462 }
463
464 class AllRangesIterator : public ValueObject {
465 public:
AllRangesIterator(LiveInterval * interval)466 explicit AllRangesIterator(LiveInterval* interval)
467 : current_interval_(interval),
468 current_range_(interval->GetFirstRange()) {}
469
Done() const470 bool Done() const { return current_interval_ == nullptr; }
CurrentRange() const471 LiveRange* CurrentRange() const { return current_range_; }
CurrentInterval() const472 LiveInterval* CurrentInterval() const { return current_interval_; }
473
Advance()474 void Advance() {
475 current_range_ = current_range_->GetNext();
476 if (current_range_ == nullptr) {
477 current_interval_ = current_interval_->GetNextSibling();
478 if (current_interval_ != nullptr) {
479 current_range_ = current_interval_->GetFirstRange();
480 }
481 }
482 }
483
484 private:
485 LiveInterval* current_interval_;
486 LiveRange* current_range_;
487
488 DISALLOW_COPY_AND_ASSIGN(AllRangesIterator);
489 };
490
ValidateInternal(bool log_fatal_on_failure) const491 bool RegisterAllocatorLinearScan::ValidateInternal(bool log_fatal_on_failure) const {
492 auto should_process = [](RegisterType current_register_type, LiveInterval* interval) {
493 if (interval == nullptr) {
494 return false;
495 }
496 RegisterType register_type = DataType::IsFloatingPointType(interval->GetType())
497 ? RegisterType::kFpRegister
498 : RegisterType::kCoreRegister;
499 return register_type == current_register_type;
500 };
501
502 // To simplify unit testing, we eagerly create the array of intervals, and
503 // call the helper method.
504 ScopedArenaAllocator allocator(allocator_->GetArenaStack());
505 ScopedArenaVector<LiveInterval*> intervals(
506 allocator.Adapter(kArenaAllocRegisterAllocatorValidate));
507 for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) {
508 HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
509 if (should_process(current_register_type_, instruction->GetLiveInterval())) {
510 intervals.push_back(instruction->GetLiveInterval());
511 }
512 }
513
514 for (LiveInterval* block_registers_interval : { block_registers_for_call_interval_,
515 block_registers_special_interval_ }) {
516 if (block_registers_interval->GetFirstRange() != nullptr) {
517 intervals.push_back(block_registers_interval);
518 }
519 }
520 const ScopedArenaVector<LiveInterval*>* physical_register_intervals =
521 (current_register_type_ == RegisterType::kCoreRegister)
522 ? &physical_core_register_intervals_
523 : &physical_fp_register_intervals_;
524 for (LiveInterval* fixed : *physical_register_intervals) {
525 if (fixed != nullptr) {
526 intervals.push_back(fixed);
527 }
528 }
529
530 for (LiveInterval* temp : temp_intervals_) {
531 if (should_process(current_register_type_, temp)) {
532 intervals.push_back(temp);
533 }
534 }
535
536 return ValidateIntervals(ArrayRef<LiveInterval* const>(intervals),
537 GetNumberOfSpillSlots(),
538 reserved_out_slots_,
539 *codegen_,
540 &liveness_,
541 current_register_type_,
542 log_fatal_on_failure);
543 }
544
DumpInterval(std::ostream & stream,LiveInterval * interval) const545 void RegisterAllocatorLinearScan::DumpInterval(std::ostream& stream, LiveInterval* interval) const {
546 interval->Dump(stream);
547 stream << ": ";
548 if (interval->HasRegister()) {
549 if (interval->IsFloatingPoint()) {
550 codegen_->DumpFloatingPointRegister(stream, interval->GetRegister());
551 } else {
552 codegen_->DumpCoreRegister(stream, interval->GetRegister());
553 }
554 } else if (interval->IsFixed()) {
555 DCHECK_EQ(interval->GetType(), DataType::Type::kVoid);
556 DCHECK(interval == block_registers_for_call_interval_ ||
557 interval == block_registers_special_interval_);
558 stream << (interval == block_registers_for_call_interval_ ? "block-for-call" : "block-special");
559 } else {
560 stream << "spilled";
561 }
562 stream << std::endl;
563 }
564
DumpAllIntervals(std::ostream & stream) const565 void RegisterAllocatorLinearScan::DumpAllIntervals(std::ostream& stream) const {
566 stream << "inactive: " << std::endl;
567 for (LiveInterval* inactive_interval : inactive_) {
568 DumpInterval(stream, inactive_interval);
569 }
570 stream << "active: " << std::endl;
571 for (LiveInterval* active_interval : active_) {
572 DumpInterval(stream, active_interval);
573 }
574 stream << "unhandled: " << std::endl;
575 auto unhandled = (unhandled_ != nullptr) ?
576 unhandled_ : &unhandled_core_intervals_;
577 for (LiveInterval* unhandled_interval : *unhandled) {
578 DumpInterval(stream, unhandled_interval);
579 }
580 stream << "handled: " << std::endl;
581 for (LiveInterval* handled_interval : handled_) {
582 DumpInterval(stream, handled_interval);
583 }
584 }
585
586 // By the book implementation of a linear scan register allocator.
LinearScan()587 void RegisterAllocatorLinearScan::LinearScan() {
588 while (!unhandled_->empty()) {
589 // (1) Remove interval with the lowest start position from unhandled.
590 LiveInterval* current = unhandled_->back();
591 unhandled_->pop_back();
592
593 // Make sure the interval is an expected state.
594 DCHECK(!current->IsFixed() && !current->HasSpillSlot());
595 // Make sure we are going in the right order.
596 DCHECK(unhandled_->empty() || unhandled_->back()->GetStart() >= current->GetStart());
597 // Make sure a low interval is always with a high.
598 DCHECK_IMPLIES(current->IsLowInterval(), unhandled_->back()->IsHighInterval());
599 // Make sure a high interval is always with a low.
600 DCHECK(current->IsLowInterval() ||
601 unhandled_->empty() ||
602 !unhandled_->back()->IsHighInterval());
603
604 size_t position = current->GetStart();
605
606 // Remember the inactive_ size here since the ones moved to inactive_ from
607 // active_ below shouldn't need to be re-checked.
608 size_t inactive_intervals_to_handle = inactive_.size();
609
610 // (2) Remove currently active intervals that are dead at this position.
611 // Move active intervals that have a lifetime hole at this position
612 // to inactive.
613 auto active_kept_end = std::remove_if(
614 active_.begin(),
615 active_.end(),
616 [this, position](LiveInterval* interval) {
617 if (interval->IsDeadAt(position)) {
618 handled_.push_back(interval);
619 return true;
620 } else if (!interval->Covers(position)) {
621 inactive_.push_back(interval);
622 return true;
623 } else {
624 return false; // Keep this interval.
625 }
626 });
627 active_.erase(active_kept_end, active_.end());
628
629 // (3) Remove currently inactive intervals that are dead at this position.
630 // Move inactive intervals that cover this position to active.
631 auto inactive_to_handle_end = inactive_.begin() + inactive_intervals_to_handle;
632 auto inactive_kept_end = std::remove_if(
633 inactive_.begin(),
634 inactive_to_handle_end,
635 [this, position](LiveInterval* interval) {
636 DCHECK(interval->GetStart() < position || interval->IsFixed());
637 if (interval->IsDeadAt(position)) {
638 handled_.push_back(interval);
639 return true;
640 } else if (interval->Covers(position)) {
641 active_.push_back(interval);
642 return true;
643 } else {
644 return false; // Keep this interval.
645 }
646 });
647 inactive_.erase(inactive_kept_end, inactive_to_handle_end);
648
649 if (current->IsHighInterval() && !current->GetLowInterval()->HasRegister()) {
650 DCHECK(!current->HasRegister());
651 // Allocating the low part was unsucessful. The splitted interval for the high part
652 // will be handled next (it is in the `unhandled_` list).
653 continue;
654 }
655
656 // (4) Try to find an available register.
657 bool success = TryAllocateFreeReg(current);
658
659 // (5) If no register could be found, we need to spill.
660 if (!success) {
661 success = AllocateBlockedReg(current);
662 }
663
664 // (6) If the interval had a register allocated, add it to the list of active
665 // intervals.
666 if (success) {
667 codegen_->AddAllocatedRegister((current_register_type_ == RegisterType::kCoreRegister)
668 ? Location::RegisterLocation(current->GetRegister())
669 : Location::FpuRegisterLocation(current->GetRegister()));
670 active_.push_back(current);
671 if (current->HasHighInterval() && !current->GetHighInterval()->HasRegister()) {
672 current->GetHighInterval()->SetRegister(GetHighForLowRegister(current->GetRegister()));
673 }
674 }
675 }
676 }
677
FreeIfNotCoverAt(LiveInterval * interval,size_t position,size_t * free_until)678 static void FreeIfNotCoverAt(LiveInterval* interval, size_t position, size_t* free_until) {
679 DCHECK(!interval->IsHighInterval());
680 // Note that the same instruction may occur multiple times in the input list,
681 // so `free_until` may have changed already.
682 // Since `position` is not the current scan position, we need to use CoversSlow.
683 if (interval->IsDeadAt(position)) {
684 // Set the register to be free. Note that inactive intervals might later
685 // update this.
686 free_until[interval->GetRegister()] = kMaxLifetimePosition;
687 if (interval->HasHighInterval()) {
688 DCHECK(interval->GetHighInterval()->IsDeadAt(position));
689 free_until[interval->GetHighInterval()->GetRegister()] = kMaxLifetimePosition;
690 }
691 } else if (!interval->CoversSlow(position)) {
692 // The interval becomes inactive at `defined_by`. We make its register
693 // available only until the next use strictly after `defined_by`.
694 free_until[interval->GetRegister()] = interval->FirstUseAfter(position);
695 if (interval->HasHighInterval()) {
696 DCHECK(!interval->GetHighInterval()->CoversSlow(position));
697 free_until[interval->GetHighInterval()->GetRegister()] = free_until[interval->GetRegister()];
698 }
699 }
700 }
701
702 // Find a free register. If multiple are found, pick the register that
703 // is free the longest.
TryAllocateFreeReg(LiveInterval * current)704 bool RegisterAllocatorLinearScan::TryAllocateFreeReg(LiveInterval* current) {
705 size_t* free_until = registers_array_;
706
707 // First set all registers to be free.
708 for (size_t i = 0; i < number_of_registers_; ++i) {
709 free_until[i] = kMaxLifetimePosition;
710 }
711
712 // For each active interval, set its register(s) to not free.
713 for (LiveInterval* interval : active_) {
714 DCHECK(interval->HasRegister() || interval->IsFixed());
715 uint32_t register_mask = GetRegisterMask(interval, current_register_type_);
716 DCHECK_NE(register_mask, 0u);
717 for (uint32_t reg : LowToHighBits(register_mask)) {
718 free_until[reg] = 0;
719 }
720 }
721
722 // An interval that starts an instruction (that is, it is not split), may
723 // re-use the registers used by the inputs of that instruciton, based on the
724 // location summary.
725 HInstruction* defined_by = current->GetDefinedBy();
726 if (defined_by != nullptr && !current->IsSplit()) {
727 LocationSummary* locations = defined_by->GetLocations();
728 if (!locations->OutputCanOverlapWithInputs() && locations->Out().IsUnallocated()) {
729 HInputsRef inputs = defined_by->GetInputs();
730 for (size_t i = 0; i < inputs.size(); ++i) {
731 if (locations->InAt(i).IsValid()) {
732 // Take the last interval of the input. It is the location of that interval
733 // that will be used at `defined_by`.
734 LiveInterval* interval = inputs[i]->GetLiveInterval()->GetLastSibling();
735 // Note that interval may have not been processed yet.
736 // TODO: Handle non-split intervals last in the work list.
737 if (interval->HasRegister() && interval->SameRegisterKind(*current)) {
738 // The input must be live until the end of `defined_by`, to comply to
739 // the linear scan algorithm. So we use `defined_by`'s end lifetime
740 // position to check whether the input is dead or is inactive after
741 // `defined_by`.
742 DCHECK(interval->CoversSlow(defined_by->GetLifetimePosition()));
743 size_t position = defined_by->GetLifetimePosition() + 1;
744 FreeIfNotCoverAt(interval, position, free_until);
745 }
746 }
747 }
748 }
749 }
750
751 // For each inactive interval, set its register to be free until
752 // the next intersection with `current`.
753 for (LiveInterval* inactive : inactive_) {
754 // Temp/Slow-path-safepoint interval has no holes.
755 DCHECK(!inactive->IsTemp());
756 if (!current->IsSplit() && !inactive->IsFixed()) {
757 // Neither current nor inactive are fixed.
758 // Thanks to SSA, a non-split interval starting in a hole of an
759 // inactive interval should never intersect with that inactive interval.
760 // Only if it's not fixed though, because fixed intervals don't come from SSA.
761 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
762 continue;
763 }
764
765 DCHECK(inactive->HasRegister() || inactive->IsFixed());
766 uint32_t register_mask = GetRegisterMask(inactive, current_register_type_);
767 DCHECK_NE(register_mask, 0u);
768 for (uint32_t reg : LowToHighBits(register_mask)) {
769 if (free_until[reg] == 0) {
770 // Already used by some active interval. Clear the register bit.
771 register_mask &= ~(1u << reg);
772 }
773 }
774 if (register_mask != 0u) {
775 size_t next_intersection = inactive->FirstIntersectionWith(current);
776 if (next_intersection != kNoLifetime) {
777 for (uint32_t reg : LowToHighBits(register_mask)) {
778 free_until[reg] = std::min(free_until[reg], next_intersection);
779 }
780 }
781 }
782 }
783
784 int reg = kNoRegister;
785 if (current->HasRegister()) {
786 // Some instructions have a fixed register output.
787 reg = current->GetRegister();
788 if (free_until[reg] == 0) {
789 DCHECK(current->IsHighInterval());
790 // AllocateBlockedReg will spill the holder of the register.
791 return false;
792 }
793 } else {
794 DCHECK(!current->IsHighInterval());
795 int hint = current->FindFirstRegisterHint(free_until, liveness_);
796 if ((hint != kNoRegister)
797 // For simplicity, if the hint we are getting for a pair cannot be used,
798 // we are just going to allocate a new pair.
799 && !(current->IsLowInterval() && IsBlocked(GetHighForLowRegister(hint)))) {
800 DCHECK(!IsBlocked(hint));
801 reg = hint;
802 } else if (current->IsLowInterval()) {
803 reg = FindAvailableRegisterPair(free_until, current->GetStart());
804 } else {
805 reg = FindAvailableRegister(free_until, current);
806 }
807 }
808
809 DCHECK_NE(reg, kNoRegister);
810 // If we could not find a register, we need to spill.
811 if (free_until[reg] == 0) {
812 return false;
813 }
814
815 if (current->IsLowInterval()) {
816 // If the high register of this interval is not available, we need to spill.
817 int high_reg = current->GetHighInterval()->GetRegister();
818 if (high_reg == kNoRegister) {
819 high_reg = GetHighForLowRegister(reg);
820 }
821 if (free_until[high_reg] == 0) {
822 return false;
823 }
824 }
825
826 current->SetRegister(reg);
827 if (!current->IsDeadAt(free_until[reg])) {
828 // If the register is only available for a subset of live ranges
829 // covered by `current`, split `current` before the position where
830 // the register is not available anymore.
831 LiveInterval* split = SplitBetween(current, current->GetStart(), free_until[reg]);
832 DCHECK(split != nullptr);
833 AddSorted(unhandled_, split);
834 }
835 return true;
836 }
837
IsBlocked(int reg) const838 bool RegisterAllocatorLinearScan::IsBlocked(int reg) const {
839 return (current_register_type_ == RegisterType::kCoreRegister)
840 ? blocked_core_registers_[reg]
841 : blocked_fp_registers_[reg];
842 }
843
FindAvailableRegisterPair(size_t * next_use,size_t starting_at) const844 int RegisterAllocatorLinearScan::FindAvailableRegisterPair(size_t* next_use, size_t starting_at) const {
845 int reg = kNoRegister;
846 // Pick the register pair that is used the last.
847 for (size_t i = 0; i < number_of_registers_; ++i) {
848 if (IsBlocked(i)) continue;
849 if (!IsLowRegister(i)) continue;
850 int high_register = GetHighForLowRegister(i);
851 if (IsBlocked(high_register)) continue;
852 int existing_high_register = GetHighForLowRegister(reg);
853 if ((reg == kNoRegister) || (next_use[i] >= next_use[reg]
854 && next_use[high_register] >= next_use[existing_high_register])) {
855 reg = i;
856 if (next_use[i] == kMaxLifetimePosition
857 && next_use[high_register] == kMaxLifetimePosition) {
858 break;
859 }
860 } else if (next_use[reg] <= starting_at || next_use[existing_high_register] <= starting_at) {
861 // If one of the current register is known to be unavailable, just unconditionally
862 // try a new one.
863 reg = i;
864 }
865 }
866 return reg;
867 }
868
IsCallerSaveRegister(int reg) const869 bool RegisterAllocatorLinearScan::IsCallerSaveRegister(int reg) const {
870 uint32_t registers_blocked_for_call = (current_register_type_ == RegisterType::kCoreRegister)
871 ? core_registers_blocked_for_call_
872 : fp_registers_blocked_for_call_;
873 DCHECK_LT(static_cast<size_t>(reg), BitSizeOf<uint32_t>());
874 return (registers_blocked_for_call & (1u << reg)) != 0u;
875 }
876
FindAvailableRegister(size_t * next_use,LiveInterval * current) const877 int RegisterAllocatorLinearScan::FindAvailableRegister(size_t* next_use, LiveInterval* current) const {
878 // We special case intervals that do not span a safepoint to try to find a caller-save
879 // register if one is available. We iterate from 0 to the number of registers,
880 // so if there are caller-save registers available at the end, we continue the iteration.
881 bool prefers_caller_save = !current->HasWillCallSafepoint();
882 int reg = kNoRegister;
883 for (size_t i = 0; i < number_of_registers_; ++i) {
884 if (IsBlocked(i)) {
885 // Register cannot be used. Continue.
886 continue;
887 }
888
889 // Best case: we found a register fully available.
890 if (next_use[i] == kMaxLifetimePosition) {
891 if (prefers_caller_save && !IsCallerSaveRegister(i)) {
892 // We can get shorter encodings on some platforms by using
893 // small register numbers. So only update the candidate if the previous
894 // one was not available for the whole method.
895 if (reg == kNoRegister || next_use[reg] != kMaxLifetimePosition) {
896 reg = i;
897 }
898 // Continue the iteration in the hope of finding a caller save register.
899 continue;
900 } else {
901 reg = i;
902 // We know the register is good enough. Return it.
903 break;
904 }
905 }
906
907 // If we had no register before, take this one as a reference.
908 if (reg == kNoRegister) {
909 reg = i;
910 continue;
911 }
912
913 // Pick the register that is used the last.
914 if (next_use[i] > next_use[reg]) {
915 reg = i;
916 continue;
917 }
918 }
919 return reg;
920 }
921
922 // Remove interval and its other half if any. Return iterator to the following element.
RemoveIntervalAndPotentialOtherHalf(ScopedArenaVector<LiveInterval * > * intervals,ScopedArenaVector<LiveInterval * >::iterator pos)923 static ArenaVector<LiveInterval*>::iterator RemoveIntervalAndPotentialOtherHalf(
924 ScopedArenaVector<LiveInterval*>* intervals, ScopedArenaVector<LiveInterval*>::iterator pos) {
925 DCHECK(intervals->begin() <= pos && pos < intervals->end());
926 LiveInterval* interval = *pos;
927 if (interval->IsLowInterval()) {
928 DCHECK(pos + 1 < intervals->end());
929 DCHECK_EQ(*(pos + 1), interval->GetHighInterval());
930 return intervals->erase(pos, pos + 2);
931 } else if (interval->IsHighInterval()) {
932 DCHECK(intervals->begin() < pos);
933 DCHECK_EQ(*(pos - 1), interval->GetLowInterval());
934 return intervals->erase(pos - 1, pos + 1);
935 } else {
936 return intervals->erase(pos);
937 }
938 }
939
TrySplitNonPairOrUnalignedPairIntervalAt(size_t position,size_t first_register_use,size_t * next_use)940 bool RegisterAllocatorLinearScan::TrySplitNonPairOrUnalignedPairIntervalAt(size_t position,
941 size_t first_register_use,
942 size_t* next_use) {
943 for (auto it = active_.begin(), end = active_.end(); it != end; ++it) {
944 LiveInterval* active = *it;
945 // Special fixed intervals that represent multiple registers do not report having a register.
946 if (active->IsFixed()) continue;
947 DCHECK(active->HasRegister());
948 if (active->IsHighInterval()) continue;
949 if (first_register_use > next_use[active->GetRegister()]) continue;
950
951 // Split the first interval found that is either:
952 // 1) A non-pair interval.
953 // 2) A pair interval whose high is not low + 1.
954 // 3) A pair interval whose low is not even.
955 if (!active->IsLowInterval() ||
956 IsLowOfUnalignedPairInterval(active) ||
957 !IsLowRegister(active->GetRegister())) {
958 LiveInterval* split = Split(active, position);
959 if (split != active) {
960 handled_.push_back(active);
961 }
962 RemoveIntervalAndPotentialOtherHalf(&active_, it);
963 AddSorted(unhandled_, split);
964 return true;
965 }
966 }
967 return false;
968 }
969
970 // Find the register that is used the last, and spill the interval
971 // that holds it. If the first use of `current` is after that register
972 // we spill `current` instead.
AllocateBlockedReg(LiveInterval * current)973 bool RegisterAllocatorLinearScan::AllocateBlockedReg(LiveInterval* current) {
974 size_t first_register_use = current->FirstRegisterUse();
975 if (current->HasRegister()) {
976 DCHECK(current->IsHighInterval());
977 // The low interval has allocated the register for the high interval. In
978 // case the low interval had to split both intervals, we may end up in a
979 // situation where the high interval does not have a register use anymore.
980 // We must still proceed in order to split currently active and inactive
981 // uses of the high interval's register, and put the high interval in the
982 // active set.
983 DCHECK_IMPLIES(first_register_use == kNoLifetime, current->GetNextSibling() != nullptr);
984 } else if (first_register_use == kNoLifetime) {
985 AllocateSpillSlotFor(current);
986 return false;
987 }
988
989 // First set all registers as not being used.
990 size_t* next_use = registers_array_;
991 for (size_t i = 0; i < number_of_registers_; ++i) {
992 next_use[i] = kMaxLifetimePosition;
993 }
994
995 // For each active interval, find the next use of its register after the
996 // start of current.
997 for (LiveInterval* active : active_) {
998 if (active->IsFixed()) {
999 uint32_t register_mask = GetRegisterMask(active, current_register_type_);
1000 DCHECK_NE(register_mask, 0u);
1001 for (uint32_t reg : LowToHighBits(register_mask)) {
1002 next_use[reg] = current->GetStart();
1003 }
1004 } else {
1005 DCHECK(active->HasRegister());
1006 size_t use = active->FirstRegisterUseAfter(current->GetStart());
1007 if (use != kNoLifetime) {
1008 next_use[active->GetRegister()] = use;
1009 }
1010 }
1011 }
1012
1013 // For each inactive interval, find the next use of its register after the
1014 // start of current.
1015 for (LiveInterval* inactive : inactive_) {
1016 // Temp/Slow-path-safepoint interval has no holes.
1017 DCHECK(!inactive->IsTemp());
1018 if (!current->IsSplit() && !inactive->IsFixed()) {
1019 // Neither current nor inactive are fixed.
1020 // Thanks to SSA, a non-split interval starting in a hole of an
1021 // inactive interval should never intersect with that inactive interval.
1022 // Only if it's not fixed though, because fixed intervals don't come from SSA.
1023 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
1024 continue;
1025 }
1026 DCHECK(inactive->HasRegister() || inactive->IsFixed());
1027 size_t next_intersection = inactive->FirstIntersectionWith(current);
1028 if (next_intersection != kNoLifetime) {
1029 if (inactive->IsFixed()) {
1030 uint32_t register_mask = GetRegisterMask(inactive, current_register_type_);
1031 DCHECK_NE(register_mask, 0u);
1032 for (uint32_t reg : LowToHighBits(register_mask)) {
1033 next_use[reg] = std::min(next_intersection, next_use[reg]);
1034 }
1035 } else {
1036 size_t use = inactive->FirstUseAfter(current->GetStart());
1037 if (use != kNoLifetime) {
1038 next_use[inactive->GetRegister()] = std::min(use, next_use[inactive->GetRegister()]);
1039 }
1040 }
1041 }
1042 }
1043
1044 int reg = kNoRegister;
1045 bool should_spill = false;
1046 if (current->HasRegister()) {
1047 DCHECK(current->IsHighInterval());
1048 reg = current->GetRegister();
1049 // When allocating the low part, we made sure the high register was available.
1050 DCHECK_LT(first_register_use, next_use[reg]);
1051 } else if (current->IsLowInterval()) {
1052 reg = FindAvailableRegisterPair(next_use, first_register_use);
1053 // We should spill if both registers are not available.
1054 should_spill = (first_register_use >= next_use[reg])
1055 || (first_register_use >= next_use[GetHighForLowRegister(reg)]);
1056 } else {
1057 DCHECK(!current->IsHighInterval());
1058 reg = FindAvailableRegister(next_use, current);
1059 should_spill = (first_register_use >= next_use[reg]);
1060 }
1061
1062 DCHECK_NE(reg, kNoRegister);
1063 if (should_spill) {
1064 DCHECK(!current->IsHighInterval());
1065 bool is_allocation_at_use_site = (current->GetStart() >= (first_register_use - 1));
1066 if (is_allocation_at_use_site) {
1067 if (!current->IsLowInterval()) {
1068 DumpInterval(std::cerr, current);
1069 DumpAllIntervals(std::cerr);
1070 // This situation has the potential to infinite loop, so we make it a non-debug CHECK.
1071 HInstruction* at = liveness_.GetInstructionFromPosition(first_register_use / 2);
1072 CHECK(false) << "There is not enough registers available for "
1073 << current->GetParent()->GetDefinedBy()->DebugName() << " "
1074 << current->GetParent()->GetDefinedBy()->GetId()
1075 << " at " << first_register_use - 1 << " "
1076 << (at == nullptr ? "" : at->DebugName());
1077 }
1078
1079 // If we're allocating a register for `current` because the instruction at
1080 // that position requires it, but we think we should spill, then there are
1081 // non-pair intervals or unaligned pair intervals blocking the allocation.
1082 // We split the first interval found, and put ourselves first in the
1083 // `unhandled_` list.
1084 bool success = TrySplitNonPairOrUnalignedPairIntervalAt(current->GetStart(),
1085 first_register_use,
1086 next_use);
1087 DCHECK(success);
1088 LiveInterval* existing = unhandled_->back();
1089 DCHECK(existing->IsHighInterval());
1090 DCHECK_EQ(existing->GetLowInterval(), current);
1091 unhandled_->push_back(current);
1092 } else {
1093 // If the first use of that instruction is after the last use of the found
1094 // register, we split this interval just before its first register use.
1095 AllocateSpillSlotFor(current);
1096 LiveInterval* split = SplitBetween(current, current->GetStart(), first_register_use - 1);
1097 DCHECK(current != split);
1098 AddSorted(unhandled_, split);
1099 }
1100 return false;
1101 } else {
1102 // Use this register and spill the active and inactives interval that
1103 // have that register.
1104 current->SetRegister(reg);
1105
1106 for (auto it = active_.begin(), end = active_.end(); it != end; ++it) {
1107 LiveInterval* active = *it;
1108 DCHECK_IMPLIES(active->IsFixed(),
1109 (GetRegisterMask(active, current_register_type_) & (1u << reg)) == 0u);
1110 if (active->GetRegister() == reg) {
1111 DCHECK(!active->IsFixed());
1112 LiveInterval* split = Split(active, current->GetStart());
1113 if (split != active) {
1114 handled_.push_back(active);
1115 }
1116 RemoveIntervalAndPotentialOtherHalf(&active_, it);
1117 AddSorted(unhandled_, split);
1118 break;
1119 }
1120 }
1121
1122 // NOTE: Retrieve end() on each iteration because we're removing elements in the loop body.
1123 for (auto it = inactive_.begin(); it != inactive_.end(); ) {
1124 LiveInterval* inactive = *it;
1125 bool erased = false;
1126 if ((GetRegisterMask(inactive, current_register_type_) & (1u << reg)) != 0u) {
1127 if (!current->IsSplit() && !inactive->IsFixed()) {
1128 // Neither current nor inactive are fixed.
1129 // Thanks to SSA, a non-split interval starting in a hole of an
1130 // inactive interval should never intersect with that inactive interval.
1131 // Only if it's not fixed though, because fixed intervals don't come from SSA.
1132 DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
1133 } else {
1134 size_t next_intersection = inactive->FirstIntersectionWith(current);
1135 if (next_intersection != kNoLifetime) {
1136 if (inactive->IsFixed()) {
1137 LiveInterval* split = Split(current, next_intersection);
1138 DCHECK_NE(split, current);
1139 AddSorted(unhandled_, split);
1140 } else {
1141 // Split at the start of `current`, which will lead to splitting
1142 // at the end of the lifetime hole of `inactive`.
1143 LiveInterval* split = Split(inactive, current->GetStart());
1144 // If it's inactive, it must start before the current interval.
1145 DCHECK_NE(split, inactive);
1146 it = RemoveIntervalAndPotentialOtherHalf(&inactive_, it);
1147 erased = true;
1148 handled_.push_back(inactive);
1149 AddSorted(unhandled_, split);
1150 }
1151 }
1152 }
1153 }
1154 // If we have erased the element, `it` already points to the next element.
1155 // Otherwise we need to move to the next element.
1156 if (!erased) {
1157 ++it;
1158 }
1159 }
1160
1161 return true;
1162 }
1163 }
1164
AddSorted(ScopedArenaVector<LiveInterval * > * array,LiveInterval * interval)1165 void RegisterAllocatorLinearScan::AddSorted(ScopedArenaVector<LiveInterval*>* array,
1166 LiveInterval* interval) {
1167 DCHECK(!interval->IsFixed() && !interval->HasSpillSlot());
1168 size_t insert_at = 0;
1169 for (size_t i = array->size(); i > 0; --i) {
1170 LiveInterval* current = (*array)[i - 1u];
1171 // High intervals must be processed right after their low equivalent.
1172 if (current->StartsAfter(interval) && !current->IsHighInterval()) {
1173 insert_at = i;
1174 break;
1175 }
1176 }
1177
1178 // Insert the high interval before the low, to ensure the low is processed before.
1179 auto insert_pos = array->begin() + insert_at;
1180 if (interval->HasHighInterval()) {
1181 array->insert(insert_pos, { interval->GetHighInterval(), interval });
1182 } else if (interval->HasLowInterval()) {
1183 array->insert(insert_pos, { interval, interval->GetLowInterval() });
1184 } else {
1185 array->insert(insert_pos, interval);
1186 }
1187 }
1188
AllocateSpillSlotFor(LiveInterval * interval)1189 void RegisterAllocatorLinearScan::AllocateSpillSlotFor(LiveInterval* interval) {
1190 if (interval->IsHighInterval()) {
1191 // The low interval already took care of allocating the spill slot.
1192 DCHECK(!interval->GetLowInterval()->HasRegister());
1193 DCHECK(interval->GetLowInterval()->GetParent()->HasSpillSlot());
1194 return;
1195 }
1196
1197 LiveInterval* parent = interval->GetParent();
1198
1199 // An instruction gets a spill slot for its entire lifetime. If the parent
1200 // of this interval already has a spill slot, there is nothing to do.
1201 if (parent->HasSpillSlot()) {
1202 return;
1203 }
1204
1205 HInstruction* defined_by = parent->GetDefinedBy();
1206 DCHECK_IMPLIES(defined_by->IsPhi(), !defined_by->AsPhi()->IsCatchPhi());
1207
1208 if (defined_by->IsParameterValue()) {
1209 // Parameters have their own stack slot.
1210 parent->SetSpillSlot(codegen_->GetStackSlotOfParameter(defined_by->AsParameterValue()));
1211 return;
1212 }
1213
1214 if (defined_by->IsCurrentMethod()) {
1215 parent->SetSpillSlot(0);
1216 return;
1217 }
1218
1219 if (defined_by->IsConstant()) {
1220 // Constants don't need a spill slot.
1221 return;
1222 }
1223
1224 ScopedArenaVector<size_t>* spill_slots = nullptr;
1225 switch (interval->GetType()) {
1226 case DataType::Type::kFloat64:
1227 spill_slots = &double_spill_slots_;
1228 break;
1229 case DataType::Type::kInt64:
1230 spill_slots = &long_spill_slots_;
1231 break;
1232 case DataType::Type::kFloat32:
1233 spill_slots = &float_spill_slots_;
1234 break;
1235 case DataType::Type::kReference:
1236 case DataType::Type::kInt32:
1237 case DataType::Type::kUint16:
1238 case DataType::Type::kUint8:
1239 case DataType::Type::kInt8:
1240 case DataType::Type::kBool:
1241 case DataType::Type::kInt16:
1242 spill_slots = &int_spill_slots_;
1243 break;
1244 case DataType::Type::kUint32:
1245 case DataType::Type::kUint64:
1246 case DataType::Type::kVoid:
1247 LOG(FATAL) << "Unexpected type for interval " << interval->GetType();
1248 }
1249
1250 // Find first available spill slots.
1251 size_t number_of_spill_slots_needed = parent->NumberOfSpillSlotsNeeded();
1252 size_t slot = 0;
1253 for (size_t e = spill_slots->size(); slot < e; ++slot) {
1254 bool found = true;
1255 for (size_t s = slot, u = std::min(slot + number_of_spill_slots_needed, e); s < u; s++) {
1256 if ((*spill_slots)[s] > parent->GetStart()) {
1257 found = false; // failure
1258 break;
1259 }
1260 }
1261 if (found) {
1262 break; // success
1263 }
1264 }
1265
1266 // Need new spill slots?
1267 size_t upper = slot + number_of_spill_slots_needed;
1268 if (upper > spill_slots->size()) {
1269 spill_slots->resize(upper);
1270 }
1271 // Set slots to end.
1272 size_t end = interval->GetLastSibling()->GetEnd();
1273 for (size_t s = slot; s < upper; s++) {
1274 (*spill_slots)[s] = end;
1275 }
1276
1277 // Note that the exact spill slot location will be computed when we resolve,
1278 // that is when we know the number of spill slots for each type.
1279 parent->SetSpillSlot(slot);
1280 }
1281
AllocateSpillSlotForCatchPhi(HPhi * phi)1282 void RegisterAllocatorLinearScan::AllocateSpillSlotForCatchPhi(HPhi* phi) {
1283 LiveInterval* interval = phi->GetLiveInterval();
1284
1285 HInstruction* previous_phi = phi->GetPrevious();
1286 DCHECK(previous_phi == nullptr || previous_phi->AsPhi()->GetRegNumber() <= phi->GetRegNumber())
1287 << "Phis expected to be sorted by vreg number, so that equivalent phis are adjacent.";
1288
1289 if (phi->IsVRegEquivalentOf(previous_phi)) {
1290 // This is an equivalent of the previous phi. We need to assign the same
1291 // catch phi slot.
1292 DCHECK(previous_phi->GetLiveInterval()->HasSpillSlot());
1293 interval->SetSpillSlot(previous_phi->GetLiveInterval()->GetSpillSlot());
1294 } else {
1295 // Allocate a new spill slot for this catch phi.
1296 // TODO: Reuse spill slots when intervals of phis from different catch
1297 // blocks do not overlap.
1298 interval->SetSpillSlot(catch_phi_spill_slots_);
1299 catch_phi_spill_slots_ += interval->NumberOfSpillSlotsNeeded();
1300 }
1301 }
1302
1303 } // namespace art
1304