register_allocator.cc revision 96f89a290eb67d7bf4b1636798fa28df14309cc7
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
22namespace art {
23
24static constexpr size_t kMaxLifetimePosition = -1;
25static constexpr size_t kDefaultNumberOfSpillSlots = 4;
26
27RegisterAllocator::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
47bool 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
66static 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
72void 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
88void 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.
106void 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
177class AllRangesIterator : public ValueObject {
178 public:
179  explicit AllRangesIterator(LiveInterval* interval)
180      : current_interval_(interval),
181        current_range_(interval->GetFirstRange()) {}
182
183  bool Done() const { return current_interval_ == nullptr; }
184  LiveRange* CurrentRange() const { return current_range_; }
185  LiveInterval* CurrentInterval() const { return current_interval_; }
186
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
204bool 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
226bool 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
294void 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.
310void 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.
366bool 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
421bool 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.
431bool 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
537void 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
549LiveInterval* 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
562static bool NeedTwoSpillSlot(Primitive::Type type) {
563  return type == Primitive::kPrimLong || type == Primitive::kPrimDouble;
564}
565
566void 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
600void 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
629void 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
648static 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.
670static constexpr size_t kInputMoveLifetimePosition = 0;
671static bool IsInputMove(HInstruction* instruction) {
672  return instruction->GetLifetimePosition() == kInputMoveLifetimePosition;
673}
674
675void 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
697void 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
740void 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
762void 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
779void 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
802void 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
848void 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`.
899static 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
908void 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