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.h"
18 
19 #include "code_generator.h"
20 #include "ssa_liveness_analysis.h"
21 
22 namespace art {
23 
24 static constexpr size_t kMaxLifetimePosition = -1;
25 static constexpr size_t kDefaultNumberOfSpillSlots = 4;
26 
RegisterAllocator(ArenaAllocator * allocator,CodeGenerator * codegen,const SsaLivenessAnalysis & liveness)27 RegisterAllocator::RegisterAllocator(ArenaAllocator* allocator,
28                                      CodeGenerator* codegen,
29                                      const SsaLivenessAnalysis& liveness)
30       : allocator_(allocator),
31         codegen_(codegen),
32         liveness_(liveness),
33         unhandled_(allocator, 0),
34         handled_(allocator, 0),
35         active_(allocator, 0),
36         inactive_(allocator, 0),
37         physical_register_intervals_(allocator, codegen->GetNumberOfRegisters()),
38         spill_slots_(allocator, kDefaultNumberOfSpillSlots),
39         processing_core_registers_(false),
40         number_of_registers_(-1),
41         registers_array_(nullptr),
42         blocked_registers_(allocator->AllocArray<bool>(codegen->GetNumberOfRegisters())) {
43   codegen->SetupBlockedRegisters(blocked_registers_);
44   physical_register_intervals_.SetSize(codegen->GetNumberOfRegisters());
45 }
46 
CanAllocateRegistersFor(const HGraph & graph,InstructionSet instruction_set)47 bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph,
48                                                 InstructionSet instruction_set) {
49   if (!Supports(instruction_set)) {
50     return false;
51   }
52   for (size_t i = 0, e = graph.GetBlocks().Size(); i < e; ++i) {
53     for (HInstructionIterator it(graph.GetBlocks().Get(i)->GetInstructions());
54          !it.Done();
55          it.Advance()) {
56       HInstruction* current = it.Current();
57       if (current->NeedsEnvironment()) return false;
58       if (current->GetType() == Primitive::kPrimLong && instruction_set != kX86_64) return false;
59       if (current->GetType() == Primitive::kPrimFloat) return false;
60       if (current->GetType() == Primitive::kPrimDouble) return false;
61     }
62   }
63   return true;
64 }
65 
ShouldProcess(bool processing_core_registers,LiveInterval * interval)66 static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) {
67   bool is_core_register = (interval->GetType() != Primitive::kPrimDouble)
68       && (interval->GetType() != Primitive::kPrimFloat);
69   return processing_core_registers == is_core_register;
70 }
71 
AllocateRegisters()72 void RegisterAllocator::AllocateRegisters() {
73   processing_core_registers_ = true;
74   AllocateRegistersInternal();
75   processing_core_registers_ = false;
76   AllocateRegistersInternal();
77 
78   Resolve();
79 
80   if (kIsDebugBuild) {
81     processing_core_registers_ = true;
82     ValidateInternal(true);
83     processing_core_registers_ = false;
84     ValidateInternal(true);
85   }
86 }
87 
BlockRegister(Location location,size_t start,size_t end,Primitive::Type type)88 void RegisterAllocator::BlockRegister(Location location,
89                                       size_t start,
90                                       size_t end,
91                                       Primitive::Type type) {
92   int reg = location.reg().RegId();
93   LiveInterval* interval = physical_register_intervals_.Get(reg);
94   if (interval == nullptr) {
95     interval = LiveInterval::MakeFixedInterval(allocator_, reg, type);
96     physical_register_intervals_.Put(reg, interval);
97     inactive_.Add(interval);
98   }
99   DCHECK(interval->GetRegister() == reg);
100   interval->AddRange(start, end);
101 }
102 
103 // TODO: make the register allocator understand instructions like HCondition
104 // that may not need to be materialized.  It doesn't need to allocate any
105 // registers for it.
AllocateRegistersInternal()106 void RegisterAllocator::AllocateRegistersInternal() {
107   number_of_registers_ = processing_core_registers_
108       ? codegen_->GetNumberOfCoreRegisters()
109       : codegen_->GetNumberOfFloatingPointRegisters();
110 
111   registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
112 
113   // Iterate post-order, to ensure the list is sorted, and the last added interval
114   // is the one with the lowest start position.
115   for (size_t i = liveness_.GetNumberOfSsaValues(); i > 0; --i) {
116     HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i - 1);
117     LiveInterval* current = instruction->GetLiveInterval();
118     if (ShouldProcess(processing_core_registers_, current)) {
119       DCHECK(unhandled_.IsEmpty() || current->StartsBefore(unhandled_.Peek()));
120 
121       LocationSummary* locations = instruction->GetLocations();
122       if (locations->GetTempCount() != 0) {
123         // Note that we already filtered out instructions requiring temporaries in
124         // RegisterAllocator::CanAllocateRegistersFor.
125         LOG(FATAL) << "Unimplemented";
126       }
127 
128       // Some instructions define their output in fixed register/stack slot. We need
129       // to ensure we know these locations before doing register allocation. For a
130       // given register, we create an interval that covers these locations. The register
131       // will be unavailable at these locations when trying to allocate one for an
132       // interval.
133       //
134       // The backwards walking ensures the ranges are ordered on increasing start positions.
135       Location output = locations->Out();
136       size_t position = instruction->GetLifetimePosition();
137       if (output.IsRegister()) {
138         // Shift the interval's start by one to account for the blocked register.
139         current->SetFrom(position + 1);
140         current->SetRegister(output.reg().RegId());
141         BlockRegister(output, position, position + 1, instruction->GetType());
142       } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) {
143         current->SetSpillSlot(output.GetStackIndex());
144       }
145       for (size_t i = 0; i < instruction->InputCount(); ++i) {
146         Location input = locations->InAt(i);
147         if (input.IsRegister()) {
148           BlockRegister(input, position, position + 1, instruction->InputAt(i)->GetType());
149         }
150       }
151 
152       // Add the interval to the correct list.
153       if (current->HasRegister()) {
154         DCHECK(instruction->IsParameterValue());
155         inactive_.Add(current);
156       } else if (current->HasSpillSlot() || instruction->IsConstant()) {
157         // Split before first register use.
158         size_t first_register_use = current->FirstRegisterUse();
159         if (first_register_use != kNoLifetime) {
160           LiveInterval* split = Split(current, first_register_use - 1);
161           // Don't add direclty to `unhandled_`, it needs to be sorted and the start
162           // of this new interval might be after intervals already in the list.
163           AddToUnhandled(split);
164         } else {
165           // Nothing to do, we won't allocate a register for this value.
166         }
167       } else {
168         DCHECK(unhandled_.IsEmpty() || current->StartsBefore(unhandled_.Peek()));
169         unhandled_.Add(current);
170       }
171     }
172   }
173 
174   LinearScan();
175 }
176 
177 class AllRangesIterator : public ValueObject {
178  public:
AllRangesIterator(LiveInterval * interval)179   explicit AllRangesIterator(LiveInterval* interval)
180       : current_interval_(interval),
181         current_range_(interval->GetFirstRange()) {}
182 
Done() const183   bool Done() const { return current_interval_ == nullptr; }
CurrentRange() const184   LiveRange* CurrentRange() const { return current_range_; }
CurrentInterval() const185   LiveInterval* CurrentInterval() const { return current_interval_; }
186 
Advance()187   void Advance() {
188     current_range_ = current_range_->GetNext();
189     if (current_range_ == nullptr) {
190       current_interval_ = current_interval_->GetNextSibling();
191       if (current_interval_ != nullptr) {
192         current_range_ = current_interval_->GetFirstRange();
193       }
194     }
195   }
196 
197  private:
198   LiveInterval* current_interval_;
199   LiveRange* current_range_;
200 
201   DISALLOW_COPY_AND_ASSIGN(AllRangesIterator);
202 };
203 
ValidateInternal(bool log_fatal_on_failure) const204 bool RegisterAllocator::ValidateInternal(bool log_fatal_on_failure) const {
205   // To simplify unit testing, we eagerly create the array of intervals, and
206   // call the helper method.
207   GrowableArray<LiveInterval*> intervals(allocator_, 0);
208   for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) {
209     HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
210     if (ShouldProcess(processing_core_registers_, instruction->GetLiveInterval())) {
211       intervals.Add(instruction->GetLiveInterval());
212     }
213   }
214 
215   for (size_t i = 0, e = physical_register_intervals_.Size(); i < e; ++i) {
216     LiveInterval* fixed = physical_register_intervals_.Get(i);
217     if (fixed != nullptr && ShouldProcess(processing_core_registers_, fixed)) {
218       intervals.Add(fixed);
219     }
220   }
221 
222   return ValidateIntervals(intervals, spill_slots_.Size(), *codegen_, allocator_,
223                            processing_core_registers_, log_fatal_on_failure);
224 }
225 
ValidateIntervals(const GrowableArray<LiveInterval * > & intervals,size_t number_of_spill_slots,const CodeGenerator & codegen,ArenaAllocator * allocator,bool processing_core_registers,bool log_fatal_on_failure)226 bool RegisterAllocator::ValidateIntervals(const GrowableArray<LiveInterval*>& intervals,
227                                           size_t number_of_spill_slots,
228                                           const CodeGenerator& codegen,
229                                           ArenaAllocator* allocator,
230                                           bool processing_core_registers,
231                                           bool log_fatal_on_failure) {
232   size_t number_of_registers = processing_core_registers
233       ? codegen.GetNumberOfCoreRegisters()
234       : codegen.GetNumberOfFloatingPointRegisters();
235   GrowableArray<ArenaBitVector*> liveness_of_values(
236       allocator, number_of_registers + number_of_spill_slots);
237 
238   // Allocate a bit vector per register. A live interval that has a register
239   // allocated will populate the associated bit vector based on its live ranges.
240   for (size_t i = 0; i < number_of_registers + number_of_spill_slots; ++i) {
241     liveness_of_values.Add(new (allocator) ArenaBitVector(allocator, 0, true));
242   }
243 
244   for (size_t i = 0, e = intervals.Size(); i < e; ++i) {
245     for (AllRangesIterator it(intervals.Get(i)); !it.Done(); it.Advance()) {
246       LiveInterval* current = it.CurrentInterval();
247       HInstruction* defined_by = current->GetParent()->GetDefinedBy();
248       if (current->GetParent()->HasSpillSlot()
249            // Parameters have their own stack slot.
250            && !(defined_by != nullptr && defined_by->IsParameterValue())) {
251         BitVector* liveness_of_spill_slot = liveness_of_values.Get(
252             number_of_registers + current->GetParent()->GetSpillSlot() / kVRegSize);
253         for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
254           if (liveness_of_spill_slot->IsBitSet(j)) {
255             if (log_fatal_on_failure) {
256               std::ostringstream message;
257               message << "Spill slot conflict at " << j;
258               LOG(FATAL) << message.str();
259             } else {
260               return false;
261             }
262           } else {
263             liveness_of_spill_slot->SetBit(j);
264           }
265         }
266       }
267 
268       if (current->HasRegister()) {
269         BitVector* liveness_of_register = liveness_of_values.Get(current->GetRegister());
270         for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
271           if (liveness_of_register->IsBitSet(j)) {
272             if (log_fatal_on_failure) {
273               std::ostringstream message;
274               message << "Register conflict at " << j << " for ";
275               if (processing_core_registers) {
276                 codegen.DumpCoreRegister(message, current->GetRegister());
277               } else {
278                 codegen.DumpFloatingPointRegister(message, current->GetRegister());
279               }
280               LOG(FATAL) << message.str();
281             } else {
282               return false;
283             }
284           } else {
285             liveness_of_register->SetBit(j);
286           }
287         }
288       }
289     }
290   }
291   return true;
292 }
293 
DumpInterval(std::ostream & stream,LiveInterval * interval) const294 void RegisterAllocator::DumpInterval(std::ostream& stream, LiveInterval* interval) const {
295   interval->Dump(stream);
296   stream << ": ";
297   if (interval->HasRegister()) {
298     if (processing_core_registers_) {
299       codegen_->DumpCoreRegister(stream, interval->GetRegister());
300     } else {
301       codegen_->DumpFloatingPointRegister(stream, interval->GetRegister());
302     }
303   } else {
304     stream << "spilled";
305   }
306   stream << std::endl;
307 }
308 
309 // By the book implementation of a linear scan register allocator.
LinearScan()310 void RegisterAllocator::LinearScan() {
311   while (!unhandled_.IsEmpty()) {
312     // (1) Remove interval with the lowest start position from unhandled.
313     LiveInterval* current = unhandled_.Pop();
314     DCHECK(!current->IsFixed() && !current->HasRegister() && !current->HasSpillSlot());
315     size_t position = current->GetStart();
316 
317     // (2) Remove currently active intervals that are dead at this position.
318     //     Move active intervals that have a lifetime hole at this position
319     //     to inactive.
320     for (size_t i = 0; i < active_.Size(); ++i) {
321       LiveInterval* interval = active_.Get(i);
322       if (interval->IsDeadAt(position)) {
323         active_.Delete(interval);
324         --i;
325         handled_.Add(interval);
326       } else if (!interval->Covers(position)) {
327         active_.Delete(interval);
328         --i;
329         inactive_.Add(interval);
330       }
331     }
332 
333     // (3) Remove currently inactive intervals that are dead at this position.
334     //     Move inactive intervals that cover this position to active.
335     for (size_t i = 0; i < inactive_.Size(); ++i) {
336       LiveInterval* interval = inactive_.Get(i);
337       if (interval->IsDeadAt(position)) {
338         inactive_.Delete(interval);
339         --i;
340         handled_.Add(interval);
341       } else if (interval->Covers(position)) {
342         inactive_.Delete(interval);
343         --i;
344         active_.Add(interval);
345       }
346     }
347 
348     // (4) Try to find an available register.
349     bool success = TryAllocateFreeReg(current);
350 
351     // (5) If no register could be found, we need to spill.
352     if (!success) {
353       success = AllocateBlockedReg(current);
354     }
355 
356     // (6) If the interval had a register allocated, add it to the list of active
357     //     intervals.
358     if (success) {
359       active_.Add(current);
360     }
361   }
362 }
363 
364 // Find a free register. If multiple are found, pick the register that
365 // is free the longest.
TryAllocateFreeReg(LiveInterval * current)366 bool RegisterAllocator::TryAllocateFreeReg(LiveInterval* current) {
367   size_t* free_until = registers_array_;
368 
369   // First set all registers to be free.
370   for (size_t i = 0; i < number_of_registers_; ++i) {
371     free_until[i] = kMaxLifetimePosition;
372   }
373 
374   // For each inactive interval, set its register to be free until
375   // the next intersection with `current`.
376   // Thanks to SSA, this should only be needed for intervals
377   // that are the result of a split.
378   for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
379     LiveInterval* inactive = inactive_.Get(i);
380     DCHECK(inactive->HasRegister());
381     size_t next_intersection = inactive->FirstIntersectionWith(current);
382     if (next_intersection != kNoLifetime) {
383       free_until[inactive->GetRegister()] = next_intersection;
384     }
385   }
386 
387   // For each active interval, set its register to not free.
388   for (size_t i = 0, e = active_.Size(); i < e; ++i) {
389     LiveInterval* interval = active_.Get(i);
390     DCHECK(interval->HasRegister());
391     free_until[interval->GetRegister()] = 0;
392   }
393 
394   // Pick the register that is free the longest.
395   int reg = -1;
396   for (size_t i = 0; i < number_of_registers_; ++i) {
397     if (IsBlocked(i)) continue;
398     if (reg == -1 || free_until[i] > free_until[reg]) {
399       reg = i;
400       if (free_until[i] == kMaxLifetimePosition) break;
401     }
402   }
403 
404   // If we could not find a register, we need to spill.
405   if (reg == -1 || free_until[reg] == 0) {
406     return false;
407   }
408 
409   current->SetRegister(reg);
410   if (!current->IsDeadAt(free_until[reg])) {
411     // If the register is only available for a subset of live ranges
412     // covered by `current`, split `current` at the position where
413     // the register is not available anymore.
414     LiveInterval* split = Split(current, free_until[reg]);
415     DCHECK(split != nullptr);
416     AddToUnhandled(split);
417   }
418   return true;
419 }
420 
IsBlocked(int reg) const421 bool RegisterAllocator::IsBlocked(int reg) const {
422   // TODO: This only works for core registers and needs to be adjusted for
423   // floating point registers.
424   DCHECK(processing_core_registers_);
425   return blocked_registers_[reg];
426 }
427 
428 // Find the register that is used the last, and spill the interval
429 // that holds it. If the first use of `current` is after that register
430 // we spill `current` instead.
AllocateBlockedReg(LiveInterval * current)431 bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
432   size_t first_register_use = current->FirstRegisterUse();
433   if (first_register_use == kNoLifetime) {
434     AllocateSpillSlotFor(current);
435     return false;
436   }
437 
438   // First set all registers as not being used.
439   size_t* next_use = registers_array_;
440   for (size_t i = 0; i < number_of_registers_; ++i) {
441     next_use[i] = kMaxLifetimePosition;
442   }
443 
444   // For each active interval, find the next use of its register after the
445   // start of current.
446   for (size_t i = 0, e = active_.Size(); i < e; ++i) {
447     LiveInterval* active = active_.Get(i);
448     DCHECK(active->HasRegister());
449     if (active->IsFixed()) {
450       next_use[active->GetRegister()] = current->GetStart();
451     } else {
452       size_t use = active->FirstRegisterUseAfter(current->GetStart());
453       if (use != kNoLifetime) {
454         next_use[active->GetRegister()] = use;
455       }
456     }
457   }
458 
459   // For each inactive interval, find the next use of its register after the
460   // start of current.
461   // Thanks to SSA, this should only be needed for intervals
462   // that are the result of a split.
463   for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
464     LiveInterval* inactive = inactive_.Get(i);
465     DCHECK(inactive->HasRegister());
466     size_t next_intersection = inactive->FirstIntersectionWith(current);
467     if (next_intersection != kNoLifetime) {
468       if (inactive->IsFixed()) {
469         next_use[inactive->GetRegister()] =
470             std::min(next_intersection, next_use[inactive->GetRegister()]);
471       } else {
472         size_t use = inactive->FirstRegisterUseAfter(current->GetStart());
473         if (use != kNoLifetime) {
474           next_use[inactive->GetRegister()] = std::min(use, next_use[inactive->GetRegister()]);
475         }
476       }
477     }
478   }
479 
480   // Pick the register that is used the last.
481   int reg = -1;
482   for (size_t i = 0; i < number_of_registers_; ++i) {
483     if (IsBlocked(i)) continue;
484     if (reg == -1 || next_use[i] > next_use[reg]) {
485       reg = i;
486       if (next_use[i] == kMaxLifetimePosition) break;
487     }
488   }
489 
490   if (first_register_use >= next_use[reg]) {
491     // If the first use of that instruction is after the last use of the found
492     // register, we split this interval just before its first register use.
493     AllocateSpillSlotFor(current);
494     LiveInterval* split = Split(current, first_register_use - 1);
495     AddToUnhandled(split);
496     return false;
497   } else {
498     // Use this register and spill the active and inactives interval that
499     // have that register.
500     current->SetRegister(reg);
501 
502     for (size_t i = 0, e = active_.Size(); i < e; ++i) {
503       LiveInterval* active = active_.Get(i);
504       if (active->GetRegister() == reg) {
505         DCHECK(!active->IsFixed());
506         LiveInterval* split = Split(active, current->GetStart());
507         active_.DeleteAt(i);
508         handled_.Add(active);
509         AddToUnhandled(split);
510         break;
511       }
512     }
513 
514     for (size_t i = 0; i < inactive_.Size(); ++i) {
515       LiveInterval* inactive = inactive_.Get(i);
516       if (inactive->GetRegister() == reg) {
517         size_t next_intersection = inactive->FirstIntersectionWith(current);
518         if (next_intersection != kNoLifetime) {
519           if (inactive->IsFixed()) {
520             LiveInterval* split = Split(current, next_intersection);
521             AddToUnhandled(split);
522           } else {
523             LiveInterval* split = Split(inactive, current->GetStart());
524             inactive_.DeleteAt(i);
525             handled_.Add(inactive);
526             AddToUnhandled(split);
527             --i;
528           }
529         }
530       }
531     }
532 
533     return true;
534   }
535 }
536 
AddToUnhandled(LiveInterval * interval)537 void RegisterAllocator::AddToUnhandled(LiveInterval* interval) {
538   size_t insert_at = 0;
539   for (size_t i = unhandled_.Size(); i > 0; --i) {
540     LiveInterval* current = unhandled_.Get(i - 1);
541     if (current->StartsAfter(interval)) {
542       insert_at = i;
543       break;
544     }
545   }
546   unhandled_.InsertAt(insert_at, interval);
547 }
548 
Split(LiveInterval * interval,size_t position)549 LiveInterval* RegisterAllocator::Split(LiveInterval* interval, size_t position) {
550   DCHECK(position >= interval->GetStart());
551   DCHECK(!interval->IsDeadAt(position));
552   if (position == interval->GetStart()) {
553     // Spill slot will be allocated when handling `interval` again.
554     interval->ClearRegister();
555     return interval;
556   } else {
557     LiveInterval* new_interval = interval->SplitAt(position);
558     return new_interval;
559   }
560 }
561 
NeedTwoSpillSlot(Primitive::Type type)562 static bool NeedTwoSpillSlot(Primitive::Type type) {
563   return type == Primitive::kPrimLong || type == Primitive::kPrimDouble;
564 }
565 
AllocateSpillSlotFor(LiveInterval * interval)566 void RegisterAllocator::AllocateSpillSlotFor(LiveInterval* interval) {
567   LiveInterval* parent = interval->GetParent();
568 
569   // An instruction gets a spill slot for its entire lifetime. If the parent
570   // of this interval already has a spill slot, there is nothing to do.
571   if (parent->HasSpillSlot()) {
572     return;
573   }
574 
575   HInstruction* defined_by = parent->GetDefinedBy();
576   if (defined_by->IsParameterValue()) {
577     // Parameters have their own stack slot.
578     parent->SetSpillSlot(codegen_->GetStackSlotOfParameter(defined_by->AsParameterValue()));
579     return;
580   }
581 
582   if (defined_by->IsConstant()) {
583     // Constants don't need a spill slot.
584     return;
585   }
586 
587   LiveInterval* last_sibling = interval;
588   while (last_sibling->GetNextSibling() != nullptr) {
589     last_sibling = last_sibling->GetNextSibling();
590   }
591   size_t end = last_sibling->GetEnd();
592 
593   if (NeedTwoSpillSlot(parent->GetType())) {
594     AllocateTwoSpillSlots(parent, end);
595   } else {
596     AllocateOneSpillSlot(parent, end);
597   }
598 }
599 
AllocateTwoSpillSlots(LiveInterval * parent,size_t end)600 void RegisterAllocator::AllocateTwoSpillSlots(LiveInterval* parent, size_t end) {
601   // Find an available spill slot.
602   size_t slot = 0;
603   for (size_t e = spill_slots_.Size(); slot < e; ++slot) {
604     // We check if it is less rather than less or equal because the parallel move
605     // resolver does not work when a single spill slot needs to be exchanged with
606     // a double spill slot. The strict comparison avoids needing to exchange these
607     // locations at the same lifetime position.
608     if (spill_slots_.Get(slot) < parent->GetStart()
609         && (slot == (e - 1) || spill_slots_.Get(slot + 1) < parent->GetStart())) {
610       break;
611     }
612   }
613 
614   if (slot == spill_slots_.Size()) {
615     // We need a new spill slot.
616     spill_slots_.Add(end);
617     spill_slots_.Add(end);
618   } else if (slot == spill_slots_.Size() - 1) {
619     spill_slots_.Put(slot, end);
620     spill_slots_.Add(end);
621   } else {
622     spill_slots_.Put(slot, end);
623     spill_slots_.Put(slot + 1, end);
624   }
625 
626   parent->SetSpillSlot(slot * kVRegSize);
627 }
628 
AllocateOneSpillSlot(LiveInterval * parent,size_t end)629 void RegisterAllocator::AllocateOneSpillSlot(LiveInterval* parent, size_t end) {
630   // Find an available spill slot.
631   size_t slot = 0;
632   for (size_t e = spill_slots_.Size(); slot < e; ++slot) {
633     if (spill_slots_.Get(slot) <= parent->GetStart()) {
634       break;
635     }
636   }
637 
638   if (slot == spill_slots_.Size()) {
639     // We need a new spill slot.
640     spill_slots_.Add(end);
641   } else {
642     spill_slots_.Put(slot, end);
643   }
644 
645   parent->SetSpillSlot(slot * kVRegSize);
646 }
647 
ConvertToLocation(LiveInterval * interval)648 static Location ConvertToLocation(LiveInterval* interval) {
649   if (interval->HasRegister()) {
650     return Location::RegisterLocation(ManagedRegister(interval->GetRegister()));
651   } else {
652     HInstruction* defined_by = interval->GetParent()->GetDefinedBy();
653     if (defined_by->IsConstant()) {
654       return defined_by->GetLocations()->Out();
655     } else {
656       DCHECK(interval->GetParent()->HasSpillSlot());
657       if (NeedTwoSpillSlot(interval->GetType())) {
658         return Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot());
659       } else {
660         return Location::StackSlot(interval->GetParent()->GetSpillSlot());
661       }
662     }
663   }
664 }
665 
666 // We create a special marker for inputs moves to differentiate them from
667 // moves created during resolution. They must be different instructions
668 // because the input moves work on the assumption that the interval moves
669 // have been executed.
670 static constexpr size_t kInputMoveLifetimePosition = 0;
IsInputMove(HInstruction * instruction)671 static bool IsInputMove(HInstruction* instruction) {
672   return instruction->GetLifetimePosition() == kInputMoveLifetimePosition;
673 }
674 
AddInputMoveFor(HInstruction * instruction,Location source,Location destination) const675 void RegisterAllocator::AddInputMoveFor(HInstruction* instruction,
676                                         Location source,
677                                         Location destination) const {
678   if (source.Equals(destination)) return;
679 
680   DCHECK(instruction->AsPhi() == nullptr);
681 
682   HInstruction* previous = instruction->GetPrevious();
683   HParallelMove* move = nullptr;
684   if (previous == nullptr
685       || previous->AsParallelMove() == nullptr
686       || !IsInputMove(previous)) {
687     move = new (allocator_) HParallelMove(allocator_);
688     move->SetLifetimePosition(kInputMoveLifetimePosition);
689     instruction->GetBlock()->InsertInstructionBefore(move, instruction);
690   } else {
691     move = previous->AsParallelMove();
692   }
693   DCHECK(IsInputMove(move));
694   move->AddMove(new (allocator_) MoveOperands(source, destination));
695 }
696 
InsertParallelMoveAt(size_t position,Location source,Location destination) const697 void RegisterAllocator::InsertParallelMoveAt(size_t position,
698                                              Location source,
699                                              Location destination) const {
700   if (source.Equals(destination)) return;
701 
702   HInstruction* at = liveness_.GetInstructionFromPosition(position / 2);
703   if (at == nullptr) {
704     // Block boundary, don't no anything the connection of split siblings will handle it.
705     return;
706   }
707   HParallelMove* move;
708   if ((position & 1) == 1) {
709     // Move must happen after the instruction.
710     DCHECK(!at->IsControlFlow());
711     move = at->GetNext()->AsParallelMove();
712     // This is a parallel move for connecting siblings in a same block. We need to
713     // differentiate it with moves for connecting blocks, and input moves.
714     if (move == nullptr || move->GetLifetimePosition() != position) {
715       move = new (allocator_) HParallelMove(allocator_);
716       move->SetLifetimePosition(position);
717       at->GetBlock()->InsertInstructionBefore(move, at->GetNext());
718     }
719   } else {
720     // Move must happen before the instruction.
721     HInstruction* previous = at->GetPrevious();
722     if (previous != nullptr && previous->AsParallelMove() != nullptr) {
723       // This is a parallel move for connecting siblings in a same block. We need to
724       // differentiate it with moves for connecting blocks, and input moves.
725       if (previous->GetLifetimePosition() != position) {
726         previous = previous->GetPrevious();
727       }
728     }
729     if (previous == nullptr || previous->AsParallelMove() == nullptr) {
730       move = new (allocator_) HParallelMove(allocator_);
731       move->SetLifetimePosition(position);
732       at->GetBlock()->InsertInstructionBefore(move, at);
733     } else {
734       move = previous->AsParallelMove();
735     }
736   }
737   move->AddMove(new (allocator_) MoveOperands(source, destination));
738 }
739 
InsertParallelMoveAtExitOf(HBasicBlock * block,Location source,Location destination) const740 void RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block,
741                                                    Location source,
742                                                    Location destination) const {
743   if (source.Equals(destination)) return;
744 
745   DCHECK_EQ(block->GetSuccessors().Size(), 1u);
746   HInstruction* last = block->GetLastInstruction();
747   HInstruction* previous = last->GetPrevious();
748   HParallelMove* move;
749   // This is a parallel move for connecting blocks. We need to differentiate
750   // it with moves for connecting siblings in a same block, and output moves.
751   if (previous == nullptr || previous->AsParallelMove() == nullptr
752       || previous->AsParallelMove()->GetLifetimePosition() != block->GetLifetimeEnd()) {
753     move = new (allocator_) HParallelMove(allocator_);
754     move->SetLifetimePosition(block->GetLifetimeEnd());
755     block->InsertInstructionBefore(move, last);
756   } else {
757     move = previous->AsParallelMove();
758   }
759   move->AddMove(new (allocator_) MoveOperands(source, destination));
760 }
761 
InsertParallelMoveAtEntryOf(HBasicBlock * block,Location source,Location destination) const762 void RegisterAllocator::InsertParallelMoveAtEntryOf(HBasicBlock* block,
763                                                     Location source,
764                                                     Location destination) const {
765   if (source.Equals(destination)) return;
766 
767   HInstruction* first = block->GetFirstInstruction();
768   HParallelMove* move = first->AsParallelMove();
769   // This is a parallel move for connecting blocks. We need to differentiate
770   // it with moves for connecting siblings in a same block, and input moves.
771   if (move == nullptr || move->GetLifetimePosition() != block->GetLifetimeStart()) {
772     move = new (allocator_) HParallelMove(allocator_);
773     move->SetLifetimePosition(block->GetLifetimeStart());
774     block->InsertInstructionBefore(move, first);
775   }
776   move->AddMove(new (allocator_) MoveOperands(source, destination));
777 }
778 
InsertMoveAfter(HInstruction * instruction,Location source,Location destination) const779 void RegisterAllocator::InsertMoveAfter(HInstruction* instruction,
780                                         Location source,
781                                         Location destination) const {
782   if (source.Equals(destination)) return;
783 
784   if (instruction->AsPhi() != nullptr) {
785     InsertParallelMoveAtEntryOf(instruction->GetBlock(), source, destination);
786     return;
787   }
788 
789   size_t position = instruction->GetLifetimePosition() + 1;
790   HParallelMove* move = instruction->GetNext()->AsParallelMove();
791   // This is a parallel move for moving the output of an instruction. We need
792   // to differentiate with input moves, moves for connecting siblings in a
793   // and moves for connecting blocks.
794   if (move == nullptr || move->GetLifetimePosition() != position) {
795     move = new (allocator_) HParallelMove(allocator_);
796     move->SetLifetimePosition(position);
797     instruction->GetBlock()->InsertInstructionBefore(move, instruction->GetNext());
798   }
799   move->AddMove(new (allocator_) MoveOperands(source, destination));
800 }
801 
ConnectSiblings(LiveInterval * interval)802 void RegisterAllocator::ConnectSiblings(LiveInterval* interval) {
803   LiveInterval* current = interval;
804   if (current->HasSpillSlot() && current->HasRegister()) {
805     // We spill eagerly, so move must be at definition.
806     InsertMoveAfter(interval->GetDefinedBy(),
807                     Location::RegisterLocation(ManagedRegister(interval->GetRegister())),
808                     NeedTwoSpillSlot(interval->GetType())
809                         ? Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot())
810                         : Location::StackSlot(interval->GetParent()->GetSpillSlot()));
811   }
812   UsePosition* use = current->GetFirstUse();
813 
814   // Walk over all siblings, updating locations of use positions, and
815   // connecting them when they are adjacent.
816   do {
817     Location source = ConvertToLocation(current);
818 
819     // Walk over all uses covered by this interval, and update the location
820     // information.
821     while (use != nullptr && use->GetPosition() <= current->GetEnd()) {
822       if (!use->GetIsEnvironment()) {
823         LocationSummary* locations = use->GetUser()->GetLocations();
824         Location expected_location = locations->InAt(use->GetInputIndex());
825         if (expected_location.IsUnallocated()) {
826           locations->SetInAt(use->GetInputIndex(), source);
827         } else {
828           AddInputMoveFor(use->GetUser(), source, expected_location);
829         }
830       }
831       use = use->GetNext();
832     }
833 
834     // If the next interval starts just after this one, and has a register,
835     // insert a move.
836     LiveInterval* next_sibling = current->GetNextSibling();
837     if (next_sibling != nullptr
838         && next_sibling->HasRegister()
839         && current->GetEnd() == next_sibling->GetStart()) {
840       Location destination = ConvertToLocation(next_sibling);
841       InsertParallelMoveAt(current->GetEnd(), source, destination);
842     }
843     current = next_sibling;
844   } while (current != nullptr);
845   DCHECK(use == nullptr);
846 }
847 
ConnectSplitSiblings(LiveInterval * interval,HBasicBlock * from,HBasicBlock * to) const848 void RegisterAllocator::ConnectSplitSiblings(LiveInterval* interval,
849                                              HBasicBlock* from,
850                                              HBasicBlock* to) const {
851   if (interval->GetNextSibling() == nullptr) {
852     // Nothing to connect. The whole range was allocated to the same location.
853     return;
854   }
855 
856   size_t from_position = from->GetLifetimeEnd() - 1;
857   size_t to_position = to->GetLifetimeStart();
858 
859   LiveInterval* destination = nullptr;
860   LiveInterval* source = nullptr;
861 
862   LiveInterval* current = interval;
863 
864   // Check the intervals that cover `from` and `to`.
865   while ((current != nullptr) && (source == nullptr || destination == nullptr)) {
866     if (current->Covers(from_position)) {
867       DCHECK(source == nullptr);
868       source = current;
869     }
870     if (current->Covers(to_position)) {
871       DCHECK(destination == nullptr);
872       destination = current;
873     }
874 
875     current = current->GetNextSibling();
876   }
877 
878   if (destination == source) {
879     // Interval was not split.
880     return;
881   }
882 
883   if (!destination->HasRegister()) {
884     // Values are eagerly spilled. Spill slot already contains appropriate value.
885     return;
886   }
887 
888   // If `from` has only one successor, we can put the moves at the exit of it. Otherwise
889   // we need to put the moves at the entry of `to`.
890   if (from->GetSuccessors().Size() == 1) {
891     InsertParallelMoveAtExitOf(from, ConvertToLocation(source), ConvertToLocation(destination));
892   } else {
893     DCHECK_EQ(to->GetPredecessors().Size(), 1u);
894     InsertParallelMoveAtEntryOf(to, ConvertToLocation(source), ConvertToLocation(destination));
895   }
896 }
897 
898 // Returns the location of `interval`, or siblings of `interval`, at `position`.
FindLocationAt(LiveInterval * interval,size_t position)899 static Location FindLocationAt(LiveInterval* interval, size_t position) {
900   LiveInterval* current = interval;
901   while (!current->Covers(position)) {
902     current = current->GetNextSibling();
903     DCHECK(current != nullptr);
904   }
905   return ConvertToLocation(current);
906 }
907 
Resolve()908 void RegisterAllocator::Resolve() {
909   codegen_->ComputeFrameSize(spill_slots_.Size());
910 
911   // Adjust the Out Location of instructions.
912   // TODO: Use pointers of Location inside LiveInterval to avoid doing another iteration.
913   for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) {
914     HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
915     LiveInterval* current = instruction->GetLiveInterval();
916     LocationSummary* locations = instruction->GetLocations();
917     Location location = locations->Out();
918     if (instruction->AsParameterValue() != nullptr) {
919       // Now that we know the frame size, adjust the parameter's location.
920       if (location.IsStackSlot()) {
921         location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
922         current->SetSpillSlot(location.GetStackIndex());
923         locations->SetOut(location);
924       } else if (location.IsDoubleStackSlot()) {
925         location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
926         current->SetSpillSlot(location.GetStackIndex());
927         locations->SetOut(location);
928       } else if (current->HasSpillSlot()) {
929         current->SetSpillSlot(current->GetSpillSlot() + codegen_->GetFrameSize());
930       }
931     }
932 
933     Location source = ConvertToLocation(current);
934 
935     if (location.IsUnallocated()) {
936       if (location.GetPolicy() == Location::kSameAsFirstInput) {
937         locations->SetInAt(0, source);
938       }
939       locations->SetOut(source);
940     } else {
941       DCHECK(source.Equals(location));
942     }
943   }
944 
945   // Connect siblings.
946   for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) {
947     HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
948     ConnectSiblings(instruction->GetLiveInterval());
949   }
950 
951   // Resolve non-linear control flow across branches. Order does not matter.
952   for (HLinearOrderIterator it(liveness_); !it.Done(); it.Advance()) {
953     HBasicBlock* block = it.Current();
954     BitVector* live = liveness_.GetLiveInSet(*block);
955     for (uint32_t idx : live->Indexes()) {
956       HInstruction* current = liveness_.GetInstructionFromSsaIndex(idx);
957       LiveInterval* interval = current->GetLiveInterval();
958       for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
959         ConnectSplitSiblings(interval, block->GetPredecessors().Get(i), block);
960       }
961     }
962   }
963 
964   // Resolve phi inputs. Order does not matter.
965   for (HLinearOrderIterator it(liveness_); !it.Done(); it.Advance()) {
966     HBasicBlock* current = it.Current();
967     for (HInstructionIterator it(current->GetPhis()); !it.Done(); it.Advance()) {
968       HInstruction* phi = it.Current();
969       for (size_t i = 0, e = current->GetPredecessors().Size(); i < e; ++i) {
970         HBasicBlock* predecessor = current->GetPredecessors().Get(i);
971         DCHECK_EQ(predecessor->GetSuccessors().Size(), 1u);
972         HInstruction* input = phi->InputAt(i);
973         Location source = FindLocationAt(input->GetLiveInterval(),
974                                          predecessor->GetLastInstruction()->GetLifetimePosition());
975         Location destination = ConvertToLocation(phi->GetLiveInterval());
976         InsertParallelMoveAtExitOf(predecessor, source, destination);
977       }
978     }
979   }
980 }
981 
982 }  // namespace art
983