register_allocator.cc revision 31d76b42ef5165351499da3f8ee0ac147428c5ed
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, const CodeGenerator& codegen)
28      : allocator_(allocator),
29        codegen_(codegen),
30        unhandled_(allocator, 0),
31        handled_(allocator, 0),
32        active_(allocator, 0),
33        inactive_(allocator, 0),
34        spill_slots_(allocator, kDefaultNumberOfSpillSlots),
35        processing_core_registers_(false),
36        number_of_registers_(-1),
37        registers_array_(nullptr),
38        blocked_registers_(allocator->AllocArray<bool>(codegen.GetNumberOfRegisters())) {
39  codegen.SetupBlockedRegisters(blocked_registers_);
40}
41
42static bool ShouldProcess(bool processing_core_registers, HInstruction* instruction) {
43  bool is_core_register = (instruction->GetType() != Primitive::kPrimDouble)
44      && (instruction->GetType() != Primitive::kPrimFloat);
45  return processing_core_registers == is_core_register;
46}
47
48void RegisterAllocator::AllocateRegistersInternal(const SsaLivenessAnalysis& liveness) {
49  number_of_registers_ = processing_core_registers_
50      ? codegen_.GetNumberOfCoreRegisters()
51      : codegen_.GetNumberOfFloatingPointRegisters();
52
53  registers_array_ = allocator_->AllocArray<size_t>(number_of_registers_);
54
55  // Iterate post-order, to ensure the list is sorted, and the last added interval
56  // is the one with the lowest start position.
57  for (size_t i = liveness.GetNumberOfSsaValues(); i > 0; --i) {
58    HInstruction* instruction = liveness.GetInstructionFromSsaIndex(i - 1);
59    if (ShouldProcess(processing_core_registers_, instruction)) {
60      LiveInterval* current = instruction->GetLiveInterval();
61      DCHECK(unhandled_.IsEmpty() || current->StartsBefore(unhandled_.Peek()));
62      unhandled_.Add(current);
63    }
64  }
65
66  LinearScan();
67  if (kIsDebugBuild) {
68    ValidateInternal(liveness, true);
69  }
70}
71
72bool RegisterAllocator::ValidateInternal(const SsaLivenessAnalysis& liveness,
73                                         bool log_fatal_on_failure) const {
74  // To simplify unit testing, we eagerly create the array of intervals, and
75  // call the helper method.
76  GrowableArray<LiveInterval*> intervals(allocator_, 0);
77  for (size_t i = 0; i < liveness.GetNumberOfSsaValues(); ++i) {
78    HInstruction* instruction = liveness.GetInstructionFromSsaIndex(i);
79    if (ShouldProcess(processing_core_registers_, instruction)) {
80      intervals.Add(instruction->GetLiveInterval());
81    }
82  }
83  return ValidateIntervals(intervals, spill_slots_.Size(), codegen_, allocator_,
84                           processing_core_registers_, log_fatal_on_failure);
85}
86
87class AllRangesIterator : public ValueObject {
88 public:
89  explicit AllRangesIterator(LiveInterval* interval)
90      : current_interval_(interval),
91        current_range_(interval->GetFirstRange()) {}
92
93  bool Done() const { return current_interval_ == nullptr; }
94  LiveRange* CurrentRange() const { return current_range_; }
95  LiveInterval* CurrentInterval() const { return current_interval_; }
96
97  void Advance() {
98    current_range_ = current_range_->GetNext();
99    if (current_range_ == nullptr) {
100      current_interval_ = current_interval_->GetNextSibling();
101      if (current_interval_ != nullptr) {
102        current_range_ = current_interval_->GetFirstRange();
103      }
104    }
105  }
106
107 private:
108  LiveInterval* current_interval_;
109  LiveRange* current_range_;
110
111  DISALLOW_COPY_AND_ASSIGN(AllRangesIterator);
112};
113
114bool RegisterAllocator::ValidateIntervals(const GrowableArray<LiveInterval*>& intervals,
115                                          size_t number_of_spill_slots,
116                                          const CodeGenerator& codegen,
117                                          ArenaAllocator* allocator,
118                                          bool processing_core_registers,
119                                          bool log_fatal_on_failure) {
120  size_t number_of_registers = processing_core_registers
121      ? codegen.GetNumberOfCoreRegisters()
122      : codegen.GetNumberOfFloatingPointRegisters();
123  GrowableArray<ArenaBitVector*> liveness_of_values(
124      allocator, number_of_registers + number_of_spill_slots);
125
126  // Allocate a bit vector per register. A live interval that has a register
127  // allocated will populate the associated bit vector based on its live ranges.
128  for (size_t i = 0; i < number_of_registers + number_of_spill_slots; ++i) {
129    liveness_of_values.Add(new (allocator) ArenaBitVector(allocator, 0, true));
130  }
131
132  for (size_t i = 0, e = intervals.Size(); i < e; ++i) {
133    for (AllRangesIterator it(intervals.Get(i)); !it.Done(); it.Advance()) {
134      LiveInterval* current = it.CurrentInterval();
135      if (current->GetParent()->HasSpillSlot()) {
136        BitVector* liveness_of_spill_slot = liveness_of_values.Get(
137            number_of_registers + current->GetParent()->GetSpillSlot() / kVRegSize);
138        for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
139          if (liveness_of_spill_slot->IsBitSet(j)) {
140            if (log_fatal_on_failure) {
141              std::ostringstream message;
142              message << "Spill slot conflict at " << j;
143              LOG(FATAL) << message.str();
144            } else {
145              return false;
146            }
147          } else {
148            liveness_of_spill_slot->SetBit(j);
149          }
150        }
151      }
152
153      if (current->HasRegister()) {
154        BitVector* liveness_of_register = liveness_of_values.Get(current->GetRegister());
155        for (size_t j = it.CurrentRange()->GetStart(); j < it.CurrentRange()->GetEnd(); ++j) {
156          if (liveness_of_register->IsBitSet(j)) {
157            if (log_fatal_on_failure) {
158              std::ostringstream message;
159              message << "Register conflict at " << j << " for ";
160              if (processing_core_registers) {
161                codegen.DumpCoreRegister(message, current->GetRegister());
162              } else {
163                codegen.DumpFloatingPointRegister(message, current->GetRegister());
164              }
165              LOG(FATAL) << message.str();
166            } else {
167              return false;
168            }
169          } else {
170            liveness_of_register->SetBit(j);
171          }
172        }
173      }
174    }
175  }
176  return true;
177}
178
179void RegisterAllocator::DumpInterval(std::ostream& stream, LiveInterval* interval) {
180  interval->Dump(stream);
181  stream << ": ";
182  if (interval->HasRegister()) {
183    if (processing_core_registers_) {
184      codegen_.DumpCoreRegister(stream, interval->GetRegister());
185    } else {
186      codegen_.DumpFloatingPointRegister(stream, interval->GetRegister());
187    }
188  } else {
189    stream << "spilled";
190  }
191  stream << std::endl;
192}
193
194// By the book implementation of a linear scan register allocator.
195void RegisterAllocator::LinearScan() {
196  while (!unhandled_.IsEmpty()) {
197    // (1) Remove interval with the lowest start position from unhandled.
198    LiveInterval* current = unhandled_.Pop();
199    size_t position = current->GetStart();
200
201    // (2) Remove currently active intervals that are dead at this position.
202    //     Move active intervals that have a lifetime hole at this position
203    //     to inactive.
204    for (size_t i = 0; i < active_.Size(); ++i) {
205      LiveInterval* interval = active_.Get(i);
206      if (interval->IsDeadAt(position)) {
207        active_.Delete(interval);
208        --i;
209        handled_.Add(interval);
210      } else if (!interval->Covers(position)) {
211        active_.Delete(interval);
212        --i;
213        inactive_.Add(interval);
214      }
215    }
216
217    // (3) Remove currently inactive intervals that are dead at this position.
218    //     Move inactive intervals that cover this position to active.
219    for (size_t i = 0; i < inactive_.Size(); ++i) {
220      LiveInterval* interval = inactive_.Get(i);
221      if (interval->IsDeadAt(position)) {
222        inactive_.Delete(interval);
223        --i;
224        handled_.Add(interval);
225      } else if (interval->Covers(position)) {
226        inactive_.Delete(interval);
227        --i;
228        active_.Add(interval);
229      }
230    }
231
232    // (4) Try to find an available register.
233    bool success = TryAllocateFreeReg(current);
234
235    // (5) If no register could be found, we need to spill.
236    if (!success) {
237      success = AllocateBlockedReg(current);
238    }
239
240    // (6) If the interval had a register allocated, add it to the list of active
241    //     intervals.
242    if (success) {
243      active_.Add(current);
244    }
245  }
246}
247
248// Find a free register. If multiple are found, pick the register that
249// is free the longest.
250bool RegisterAllocator::TryAllocateFreeReg(LiveInterval* current) {
251  size_t* free_until = registers_array_;
252
253  // First set all registers to be free.
254  for (size_t i = 0; i < number_of_registers_; ++i) {
255    free_until[i] = kMaxLifetimePosition;
256  }
257
258  // For each active interval, set its register to not free.
259  for (size_t i = 0, e = active_.Size(); i < e; ++i) {
260    LiveInterval* interval = active_.Get(i);
261    DCHECK(interval->HasRegister());
262    free_until[interval->GetRegister()] = 0;
263  }
264
265  // For each inactive interval, set its register to be free until
266  // the next intersection with `current`.
267  // Thanks to SSA, this should only be needed for intervals
268  // that are the result of a split.
269  for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
270    LiveInterval* inactive = inactive_.Get(i);
271    DCHECK(inactive->HasRegister());
272    size_t next_intersection = inactive->FirstIntersectionWith(current);
273    if (next_intersection != kNoLifetime) {
274      free_until[inactive->GetRegister()] = next_intersection;
275    }
276  }
277
278  // Pick the register that is free the longest.
279  int reg = -1;
280  for (size_t i = 0; i < number_of_registers_; ++i) {
281    if (IsBlocked(i)) continue;
282    if (reg == -1 || free_until[i] > free_until[reg]) {
283      reg = i;
284      if (free_until[i] == kMaxLifetimePosition) break;
285    }
286  }
287
288  // If we could not find a register, we need to spill.
289  if (reg == -1 || free_until[reg] == 0) {
290    return false;
291  }
292
293  current->SetRegister(reg);
294  if (!current->IsDeadAt(free_until[reg])) {
295    // If the register is only available for a subset of live ranges
296    // covered by `current`, split `current` at the position where
297    // the register is not available anymore.
298    LiveInterval* split = Split(current, free_until[reg]);
299    DCHECK(split != nullptr);
300    AddToUnhandled(split);
301  }
302  return true;
303}
304
305bool RegisterAllocator::IsBlocked(int reg) const {
306  // TODO: This only works for core registers and needs to be adjusted for
307  // floating point registers.
308  DCHECK(processing_core_registers_);
309  return blocked_registers_[reg];
310}
311
312// Find the register that is used the last, and spill the interval
313// that holds it. If the first use of `current` is after that register
314// we spill `current` instead.
315bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) {
316  size_t first_register_use = current->FirstRegisterUse();
317  if (current->FirstRegisterUse() == kNoLifetime) {
318    AllocateSpillSlotFor(current);
319    return false;
320  }
321
322  // First set all registers as not being used.
323  size_t* next_use = registers_array_;
324  for (size_t i = 0; i < number_of_registers_; ++i) {
325    next_use[i] = kMaxLifetimePosition;
326  }
327
328  // For each active interval, find the next use of its register after the
329  // start of current.
330  for (size_t i = 0, e = active_.Size(); i < e; ++i) {
331    LiveInterval* active = active_.Get(i);
332    DCHECK(active->HasRegister());
333    size_t use = active->FirstRegisterUseAfter(current->GetStart());
334    if (use != kNoLifetime) {
335      next_use[active->GetRegister()] = use;
336    }
337  }
338
339  // For each inactive interval, find the next use of its register after the
340  // start of current.
341  // Thanks to SSA, this should only be needed for intervals
342  // that are the result of a split.
343  for (size_t i = 0, e = inactive_.Size(); i < e; ++i) {
344    LiveInterval* inactive = inactive_.Get(i);
345    DCHECK(inactive->HasRegister());
346    size_t use = inactive->FirstRegisterUseAfter(current->GetStart());
347    if (use != kNoLifetime) {
348      next_use[inactive->GetRegister()] = use;
349    }
350  }
351
352  // Pick the register that is used the last.
353  int reg = -1;
354  for (size_t i = 0; i < number_of_registers_; ++i) {
355    if (IsBlocked(i)) continue;
356    if (reg == -1 || next_use[i] > next_use[reg]) {
357      reg = i;
358      if (next_use[i] == kMaxLifetimePosition) break;
359    }
360  }
361
362  if (first_register_use >= next_use[reg]) {
363    // If the first use of that instruction is after the last use of the found
364    // register, we split this interval just before its first register use.
365    AllocateSpillSlotFor(current);
366    LiveInterval* split = Split(current, first_register_use - 1);
367    AddToUnhandled(split);
368    return false;
369  } else {
370    // Use this register and spill the active and inactives interval that
371    // have that register.
372    current->SetRegister(reg);
373
374    for (size_t i = 0, e = active_.Size(); i < e; ++i) {
375      LiveInterval* active = active_.Get(i);
376      if (active->GetRegister() == reg) {
377        LiveInterval* split = Split(active, current->GetStart());
378        active_.DeleteAt(i);
379        handled_.Add(active);
380        AddToUnhandled(split);
381        break;
382      }
383    }
384
385    for (size_t i = 0; i < inactive_.Size(); ++i) {
386      LiveInterval* inactive = inactive_.Get(i);
387      if (inactive->GetRegister() == reg) {
388        LiveInterval* split = Split(inactive, current->GetStart());
389        inactive_.DeleteAt(i);
390        handled_.Add(inactive);
391        AddToUnhandled(split);
392        --i;
393      }
394    }
395
396    return true;
397  }
398}
399
400void RegisterAllocator::AddToUnhandled(LiveInterval* interval) {
401  for (size_t i = unhandled_.Size(); i > 0; --i) {
402    LiveInterval* current = unhandled_.Get(i - 1);
403    if (current->StartsAfter(interval)) {
404      unhandled_.InsertAt(i, interval);
405      break;
406    }
407  }
408}
409
410LiveInterval* RegisterAllocator::Split(LiveInterval* interval, size_t position) {
411  DCHECK(position >= interval->GetStart());
412  DCHECK(!interval->IsDeadAt(position));
413  if (position == interval->GetStart()) {
414    // Spill slot will be allocated when handling `interval` again.
415    interval->ClearRegister();
416    return interval;
417  } else {
418    LiveInterval* new_interval = interval->SplitAt(position);
419    return new_interval;
420  }
421}
422
423void RegisterAllocator::AllocateSpillSlotFor(LiveInterval* interval) {
424  LiveInterval* parent = interval->GetParent();
425
426  // An instruction gets a spill slot for its entire lifetime. If the parent
427  // of this interval already has a spill slot, there is nothing to do.
428  if (parent->HasSpillSlot()) {
429    return;
430  }
431
432  // Find when this instruction dies.
433  LiveInterval* last_sibling = interval;
434  while (last_sibling->GetNextSibling() != nullptr) {
435    last_sibling = last_sibling->GetNextSibling();
436  }
437  size_t end = last_sibling->GetEnd();
438
439  // Find an available spill slot.
440  size_t slot = 0;
441  for (size_t e = spill_slots_.Size(); slot < e; ++slot) {
442    if (spill_slots_.Get(slot) <= parent->GetStart()) {
443      break;
444    }
445  }
446
447  if (slot == spill_slots_.Size()) {
448    // We need a new spill slot.
449    spill_slots_.Add(end);
450  } else {
451    spill_slots_.Put(slot, end);
452  }
453
454  interval->GetParent()->SetSpillSlot(slot * kVRegSize);
455}
456
457}  // namespace art
458