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 <iostream>
20 #include <sstream>
21 
22 #include "base/bit_vector-inl.h"
23 #include "code_generator.h"
24 #include "ssa_liveness_analysis.h"
25 
26 namespace art {
27 
28 static constexpr size_t kMaxLifetimePosition = -1;
29 static constexpr size_t kDefaultNumberOfSpillSlots = 4;
30 
31 // For simplicity, we implement register pairs as (reg, reg + 1).
32 // Note that this is a requirement for double registers on ARM, since we
33 // allocate SRegister.
GetHighForLowRegister(int reg)34 static int GetHighForLowRegister(int reg) { return reg + 1; }
IsLowRegister(int reg)35 static bool IsLowRegister(int reg) { return (reg & 1) == 0; }
IsLowOfUnalignedPairInterval(LiveInterval * low)36 static bool IsLowOfUnalignedPairInterval(LiveInterval* low) {
37   return GetHighForLowRegister(low->GetRegister()) != low->GetHighInterval()->GetRegister();
38 }
39 
RegisterAllocator(ArenaAllocator * allocator,CodeGenerator * codegen,const SsaLivenessAnalysis & liveness)40 RegisterAllocator::RegisterAllocator(ArenaAllocator* allocator,
41                                      CodeGenerator* codegen,
42                                      const SsaLivenessAnalysis& liveness)
43       : allocator_(allocator),
44         codegen_(codegen),
45         liveness_(liveness),
46         unhandled_core_intervals_(allocator, 0),
47         unhandled_fp_intervals_(allocator, 0),
48         unhandled_(nullptr),
49         handled_(allocator, 0),
50         active_(allocator, 0),
51         inactive_(allocator, 0),
52         physical_core_register_intervals_(allocator, codegen->GetNumberOfCoreRegisters()),
53         physical_fp_register_intervals_(allocator, codegen->GetNumberOfFloatingPointRegisters()),
54         temp_intervals_(allocator, 4),
55         int_spill_slots_(allocator, kDefaultNumberOfSpillSlots),
56         long_spill_slots_(allocator, kDefaultNumberOfSpillSlots),
57         float_spill_slots_(allocator, kDefaultNumberOfSpillSlots),
58         double_spill_slots_(allocator, kDefaultNumberOfSpillSlots),
59         safepoints_(allocator, 0),
60         processing_core_registers_(false),
61         number_of_registers_(-1),
62         registers_array_(nullptr),
63         blocked_core_registers_(codegen->GetBlockedCoreRegisters()),
64         blocked_fp_registers_(codegen->GetBlockedFloatingPointRegisters()),
65         reserved_out_slots_(0),
66         maximum_number_of_live_core_registers_(0),
67         maximum_number_of_live_fp_registers_(0) {
68   static constexpr bool kIsBaseline = false;
69   codegen->SetupBlockedRegisters(kIsBaseline);
70   physical_core_register_intervals_.SetSize(codegen->GetNumberOfCoreRegisters());
71   physical_fp_register_intervals_.SetSize(codegen->GetNumberOfFloatingPointRegisters());
72   // Always reserve for the current method and the graph's max out registers.
73   // TODO: compute it instead.
74   // ArtMethod* takes 2 vregs for 64 bits.
75   reserved_out_slots_ = InstructionSetPointerSize(codegen->GetInstructionSet()) / kVRegSize +
76       codegen->GetGraph()->GetMaximumNumberOfOutVRegs();
77 }
78 
CanAllocateRegistersFor(const HGraph & graph ATTRIBUTE_UNUSED,InstructionSet instruction_set)79 bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph ATTRIBUTE_UNUSED,
80                                                 InstructionSet instruction_set) {
81   return instruction_set == kArm64
82       || instruction_set == kX86_64
83       || instruction_set == kMips64
84       || instruction_set == kArm
85       || instruction_set == kX86
86       || instruction_set == kThumb2;
87 }
88 
ShouldProcess(bool processing_core_registers,LiveInterval * interval)89 static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) {
90   if (interval == nullptr) return false;
91   bool is_core_register = (interval->GetType() != Primitive::kPrimDouble)
92       && (interval->GetType() != Primitive::kPrimFloat);
93   return processing_core_registers == is_core_register;
94 }
95 
AllocateRegisters()96 void RegisterAllocator::AllocateRegisters() {
97   AllocateRegistersInternal();
98   Resolve();
99 
100   if (kIsDebugBuild) {
101     processing_core_registers_ = true;
102     ValidateInternal(true);
103     processing_core_registers_ = false;
104     ValidateInternal(true);
105     // Check that the linear order is still correct with regards to lifetime positions.
106     // Since only parallel moves have been inserted during the register allocation,
107     // these checks are mostly for making sure these moves have been added correctly.
108     size_t current_liveness = 0;
109     for (HLinearOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
110       HBasicBlock* block = it.Current();
111       for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
112         HInstruction* instruction = inst_it.Current();
113         DCHECK_LE(current_liveness, instruction->GetLifetimePosition());
114         current_liveness = instruction->GetLifetimePosition();
115       }
116       for (HInstructionIterator inst_it(block->GetInstructions());
117            !inst_it.Done();
118            inst_it.Advance()) {
119         HInstruction* instruction = inst_it.Current();
120         DCHECK_LE(current_liveness, instruction->GetLifetimePosition()) << instruction->DebugName();
121         current_liveness = instruction->GetLifetimePosition();
122       }
123     }
124   }
125 }
126 
BlockRegister(Location location,size_t start,size_t end)127 void RegisterAllocator::BlockRegister(Location location,
128                                       size_t start,
129                                       size_t end) {
130   int reg = location.reg();
131   DCHECK(location.IsRegister() || location.IsFpuRegister());
132   LiveInterval* interval = location.IsRegister()
133       ? physical_core_register_intervals_.Get(reg)
134       : physical_fp_register_intervals_.Get(reg);
135   Primitive::Type type = location.IsRegister()
136       ? Primitive::kPrimInt
137       : Primitive::kPrimFloat;
138   if (interval == nullptr) {
139     interval = LiveInterval::MakeFixedInterval(allocator_, reg, type);
140     if (location.IsRegister()) {
141       physical_core_register_intervals_.Put(reg, interval);
142     } else {
143       physical_fp_register_intervals_.Put(reg, interval);
144     }
145   }
146   DCHECK(interval->GetRegister() == reg);
147   interval->AddRange(start, end);
148 }
149 
AllocateRegistersInternal()150 void RegisterAllocator::AllocateRegistersInternal() {
151   // Iterate post-order, to ensure the list is sorted, and the last added interval
152   // is the one with the lowest start position.
153   for (HLinearPostOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
154     HBasicBlock* block = it.Current();
155     for (HBackwardInstructionIterator back_it(block->GetInstructions()); !back_it.Done();
156          back_it.Advance()) {
157       ProcessInstruction(back_it.Current());
158     }
159     for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
160       ProcessInstruction(inst_it.Current());
161     }
162   }
163 
164   number_of_registers_ = codegen_->GetNumberOfCoreRegisters();
165   registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
166   processing_core_registers_ = true;
167   unhandled_ = &unhandled_core_intervals_;
168   for (size_t i = 0, e = physical_core_register_intervals_.Size(); i < e; ++i) {
169     LiveInterval* fixed = physical_core_register_intervals_.Get(i);
170     if (fixed != nullptr) {
171       // Fixed interval is added to inactive_ instead of unhandled_.
172       // It's also the only type of inactive interval whose start position
173       // can be after the current interval during linear scan.
174       // Fixed interval is never split and never moves to unhandled_.
175       inactive_.Add(fixed);
176     }
177   }
178   LinearScan();
179 
180   inactive_.Reset();
181   active_.Reset();
182   handled_.Reset();
183 
184   number_of_registers_ = codegen_->GetNumberOfFloatingPointRegisters();
185   registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
186   processing_core_registers_ = false;
187   unhandled_ = &unhandled_fp_intervals_;
188   for (size_t i = 0, e = physical_fp_register_intervals_.Size(); i < e; ++i) {
189     LiveInterval* fixed = physical_fp_register_intervals_.Get(i);
190     if (fixed != nullptr) {
191       // Fixed interval is added to inactive_ instead of unhandled_.
192       // It's also the only type of inactive interval whose start position
193       // can be after the current interval during linear scan.
194       // Fixed interval is never split and never moves to unhandled_.
195       inactive_.Add(fixed);
196     }
197   }
198   LinearScan();
199 }
200 
ProcessInstruction(HInstruction * instruction)201 void RegisterAllocator::ProcessInstruction(HInstruction* instruction) {
202   LocationSummary* locations = instruction->GetLocations();
203   size_t position = instruction->GetLifetimePosition();
204 
205   if (locations == nullptr) return;
206 
207   // Create synthesized intervals for temporaries.
208   for (size_t i = 0; i < locations->GetTempCount(); ++i) {
209     Location temp = locations->GetTemp(i);
210     if (temp.IsRegister() || temp.IsFpuRegister()) {
211       BlockRegister(temp, position, position + 1);
212     } else {
213       DCHECK(temp.IsUnallocated());
214       switch (temp.GetPolicy()) {
215         case Location::kRequiresRegister: {
216           LiveInterval* interval =
217               LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimInt);
218           temp_intervals_.Add(interval);
219           interval->AddTempUse(instruction, i);
220           unhandled_core_intervals_.Add(interval);
221           break;
222         }
223 
224         case Location::kRequiresFpuRegister: {
225           LiveInterval* interval =
226               LiveInterval::MakeTempInterval(allocator_, Primitive::kPrimDouble);
227           temp_intervals_.Add(interval);
228           interval->AddTempUse(instruction, i);
229           if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) {
230             interval->AddHighInterval(/* is_temp */ true);
231             LiveInterval* high = interval->GetHighInterval();
232             temp_intervals_.Add(high);
233             unhandled_fp_intervals_.Add(high);
234           }
235           unhandled_fp_intervals_.Add(interval);
236           break;
237         }
238 
239         default:
240           LOG(FATAL) << "Unexpected policy for temporary location "
241                      << temp.GetPolicy();
242       }
243     }
244   }
245 
246   bool core_register = (instruction->GetType() != Primitive::kPrimDouble)
247       && (instruction->GetType() != Primitive::kPrimFloat);
248 
249   if (locations->CanCall()) {
250     if (codegen_->IsLeafMethod()) {
251       // TODO: We do this here because we do not want the suspend check to artificially
252       // create live registers. We should find another place, but this is currently the
253       // simplest.
254       DCHECK(instruction->IsSuspendCheckEntry());
255       instruction->GetBlock()->RemoveInstruction(instruction);
256       return;
257     }
258     safepoints_.Add(instruction);
259     if (locations->OnlyCallsOnSlowPath()) {
260       // We add a synthesized range at this position to record the live registers
261       // at this position. Ideally, we could just update the safepoints when locations
262       // are updated, but we currently need to know the full stack size before updating
263       // locations (because of parameters and the fact that we don't have a frame pointer).
264       // And knowing the full stack size requires to know the maximum number of live
265       // registers at calls in slow paths.
266       // By adding the following interval in the algorithm, we can compute this
267       // maximum before updating locations.
268       LiveInterval* interval = LiveInterval::MakeSlowPathInterval(allocator_, instruction);
269       interval->AddRange(position, position + 1);
270       AddSorted(&unhandled_core_intervals_, interval);
271       AddSorted(&unhandled_fp_intervals_, interval);
272     }
273   }
274 
275   if (locations->WillCall()) {
276     // Block all registers.
277     for (size_t i = 0; i < codegen_->GetNumberOfCoreRegisters(); ++i) {
278       if (!codegen_->IsCoreCalleeSaveRegister(i)) {
279         BlockRegister(Location::RegisterLocation(i),
280                       position,
281                       position + 1);
282       }
283     }
284     for (size_t i = 0; i < codegen_->GetNumberOfFloatingPointRegisters(); ++i) {
285       if (!codegen_->IsFloatingPointCalleeSaveRegister(i)) {
286         BlockRegister(Location::FpuRegisterLocation(i),
287                       position,
288                       position + 1);
289       }
290     }
291   }
292 
293   for (size_t i = 0; i < instruction->InputCount(); ++i) {
294     Location input = locations->InAt(i);
295     if (input.IsRegister() || input.IsFpuRegister()) {
296       BlockRegister(input, position, position + 1);
297     } else if (input.IsPair()) {
298       BlockRegister(input.ToLow(), position, position + 1);
299       BlockRegister(input.ToHigh(), position, position + 1);
300     }
301   }
302 
303   LiveInterval* current = instruction->GetLiveInterval();
304   if (current == nullptr) return;
305 
306   GrowableArray<LiveInterval*>& unhandled = core_register
307       ? unhandled_core_intervals_
308       : unhandled_fp_intervals_;
309 
310   DCHECK(unhandled.IsEmpty() || current->StartsBeforeOrAt(unhandled.Peek()));
311 
312   if (codegen_->NeedsTwoRegisters(current->GetType())) {
313     current->AddHighInterval();
314   }
315 
316   for (size_t safepoint_index = safepoints_.Size(); safepoint_index > 0; --safepoint_index) {
317     HInstruction* safepoint = safepoints_.Get(safepoint_index - 1);
318     size_t safepoint_position = safepoint->GetLifetimePosition();
319 
320     // Test that safepoints are ordered in the optimal way.
321     DCHECK(safepoint_index == safepoints_.Size()
322            || safepoints_.Get(safepoint_index)->GetLifetimePosition() < safepoint_position);
323 
324     if (safepoint_position == current->GetStart()) {
325       // The safepoint is for this instruction, so the location of the instruction
326       // does not need to be saved.
327       DCHECK_EQ(safepoint_index, safepoints_.Size());
328       DCHECK_EQ(safepoint, instruction);
329       continue;
330     } else if (current->IsDeadAt(safepoint_position)) {
331       break;
332     } else if (!current->Covers(safepoint_position)) {
333       // Hole in the interval.
334       continue;
335     }
336     current->AddSafepoint(safepoint);
337   }
338   current->ResetSearchCache();
339 
340   // Some instructions define their output in fixed register/stack slot. We need
341   // to ensure we know these locations before doing register allocation. For a
342   // given register, we create an interval that covers these locations. The register
343   // will be unavailable at these locations when trying to allocate one for an
344   // interval.
345   //
346   // The backwards walking ensures the ranges are ordered on increasing start positions.
347   Location output = locations->Out();
348   if (output.IsUnallocated() && output.GetPolicy() == Location::kSameAsFirstInput) {
349     Location first = locations->InAt(0);
350     if (first.IsRegister() || first.IsFpuRegister()) {
351       current->SetFrom(position + 1);
352       current->SetRegister(first.reg());
353     } else if (first.IsPair()) {
354       current->SetFrom(position + 1);
355       current->SetRegister(first.low());
356       LiveInterval* high = current->GetHighInterval();
357       high->SetRegister(first.high());
358       high->SetFrom(position + 1);
359     }
360   } else if (output.IsRegister() || output.IsFpuRegister()) {
361     // Shift the interval's start by one to account for the blocked register.
362     current->SetFrom(position + 1);
363     current->SetRegister(output.reg());
364     BlockRegister(output, position, position + 1);
365   } else if (output.IsPair()) {
366     current->SetFrom(position + 1);
367     current->SetRegister(output.low());
368     LiveInterval* high = current->GetHighInterval();
369     high->SetRegister(output.high());
370     high->SetFrom(position + 1);
371     BlockRegister(output.ToLow(), position, position + 1);
372     BlockRegister(output.ToHigh(), position, position + 1);
373   } else if (output.IsStackSlot() || output.IsDoubleStackSlot()) {
374     current->SetSpillSlot(output.GetStackIndex());
375   } else {
376     DCHECK(output.IsUnallocated() || output.IsConstant());
377   }
378 
379   // If needed, add interval to the list of unhandled intervals.
380   if (current->HasSpillSlot() || instruction->IsConstant()) {
381     // Split just before first register use.
382     size_t first_register_use = current->FirstRegisterUse();
383     if (first_register_use != kNoLifetime) {
384       LiveInterval* split = SplitBetween(current, current->GetStart(), first_register_use - 1);
385       // Don't add directly to `unhandled`, it needs to be sorted and the start
386       // of this new interval might be after intervals already in the list.
387       AddSorted(&unhandled, split);
388     } else {
389       // Nothing to do, we won't allocate a register for this value.
390     }
391   } else {
392     // Don't add directly to `unhandled`, temp or safepoint intervals
393     // for this instruction may have been added, and those can be
394     // processed first.
395     AddSorted(&unhandled, current);
396   }
397 }
398 
399 class AllRangesIterator : public ValueObject {
400  public:
AllRangesIterator(LiveInterval * interval)401   explicit AllRangesIterator(LiveInterval* interval)
402       : current_interval_(interval),
403         current_range_(interval->GetFirstRange()) {}
404 
Done() const405   bool Done() const { return current_interval_ == nullptr; }
CurrentRange() const406   LiveRange* CurrentRange() const { return current_range_; }
CurrentInterval() const407   LiveInterval* CurrentInterval() const { return current_interval_; }
408 
Advance()409   void Advance() {
410     current_range_ = current_range_->GetNext();
411     if (current_range_ == nullptr) {
412       current_interval_ = current_interval_->GetNextSibling();
413       if (current_interval_ != nullptr) {
414         current_range_ = current_interval_->GetFirstRange();
415       }
416     }
417   }
418 
419  private:
420   LiveInterval* current_interval_;
421   LiveRange* current_range_;
422 
423   DISALLOW_COPY_AND_ASSIGN(AllRangesIterator);
424 };
425 
ValidateInternal(bool log_fatal_on_failure) const426 bool RegisterAllocator::ValidateInternal(bool log_fatal_on_failure) const {
427   // To simplify unit testing, we eagerly create the array of intervals, and
428   // call the helper method.
429   GrowableArray<LiveInterval*> intervals(allocator_, 0);
430   for (size_t i = 0; i < liveness_.GetNumberOfSsaValues(); ++i) {
431     HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
432     if (ShouldProcess(processing_core_registers_, instruction->GetLiveInterval())) {
433       intervals.Add(instruction->GetLiveInterval());
434     }
435   }
436 
437   if (processing_core_registers_) {
438     for (size_t i = 0, e = physical_core_register_intervals_.Size(); i < e; ++i) {
439       LiveInterval* fixed = physical_core_register_intervals_.Get(i);
440       if (fixed != nullptr) {
441         intervals.Add(fixed);
442       }
443     }
444   } else {
445     for (size_t i = 0, e = physical_fp_register_intervals_.Size(); i < e; ++i) {
446       LiveInterval* fixed = physical_fp_register_intervals_.Get(i);
447       if (fixed != nullptr) {
448         intervals.Add(fixed);
449       }
450     }
451   }
452 
453   for (size_t i = 0, e = temp_intervals_.Size(); i < e; ++i) {
454     LiveInterval* temp = temp_intervals_.Get(i);
455     if (ShouldProcess(processing_core_registers_, temp)) {
456       intervals.Add(temp);
457     }
458   }
459 
460   return ValidateIntervals(intervals, GetNumberOfSpillSlots(), reserved_out_slots_, *codegen_,
461                            allocator_, processing_core_registers_, log_fatal_on_failure);
462 }
463 
ValidateIntervals(const GrowableArray<LiveInterval * > & intervals,size_t number_of_spill_slots,size_t number_of_out_slots,const CodeGenerator & codegen,ArenaAllocator * allocator,bool processing_core_registers,bool log_fatal_on_failure)464 bool RegisterAllocator::ValidateIntervals(const GrowableArray<LiveInterval*>& intervals,
465                                           size_t number_of_spill_slots,
466                                           size_t number_of_out_slots,
467                                           const CodeGenerator& codegen,
468                                           ArenaAllocator* allocator,
469                                           bool processing_core_registers,
470                                           bool log_fatal_on_failure) {
471   size_t number_of_registers = processing_core_registers
472       ? codegen.GetNumberOfCoreRegisters()
473       : codegen.GetNumberOfFloatingPointRegisters();
474   GrowableArray<ArenaBitVector*> liveness_of_values(
475       allocator, number_of_registers + number_of_spill_slots);
476 
477   // Allocate a bit vector per register. A live interval that has a register
478   // allocated will populate the associated bit vector based on its live ranges.
479   for (size_t i = 0; i < number_of_registers + number_of_spill_slots; ++i) {
480     liveness_of_values.Add(new (allocator) ArenaBitVector(allocator, 0, true));
481   }
482 
483   for (size_t i = 0, e = intervals.Size(); i < e; ++i) {
484     for (AllRangesIterator it(intervals.Get(i)); !it.Done(); it.Advance()) {
485       LiveInterval* current = it.CurrentInterval();
486       HInstruction* defined_by = current->GetParent()->GetDefinedBy();
487       if (current->GetParent()->HasSpillSlot()
488            // Parameters have their own stack slot.
489            && !(defined_by != nullptr && defined_by->IsParameterValue())) {
490         BitVector* liveness_of_spill_slot = liveness_of_values.Get(number_of_registers
491             + current->GetParent()->GetSpillSlot() / kVRegSize
492             - number_of_out_slots);
493         for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
494           if (liveness_of_spill_slot->IsBitSet(j)) {
495             if (log_fatal_on_failure) {
496               std::ostringstream message;
497               message << "Spill slot conflict at " << j;
498               LOG(FATAL) << message.str();
499             } else {
500               return false;
501             }
502           } else {
503             liveness_of_spill_slot->SetBit(j);
504           }
505         }
506       }
507 
508       if (current->HasRegister()) {
509         BitVector* liveness_of_register = liveness_of_values.Get(current->GetRegister());
510         for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
511           if (liveness_of_register->IsBitSet(j)) {
512             if (current->IsUsingInputRegister() && current->CanUseInputRegister()) {
513               continue;
514             }
515             if (log_fatal_on_failure) {
516               std::ostringstream message;
517               message << "Register conflict at " << j << " ";
518               if (defined_by != nullptr) {
519                 message << "(" << defined_by->DebugName() << ")";
520               }
521               message << "for ";
522               if (processing_core_registers) {
523                 codegen.DumpCoreRegister(message, current->GetRegister());
524               } else {
525                 codegen.DumpFloatingPointRegister(message, current->GetRegister());
526               }
527               LOG(FATAL) << message.str();
528             } else {
529               return false;
530             }
531           } else {
532             liveness_of_register->SetBit(j);
533           }
534         }
535       }
536     }
537   }
538   return true;
539 }
540 
DumpInterval(std::ostream & stream,LiveInterval * interval) const541 void RegisterAllocator::DumpInterval(std::ostream& stream, LiveInterval* interval) const {
542   interval->Dump(stream);
543   stream << ": ";
544   if (interval->HasRegister()) {
545     if (interval->IsFloatingPoint()) {
546       codegen_->DumpFloatingPointRegister(stream, interval->GetRegister());
547     } else {
548       codegen_->DumpCoreRegister(stream, interval->GetRegister());
549     }
550   } else {
551     stream << "spilled";
552   }
553   stream << std::endl;
554 }
555 
DumpAllIntervals(std::ostream & stream) const556 void RegisterAllocator::DumpAllIntervals(std::ostream& stream) const {
557   stream << "inactive: " << std::endl;
558   for (size_t i = 0; i < inactive_.Size(); i ++) {
559     DumpInterval(stream, inactive_.Get(i));
560   }
561   stream << "active: " << std::endl;
562   for (size_t i = 0; i < active_.Size(); i ++) {
563     DumpInterval(stream, active_.Get(i));
564   }
565   stream << "unhandled: " << std::endl;
566   auto unhandled = (unhandled_ != nullptr) ?
567       unhandled_ : &unhandled_core_intervals_;
568   for (size_t i = 0; i < unhandled->Size(); i ++) {
569     DumpInterval(stream, unhandled->Get(i));
570   }
571   stream << "handled: " << std::endl;
572   for (size_t i = 0; i < handled_.Size(); i ++) {
573     DumpInterval(stream, handled_.Get(i));
574   }
575 }
576 
577 // By the book implementation of a linear scan register allocator.
LinearScan()578 void RegisterAllocator::LinearScan() {
579   while (!unhandled_->IsEmpty()) {
580     // (1) Remove interval with the lowest start position from unhandled.
581     LiveInterval* current = unhandled_->Pop();
582     DCHECK(!current->IsFixed() && !current->HasSpillSlot());
583     DCHECK(unhandled_->IsEmpty() || unhandled_->Peek()->GetStart() >= current->GetStart());
584     DCHECK(!current->IsLowInterval() || unhandled_->Peek()->IsHighInterval());
585 
586     size_t position = current->GetStart();
587 
588     // Remember the inactive_ size here since the ones moved to inactive_ from
589     // active_ below shouldn't need to be re-checked.
590     size_t inactive_intervals_to_handle = inactive_.Size();
591 
592     // (2) Remove currently active intervals that are dead at this position.
593     //     Move active intervals that have a lifetime hole at this position
594     //     to inactive.
595     for (size_t i = 0; i < active_.Size(); ++i) {
596       LiveInterval* interval = active_.Get(i);
597       if (interval->IsDeadAt(position)) {
598         active_.Delete(interval);
599         --i;
600         handled_.Add(interval);
601       } else if (!interval->Covers(position)) {
602         active_.Delete(interval);
603         --i;
604         inactive_.Add(interval);
605       }
606     }
607 
608     // (3) Remove currently inactive intervals that are dead at this position.
609     //     Move inactive intervals that cover this position to active.
610     for (size_t i = 0; i < inactive_intervals_to_handle; ++i) {
611       LiveInterval* interval = inactive_.Get(i);
612       DCHECK(interval->GetStart() < position || interval->IsFixed());
613       if (interval->IsDeadAt(position)) {
614         inactive_.Delete(interval);
615         --i;
616         --inactive_intervals_to_handle;
617         handled_.Add(interval);
618       } else if (interval->Covers(position)) {
619         inactive_.Delete(interval);
620         --i;
621         --inactive_intervals_to_handle;
622         active_.Add(interval);
623       }
624     }
625 
626     if (current->IsSlowPathSafepoint()) {
627       // Synthesized interval to record the maximum number of live registers
628       // at safepoints. No need to allocate a register for it.
629       if (processing_core_registers_) {
630         maximum_number_of_live_core_registers_ =
631           std::max(maximum_number_of_live_core_registers_, active_.Size());
632       } else {
633         maximum_number_of_live_fp_registers_ =
634           std::max(maximum_number_of_live_fp_registers_, active_.Size());
635       }
636       DCHECK(unhandled_->IsEmpty() || unhandled_->Peek()->GetStart() > current->GetStart());
637       continue;
638     }
639 
640     if (current->IsHighInterval() && !current->GetLowInterval()->HasRegister()) {
641       DCHECK(!current->HasRegister());
642       // Allocating the low part was unsucessful. The splitted interval for the high part
643       // will be handled next (it is in the `unhandled_` list).
644       continue;
645     }
646 
647     // (4) Try to find an available register.
648     bool success = TryAllocateFreeReg(current);
649 
650     // (5) If no register could be found, we need to spill.
651     if (!success) {
652       success = AllocateBlockedReg(current);
653     }
654 
655     // (6) If the interval had a register allocated, add it to the list of active
656     //     intervals.
657     if (success) {
658       codegen_->AddAllocatedRegister(processing_core_registers_
659           ? Location::RegisterLocation(current->GetRegister())
660           : Location::FpuRegisterLocation(current->GetRegister()));
661       active_.Add(current);
662       if (current->HasHighInterval() && !current->GetHighInterval()->HasRegister()) {
663         current->GetHighInterval()->SetRegister(GetHighForLowRegister(current->GetRegister()));
664       }
665     }
666   }
667 }
668 
FreeIfNotCoverAt(LiveInterval * interval,size_t position,size_t * free_until)669 static void FreeIfNotCoverAt(LiveInterval* interval, size_t position, size_t* free_until) {
670   DCHECK(!interval->IsHighInterval());
671   // Note that the same instruction may occur multiple times in the input list,
672   // so `free_until` may have changed already.
673   // Since `position` is not the current scan position, we need to use CoversSlow.
674   if (interval->IsDeadAt(position)) {
675     // Set the register to be free. Note that inactive intervals might later
676     // update this.
677     free_until[interval->GetRegister()] = kMaxLifetimePosition;
678     if (interval->HasHighInterval()) {
679       DCHECK(interval->GetHighInterval()->IsDeadAt(position));
680       free_until[interval->GetHighInterval()->GetRegister()] = kMaxLifetimePosition;
681     }
682   } else if (!interval->CoversSlow(position)) {
683     // The interval becomes inactive at `defined_by`. We make its register
684     // available only until the next use strictly after `defined_by`.
685     free_until[interval->GetRegister()] = interval->FirstUseAfter(position);
686     if (interval->HasHighInterval()) {
687       DCHECK(!interval->GetHighInterval()->CoversSlow(position));
688       free_until[interval->GetHighInterval()->GetRegister()] = free_until[interval->GetRegister()];
689     }
690   }
691 }
692 
693 // Find a free register. If multiple are found, pick the register that
694 // is free the longest.
TryAllocateFreeReg(LiveInterval * current)695 bool RegisterAllocator::TryAllocateFreeReg(LiveInterval* current) {
696   size_t* free_until = registers_array_;
697 
698   // First set all registers to be free.
699   for (size_t i = 0; i < number_of_registers_; ++i) {
700     free_until[i] = kMaxLifetimePosition;
701   }
702 
703   // For each active interval, set its register to not free.
704   for (size_t i = 0, e = active_.Size(); i < e; ++i) {
705     LiveInterval* interval = active_.Get(i);
706     DCHECK(interval->HasRegister());
707     free_until[interval->GetRegister()] = 0;
708   }
709 
710   // An interval that starts an instruction (that is, it is not split), may
711   // re-use the registers used by the inputs of that instruciton, based on the
712   // location summary.
713   HInstruction* defined_by = current->GetDefinedBy();
714   if (defined_by != nullptr && !current->IsSplit()) {
715     LocationSummary* locations = defined_by->GetLocations();
716     if (!locations->OutputCanOverlapWithInputs() && locations->Out().IsUnallocated()) {
717       for (HInputIterator it(defined_by); !it.Done(); it.Advance()) {
718         // Take the last interval of the input. It is the location of that interval
719         // that will be used at `defined_by`.
720         LiveInterval* interval = it.Current()->GetLiveInterval()->GetLastSibling();
721         // Note that interval may have not been processed yet.
722         // TODO: Handle non-split intervals last in the work list.
723         if (interval->HasRegister() && interval->SameRegisterKind(*current)) {
724           // The input must be live until the end of `defined_by`, to comply to
725           // the linear scan algorithm. So we use `defined_by`'s end lifetime
726           // position to check whether the input is dead or is inactive after
727           // `defined_by`.
728           DCHECK(interval->CoversSlow(defined_by->GetLifetimePosition()));
729           size_t position = defined_by->GetLifetimePosition() + 1;
730           FreeIfNotCoverAt(interval, position, free_until);
731         }
732       }
733     }
734   }
735 
736   // For each inactive interval, set its register to be free until
737   // the next intersection with `current`.
738   for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
739     LiveInterval* inactive = inactive_.Get(i);
740     // Temp/Slow-path-safepoint interval has no holes.
741     DCHECK(!inactive->IsTemp() && !inactive->IsSlowPathSafepoint());
742     if (!current->IsSplit() && !inactive->IsFixed()) {
743       // Neither current nor inactive are fixed.
744       // Thanks to SSA, a non-split interval starting in a hole of an
745       // inactive interval should never intersect with that inactive interval.
746       // Only if it's not fixed though, because fixed intervals don't come from SSA.
747       DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
748       continue;
749     }
750 
751     DCHECK(inactive->HasRegister());
752     if (free_until[inactive->GetRegister()] == 0) {
753       // Already used by some active interval. No need to intersect.
754       continue;
755     }
756     size_t next_intersection = inactive->FirstIntersectionWith(current);
757     if (next_intersection != kNoLifetime) {
758       free_until[inactive->GetRegister()] =
759           std::min(free_until[inactive->GetRegister()], next_intersection);
760     }
761   }
762 
763   int reg = kNoRegister;
764   if (current->HasRegister()) {
765     // Some instructions have a fixed register output.
766     reg = current->GetRegister();
767     if (free_until[reg] == 0) {
768       DCHECK(current->IsHighInterval());
769       // AllocateBlockedReg will spill the holder of the register.
770       return false;
771     }
772   } else {
773     DCHECK(!current->IsHighInterval());
774     int hint = current->FindFirstRegisterHint(free_until, liveness_);
775     if ((hint != kNoRegister)
776         // For simplicity, if the hint we are getting for a pair cannot be used,
777         // we are just going to allocate a new pair.
778         && !(current->IsLowInterval() && IsBlocked(GetHighForLowRegister(hint)))) {
779       DCHECK(!IsBlocked(hint));
780       reg = hint;
781     } else if (current->IsLowInterval()) {
782       reg = FindAvailableRegisterPair(free_until, current->GetStart());
783     } else {
784       reg = FindAvailableRegister(free_until);
785     }
786   }
787 
788   DCHECK_NE(reg, kNoRegister);
789   // If we could not find a register, we need to spill.
790   if (free_until[reg] == 0) {
791     return false;
792   }
793 
794   if (current->IsLowInterval()) {
795     // If the high register of this interval is not available, we need to spill.
796     int high_reg = current->GetHighInterval()->GetRegister();
797     if (high_reg == kNoRegister) {
798       high_reg = GetHighForLowRegister(reg);
799     }
800     if (free_until[high_reg] == 0) {
801       return false;
802     }
803   }
804 
805   current->SetRegister(reg);
806   if (!current->IsDeadAt(free_until[reg])) {
807     // If the register is only available for a subset of live ranges
808     // covered by `current`, split `current` at the position where
809     // the register is not available anymore.
810     LiveInterval* split = Split(current, free_until[reg]);
811     DCHECK(split != nullptr);
812     AddSorted(unhandled_, split);
813   }
814   return true;
815 }
816 
IsBlocked(int reg) const817 bool RegisterAllocator::IsBlocked(int reg) const {
818   return processing_core_registers_
819       ? blocked_core_registers_[reg]
820       : blocked_fp_registers_[reg];
821 }
822 
FindAvailableRegisterPair(size_t * next_use,size_t starting_at) const823 int RegisterAllocator::FindAvailableRegisterPair(size_t* next_use, size_t starting_at) const {
824   int reg = kNoRegister;
825   // Pick the register pair that is used the last.
826   for (size_t i = 0; i < number_of_registers_; ++i) {
827     if (IsBlocked(i)) continue;
828     if (!IsLowRegister(i)) continue;
829     int high_register = GetHighForLowRegister(i);
830     if (IsBlocked(high_register)) continue;
831     int existing_high_register = GetHighForLowRegister(reg);
832     if ((reg == kNoRegister) || (next_use[i] >= next_use[reg]
833                         && next_use[high_register] >= next_use[existing_high_register])) {
834       reg = i;
835       if (next_use[i] == kMaxLifetimePosition
836           && next_use[high_register] == kMaxLifetimePosition) {
837         break;
838       }
839     } else if (next_use[reg] <= starting_at || next_use[existing_high_register] <= starting_at) {
840       // If one of the current register is known to be unavailable, just unconditionally
841       // try a new one.
842       reg = i;
843     }
844   }
845   return reg;
846 }
847 
FindAvailableRegister(size_t * next_use) const848 int RegisterAllocator::FindAvailableRegister(size_t* next_use) const {
849   int reg = kNoRegister;
850   // Pick the register that is used the last.
851   for (size_t i = 0; i < number_of_registers_; ++i) {
852     if (IsBlocked(i)) continue;
853     if (reg == kNoRegister || next_use[i] > next_use[reg]) {
854       reg = i;
855       if (next_use[i] == kMaxLifetimePosition) break;
856     }
857   }
858   return reg;
859 }
860 
TrySplitNonPairOrUnalignedPairIntervalAt(size_t position,size_t first_register_use,size_t * next_use)861 bool RegisterAllocator::TrySplitNonPairOrUnalignedPairIntervalAt(size_t position,
862                                                                  size_t first_register_use,
863                                                                  size_t* next_use) {
864   for (size_t i = 0, e = active_.Size(); i < e; ++i) {
865     LiveInterval* active = active_.Get(i);
866     DCHECK(active->HasRegister());
867     if (active->IsFixed()) continue;
868     if (active->IsHighInterval()) continue;
869     if (first_register_use > next_use[active->GetRegister()]) continue;
870 
871     // Split the first interval found.
872     if (!active->IsLowInterval() || IsLowOfUnalignedPairInterval(active)) {
873       LiveInterval* split = Split(active, position);
874       active_.DeleteAt(i);
875       if (split != active) {
876         handled_.Add(active);
877       }
878       AddSorted(unhandled_, split);
879       return true;
880     }
881   }
882   return false;
883 }
884 
PotentiallyRemoveOtherHalf(LiveInterval * interval,GrowableArray<LiveInterval * > * intervals,size_t index)885 bool RegisterAllocator::PotentiallyRemoveOtherHalf(LiveInterval* interval,
886                                                    GrowableArray<LiveInterval*>* intervals,
887                                                    size_t index) {
888   if (interval->IsLowInterval()) {
889     DCHECK_EQ(intervals->Get(index), interval->GetHighInterval());
890     intervals->DeleteAt(index);
891     return true;
892   } else if (interval->IsHighInterval()) {
893     DCHECK_GT(index, 0u);
894     DCHECK_EQ(intervals->Get(index - 1), interval->GetLowInterval());
895     intervals->DeleteAt(index - 1);
896     return true;
897   } else {
898     return false;
899   }
900 }
901 
902 // Find the register that is used the last, and spill the interval
903 // that holds it. If the first use of `current` is after that register
904 // we spill `current` instead.
AllocateBlockedReg(LiveInterval * current)905 bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
906   size_t first_register_use = current->FirstRegisterUse();
907   if (first_register_use == kNoLifetime) {
908     AllocateSpillSlotFor(current);
909     return false;
910   }
911 
912   // We use the first use to compare with other intervals. If this interval
913   // is used after any active intervals, we will spill this interval.
914   size_t first_use = current->FirstUseAfter(current->GetStart());
915 
916   // First set all registers as not being used.
917   size_t* next_use = registers_array_;
918   for (size_t i = 0; i < number_of_registers_; ++i) {
919     next_use[i] = kMaxLifetimePosition;
920   }
921 
922   // For each active interval, find the next use of its register after the
923   // start of current.
924   for (size_t i = 0, e = active_.Size(); i < e; ++i) {
925     LiveInterval* active = active_.Get(i);
926     DCHECK(active->HasRegister());
927     if (active->IsFixed()) {
928       next_use[active->GetRegister()] = current->GetStart();
929     } else {
930       size_t use = active->FirstUseAfter(current->GetStart());
931       if (use != kNoLifetime) {
932         next_use[active->GetRegister()] = use;
933       }
934     }
935   }
936 
937   // For each inactive interval, find the next use of its register after the
938   // start of current.
939   for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
940     LiveInterval* inactive = inactive_.Get(i);
941     // Temp/Slow-path-safepoint interval has no holes.
942     DCHECK(!inactive->IsTemp() && !inactive->IsSlowPathSafepoint());
943     if (!current->IsSplit() && !inactive->IsFixed()) {
944       // Neither current nor inactive are fixed.
945       // Thanks to SSA, a non-split interval starting in a hole of an
946       // inactive interval should never intersect with that inactive interval.
947       // Only if it's not fixed though, because fixed intervals don't come from SSA.
948       DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
949       continue;
950     }
951     DCHECK(inactive->HasRegister());
952     size_t next_intersection = inactive->FirstIntersectionWith(current);
953     if (next_intersection != kNoLifetime) {
954       if (inactive->IsFixed()) {
955         next_use[inactive->GetRegister()] =
956             std::min(next_intersection, next_use[inactive->GetRegister()]);
957       } else {
958         size_t use = inactive->FirstUseAfter(current->GetStart());
959         if (use != kNoLifetime) {
960           next_use[inactive->GetRegister()] = std::min(use, next_use[inactive->GetRegister()]);
961         }
962       }
963     }
964   }
965 
966   int reg = kNoRegister;
967   bool should_spill = false;
968   if (current->HasRegister()) {
969     DCHECK(current->IsHighInterval());
970     reg = current->GetRegister();
971     // When allocating the low part, we made sure the high register was available.
972     DCHECK_LT(first_use, next_use[reg]);
973   } else if (current->IsLowInterval()) {
974     reg = FindAvailableRegisterPair(next_use, first_register_use);
975     // We should spill if both registers are not available.
976     should_spill = (first_use >= next_use[reg])
977       || (first_use >= next_use[GetHighForLowRegister(reg)]);
978   } else {
979     DCHECK(!current->IsHighInterval());
980     reg = FindAvailableRegister(next_use);
981     should_spill = (first_use >= next_use[reg]);
982   }
983 
984   DCHECK_NE(reg, kNoRegister);
985   if (should_spill) {
986     DCHECK(!current->IsHighInterval());
987     bool is_allocation_at_use_site = (current->GetStart() >= (first_register_use - 1));
988     if (current->IsLowInterval()
989         && is_allocation_at_use_site
990         && TrySplitNonPairOrUnalignedPairIntervalAt(current->GetStart(),
991                                                     first_register_use,
992                                                     next_use)) {
993       // If we're allocating a register for `current` because the instruction at
994       // that position requires it, but we think we should spill, then there are
995       // non-pair intervals or unaligned pair intervals blocking the allocation.
996       // We split the first interval found, and put ourselves first in the
997       // `unhandled_` list.
998       LiveInterval* existing = unhandled_->Peek();
999       DCHECK(existing->IsHighInterval());
1000       DCHECK_EQ(existing->GetLowInterval(), current);
1001       unhandled_->Add(current);
1002     } else {
1003       // If the first use of that instruction is after the last use of the found
1004       // register, we split this interval just before its first register use.
1005       AllocateSpillSlotFor(current);
1006       LiveInterval* split = SplitBetween(current, current->GetStart(), first_register_use - 1);
1007       if (current == split) {
1008         DumpInterval(std::cerr, current);
1009         DumpAllIntervals(std::cerr);
1010         // This situation has the potential to infinite loop, so we make it a non-debug CHECK.
1011         HInstruction* at = liveness_.GetInstructionFromPosition(first_register_use / 2);
1012         CHECK(false) << "There is not enough registers available for "
1013           << split->GetParent()->GetDefinedBy()->DebugName() << " "
1014           << split->GetParent()->GetDefinedBy()->GetId()
1015           << " at " << first_register_use - 1 << " "
1016           << (at == nullptr ? "" : at->DebugName());
1017       }
1018       AddSorted(unhandled_, split);
1019     }
1020     return false;
1021   } else {
1022     // Use this register and spill the active and inactives interval that
1023     // have that register.
1024     current->SetRegister(reg);
1025 
1026     for (size_t i = 0, e = active_.Size(); i < e; ++i) {
1027       LiveInterval* active = active_.Get(i);
1028       if (active->GetRegister() == reg) {
1029         DCHECK(!active->IsFixed());
1030         LiveInterval* split = Split(active, current->GetStart());
1031         if (split != active) {
1032           handled_.Add(active);
1033         }
1034         active_.DeleteAt(i);
1035         PotentiallyRemoveOtherHalf(active, &active_, i);
1036         AddSorted(unhandled_, split);
1037         break;
1038       }
1039     }
1040 
1041     for (size_t i = 0; i < inactive_.Size(); ++i) {
1042       LiveInterval* inactive = inactive_.Get(i);
1043       if (inactive->GetRegister() == reg) {
1044         if (!current->IsSplit() && !inactive->IsFixed()) {
1045           // Neither current nor inactive are fixed.
1046           // Thanks to SSA, a non-split interval starting in a hole of an
1047           // inactive interval should never intersect with that inactive interval.
1048           // Only if it's not fixed though, because fixed intervals don't come from SSA.
1049           DCHECK_EQ(inactive->FirstIntersectionWith(current), kNoLifetime);
1050           continue;
1051         }
1052         size_t next_intersection = inactive->FirstIntersectionWith(current);
1053         if (next_intersection != kNoLifetime) {
1054           if (inactive->IsFixed()) {
1055             LiveInterval* split = Split(current, next_intersection);
1056             DCHECK_NE(split, current);
1057             AddSorted(unhandled_, split);
1058           } else {
1059             // Split at the start of `current`, which will lead to splitting
1060             // at the end of the lifetime hole of `inactive`.
1061             LiveInterval* split = Split(inactive, current->GetStart());
1062             // If it's inactive, it must start before the current interval.
1063             DCHECK_NE(split, inactive);
1064             inactive_.DeleteAt(i);
1065             if (PotentiallyRemoveOtherHalf(inactive, &inactive_, i) && inactive->IsHighInterval()) {
1066               // We have removed an entry prior to `inactive`. So we need to decrement.
1067               --i;
1068             }
1069             // Decrement because we have removed `inactive` from the list.
1070             --i;
1071             handled_.Add(inactive);
1072             AddSorted(unhandled_, split);
1073           }
1074         }
1075       }
1076     }
1077 
1078     return true;
1079   }
1080 }
1081 
AddSorted(GrowableArray<LiveInterval * > * array,LiveInterval * interval)1082 void RegisterAllocator::AddSorted(GrowableArray<LiveInterval*>* array, LiveInterval* interval) {
1083   DCHECK(!interval->IsFixed() && !interval->HasSpillSlot());
1084   size_t insert_at = 0;
1085   for (size_t i = array->Size(); i > 0; --i) {
1086     LiveInterval* current = array->Get(i - 1);
1087     // High intervals must be processed right after their low equivalent.
1088     if (current->StartsAfter(interval) && !current->IsHighInterval()) {
1089       insert_at = i;
1090       break;
1091     } else if ((current->GetStart() == interval->GetStart()) && current->IsSlowPathSafepoint()) {
1092       // Ensure the slow path interval is the last to be processed at its location: we want the
1093       // interval to know all live registers at this location.
1094       DCHECK(i == 1 || array->Get(i - 2)->StartsAfter(current));
1095       insert_at = i;
1096       break;
1097     }
1098   }
1099 
1100   array->InsertAt(insert_at, interval);
1101   // Insert the high interval before the low, to ensure the low is processed before.
1102   if (interval->HasHighInterval()) {
1103     array->InsertAt(insert_at, interval->GetHighInterval());
1104   } else if (interval->HasLowInterval()) {
1105     array->InsertAt(insert_at + 1, interval->GetLowInterval());
1106   }
1107 }
1108 
SplitBetween(LiveInterval * interval,size_t from,size_t to)1109 LiveInterval* RegisterAllocator::SplitBetween(LiveInterval* interval, size_t from, size_t to) {
1110   HBasicBlock* block_from = liveness_.GetBlockFromPosition(from / 2);
1111   HBasicBlock* block_to = liveness_.GetBlockFromPosition(to / 2);
1112   DCHECK(block_from != nullptr);
1113   DCHECK(block_to != nullptr);
1114 
1115   // Both locations are in the same block. We split at the given location.
1116   if (block_from == block_to) {
1117     return Split(interval, to);
1118   }
1119 
1120   /*
1121    * Non-linear control flow will force moves at every branch instruction to the new location.
1122    * To avoid having all branches doing the moves, we find the next non-linear position and
1123    * split the interval at this position. Take the following example (block number is the linear
1124    * order position):
1125    *
1126    *     B1
1127    *    /  \
1128    *   B2  B3
1129    *    \  /
1130    *     B4
1131    *
1132    * B2 needs to split an interval, whose next use is in B4. If we were to split at the
1133    * beginning of B4, B3 would need to do a move between B3 and B4 to ensure the interval
1134    * is now in the correct location. It makes performance worst if the interval is spilled
1135    * and both B2 and B3 need to reload it before entering B4.
1136    *
1137    * By splitting at B3, we give a chance to the register allocator to allocate the
1138    * interval to the same register as in B1, and therefore avoid doing any
1139    * moves in B3.
1140    */
1141   if (block_from->GetDominator() != nullptr) {
1142     const GrowableArray<HBasicBlock*>& dominated = block_from->GetDominator()->GetDominatedBlocks();
1143     for (size_t i = 0; i < dominated.Size(); ++i) {
1144       size_t position = dominated.Get(i)->GetLifetimeStart();
1145       if ((position > from) && (block_to->GetLifetimeStart() > position)) {
1146         // Even if we found a better block, we continue iterating in case
1147         // a dominated block is closer.
1148         // Note that dominated blocks are not sorted in liveness order.
1149         block_to = dominated.Get(i);
1150         DCHECK_NE(block_to, block_from);
1151       }
1152     }
1153   }
1154 
1155   // If `to` is in a loop, find the outermost loop header which does not contain `from`.
1156   for (HLoopInformationOutwardIterator it(*block_to); !it.Done(); it.Advance()) {
1157     HBasicBlock* header = it.Current()->GetHeader();
1158     if (block_from->GetLifetimeStart() >= header->GetLifetimeStart()) {
1159       break;
1160     }
1161     block_to = header;
1162   }
1163 
1164   // Split at the start of the found block, to piggy back on existing moves
1165   // due to resolution if non-linear control flow (see `ConnectSplitSiblings`).
1166   return Split(interval, block_to->GetLifetimeStart());
1167 }
1168 
Split(LiveInterval * interval,size_t position)1169 LiveInterval* RegisterAllocator::Split(LiveInterval* interval, size_t position) {
1170   DCHECK_GE(position, interval->GetStart());
1171   DCHECK(!interval->IsDeadAt(position));
1172   if (position == interval->GetStart()) {
1173     // Spill slot will be allocated when handling `interval` again.
1174     interval->ClearRegister();
1175     if (interval->HasHighInterval()) {
1176       interval->GetHighInterval()->ClearRegister();
1177     } else if (interval->HasLowInterval()) {
1178       interval->GetLowInterval()->ClearRegister();
1179     }
1180     return interval;
1181   } else {
1182     LiveInterval* new_interval = interval->SplitAt(position);
1183     if (interval->HasHighInterval()) {
1184       LiveInterval* high = interval->GetHighInterval()->SplitAt(position);
1185       new_interval->SetHighInterval(high);
1186       high->SetLowInterval(new_interval);
1187     } else if (interval->HasLowInterval()) {
1188       LiveInterval* low = interval->GetLowInterval()->SplitAt(position);
1189       new_interval->SetLowInterval(low);
1190       low->SetHighInterval(new_interval);
1191     }
1192     return new_interval;
1193   }
1194 }
1195 
AllocateSpillSlotFor(LiveInterval * interval)1196 void RegisterAllocator::AllocateSpillSlotFor(LiveInterval* interval) {
1197   if (interval->IsHighInterval()) {
1198     // The low interval will contain the spill slot.
1199     return;
1200   }
1201 
1202   LiveInterval* parent = interval->GetParent();
1203 
1204   // An instruction gets a spill slot for its entire lifetime. If the parent
1205   // of this interval already has a spill slot, there is nothing to do.
1206   if (parent->HasSpillSlot()) {
1207     return;
1208   }
1209 
1210   HInstruction* defined_by = parent->GetDefinedBy();
1211   if (defined_by->IsParameterValue()) {
1212     // Parameters have their own stack slot.
1213     parent->SetSpillSlot(codegen_->GetStackSlotOfParameter(defined_by->AsParameterValue()));
1214     return;
1215   }
1216 
1217   if (defined_by->IsConstant()) {
1218     // Constants don't need a spill slot.
1219     return;
1220   }
1221 
1222   LiveInterval* last_sibling = interval;
1223   while (last_sibling->GetNextSibling() != nullptr) {
1224     last_sibling = last_sibling->GetNextSibling();
1225   }
1226   size_t end = last_sibling->GetEnd();
1227 
1228   GrowableArray<size_t>* spill_slots = nullptr;
1229   switch (interval->GetType()) {
1230     case Primitive::kPrimDouble:
1231       spill_slots = &double_spill_slots_;
1232       break;
1233     case Primitive::kPrimLong:
1234       spill_slots = &long_spill_slots_;
1235       break;
1236     case Primitive::kPrimFloat:
1237       spill_slots = &float_spill_slots_;
1238       break;
1239     case Primitive::kPrimNot:
1240     case Primitive::kPrimInt:
1241     case Primitive::kPrimChar:
1242     case Primitive::kPrimByte:
1243     case Primitive::kPrimBoolean:
1244     case Primitive::kPrimShort:
1245       spill_slots = &int_spill_slots_;
1246       break;
1247     case Primitive::kPrimVoid:
1248       LOG(FATAL) << "Unexpected type for interval " << interval->GetType();
1249   }
1250 
1251   // Find an available spill slot.
1252   size_t slot = 0;
1253   for (size_t e = spill_slots->Size(); slot < e; ++slot) {
1254     if (spill_slots->Get(slot) <= parent->GetStart()
1255         && (slot == (e - 1) || spill_slots->Get(slot + 1) <= parent->GetStart())) {
1256       break;
1257     }
1258   }
1259 
1260   if (parent->NeedsTwoSpillSlots()) {
1261     if (slot == spill_slots->Size()) {
1262       // We need a new spill slot.
1263       spill_slots->Add(end);
1264       spill_slots->Add(end);
1265     } else if (slot == spill_slots->Size() - 1) {
1266       spill_slots->Put(slot, end);
1267       spill_slots->Add(end);
1268     } else {
1269       spill_slots->Put(slot, end);
1270       spill_slots->Put(slot + 1, end);
1271     }
1272   } else {
1273     if (slot == spill_slots->Size()) {
1274       // We need a new spill slot.
1275       spill_slots->Add(end);
1276     } else {
1277       spill_slots->Put(slot, end);
1278     }
1279   }
1280 
1281   // Note that the exact spill slot location will be computed when we resolve,
1282   // that is when we know the number of spill slots for each type.
1283   parent->SetSpillSlot(slot);
1284 }
1285 
IsValidDestination(Location destination)1286 static bool IsValidDestination(Location destination) {
1287   return destination.IsRegister()
1288       || destination.IsRegisterPair()
1289       || destination.IsFpuRegister()
1290       || destination.IsFpuRegisterPair()
1291       || destination.IsStackSlot()
1292       || destination.IsDoubleStackSlot();
1293 }
1294 
AddMove(HParallelMove * move,Location source,Location destination,HInstruction * instruction,Primitive::Type type) const1295 void RegisterAllocator::AddMove(HParallelMove* move,
1296                                 Location source,
1297                                 Location destination,
1298                                 HInstruction* instruction,
1299                                 Primitive::Type type) const {
1300   if (type == Primitive::kPrimLong
1301       && codegen_->ShouldSplitLongMoves()
1302       // The parallel move resolver knows how to deal with long constants.
1303       && !source.IsConstant()) {
1304     move->AddMove(source.ToLow(), destination.ToLow(), Primitive::kPrimInt, instruction);
1305     move->AddMove(source.ToHigh(), destination.ToHigh(), Primitive::kPrimInt, nullptr);
1306   } else {
1307     move->AddMove(source, destination, type, instruction);
1308   }
1309 }
1310 
AddInputMoveFor(HInstruction * input,HInstruction * user,Location source,Location destination) const1311 void RegisterAllocator::AddInputMoveFor(HInstruction* input,
1312                                         HInstruction* user,
1313                                         Location source,
1314                                         Location destination) const {
1315   if (source.Equals(destination)) return;
1316 
1317   DCHECK(!user->IsPhi());
1318 
1319   HInstruction* previous = user->GetPrevious();
1320   HParallelMove* move = nullptr;
1321   if (previous == nullptr
1322       || !previous->IsParallelMove()
1323       || previous->GetLifetimePosition() < user->GetLifetimePosition()) {
1324     move = new (allocator_) HParallelMove(allocator_);
1325     move->SetLifetimePosition(user->GetLifetimePosition());
1326     user->GetBlock()->InsertInstructionBefore(move, user);
1327   } else {
1328     move = previous->AsParallelMove();
1329   }
1330   DCHECK_EQ(move->GetLifetimePosition(), user->GetLifetimePosition());
1331   AddMove(move, source, destination, nullptr, input->GetType());
1332 }
1333 
IsInstructionStart(size_t position)1334 static bool IsInstructionStart(size_t position) {
1335   return (position & 1) == 0;
1336 }
1337 
IsInstructionEnd(size_t position)1338 static bool IsInstructionEnd(size_t position) {
1339   return (position & 1) == 1;
1340 }
1341 
InsertParallelMoveAt(size_t position,HInstruction * instruction,Location source,Location destination) const1342 void RegisterAllocator::InsertParallelMoveAt(size_t position,
1343                                              HInstruction* instruction,
1344                                              Location source,
1345                                              Location destination) const {
1346   DCHECK(IsValidDestination(destination)) << destination;
1347   if (source.Equals(destination)) return;
1348 
1349   HInstruction* at = liveness_.GetInstructionFromPosition(position / 2);
1350   HParallelMove* move;
1351   if (at == nullptr) {
1352     if (IsInstructionStart(position)) {
1353       // Block boundary, don't do anything the connection of split siblings will handle it.
1354       return;
1355     } else {
1356       // Move must happen before the first instruction of the block.
1357       at = liveness_.GetInstructionFromPosition((position + 1) / 2);
1358       // Note that parallel moves may have already been inserted, so we explicitly
1359       // ask for the first instruction of the block: `GetInstructionFromPosition` does
1360       // not contain the `HParallelMove` instructions.
1361       at = at->GetBlock()->GetFirstInstruction();
1362 
1363       if (at->GetLifetimePosition() < position) {
1364         // We may insert moves for split siblings and phi spills at the beginning of the block.
1365         // Since this is a different lifetime position, we need to go to the next instruction.
1366         DCHECK(at->IsParallelMove());
1367         at = at->GetNext();
1368       }
1369 
1370       if (at->GetLifetimePosition() != position) {
1371         DCHECK_GT(at->GetLifetimePosition(), position);
1372         move = new (allocator_) HParallelMove(allocator_);
1373         move->SetLifetimePosition(position);
1374         at->GetBlock()->InsertInstructionBefore(move, at);
1375       } else {
1376         DCHECK(at->IsParallelMove());
1377         move = at->AsParallelMove();
1378       }
1379     }
1380   } else if (IsInstructionEnd(position)) {
1381     // Move must happen after the instruction.
1382     DCHECK(!at->IsControlFlow());
1383     move = at->GetNext()->AsParallelMove();
1384     // This is a parallel move for connecting siblings in a same block. We need to
1385     // differentiate it with moves for connecting blocks, and input moves.
1386     if (move == nullptr || move->GetLifetimePosition() > position) {
1387       move = new (allocator_) HParallelMove(allocator_);
1388       move->SetLifetimePosition(position);
1389       at->GetBlock()->InsertInstructionBefore(move, at->GetNext());
1390     }
1391   } else {
1392     // Move must happen before the instruction.
1393     HInstruction* previous = at->GetPrevious();
1394     if (previous == nullptr
1395         || !previous->IsParallelMove()
1396         || previous->GetLifetimePosition() != position) {
1397       // If the previous is a parallel move, then its position must be lower
1398       // than the given `position`: it was added just after the non-parallel
1399       // move instruction that precedes `instruction`.
1400       DCHECK(previous == nullptr
1401              || !previous->IsParallelMove()
1402              || previous->GetLifetimePosition() < position);
1403       move = new (allocator_) HParallelMove(allocator_);
1404       move->SetLifetimePosition(position);
1405       at->GetBlock()->InsertInstructionBefore(move, at);
1406     } else {
1407       move = previous->AsParallelMove();
1408     }
1409   }
1410   DCHECK_EQ(move->GetLifetimePosition(), position);
1411   AddMove(move, source, destination, instruction, instruction->GetType());
1412 }
1413 
InsertParallelMoveAtExitOf(HBasicBlock * block,HInstruction * instruction,Location source,Location destination) const1414 void RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block,
1415                                                    HInstruction* instruction,
1416                                                    Location source,
1417                                                    Location destination) const {
1418   DCHECK(IsValidDestination(destination)) << destination;
1419   if (source.Equals(destination)) return;
1420 
1421   DCHECK_EQ(block->GetSuccessors().Size(), 1u);
1422   HInstruction* last = block->GetLastInstruction();
1423   // We insert moves at exit for phi predecessors and connecting blocks.
1424   // A block ending with an if cannot branch to a block with phis because
1425   // we do not allow critical edges. It can also not connect
1426   // a split interval between two blocks: the move has to happen in the successor.
1427   DCHECK(!last->IsIf());
1428   HInstruction* previous = last->GetPrevious();
1429   HParallelMove* move;
1430   // This is a parallel move for connecting blocks. We need to differentiate
1431   // it with moves for connecting siblings in a same block, and output moves.
1432   size_t position = last->GetLifetimePosition();
1433   if (previous == nullptr || !previous->IsParallelMove()
1434       || previous->AsParallelMove()->GetLifetimePosition() != position) {
1435     move = new (allocator_) HParallelMove(allocator_);
1436     move->SetLifetimePosition(position);
1437     block->InsertInstructionBefore(move, last);
1438   } else {
1439     move = previous->AsParallelMove();
1440   }
1441   AddMove(move, source, destination, instruction, instruction->GetType());
1442 }
1443 
InsertParallelMoveAtEntryOf(HBasicBlock * block,HInstruction * instruction,Location source,Location destination) const1444 void RegisterAllocator::InsertParallelMoveAtEntryOf(HBasicBlock* block,
1445                                                     HInstruction* instruction,
1446                                                     Location source,
1447                                                     Location destination) const {
1448   DCHECK(IsValidDestination(destination)) << destination;
1449   if (source.Equals(destination)) return;
1450 
1451   HInstruction* first = block->GetFirstInstruction();
1452   HParallelMove* move = first->AsParallelMove();
1453   size_t position = block->GetLifetimeStart();
1454   // This is a parallel move for connecting blocks. We need to differentiate
1455   // it with moves for connecting siblings in a same block, and input moves.
1456   if (move == nullptr || move->GetLifetimePosition() != position) {
1457     move = new (allocator_) HParallelMove(allocator_);
1458     move->SetLifetimePosition(position);
1459     block->InsertInstructionBefore(move, first);
1460   }
1461   AddMove(move, source, destination, instruction, instruction->GetType());
1462 }
1463 
InsertMoveAfter(HInstruction * instruction,Location source,Location destination) const1464 void RegisterAllocator::InsertMoveAfter(HInstruction* instruction,
1465                                         Location source,
1466                                         Location destination) const {
1467   DCHECK(IsValidDestination(destination)) << destination;
1468   if (source.Equals(destination)) return;
1469 
1470   if (instruction->IsPhi()) {
1471     InsertParallelMoveAtEntryOf(instruction->GetBlock(), instruction, source, destination);
1472     return;
1473   }
1474 
1475   size_t position = instruction->GetLifetimePosition() + 1;
1476   HParallelMove* move = instruction->GetNext()->AsParallelMove();
1477   // This is a parallel move for moving the output of an instruction. We need
1478   // to differentiate with input moves, moves for connecting siblings in a
1479   // and moves for connecting blocks.
1480   if (move == nullptr || move->GetLifetimePosition() != position) {
1481     move = new (allocator_) HParallelMove(allocator_);
1482     move->SetLifetimePosition(position);
1483     instruction->GetBlock()->InsertInstructionBefore(move, instruction->GetNext());
1484   }
1485   AddMove(move, source, destination, instruction, instruction->GetType());
1486 }
1487 
ConnectSiblings(LiveInterval * interval)1488 void RegisterAllocator::ConnectSiblings(LiveInterval* interval) {
1489   LiveInterval* current = interval;
1490   if (current->HasSpillSlot() && current->HasRegister()) {
1491     // We spill eagerly, so move must be at definition.
1492     InsertMoveAfter(interval->GetDefinedBy(),
1493                     interval->ToLocation(),
1494                     interval->NeedsTwoSpillSlots()
1495                         ? Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot())
1496                         : Location::StackSlot(interval->GetParent()->GetSpillSlot()));
1497   }
1498   UsePosition* use = current->GetFirstUse();
1499   UsePosition* env_use = current->GetFirstEnvironmentUse();
1500 
1501   // Walk over all siblings, updating locations of use positions, and
1502   // connecting them when they are adjacent.
1503   do {
1504     Location source = current->ToLocation();
1505 
1506     // Walk over all uses covered by this interval, and update the location
1507     // information.
1508 
1509     LiveRange* range = current->GetFirstRange();
1510     while (range != nullptr) {
1511       while (use != nullptr && use->GetPosition() < range->GetStart()) {
1512         DCHECK(use->IsSynthesized());
1513         use = use->GetNext();
1514       }
1515       while (use != nullptr && use->GetPosition() <= range->GetEnd()) {
1516         DCHECK(!use->GetIsEnvironment());
1517         DCHECK(current->CoversSlow(use->GetPosition()) || (use->GetPosition() == range->GetEnd()));
1518         if (!use->IsSynthesized()) {
1519           LocationSummary* locations = use->GetUser()->GetLocations();
1520           Location expected_location = locations->InAt(use->GetInputIndex());
1521           // The expected (actual) location may be invalid in case the input is unused. Currently
1522           // this only happens for intrinsics.
1523           if (expected_location.IsValid()) {
1524             if (expected_location.IsUnallocated()) {
1525               locations->SetInAt(use->GetInputIndex(), source);
1526             } else if (!expected_location.IsConstant()) {
1527               AddInputMoveFor(interval->GetDefinedBy(), use->GetUser(), source, expected_location);
1528             }
1529           } else {
1530             DCHECK(use->GetUser()->IsInvoke());
1531             DCHECK(use->GetUser()->AsInvoke()->GetIntrinsic() != Intrinsics::kNone);
1532           }
1533         }
1534         use = use->GetNext();
1535       }
1536 
1537       // Walk over the environment uses, and update their locations.
1538       while (env_use != nullptr && env_use->GetPosition() < range->GetStart()) {
1539         env_use = env_use->GetNext();
1540       }
1541 
1542       while (env_use != nullptr && env_use->GetPosition() <= range->GetEnd()) {
1543         DCHECK(current->CoversSlow(env_use->GetPosition())
1544                || (env_use->GetPosition() == range->GetEnd()));
1545         HEnvironment* environment = env_use->GetUser()->GetEnvironment();
1546         environment->SetLocationAt(env_use->GetInputIndex(), source);
1547         env_use = env_use->GetNext();
1548       }
1549 
1550       range = range->GetNext();
1551     }
1552 
1553     // If the next interval starts just after this one, and has a register,
1554     // insert a move.
1555     LiveInterval* next_sibling = current->GetNextSibling();
1556     if (next_sibling != nullptr
1557         && next_sibling->HasRegister()
1558         && current->GetEnd() == next_sibling->GetStart()) {
1559       Location destination = next_sibling->ToLocation();
1560       InsertParallelMoveAt(current->GetEnd(), interval->GetDefinedBy(), source, destination);
1561     }
1562 
1563     for (SafepointPosition* safepoint_position = current->GetFirstSafepoint();
1564          safepoint_position != nullptr;
1565          safepoint_position = safepoint_position->GetNext()) {
1566       DCHECK(current->CoversSlow(safepoint_position->GetPosition()));
1567 
1568       LocationSummary* locations = safepoint_position->GetLocations();
1569       if ((current->GetType() == Primitive::kPrimNot) && current->GetParent()->HasSpillSlot()) {
1570         locations->SetStackBit(current->GetParent()->GetSpillSlot() / kVRegSize);
1571       }
1572 
1573       switch (source.GetKind()) {
1574         case Location::kRegister: {
1575           locations->AddLiveRegister(source);
1576           if (kIsDebugBuild && locations->OnlyCallsOnSlowPath()) {
1577             DCHECK_LE(locations->GetNumberOfLiveRegisters(),
1578                       maximum_number_of_live_core_registers_ +
1579                       maximum_number_of_live_fp_registers_);
1580           }
1581           if (current->GetType() == Primitive::kPrimNot) {
1582             locations->SetRegisterBit(source.reg());
1583           }
1584           break;
1585         }
1586         case Location::kFpuRegister: {
1587           locations->AddLiveRegister(source);
1588           break;
1589         }
1590 
1591         case Location::kRegisterPair:
1592         case Location::kFpuRegisterPair: {
1593           locations->AddLiveRegister(source.ToLow());
1594           locations->AddLiveRegister(source.ToHigh());
1595           break;
1596         }
1597         case Location::kStackSlot:  // Fall-through
1598         case Location::kDoubleStackSlot:  // Fall-through
1599         case Location::kConstant: {
1600           // Nothing to do.
1601           break;
1602         }
1603         default: {
1604           LOG(FATAL) << "Unexpected location for object";
1605         }
1606       }
1607     }
1608     current = next_sibling;
1609   } while (current != nullptr);
1610 
1611   if (kIsDebugBuild) {
1612     // Following uses can only be synthesized uses.
1613     while (use != nullptr) {
1614       DCHECK(use->IsSynthesized());
1615       use = use->GetNext();
1616     }
1617   }
1618 }
1619 
ConnectSplitSiblings(LiveInterval * interval,HBasicBlock * from,HBasicBlock * to) const1620 void RegisterAllocator::ConnectSplitSiblings(LiveInterval* interval,
1621                                              HBasicBlock* from,
1622                                              HBasicBlock* to) const {
1623   if (interval->GetNextSibling() == nullptr) {
1624     // Nothing to connect. The whole range was allocated to the same location.
1625     return;
1626   }
1627 
1628   // Find the intervals that cover `from` and `to`.
1629   LiveInterval* destination = interval->GetSiblingAt(to->GetLifetimeStart());
1630   LiveInterval* source = interval->GetSiblingAt(from->GetLifetimeEnd() - 1);
1631 
1632   if (destination == source) {
1633     // Interval was not split.
1634     return;
1635   }
1636   DCHECK(destination != nullptr && source != nullptr);
1637 
1638   if (!destination->HasRegister()) {
1639     // Values are eagerly spilled. Spill slot already contains appropriate value.
1640     return;
1641   }
1642 
1643   // If `from` has only one successor, we can put the moves at the exit of it. Otherwise
1644   // we need to put the moves at the entry of `to`.
1645   if (from->GetSuccessors().Size() == 1) {
1646     InsertParallelMoveAtExitOf(from,
1647                                interval->GetParent()->GetDefinedBy(),
1648                                source->ToLocation(),
1649                                destination->ToLocation());
1650   } else {
1651     DCHECK_EQ(to->GetPredecessors().Size(), 1u);
1652     InsertParallelMoveAtEntryOf(to,
1653                                 interval->GetParent()->GetDefinedBy(),
1654                                 source->ToLocation(),
1655                                 destination->ToLocation());
1656   }
1657 }
1658 
Resolve()1659 void RegisterAllocator::Resolve() {
1660   codegen_->InitializeCodeGeneration(GetNumberOfSpillSlots(),
1661                                      maximum_number_of_live_core_registers_,
1662                                      maximum_number_of_live_fp_registers_,
1663                                      reserved_out_slots_,
1664                                      codegen_->GetGraph()->GetLinearOrder());
1665 
1666   // Adjust the Out Location of instructions.
1667   // TODO: Use pointers of Location inside LiveInterval to avoid doing another iteration.
1668   for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) {
1669     HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
1670     LiveInterval* current = instruction->GetLiveInterval();
1671     LocationSummary* locations = instruction->GetLocations();
1672     Location location = locations->Out();
1673     if (instruction->IsParameterValue()) {
1674       // Now that we know the frame size, adjust the parameter's location.
1675       if (location.IsStackSlot()) {
1676         location = Location::StackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
1677         current->SetSpillSlot(location.GetStackIndex());
1678         locations->UpdateOut(location);
1679       } else if (location.IsDoubleStackSlot()) {
1680         location = Location::DoubleStackSlot(location.GetStackIndex() + codegen_->GetFrameSize());
1681         current->SetSpillSlot(location.GetStackIndex());
1682         locations->UpdateOut(location);
1683       } else if (current->HasSpillSlot()) {
1684         current->SetSpillSlot(current->GetSpillSlot() + codegen_->GetFrameSize());
1685       }
1686     } else if (current->HasSpillSlot()) {
1687       // Adjust the stack slot, now that we know the number of them for each type.
1688       // The way this implementation lays out the stack is the following:
1689       // [parameter slots     ]
1690       // [double spill slots  ]
1691       // [long spill slots    ]
1692       // [float spill slots   ]
1693       // [int/ref values      ]
1694       // [maximum out values  ] (number of arguments for calls)
1695       // [art method          ].
1696       uint32_t slot = current->GetSpillSlot();
1697       switch (current->GetType()) {
1698         case Primitive::kPrimDouble:
1699           slot += long_spill_slots_.Size();
1700           FALLTHROUGH_INTENDED;
1701         case Primitive::kPrimLong:
1702           slot += float_spill_slots_.Size();
1703           FALLTHROUGH_INTENDED;
1704         case Primitive::kPrimFloat:
1705           slot += int_spill_slots_.Size();
1706           FALLTHROUGH_INTENDED;
1707         case Primitive::kPrimNot:
1708         case Primitive::kPrimInt:
1709         case Primitive::kPrimChar:
1710         case Primitive::kPrimByte:
1711         case Primitive::kPrimBoolean:
1712         case Primitive::kPrimShort:
1713           slot += reserved_out_slots_;
1714           break;
1715         case Primitive::kPrimVoid:
1716           LOG(FATAL) << "Unexpected type for interval " << current->GetType();
1717       }
1718       current->SetSpillSlot(slot * kVRegSize);
1719     }
1720 
1721     Location source = current->ToLocation();
1722 
1723     if (location.IsUnallocated()) {
1724       if (location.GetPolicy() == Location::kSameAsFirstInput) {
1725         if (locations->InAt(0).IsUnallocated()) {
1726           locations->SetInAt(0, source);
1727         } else {
1728           DCHECK(locations->InAt(0).Equals(source));
1729         }
1730       }
1731       locations->UpdateOut(source);
1732     } else {
1733       DCHECK(source.Equals(location));
1734     }
1735   }
1736 
1737   // Connect siblings.
1738   for (size_t i = 0, e = liveness_.GetNumberOfSsaValues(); i < e; ++i) {
1739     HInstruction* instruction = liveness_.GetInstructionFromSsaIndex(i);
1740     ConnectSiblings(instruction->GetLiveInterval());
1741   }
1742 
1743   // Resolve non-linear control flow across branches. Order does not matter.
1744   for (HLinearOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
1745     HBasicBlock* block = it.Current();
1746     BitVector* live = liveness_.GetLiveInSet(*block);
1747     for (uint32_t idx : live->Indexes()) {
1748       HInstruction* current = liveness_.GetInstructionFromSsaIndex(idx);
1749       LiveInterval* interval = current->GetLiveInterval();
1750       for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
1751         ConnectSplitSiblings(interval, block->GetPredecessors().Get(i), block);
1752       }
1753     }
1754   }
1755 
1756   // Resolve phi inputs. Order does not matter.
1757   for (HLinearOrderIterator it(*codegen_->GetGraph()); !it.Done(); it.Advance()) {
1758     HBasicBlock* current = it.Current();
1759     for (HInstructionIterator inst_it(current->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
1760       HInstruction* phi = inst_it.Current();
1761       for (size_t i = 0, e = current->GetPredecessors().Size(); i < e; ++i) {
1762         HBasicBlock* predecessor = current->GetPredecessors().Get(i);
1763         DCHECK_EQ(predecessor->GetSuccessors().Size(), 1u);
1764         HInstruction* input = phi->InputAt(i);
1765         Location source = input->GetLiveInterval()->GetLocationAt(
1766             predecessor->GetLifetimeEnd() - 1);
1767         Location destination = phi->GetLiveInterval()->ToLocation();
1768         InsertParallelMoveAtExitOf(predecessor, phi, source, destination);
1769       }
1770     }
1771   }
1772 
1773   // Assign temp locations.
1774   for (size_t i = 0; i < temp_intervals_.Size(); ++i) {
1775     LiveInterval* temp = temp_intervals_.Get(i);
1776     if (temp->IsHighInterval()) {
1777       // High intervals can be skipped, they are already handled by the low interval.
1778       continue;
1779     }
1780     HInstruction* at = liveness_.GetTempUser(temp);
1781     size_t temp_index = liveness_.GetTempIndex(temp);
1782     LocationSummary* locations = at->GetLocations();
1783     switch (temp->GetType()) {
1784       case Primitive::kPrimInt:
1785         locations->SetTempAt(temp_index, Location::RegisterLocation(temp->GetRegister()));
1786         break;
1787 
1788       case Primitive::kPrimDouble:
1789         if (codegen_->NeedsTwoRegisters(Primitive::kPrimDouble)) {
1790           Location location = Location::FpuRegisterPairLocation(
1791               temp->GetRegister(), temp->GetHighInterval()->GetRegister());
1792           locations->SetTempAt(temp_index, location);
1793         } else {
1794           locations->SetTempAt(temp_index, Location::FpuRegisterLocation(temp->GetRegister()));
1795         }
1796         break;
1797 
1798       default:
1799         LOG(FATAL) << "Unexpected type for temporary location "
1800                    << temp->GetType();
1801     }
1802   }
1803 }
1804 
1805 }  // namespace art
1806