blob: 8eb98a186bff48868c959d655f0ba4b5df9c5626 [file] [log] [blame]
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001/*
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#ifndef ART_COMPILER_OPTIMIZING_SSA_LIVENESS_ANALYSIS_H_
18#define ART_COMPILER_OPTIMIZING_SSA_LIVENESS_ANALYSIS_H_
19
20#include "nodes.h"
Nicolas Geoffray829280c2015-01-28 10:20:37 +000021#include <iostream>
Nicolas Geoffray804d0932014-05-02 08:46:00 +010022
23namespace art {
24
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010025class CodeGenerator;
26
Nicolas Geoffray01ef3452014-10-01 11:32:17 +010027static constexpr int kNoRegister = -1;
28
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070029class BlockInfo : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010030 public:
31 BlockInfo(ArenaAllocator* allocator, const HBasicBlock& block, size_t number_of_ssa_values)
32 : block_(block),
33 live_in_(allocator, number_of_ssa_values, false),
34 live_out_(allocator, number_of_ssa_values, false),
35 kill_(allocator, number_of_ssa_values, false) {
Ian Rogerscf7f1912014-10-22 22:06:39 -070036 UNUSED(block_);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010037 live_in_.ClearAllBits();
38 live_out_.ClearAllBits();
39 kill_.ClearAllBits();
40 }
41
42 private:
43 const HBasicBlock& block_;
44 ArenaBitVector live_in_;
45 ArenaBitVector live_out_;
46 ArenaBitVector kill_;
47
48 friend class SsaLivenessAnalysis;
49
50 DISALLOW_COPY_AND_ASSIGN(BlockInfo);
51};
52
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010053/**
Nicolas Geoffray39468442014-09-02 15:17:15 +010054 * A live range contains the start and end of a range where an instruction or a temporary
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010055 * is live.
56 */
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070057class LiveRange FINAL : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010058 public:
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010059 LiveRange(size_t start, size_t end, LiveRange* next) : start_(start), end_(end), next_(next) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010060 DCHECK_LT(start, end);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010061 DCHECK(next_ == nullptr || next_->GetStart() > GetEnd());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010062 }
63
64 size_t GetStart() const { return start_; }
65 size_t GetEnd() const { return end_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010066 LiveRange* GetNext() const { return next_; }
67
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070068 bool IntersectsWith(const LiveRange& other) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010069 return (start_ >= other.start_ && start_ < other.end_)
70 || (other.start_ >= start_ && other.start_ < end_);
71 }
72
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070073 bool IsBefore(const LiveRange& other) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010074 return end_ <= other.start_;
75 }
76
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070077 void Dump(std::ostream& stream) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010078 stream << "[" << start_ << ", " << end_ << ")";
79 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010080
Nicolas Geoffray840e5462015-01-07 16:01:24 +000081 LiveRange* Dup(ArenaAllocator* allocator) const {
82 return new (allocator) LiveRange(
83 start_, end_, next_ == nullptr ? nullptr : next_->Dup(allocator));
84 }
85
86 LiveRange* GetLastRange() {
87 return next_ == nullptr ? this : next_->GetLastRange();
88 }
89
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010090 private:
91 size_t start_;
Nicolas Geoffray76905622014-09-25 14:39:26 +010092 size_t end_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010093 LiveRange* next_;
94
95 friend class LiveInterval;
96
97 DISALLOW_COPY_AND_ASSIGN(LiveRange);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010098};
99
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100100/**
101 * A use position represents a live interval use at a given position.
102 */
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700103class UsePosition : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100104 public:
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100105 UsePosition(HInstruction* user,
106 size_t input_index,
107 bool is_environment,
108 size_t position,
109 UsePosition* next)
110 : user_(user),
111 input_index_(input_index),
112 is_environment_(is_environment),
113 position_(position),
114 next_(next) {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100115 DCHECK(user->IsPhi()
116 || (GetPosition() == user->GetLifetimePosition() + 1)
117 || (GetPosition() == user->GetLifetimePosition()));
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100118 DCHECK(next_ == nullptr || next->GetPosition() >= GetPosition());
119 }
120
121 size_t GetPosition() const { return position_; }
122
123 UsePosition* GetNext() const { return next_; }
Nicolas Geoffray76905622014-09-25 14:39:26 +0100124 void SetNext(UsePosition* next) { next_ = next; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100125
126 HInstruction* GetUser() const { return user_; }
127
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100128 bool GetIsEnvironment() const { return is_environment_; }
129
130 size_t GetInputIndex() const { return input_index_; }
131
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100132 void Dump(std::ostream& stream) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100133 stream << position_;
134 }
135
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000136 UsePosition* Dup(ArenaAllocator* allocator) const {
137 return new (allocator) UsePosition(
138 user_, input_index_, is_environment_, position_,
139 next_ == nullptr ? nullptr : next_->Dup(allocator));
140 }
141
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100142 private:
143 HInstruction* const user_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100144 const size_t input_index_;
145 const bool is_environment_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100146 const size_t position_;
Nicolas Geoffray76905622014-09-25 14:39:26 +0100147 UsePosition* next_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100148
149 DISALLOW_COPY_AND_ASSIGN(UsePosition);
150};
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100151
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100152class SafepointPosition : public ArenaObject<kArenaAllocMisc> {
153 public:
154 explicit SafepointPosition(HInstruction* instruction)
155 : instruction_(instruction),
156 next_(nullptr) {}
157
158 void SetNext(SafepointPosition* next) {
159 next_ = next;
160 }
161
162 size_t GetPosition() const {
163 return instruction_->GetLifetimePosition();
164 }
165
166 SafepointPosition* GetNext() const {
167 return next_;
168 }
169
170 LocationSummary* GetLocations() const {
171 return instruction_->GetLocations();
172 }
173
174 HInstruction* GetInstruction() const {
175 return instruction_;
176 }
177
178 private:
179 HInstruction* const instruction_;
180 SafepointPosition* next_;
181
182 DISALLOW_COPY_AND_ASSIGN(SafepointPosition);
183};
184
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100185/**
186 * An interval is a list of disjoint live ranges where an instruction is live.
187 * Each instruction that has uses gets an interval.
188 */
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700189class LiveInterval : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100190 public:
Mingyao Yang296bd602014-10-06 16:47:28 -0700191 static LiveInterval* MakeInterval(ArenaAllocator* allocator,
192 Primitive::Type type,
193 HInstruction* instruction = nullptr) {
194 return new (allocator) LiveInterval(allocator, type, instruction);
195 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100196
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100197 static LiveInterval* MakeSlowPathInterval(ArenaAllocator* allocator, HInstruction* instruction) {
198 return new (allocator) LiveInterval(
199 allocator, Primitive::kPrimVoid, instruction, false, kNoRegister, false, true);
200 }
201
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100202 static LiveInterval* MakeFixedInterval(ArenaAllocator* allocator, int reg, Primitive::Type type) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100203 return new (allocator) LiveInterval(allocator, type, nullptr, true, reg, false);
204 }
205
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100206 static LiveInterval* MakeTempInterval(ArenaAllocator* allocator, Primitive::Type type) {
207 return new (allocator) LiveInterval(allocator, type, nullptr, false, kNoRegister, true);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100208 }
209
210 bool IsFixed() const { return is_fixed_; }
Mingyao Yang296bd602014-10-06 16:47:28 -0700211 bool IsTemp() const { return is_temp_; }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100212 bool IsSlowPathSafepoint() const { return is_slow_path_safepoint_; }
Mingyao Yang296bd602014-10-06 16:47:28 -0700213 // This interval is the result of a split.
214 bool IsSplit() const { return parent_ != this; }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100215
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000216 void AddTempUse(HInstruction* instruction, size_t temp_index) {
217 DCHECK(IsTemp());
218 DCHECK(first_use_ == nullptr) << "A temporary can only have one user";
219 size_t position = instruction->GetLifetimePosition();
220 first_use_ = new (allocator_) UsePosition(
221 instruction, temp_index, /* is_environment */ false, position, first_use_);
222 AddRange(position, position + 1);
223 }
224
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000225 void AddUse(HInstruction* instruction,
226 size_t input_index,
227 bool is_environment,
228 bool keep_alive = false) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100229 // Set the use within the instruction.
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000230 size_t position = instruction->GetLifetimePosition() + 1;
231 LocationSummary* locations = instruction->GetLocations();
232 if (!is_environment) {
233 if (locations->IsFixedInput(input_index) || locations->OutputUsesSameAs(input_index)) {
234 // For fixed inputs and output same as input, the register allocator
235 // requires to have inputs die at the instruction, so that input moves use the
236 // location of the input just before that instruction (and not potential moves due
237 // to splitting).
238 position = instruction->GetLifetimePosition();
239 }
Nicolas Geoffray76905622014-09-25 14:39:26 +0100240 }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000241
242 DCHECK(position == instruction->GetLifetimePosition()
243 || position == instruction->GetLifetimePosition() + 1);
244
Nicolas Geoffray76905622014-09-25 14:39:26 +0100245 if ((first_use_ != nullptr)
246 && (first_use_->GetUser() == instruction)
247 && (first_use_->GetPosition() < position)) {
248 // The user uses the instruction multiple times, and one use dies before the other.
249 // We update the use list so that the latter is first.
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000250 DCHECK(!is_environment);
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100251 UsePosition* cursor = first_use_;
252 while ((cursor->GetNext() != nullptr) && (cursor->GetNext()->GetPosition() < position)) {
253 cursor = cursor->GetNext();
254 }
Nicolas Geoffray76905622014-09-25 14:39:26 +0100255 DCHECK(first_use_->GetPosition() + 1 == position);
256 UsePosition* new_use = new (allocator_) UsePosition(
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100257 instruction, input_index, is_environment, position, cursor->GetNext());
258 cursor->SetNext(new_use);
Nicolas Geoffray76905622014-09-25 14:39:26 +0100259 if (first_range_->GetEnd() == first_use_->GetPosition()) {
260 first_range_->end_ = position;
261 }
262 return;
263 }
264
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000265 first_use_ = new (allocator_) UsePosition(
266 instruction, input_index, is_environment, position, first_use_);
267
268 if (is_environment && !keep_alive) {
269 // If this environment use does not keep the instruction live, it does not
270 // affect the live range of that instruction.
271 return;
272 }
273
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100274 size_t start_block_position = instruction->GetBlock()->GetLifetimeStart();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100275 if (first_range_ == nullptr) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100276 // First time we see a use of that interval.
David Brazdil3fc992f2015-04-16 18:31:55 +0100277 first_range_ = last_range_ = range_search_start_ =
278 new (allocator_) LiveRange(start_block_position, position, nullptr);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100279 } else if (first_range_->GetStart() == start_block_position) {
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100280 // There is a use later in the same block or in a following block.
281 // Note that in such a case, `AddRange` for the whole blocks has been called
282 // before arriving in this method, and this is the reason the start of
283 // `first_range_` is before the given `position`.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100284 DCHECK_LE(position, first_range_->GetEnd());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100285 } else {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100286 DCHECK(first_range_->GetStart() > position);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100287 // There is a hole in the interval. Create a new range.
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100288 // Note that the start of `first_range_` can be equal to `end`: two blocks
289 // having adjacent lifetime positions are not necessarily
290 // predecessor/successor. When two blocks are predecessor/successor, the
291 // liveness algorithm has called `AddRange` before arriving in this method,
292 // and the check line 205 would succeed.
David Brazdil3fc992f2015-04-16 18:31:55 +0100293 first_range_ = range_search_start_ =
294 new (allocator_) LiveRange(start_block_position, position, first_range_);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100295 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100296 }
297
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100298 void AddPhiUse(HInstruction* instruction, size_t input_index, HBasicBlock* block) {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100299 DCHECK(instruction->IsPhi());
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100300 first_use_ = new (allocator_) UsePosition(
301 instruction, input_index, false, block->GetLifetimeEnd(), first_use_);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100302 }
303
304 void AddRange(size_t start, size_t end) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100305 if (first_range_ == nullptr) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100306 first_range_ = last_range_ = range_search_start_ =
307 new (allocator_) LiveRange(start, end, first_range_);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100308 } else if (first_range_->GetStart() == end) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100309 // There is a use in the following block.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100310 first_range_->start_ = start;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100311 } else if (first_range_->GetStart() == start && first_range_->GetEnd() == end) {
312 DCHECK(is_fixed_);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100313 } else {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100314 DCHECK_GT(first_range_->GetStart(), end);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100315 // There is a hole in the interval. Create a new range.
David Brazdil3fc992f2015-04-16 18:31:55 +0100316 first_range_ = range_search_start_ = new (allocator_) LiveRange(start, end, first_range_);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100317 }
318 }
319
320 void AddLoopRange(size_t start, size_t end) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100321 DCHECK(first_range_ != nullptr);
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000322 DCHECK_LE(start, first_range_->GetStart());
323 // Find the range that covers the positions after the loop.
324 LiveRange* after_loop = first_range_;
325 LiveRange* last_in_loop = nullptr;
326 while (after_loop != nullptr && after_loop->GetEnd() < end) {
327 DCHECK_LE(start, after_loop->GetStart());
328 last_in_loop = after_loop;
329 after_loop = after_loop->GetNext();
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100330 }
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000331 if (after_loop == nullptr) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100332 // Uses are only in the loop.
David Brazdil3fc992f2015-04-16 18:31:55 +0100333 first_range_ = last_range_ = range_search_start_ = new (allocator_) LiveRange(start, end, nullptr);
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000334 } else if (after_loop->GetStart() <= end) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100335 first_range_ = range_search_start_ = after_loop;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100336 // There are uses after the loop.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100337 first_range_->start_ = start;
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000338 } else {
339 // The use after the loop is after a lifetime hole.
340 DCHECK(last_in_loop != nullptr);
David Brazdil3fc992f2015-04-16 18:31:55 +0100341 first_range_ = range_search_start_ = last_in_loop;
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000342 first_range_->start_ = start;
343 first_range_->end_ = end;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100344 }
345 }
346
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100347 bool HasSpillSlot() const { return spill_slot_ != kNoSpillSlot; }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100348 void SetSpillSlot(int slot) {
349 DCHECK(!is_fixed_);
350 DCHECK(!is_temp_);
351 spill_slot_ = slot;
352 }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100353 int GetSpillSlot() const { return spill_slot_; }
354
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100355 void SetFrom(size_t from) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100356 if (first_range_ != nullptr) {
357 first_range_->start_ = from;
358 } else {
359 // Instruction without uses.
Nicolas Geoffray915b9d02015-03-11 15:11:19 +0000360 DCHECK(!defined_by_->HasNonEnvironmentUses());
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100361 DCHECK(from == defined_by_->GetLifetimePosition());
David Brazdil3fc992f2015-04-16 18:31:55 +0100362 first_range_ = last_range_ = range_search_start_ =
363 new (allocator_) LiveRange(from, from + 2, nullptr);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100364 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100365 }
366
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100367 LiveInterval* GetParent() const { return parent_; }
368
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100369 LiveRange* GetFirstRange() const { return first_range_; }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000370 LiveRange* GetLastRange() const { return last_range_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100371
372 int GetRegister() const { return register_; }
373 void SetRegister(int reg) { register_ = reg; }
374 void ClearRegister() { register_ = kNoRegister; }
375 bool HasRegister() const { return register_ != kNoRegister; }
376
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100377 bool IsDeadAt(size_t position) const {
David Brazdil241a4862015-04-16 17:59:03 +0100378 return GetEnd() <= position;
379 }
380
381 bool IsDefinedAt(size_t position) const {
382 return GetStart() <= position && !IsDeadAt(position);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100383 }
384
David Brazdil3fc992f2015-04-16 18:31:55 +0100385 // Returns true if the interval contains a LiveRange covering `position`.
386 // The range at or immediately after the current position of linear scan
387 // is cached for better performance. If `position` can be smaller than
388 // that, CoversSlow should be used instead.
David Brazdil5b8e6a52015-02-25 16:17:05 +0000389 bool Covers(size_t position) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100390 LiveRange* candidate = FindRangeAtOrAfter(position, range_search_start_);
391 range_search_start_ = candidate;
392 return (candidate != nullptr && candidate->GetStart() <= position);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100393 }
394
David Brazdil3fc992f2015-04-16 18:31:55 +0100395 // Same as Covers but always tests all ranges.
396 bool CoversSlow(size_t position) const {
397 LiveRange* candidate = FindRangeAtOrAfter(position, first_range_);
398 return candidate != nullptr && candidate->GetStart() <= position;
399 }
400
401 // Returns the first intersection of this interval with `current`, which
402 // must be the interval currently being allocated by linear scan.
403 size_t FirstIntersectionWith(LiveInterval* current) const {
404 // Find the first range after the start of `current`. We use the search
405 // cache to improve performance.
406 DCHECK(GetStart() <= current->GetStart() || IsFixed());
407 LiveRange* other_range = current->first_range_;
408 LiveRange* my_range = FindRangeAtOrAfter(other_range->GetStart(), range_search_start_);
409 if (my_range == nullptr) {
410 return kNoLifetime;
411 }
412
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100413 // Advance both intervals and find the first matching range start in
414 // this interval.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100415 do {
David Brazdil714e14f2015-02-25 11:57:05 +0000416 if (my_range->IsBefore(*other_range)) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100417 my_range = my_range->GetNext();
418 if (my_range == nullptr) {
419 return kNoLifetime;
420 }
David Brazdil714e14f2015-02-25 11:57:05 +0000421 } else if (other_range->IsBefore(*my_range)) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100422 other_range = other_range->GetNext();
423 if (other_range == nullptr) {
424 return kNoLifetime;
425 }
David Brazdil714e14f2015-02-25 11:57:05 +0000426 } else {
427 DCHECK(my_range->IntersectsWith(*other_range));
428 return std::max(my_range->GetStart(), other_range->GetStart());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100429 }
430 } while (true);
431 }
432
433 size_t GetStart() const {
434 return first_range_->GetStart();
435 }
436
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100437 size_t GetEnd() const {
438 return last_range_->GetEnd();
439 }
440
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100441 size_t FirstRegisterUseAfter(size_t position) const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100442 if (is_temp_) {
443 return position == GetStart() ? position : kNoLifetime;
444 }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100445 if (position == GetStart() && defined_by_ != nullptr) {
Nicolas Geoffrayde025a72014-06-19 17:06:46 +0100446 LocationSummary* locations = defined_by_->GetLocations();
447 Location location = locations->Out();
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100448 // This interval is the first interval of the instruction. If the output
449 // of the instruction requires a register, we return the position of that instruction
450 // as the first register use.
451 if (location.IsUnallocated()) {
452 if ((location.GetPolicy() == Location::kRequiresRegister)
453 || (location.GetPolicy() == Location::kSameAsFirstInput
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000454 && (locations->InAt(0).IsRegister()
455 || locations->InAt(0).IsRegisterPair()
456 || locations->InAt(0).GetPolicy() == Location::kRequiresRegister))) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100457 return position;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100458 } else if ((location.GetPolicy() == Location::kRequiresFpuRegister)
459 || (location.GetPolicy() == Location::kSameAsFirstInput
460 && locations->InAt(0).GetPolicy() == Location::kRequiresFpuRegister)) {
461 return position;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100462 }
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000463 } else if (location.IsRegister() || location.IsRegisterPair()) {
464 return position;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100465 }
466 }
467
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100468 UsePosition* use = first_use_;
Nicolas Geoffrayde025a72014-06-19 17:06:46 +0100469 size_t end = GetEnd();
470 while (use != nullptr && use->GetPosition() <= end) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100471 size_t use_position = use->GetPosition();
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +0100472 if (use_position > position && !use->GetIsEnvironment()) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100473 Location location = use->GetUser()->GetLocations()->InAt(use->GetInputIndex());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100474 if (location.IsUnallocated()
475 && (location.GetPolicy() == Location::kRequiresRegister
476 || location.GetPolicy() == Location::kRequiresFpuRegister)) {
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +0100477 return use_position;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100478 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100479 }
480 use = use->GetNext();
481 }
482 return kNoLifetime;
483 }
484
485 size_t FirstRegisterUse() const {
486 return FirstRegisterUseAfter(GetStart());
487 }
488
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000489 size_t FirstUseAfter(size_t position) const {
490 if (is_temp_) {
491 return position == GetStart() ? position : kNoLifetime;
492 }
493
494 UsePosition* use = first_use_;
495 size_t end = GetEnd();
496 while (use != nullptr && use->GetPosition() <= end) {
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000497 if (!use->GetIsEnvironment()) {
498 size_t use_position = use->GetPosition();
499 if (use_position > position) {
500 return use_position;
501 }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000502 }
503 use = use->GetNext();
504 }
505 return kNoLifetime;
506 }
507
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100508 UsePosition* GetFirstUse() const {
509 return first_use_;
510 }
511
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100512 Primitive::Type GetType() const {
513 return type_;
514 }
515
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100516 HInstruction* GetDefinedBy() const {
517 return defined_by_;
518 }
519
Nicolas Geoffray43af7282015-04-16 13:01:01 +0100520 SafepointPosition* FindSafepointJustBefore(size_t position) const {
521 for (SafepointPosition* safepoint = first_safepoint_, *previous = nullptr;
522 safepoint != nullptr;
523 previous = safepoint, safepoint = safepoint->GetNext()) {
524 if (safepoint->GetPosition() >= position) return previous;
525 }
526 return last_safepoint_;
527 }
528
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100529 /**
530 * Split this interval at `position`. This interval is changed to:
531 * [start ... position).
532 *
533 * The new interval covers:
534 * [position ... end)
535 */
536 LiveInterval* SplitAt(size_t position) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100537 DCHECK(!is_temp_);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100538 DCHECK(!is_fixed_);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100539 DCHECK_GT(position, GetStart());
540
David Brazdil241a4862015-04-16 17:59:03 +0100541 if (GetEnd() <= position) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100542 // This range dies before `position`, no need to split.
543 return nullptr;
544 }
545
546 LiveInterval* new_interval = new (allocator_) LiveInterval(allocator_, type_);
Nicolas Geoffray43af7282015-04-16 13:01:01 +0100547 SafepointPosition* new_last_safepoint = FindSafepointJustBefore(position);
548 if (new_last_safepoint == nullptr) {
549 new_interval->first_safepoint_ = first_safepoint_;
550 new_interval->last_safepoint_ = last_safepoint_;
551 first_safepoint_ = last_safepoint_ = nullptr;
552 } else if (last_safepoint_ != new_last_safepoint) {
553 new_interval->last_safepoint_ = last_safepoint_;
554 new_interval->first_safepoint_ = new_last_safepoint->GetNext();
555 DCHECK(new_interval->first_safepoint_ != nullptr);
556 last_safepoint_ = new_last_safepoint;
557 last_safepoint_->SetNext(nullptr);
558 }
559
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100560 new_interval->next_sibling_ = next_sibling_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100561 next_sibling_ = new_interval;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100562 new_interval->parent_ = parent_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100563
564 new_interval->first_use_ = first_use_;
565 LiveRange* current = first_range_;
566 LiveRange* previous = nullptr;
567 // Iterate over the ranges, and either find a range that covers this position, or
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +0000568 // two ranges in between this position (that is, the position is in a lifetime hole).
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100569 do {
570 if (position >= current->GetEnd()) {
571 // Move to next range.
572 previous = current;
573 current = current->next_;
574 } else if (position <= current->GetStart()) {
575 // If the previous range did not cover this position, we know position is in
576 // a lifetime hole. We can just break the first_range_ and last_range_ links
577 // and return the new interval.
578 DCHECK(previous != nullptr);
579 DCHECK(current != first_range_);
580 new_interval->last_range_ = last_range_;
581 last_range_ = previous;
582 previous->next_ = nullptr;
583 new_interval->first_range_ = current;
David Brazdil3fc992f2015-04-16 18:31:55 +0100584 if (range_search_start_ != nullptr && range_search_start_->GetEnd() >= current->GetEnd()) {
585 // Search start point is inside `new_interval`. Change it to nullptr
586 // (i.e. the end of the interval) in the original interval.
587 range_search_start_ = nullptr;
588 }
589 new_interval->range_search_start_ = new_interval->first_range_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100590 return new_interval;
591 } else {
592 // This range covers position. We create a new last_range_ for this interval
593 // that covers last_range_->Start() and position. We also shorten the current
594 // range and make it the first range of the new interval.
595 DCHECK(position < current->GetEnd() && position > current->GetStart());
596 new_interval->last_range_ = last_range_;
597 last_range_ = new (allocator_) LiveRange(current->start_, position, nullptr);
598 if (previous != nullptr) {
599 previous->next_ = last_range_;
600 } else {
601 first_range_ = last_range_;
602 }
603 new_interval->first_range_ = current;
604 current->start_ = position;
David Brazdil3fc992f2015-04-16 18:31:55 +0100605 if (range_search_start_ != nullptr && range_search_start_->GetEnd() >= current->GetEnd()) {
606 // Search start point is inside `new_interval`. Change it to `last_range`
607 // in the original interval. This is conservative but always correct.
608 range_search_start_ = last_range_;
609 }
610 new_interval->range_search_start_ = new_interval->first_range_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100611 return new_interval;
612 }
613 } while (current != nullptr);
614
615 LOG(FATAL) << "Unreachable";
616 return nullptr;
617 }
618
Nicolas Geoffray76905622014-09-25 14:39:26 +0100619 bool StartsBeforeOrAt(LiveInterval* other) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100620 return GetStart() <= other->GetStart();
621 }
622
623 bool StartsAfter(LiveInterval* other) const {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100624 return GetStart() > other->GetStart();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100625 }
626
627 void Dump(std::ostream& stream) const {
628 stream << "ranges: { ";
629 LiveRange* current = first_range_;
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000630 while (current != nullptr) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100631 current->Dump(stream);
632 stream << " ";
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000633 current = current->GetNext();
634 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100635 stream << "}, uses: { ";
636 UsePosition* use = first_use_;
637 if (use != nullptr) {
638 do {
639 use->Dump(stream);
640 stream << " ";
641 } while ((use = use->GetNext()) != nullptr);
642 }
643 stream << "}";
Mingyao Yang296bd602014-10-06 16:47:28 -0700644 stream << " is_fixed: " << is_fixed_ << ", is_split: " << IsSplit();
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000645 stream << " is_high: " << IsHighInterval();
646 stream << " is_low: " << IsLowInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100647 }
648
649 LiveInterval* GetNextSibling() const { return next_sibling_; }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000650 LiveInterval* GetLastSibling() {
651 LiveInterval* result = this;
652 while (result->next_sibling_ != nullptr) {
653 result = result->next_sibling_;
654 }
655 return result;
656 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100657
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100658 // Returns the first register hint that is at least free before
659 // the value contained in `free_until`. If none is found, returns
660 // `kNoRegister`.
661 int FindFirstRegisterHint(size_t* free_until) const;
662
663 // If there is enough at the definition site to find a register (for example
664 // it uses the same input as the first input), returns the register as a hint.
665 // Returns kNoRegister otherwise.
666 int FindHintAtDefinition() const;
667
668 // Returns whether the interval needs two (Dex virtual register size `kVRegSize`)
669 // slots for spilling.
670 bool NeedsTwoSpillSlots() const;
671
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100672 bool IsFloatingPoint() const {
673 return type_ == Primitive::kPrimFloat || type_ == Primitive::kPrimDouble;
674 }
675
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100676 // Converts the location of the interval to a `Location` object.
677 Location ToLocation() const;
678
679 // Returns the location of the interval following its siblings at `position`.
David Brazdil5b8e6a52015-02-25 16:17:05 +0000680 Location GetLocationAt(size_t position);
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100681
David Brazdil241a4862015-04-16 17:59:03 +0100682 // Finds the sibling that is defined at `position`.
683 LiveInterval* GetSiblingAt(size_t position);
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100684
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100685 // Returns whether `other` and `this` share the same kind of register.
686 bool SameRegisterKind(Location other) const;
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000687 bool SameRegisterKind(const LiveInterval& other) const {
688 return IsFloatingPoint() == other.IsFloatingPoint();
689 }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100690
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000691 bool HasHighInterval() const {
Nicolas Geoffray3747b482015-01-19 17:17:16 +0000692 return IsLowInterval();
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000693 }
694
695 bool HasLowInterval() const {
696 return IsHighInterval();
697 }
698
699 LiveInterval* GetLowInterval() const {
700 DCHECK(HasLowInterval());
701 return high_or_low_interval_;
702 }
703
704 LiveInterval* GetHighInterval() const {
705 DCHECK(HasHighInterval());
706 return high_or_low_interval_;
707 }
708
709 bool IsHighInterval() const {
710 return GetParent()->is_high_interval_;
711 }
712
713 bool IsLowInterval() const {
714 return !IsHighInterval() && (GetParent()->high_or_low_interval_ != nullptr);
715 }
716
717 void SetLowInterval(LiveInterval* low) {
718 DCHECK(IsHighInterval());
719 high_or_low_interval_ = low;
720 }
721
722 void SetHighInterval(LiveInterval* high) {
723 DCHECK(IsLowInterval());
724 high_or_low_interval_ = high;
725 }
726
727 void AddHighInterval(bool is_temp = false) {
728 DCHECK_EQ(GetParent(), this);
729 DCHECK(!HasHighInterval());
730 DCHECK(!HasLowInterval());
731 high_or_low_interval_ = new (allocator_) LiveInterval(
732 allocator_, type_, defined_by_, false, kNoRegister, is_temp, false, true);
733 high_or_low_interval_->high_or_low_interval_ = this;
734 if (first_range_ != nullptr) {
735 high_or_low_interval_->first_range_ = first_range_->Dup(allocator_);
David Brazdilc08675c2015-04-17 15:49:51 +0100736 high_or_low_interval_->last_range_ = high_or_low_interval_->first_range_->GetLastRange();
David Brazdil3fc992f2015-04-16 18:31:55 +0100737 high_or_low_interval_->range_search_start_ = high_or_low_interval_->first_range_;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000738 }
739 if (first_use_ != nullptr) {
740 high_or_low_interval_->first_use_ = first_use_->Dup(allocator_);
741 }
742 }
743
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000744 // Returns whether an interval, when it is non-split, is using
745 // the same register of one of its input.
746 bool IsUsingInputRegister() const {
David Brazdil3fc992f2015-04-16 18:31:55 +0100747 CHECK(kIsDebugBuild) << "Function should be used only for DCHECKs";
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000748 if (defined_by_ != nullptr && !IsSplit()) {
749 for (HInputIterator it(defined_by_); !it.Done(); it.Advance()) {
750 LiveInterval* interval = it.Current()->GetLiveInterval();
751
David Brazdil3fc992f2015-04-16 18:31:55 +0100752 // Find the interval that covers `defined_by`_. Calls to this function
753 // are made outside the linear scan, hence we need to use CoversSlow.
754 while (interval != nullptr && !interval->CoversSlow(defined_by_->GetLifetimePosition())) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000755 interval = interval->GetNextSibling();
756 }
757
758 // Check if both intervals have the same register of the same kind.
759 if (interval != nullptr
760 && interval->SameRegisterKind(*this)
761 && interval->GetRegister() == GetRegister()) {
762 return true;
763 }
764 }
765 }
766 return false;
767 }
768
769 // Returns whether an interval, when it is non-split, can safely use
770 // the same register of one of its input. Note that this method requires
771 // IsUsingInputRegister() to be true.
772 bool CanUseInputRegister() const {
David Brazdil3fc992f2015-04-16 18:31:55 +0100773 CHECK(kIsDebugBuild) << "Function should be used only for DCHECKs";
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000774 DCHECK(IsUsingInputRegister());
775 if (defined_by_ != nullptr && !IsSplit()) {
776 LocationSummary* locations = defined_by_->GetLocations();
777 if (locations->OutputCanOverlapWithInputs()) {
778 return false;
779 }
780 for (HInputIterator it(defined_by_); !it.Done(); it.Advance()) {
781 LiveInterval* interval = it.Current()->GetLiveInterval();
782
David Brazdil3fc992f2015-04-16 18:31:55 +0100783 // Find the interval that covers `defined_by`_. Calls to this function
784 // are made outside the linear scan, hence we need to use CoversSlow.
785 while (interval != nullptr && !interval->CoversSlow(defined_by_->GetLifetimePosition())) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000786 interval = interval->GetNextSibling();
787 }
788
789 if (interval != nullptr
790 && interval->SameRegisterKind(*this)
791 && interval->GetRegister() == GetRegister()) {
792 // We found the input that has the same register. Check if it is live after
793 // `defined_by`_.
David Brazdil3fc992f2015-04-16 18:31:55 +0100794 return !interval->CoversSlow(defined_by_->GetLifetimePosition() + 1);
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000795 }
796 }
797 }
798 LOG(FATAL) << "Unreachable";
799 UNREACHABLE();
800 }
801
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100802 void AddSafepoint(HInstruction* instruction) {
803 SafepointPosition* safepoint = new (allocator_) SafepointPosition(instruction);
804 if (first_safepoint_ == nullptr) {
805 first_safepoint_ = last_safepoint_ = safepoint;
806 } else {
807 DCHECK_LT(last_safepoint_->GetPosition(), safepoint->GetPosition());
808 last_safepoint_->SetNext(safepoint);
809 last_safepoint_ = safepoint;
810 }
811 }
812
813 SafepointPosition* GetFirstSafepoint() const {
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100814 return first_safepoint_;
815 }
816
David Brazdil3fc992f2015-04-16 18:31:55 +0100817 // Resets the starting point for range-searching queries to the first range.
818 // Intervals must be reset prior to starting a new linear scan over them.
819 void ResetSearchCache() {
820 range_search_start_ = first_range_;
821 }
822
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100823 private:
Mingyao Yang296bd602014-10-06 16:47:28 -0700824 LiveInterval(ArenaAllocator* allocator,
825 Primitive::Type type,
826 HInstruction* defined_by = nullptr,
827 bool is_fixed = false,
828 int reg = kNoRegister,
829 bool is_temp = false,
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000830 bool is_slow_path_safepoint = false,
831 bool is_high_interval = false)
Mingyao Yang296bd602014-10-06 16:47:28 -0700832 : allocator_(allocator),
833 first_range_(nullptr),
834 last_range_(nullptr),
David Brazdil3fc992f2015-04-16 18:31:55 +0100835 range_search_start_(nullptr),
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100836 first_safepoint_(nullptr),
837 last_safepoint_(nullptr),
Mingyao Yang296bd602014-10-06 16:47:28 -0700838 first_use_(nullptr),
839 type_(type),
840 next_sibling_(nullptr),
841 parent_(this),
842 register_(reg),
843 spill_slot_(kNoSpillSlot),
844 is_fixed_(is_fixed),
845 is_temp_(is_temp),
846 is_slow_path_safepoint_(is_slow_path_safepoint),
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000847 is_high_interval_(is_high_interval),
848 high_or_low_interval_(nullptr),
Mingyao Yang296bd602014-10-06 16:47:28 -0700849 defined_by_(defined_by) {}
850
David Brazdil3fc992f2015-04-16 18:31:55 +0100851 // Searches for a LiveRange that either covers the given position or is the
852 // first next LiveRange. Returns nullptr if no such LiveRange exists. Ranges
853 // known to end before `position` can be skipped with `search_start`.
854 LiveRange* FindRangeAtOrAfter(size_t position, LiveRange* search_start) const {
David Brazdil5b8e6a52015-02-25 16:17:05 +0000855 if (kIsDebugBuild) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100856 if (search_start != first_range_) {
857 // If we are not searching the entire list of ranges, make sure we do
858 // not skip the range we are searching for.
859 if (search_start == nullptr) {
860 DCHECK(IsDeadAt(position));
861 } else if (search_start->GetStart() > position) {
862 DCHECK_EQ(search_start, FindRangeAtOrAfter(position, first_range_));
863 }
David Brazdil5b8e6a52015-02-25 16:17:05 +0000864 }
865 }
866
David Brazdil3fc992f2015-04-16 18:31:55 +0100867 LiveRange* range;
868 for (range = search_start;
869 range != nullptr && range->GetEnd() <= position;
870 range = range->GetNext()) {
871 continue;
David Brazdil5b8e6a52015-02-25 16:17:05 +0000872 }
David Brazdil3fc992f2015-04-16 18:31:55 +0100873 return range;
David Brazdil5b8e6a52015-02-25 16:17:05 +0000874 }
875
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100876 ArenaAllocator* const allocator_;
877
878 // Ranges of this interval. We need a quick access to the last range to test
879 // for liveness (see `IsDeadAt`).
880 LiveRange* first_range_;
881 LiveRange* last_range_;
882
David Brazdil3fc992f2015-04-16 18:31:55 +0100883 // The first range at or after the current position of a linear scan. It is
884 // used to optimize range-searching queries.
885 LiveRange* range_search_start_;
886
Nicolas Geoffray43af7282015-04-16 13:01:01 +0100887 // Safepoints where this interval is live.
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100888 SafepointPosition* first_safepoint_;
889 SafepointPosition* last_safepoint_;
890
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100891 // Uses of this interval. Note that this linked list is shared amongst siblings.
892 UsePosition* first_use_;
893
894 // The instruction type this interval corresponds to.
895 const Primitive::Type type_;
896
897 // Live interval that is the result of a split.
898 LiveInterval* next_sibling_;
899
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100900 // The first interval from which split intervals come from.
901 LiveInterval* parent_;
902
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100903 // The register allocated to this interval.
904 int register_;
905
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100906 // The spill slot allocated to this interval.
907 int spill_slot_;
908
909 // Whether the interval is for a fixed register.
Nicolas Geoffray39468442014-09-02 15:17:15 +0100910 const bool is_fixed_;
911
912 // Whether the interval is for a temporary.
913 const bool is_temp_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100914
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100915 // Whether the interval is for a safepoint that calls on slow path.
916 const bool is_slow_path_safepoint_;
917
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000918 // Whether this interval is a synthesized interval for register pair.
919 const bool is_high_interval_;
920
921 // If this interval needs a register pair, the high or low equivalent.
922 // `is_high_interval_` tells whether this holds the low or the high.
923 LiveInterval* high_or_low_interval_;
924
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100925 // The instruction represented by this interval.
926 HInstruction* const defined_by_;
927
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100928 static constexpr int kNoRegister = -1;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100929 static constexpr int kNoSpillSlot = -1;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100930
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +0000931 ART_FRIEND_TEST(RegisterAllocatorTest, SpillInactive);
932
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100933 DISALLOW_COPY_AND_ASSIGN(LiveInterval);
934};
935
Nicolas Geoffray915b9d02015-03-11 15:11:19 +0000936/**
937 * Analysis that computes the liveness of instructions:
938 *
939 * (a) Non-environment uses of an instruction always make
940 * the instruction live.
941 * (b) Environment uses of an instruction whose type is
942 * object (that is, non-primitive), make the instruction live.
943 * This is due to having to keep alive objects that have
944 * finalizers deleting native objects.
945 * (c) When the graph has the debuggable property, environment uses
946 * of an instruction that has a primitive type make the instruction live.
947 * If the graph does not have the debuggable property, the environment
948 * use has no effect, and may get a 'none' value after register allocation.
949 *
950 * (b) and (c) are implemented through SsaLivenessAnalysis::ShouldBeLiveForEnvironment.
951 */
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100952class SsaLivenessAnalysis : public ValueObject {
953 public:
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100954 SsaLivenessAnalysis(HGraph* graph, CodeGenerator* codegen)
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100955 : graph_(graph),
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100956 codegen_(codegen),
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100957 block_infos_(graph->GetArena(), graph->GetBlocks().Size()),
958 instructions_from_ssa_index_(graph->GetArena(), 0),
959 instructions_from_lifetime_position_(graph->GetArena(), 0),
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100960 number_of_ssa_values_(0) {
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100961 block_infos_.SetSize(graph->GetBlocks().Size());
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100962 }
963
964 void Analyze();
965
966 BitVector* GetLiveInSet(const HBasicBlock& block) const {
967 return &block_infos_.Get(block.GetBlockId())->live_in_;
968 }
969
970 BitVector* GetLiveOutSet(const HBasicBlock& block) const {
971 return &block_infos_.Get(block.GetBlockId())->live_out_;
972 }
973
974 BitVector* GetKillSet(const HBasicBlock& block) const {
975 return &block_infos_.Get(block.GetBlockId())->kill_;
976 }
977
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100978 HInstruction* GetInstructionFromSsaIndex(size_t index) const {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100979 return instructions_from_ssa_index_.Get(index);
980 }
981
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100982 HInstruction* GetInstructionFromPosition(size_t index) const {
983 return instructions_from_lifetime_position_.Get(index);
984 }
985
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100986 HInstruction* GetTempUser(LiveInterval* temp) const {
987 // A temporary shares the same lifetime start as the instruction that requires it.
988 DCHECK(temp->IsTemp());
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000989 HInstruction* user = GetInstructionFromPosition(temp->GetStart() / 2);
990 DCHECK_EQ(user, temp->GetFirstUse()->GetUser());
991 return user;
992 }
993
994 size_t GetTempIndex(LiveInterval* temp) const {
995 // We use the input index to store the index of the temporary in the user's temporary list.
996 DCHECK(temp->IsTemp());
997 return temp->GetFirstUse()->GetInputIndex();
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100998 }
999
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001000 size_t GetMaxLifetimePosition() const {
1001 return instructions_from_lifetime_position_.Size() * 2 - 1;
1002 }
1003
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001004 size_t GetNumberOfSsaValues() const {
1005 return number_of_ssa_values_;
1006 }
1007
Andreas Gampe7c3952f2015-02-19 18:21:24 -08001008 static constexpr const char* kLivenessPassName = "liveness";
1009
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001010 private:
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +01001011 // Linearize the graph so that:
1012 // (1): a block is always after its dominator,
1013 // (2): blocks of loops are contiguous.
1014 // This creates a natural and efficient ordering when visualizing live ranges.
1015 void LinearizeGraph();
1016
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001017 // Give an SSA number to each instruction that defines a value used by another instruction,
1018 // and setup the lifetime information of each instruction and block.
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001019 void NumberInstructions();
1020
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001021 // Compute live ranges of instructions, as well as live_in, live_out and kill sets.
1022 void ComputeLiveness();
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001023
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001024 // Compute the live ranges of instructions, as well as the initial live_in, live_out and
1025 // kill sets, that do not take into account backward branches.
1026 void ComputeLiveRanges();
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001027
1028 // After computing the initial sets, this method does a fixed point
1029 // calculation over the live_in and live_out set to take into account
1030 // backwards branches.
1031 void ComputeLiveInAndLiveOutSets();
1032
1033 // Update the live_in set of the block and returns whether it has changed.
1034 bool UpdateLiveIn(const HBasicBlock& block);
1035
1036 // Update the live_out set of the block and returns whether it has changed.
1037 bool UpdateLiveOut(const HBasicBlock& block);
1038
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001039 static bool ShouldBeLiveForEnvironment(HInstruction* instruction) {
1040 if (instruction == nullptr) return false;
1041 if (instruction->GetBlock()->GetGraph()->IsDebuggable()) return true;
1042 return instruction->GetType() == Primitive::kPrimNot;
1043 }
1044
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01001045 HGraph* const graph_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001046 CodeGenerator* const codegen_;
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001047 GrowableArray<BlockInfo*> block_infos_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001048
1049 // Temporary array used when computing live_in, live_out, and kill sets.
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001050 GrowableArray<HInstruction*> instructions_from_ssa_index_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001051
1052 // Temporary array used when inserting moves in the graph.
1053 GrowableArray<HInstruction*> instructions_from_lifetime_position_;
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001054 size_t number_of_ssa_values_;
1055
1056 DISALLOW_COPY_AND_ASSIGN(SsaLivenessAnalysis);
1057};
1058
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001059} // namespace art
1060
1061#endif // ART_COMPILER_OPTIMIZING_SSA_LIVENESS_ANALYSIS_H_