blob: ec4ab31d617643231890975bc7da05beeedcce9c [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
Nicolas Geoffray829280c2015-01-28 10:20:37 +000020#include <iostream>
Nicolas Geoffray804d0932014-05-02 08:46:00 +010021
Vladimir Marko82b07402017-03-01 19:02:04 +000022#include "base/iteration_range.h"
Vladimir Marko356bd282017-03-01 12:01:11 +000023#include "nodes.h"
Vladimir Marko82b07402017-03-01 19:02:04 +000024#include "utils/intrusive_forward_list.h"
Vladimir Marko356bd282017-03-01 12:01:11 +000025
Nicolas Geoffray804d0932014-05-02 08:46:00 +010026namespace art {
27
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010028class CodeGenerator;
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +010029class SsaLivenessAnalysis;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010030
Nicolas Geoffray01ef3452014-10-01 11:32:17 +010031static constexpr int kNoRegister = -1;
32
Vladimir Marko5233f932015-09-29 19:01:15 +010033class BlockInfo : public ArenaObject<kArenaAllocSsaLiveness> {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010034 public:
35 BlockInfo(ArenaAllocator* allocator, const HBasicBlock& block, size_t number_of_ssa_values)
36 : block_(block),
Vladimir Markof6a35de2016-03-21 12:01:50 +000037 live_in_(allocator, number_of_ssa_values, false, kArenaAllocSsaLiveness),
38 live_out_(allocator, number_of_ssa_values, false, kArenaAllocSsaLiveness),
39 kill_(allocator, number_of_ssa_values, false, kArenaAllocSsaLiveness) {
Ian Rogerscf7f1912014-10-22 22:06:39 -070040 UNUSED(block_);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010041 live_in_.ClearAllBits();
42 live_out_.ClearAllBits();
43 kill_.ClearAllBits();
44 }
45
46 private:
47 const HBasicBlock& block_;
48 ArenaBitVector live_in_;
49 ArenaBitVector live_out_;
50 ArenaBitVector kill_;
51
52 friend class SsaLivenessAnalysis;
53
54 DISALLOW_COPY_AND_ASSIGN(BlockInfo);
55};
56
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010057/**
Nicolas Geoffray39468442014-09-02 15:17:15 +010058 * A live range contains the start and end of a range where an instruction or a temporary
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010059 * is live.
60 */
Vladimir Marko5233f932015-09-29 19:01:15 +010061class LiveRange FINAL : public ArenaObject<kArenaAllocSsaLiveness> {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010062 public:
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010063 LiveRange(size_t start, size_t end, LiveRange* next) : start_(start), end_(end), next_(next) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010064 DCHECK_LT(start, end);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010065 DCHECK(next_ == nullptr || next_->GetStart() > GetEnd());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010066 }
67
68 size_t GetStart() const { return start_; }
69 size_t GetEnd() const { return end_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010070 LiveRange* GetNext() const { return next_; }
71
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070072 bool IntersectsWith(const LiveRange& other) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010073 return (start_ >= other.start_ && start_ < other.end_)
74 || (other.start_ >= start_ && other.start_ < end_);
75 }
76
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070077 bool IsBefore(const LiveRange& other) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010078 return end_ <= other.start_;
79 }
80
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070081 void Dump(std::ostream& stream) const {
David Brazdilc7a24852015-05-15 16:44:05 +010082 stream << "[" << start_ << "," << end_ << ")";
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010083 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010084
Nicolas Geoffray840e5462015-01-07 16:01:24 +000085 LiveRange* Dup(ArenaAllocator* allocator) const {
86 return new (allocator) LiveRange(
87 start_, end_, next_ == nullptr ? nullptr : next_->Dup(allocator));
88 }
89
90 LiveRange* GetLastRange() {
91 return next_ == nullptr ? this : next_->GetLastRange();
92 }
93
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010094 private:
95 size_t start_;
Nicolas Geoffray76905622014-09-25 14:39:26 +010096 size_t end_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010097 LiveRange* next_;
98
99 friend class LiveInterval;
100
101 DISALLOW_COPY_AND_ASSIGN(LiveRange);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100102};
103
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100104/**
105 * A use position represents a live interval use at a given position.
106 */
Vladimir Marko82b07402017-03-01 19:02:04 +0000107class UsePosition : public ArenaObject<kArenaAllocSsaLiveness>,
108 public IntrusiveForwardListNode<UsePosition> {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100109 public:
Vladimir Marko82b07402017-03-01 19:02:04 +0000110 UsePosition(HInstruction* user, size_t input_index, size_t position)
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100111 : user_(user),
112 input_index_(input_index),
Vladimir Marko82b07402017-03-01 19:02:04 +0000113 position_(position) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100114 }
115
Vladimir Marko356bd282017-03-01 12:01:11 +0000116 explicit UsePosition(size_t position)
117 : user_(nullptr),
118 input_index_(kNoInput),
Vladimir Marko82b07402017-03-01 19:02:04 +0000119 position_(dchecked_integral_cast<uint32_t>(position)) {
Vladimir Marko356bd282017-03-01 12:01:11 +0000120 }
Nicolas Geoffray57902602015-04-21 14:28:41 +0100121
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100122 size_t GetPosition() const { return position_; }
123
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100124 HInstruction* GetUser() const { return user_; }
125
Nicolas Geoffray57902602015-04-21 14:28:41 +0100126 bool IsSynthesized() const { return user_ == nullptr; }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100127
128 size_t GetInputIndex() const { return input_index_; }
129
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100130 void Dump(std::ostream& stream) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100131 stream << position_;
Nicolas Geoffray57902602015-04-21 14:28:41 +0100132 }
133
134 HLoopInformation* GetLoopInformation() const {
135 return user_->GetBlock()->GetLoopInformation();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100136 }
137
Vladimir Marko82b07402017-03-01 19:02:04 +0000138 UsePosition* Clone(ArenaAllocator* allocator) const {
139 return new (allocator) UsePosition(user_, input_index_, position_);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000140 }
141
Nicolas Geoffray57902602015-04-21 14:28:41 +0100142 bool RequiresRegister() const {
Nicolas Geoffray57902602015-04-21 14:28:41 +0100143 if (IsSynthesized()) return false;
144 Location location = GetUser()->GetLocations()->InAt(GetInputIndex());
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700145 return location.IsUnallocated() && location.RequiresRegisterKind();
Nicolas Geoffray57902602015-04-21 14:28:41 +0100146 }
147
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100148 private:
Vladimir Marko356bd282017-03-01 12:01:11 +0000149 static constexpr uint32_t kNoInput = static_cast<uint32_t>(-1);
150
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100151 HInstruction* const user_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100152 const size_t input_index_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100153 const size_t position_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100154
155 DISALLOW_COPY_AND_ASSIGN(UsePosition);
156};
Vladimir Marko82b07402017-03-01 19:02:04 +0000157using UsePositionList = IntrusiveForwardList<UsePosition>;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100158
Vladimir Marko356bd282017-03-01 12:01:11 +0000159/**
160 * An environment use position represents a live interval for environment use at a given position.
161 */
Vladimir Marko82b07402017-03-01 19:02:04 +0000162class EnvUsePosition : public ArenaObject<kArenaAllocSsaLiveness>,
163 public IntrusiveForwardListNode<EnvUsePosition> {
Vladimir Marko356bd282017-03-01 12:01:11 +0000164 public:
165 EnvUsePosition(HEnvironment* environment,
166 size_t input_index,
Vladimir Marko82b07402017-03-01 19:02:04 +0000167 size_t position)
Vladimir Marko356bd282017-03-01 12:01:11 +0000168 : environment_(environment),
169 input_index_(input_index),
Vladimir Marko82b07402017-03-01 19:02:04 +0000170 position_(position) {
Vladimir Marko356bd282017-03-01 12:01:11 +0000171 DCHECK(environment != nullptr);
Vladimir Marko356bd282017-03-01 12:01:11 +0000172 }
173
174 size_t GetPosition() const { return position_; }
175
Vladimir Marko356bd282017-03-01 12:01:11 +0000176 HEnvironment* GetEnvironment() const { return environment_; }
177 size_t GetInputIndex() const { return input_index_; }
178
179 void Dump(std::ostream& stream) const {
180 stream << position_;
181 }
182
Vladimir Marko82b07402017-03-01 19:02:04 +0000183 EnvUsePosition* Clone(ArenaAllocator* allocator) const {
184 return new (allocator) EnvUsePosition(environment_, input_index_, position_);
Vladimir Marko356bd282017-03-01 12:01:11 +0000185 }
186
187 private:
188 HEnvironment* const environment_;
189 const size_t input_index_;
190 const size_t position_;
Vladimir Marko356bd282017-03-01 12:01:11 +0000191
192 DISALLOW_COPY_AND_ASSIGN(EnvUsePosition);
193};
Vladimir Marko82b07402017-03-01 19:02:04 +0000194using EnvUsePositionList = IntrusiveForwardList<EnvUsePosition>;
195
196template <typename Iterator>
197inline Iterator FindUseAtOrAfterPosition(Iterator first, Iterator last, size_t position) {
198 using value_type = const typename Iterator::value_type;
199 static_assert(std::is_same<value_type, const UsePosition>::value ||
200 std::is_same<value_type, const EnvUsePosition>::value,
201 "Expecting value type UsePosition or EnvUsePosition.");
202 Iterator ret = std::find_if(
203 first, last, [position](const value_type& use) { return use.GetPosition() >= position; });
204 // Check that the processed range is sorted. Do not check the rest of the range to avoid
205 // increasing the complexity of callers from O(n) to O(n^2).
206 DCHECK(std::is_sorted(
207 first,
208 ret,
209 [](const value_type& lhs, const value_type& rhs) {
210 return lhs.GetPosition() < rhs.GetPosition();
211 }));
212 return ret;
213}
214
215template <typename Iterator>
216inline IterationRange<Iterator> FindMatchingUseRange(Iterator first,
217 Iterator last,
218 size_t position_begin,
219 size_t position_end) {
220 Iterator begin = FindUseAtOrAfterPosition(first, last, position_begin);
221 Iterator end = FindUseAtOrAfterPosition(begin, last, position_end);
222 return MakeIterationRange(begin, end);
223}
Vladimir Marko356bd282017-03-01 12:01:11 +0000224
Vladimir Marko5233f932015-09-29 19:01:15 +0100225class SafepointPosition : public ArenaObject<kArenaAllocSsaLiveness> {
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100226 public:
227 explicit SafepointPosition(HInstruction* instruction)
228 : instruction_(instruction),
229 next_(nullptr) {}
230
231 void SetNext(SafepointPosition* next) {
232 next_ = next;
233 }
234
235 size_t GetPosition() const {
236 return instruction_->GetLifetimePosition();
237 }
238
239 SafepointPosition* GetNext() const {
240 return next_;
241 }
242
243 LocationSummary* GetLocations() const {
244 return instruction_->GetLocations();
245 }
246
247 HInstruction* GetInstruction() const {
248 return instruction_;
249 }
250
251 private:
252 HInstruction* const instruction_;
253 SafepointPosition* next_;
254
255 DISALLOW_COPY_AND_ASSIGN(SafepointPosition);
256};
257
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100258/**
259 * An interval is a list of disjoint live ranges where an instruction is live.
260 * Each instruction that has uses gets an interval.
261 */
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100262class LiveInterval : public ArenaObject<kArenaAllocSsaLiveness> {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100263 public:
Mingyao Yang296bd602014-10-06 16:47:28 -0700264 static LiveInterval* MakeInterval(ArenaAllocator* allocator,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100265 DataType::Type type,
Mingyao Yang296bd602014-10-06 16:47:28 -0700266 HInstruction* instruction = nullptr) {
267 return new (allocator) LiveInterval(allocator, type, instruction);
268 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100269
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100270 static LiveInterval* MakeFixedInterval(ArenaAllocator* allocator, int reg, DataType::Type type) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100271 return new (allocator) LiveInterval(allocator, type, nullptr, true, reg, false);
272 }
273
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100274 static LiveInterval* MakeTempInterval(ArenaAllocator* allocator, DataType::Type type) {
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100275 return new (allocator) LiveInterval(allocator, type, nullptr, false, kNoRegister, true);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100276 }
277
278 bool IsFixed() const { return is_fixed_; }
Mingyao Yang296bd602014-10-06 16:47:28 -0700279 bool IsTemp() const { return is_temp_; }
Mingyao Yang296bd602014-10-06 16:47:28 -0700280 // This interval is the result of a split.
281 bool IsSplit() const { return parent_ != this; }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100282
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000283 void AddTempUse(HInstruction* instruction, size_t temp_index) {
284 DCHECK(IsTemp());
Vladimir Marko82b07402017-03-01 19:02:04 +0000285 DCHECK(GetUses().empty()) << "A temporary can only have one user";
286 DCHECK(GetEnvironmentUses().empty()) << "A temporary cannot have environment user";
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000287 size_t position = instruction->GetLifetimePosition();
Vladimir Marko82b07402017-03-01 19:02:04 +0000288 UsePosition* new_use = new (allocator_) UsePosition(instruction, temp_index, position);
289 uses_.push_front(*new_use);
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000290 AddRange(position, position + 1);
291 }
292
David Brazdilb3e773e2016-01-26 11:28:37 +0000293 // Record use of an input. The use will be recorded as an environment use if
294 // `environment` is not null and as register use otherwise. If `actual_user`
295 // is specified, the use will be recorded at `actual_user`'s lifetime position.
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000296 void AddUse(HInstruction* instruction,
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100297 HEnvironment* environment,
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000298 size_t input_index,
David Brazdilb3e773e2016-01-26 11:28:37 +0000299 HInstruction* actual_user = nullptr,
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000300 bool keep_alive = false) {
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100301 bool is_environment = (environment != nullptr);
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000302 LocationSummary* locations = instruction->GetLocations();
David Brazdilb3e773e2016-01-26 11:28:37 +0000303 if (actual_user == nullptr) {
304 actual_user = instruction;
305 }
306
307 // Set the use within the instruction.
308 size_t position = actual_user->GetLifetimePosition() + 1;
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000309 if (!is_environment) {
310 if (locations->IsFixedInput(input_index) || locations->OutputUsesSameAs(input_index)) {
311 // For fixed inputs and output same as input, the register allocator
312 // requires to have inputs die at the instruction, so that input moves use the
313 // location of the input just before that instruction (and not potential moves due
314 // to splitting).
David Brazdilb3e773e2016-01-26 11:28:37 +0000315 DCHECK_EQ(instruction, actual_user);
316 position = actual_user->GetLifetimePosition();
Nicolas Geoffray57902602015-04-21 14:28:41 +0100317 } else if (!locations->InAt(input_index).IsValid()) {
318 return;
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000319 }
Nicolas Geoffray76905622014-09-25 14:39:26 +0100320 }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000321
Nicolas Geoffray57902602015-04-21 14:28:41 +0100322 if (!is_environment && instruction->IsInLoop()) {
323 AddBackEdgeUses(*instruction->GetBlock());
324 }
325
Vladimir Marko82b07402017-03-01 19:02:04 +0000326 if ((!uses_.empty()) &&
327 (uses_.front().GetUser() == actual_user) &&
328 (uses_.front().GetPosition() < position)) {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100329 // The user uses the instruction multiple times, and one use dies before the other.
330 // We update the use list so that the latter is first.
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000331 DCHECK(!is_environment);
Vladimir Marko82b07402017-03-01 19:02:04 +0000332 DCHECK(uses_.front().GetPosition() + 1 == position);
333 UsePositionList::iterator next_pos = uses_.begin();
334 UsePositionList::iterator insert_pos;
335 do {
336 insert_pos = next_pos;
337 ++next_pos;
338 } while (next_pos != uses_.end() && next_pos->GetPosition() < position);
339 UsePosition* new_use = new (allocator_) UsePosition(instruction, input_index, position);
340 uses_.insert_after(insert_pos, *new_use);
341 if (first_range_->GetEnd() == uses_.front().GetPosition()) {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100342 first_range_->end_ = position;
343 }
344 return;
345 }
346
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100347 if (is_environment) {
Vladimir Marko82b07402017-03-01 19:02:04 +0000348 DCHECK(env_uses_.empty() || position <= env_uses_.front().GetPosition());
349 EnvUsePosition* new_env_use =
350 new (allocator_) EnvUsePosition(environment, input_index, position);
351 env_uses_.push_front(*new_env_use);
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100352 } else {
Vladimir Marko82b07402017-03-01 19:02:04 +0000353 DCHECK(uses_.empty() || position <= uses_.front().GetPosition());
354 UsePosition* new_use = new (allocator_) UsePosition(instruction, input_index, position);
355 uses_.push_front(*new_use);
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100356 }
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000357
358 if (is_environment && !keep_alive) {
359 // If this environment use does not keep the instruction live, it does not
360 // affect the live range of that instruction.
361 return;
362 }
363
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100364 size_t start_block_position = instruction->GetBlock()->GetLifetimeStart();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100365 if (first_range_ == nullptr) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100366 // First time we see a use of that interval.
David Brazdil3fc992f2015-04-16 18:31:55 +0100367 first_range_ = last_range_ = range_search_start_ =
368 new (allocator_) LiveRange(start_block_position, position, nullptr);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100369 } else if (first_range_->GetStart() == start_block_position) {
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100370 // There is a use later in the same block or in a following block.
371 // Note that in such a case, `AddRange` for the whole blocks has been called
372 // before arriving in this method, and this is the reason the start of
373 // `first_range_` is before the given `position`.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100374 DCHECK_LE(position, first_range_->GetEnd());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100375 } else {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100376 DCHECK(first_range_->GetStart() > position);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100377 // There is a hole in the interval. Create a new range.
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100378 // Note that the start of `first_range_` can be equal to `end`: two blocks
379 // having adjacent lifetime positions are not necessarily
380 // predecessor/successor. When two blocks are predecessor/successor, the
381 // liveness algorithm has called `AddRange` before arriving in this method,
382 // and the check line 205 would succeed.
David Brazdil3fc992f2015-04-16 18:31:55 +0100383 first_range_ = range_search_start_ =
384 new (allocator_) LiveRange(start_block_position, position, first_range_);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100385 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100386 }
387
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100388 void AddPhiUse(HInstruction* instruction, size_t input_index, HBasicBlock* block) {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100389 DCHECK(instruction->IsPhi());
Nicolas Geoffray57902602015-04-21 14:28:41 +0100390 if (block->IsInLoop()) {
391 AddBackEdgeUses(*block);
392 }
Vladimir Marko82b07402017-03-01 19:02:04 +0000393 UsePosition* new_use =
394 new (allocator_) UsePosition(instruction, input_index, block->GetLifetimeEnd());
395 uses_.push_front(*new_use);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100396 }
397
Mingyao Yang01b47b02017-02-03 12:09:57 -0800398 ALWAYS_INLINE void AddRange(size_t start, size_t end) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100399 if (first_range_ == nullptr) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100400 first_range_ = last_range_ = range_search_start_ =
401 new (allocator_) LiveRange(start, end, first_range_);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100402 } else if (first_range_->GetStart() == end) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100403 // There is a use in the following block.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100404 first_range_->start_ = start;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100405 } else if (first_range_->GetStart() == start && first_range_->GetEnd() == end) {
406 DCHECK(is_fixed_);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100407 } else {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100408 DCHECK_GT(first_range_->GetStart(), end);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100409 // There is a hole in the interval. Create a new range.
David Brazdil3fc992f2015-04-16 18:31:55 +0100410 first_range_ = range_search_start_ = new (allocator_) LiveRange(start, end, first_range_);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100411 }
412 }
413
414 void AddLoopRange(size_t start, size_t end) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100415 DCHECK(first_range_ != nullptr);
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000416 DCHECK_LE(start, first_range_->GetStart());
417 // Find the range that covers the positions after the loop.
418 LiveRange* after_loop = first_range_;
419 LiveRange* last_in_loop = nullptr;
420 while (after_loop != nullptr && after_loop->GetEnd() < end) {
421 DCHECK_LE(start, after_loop->GetStart());
422 last_in_loop = after_loop;
423 after_loop = after_loop->GetNext();
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100424 }
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000425 if (after_loop == nullptr) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100426 // Uses are only in the loop.
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700427 first_range_ = last_range_ = range_search_start_ =
428 new (allocator_) LiveRange(start, end, nullptr);
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000429 } else if (after_loop->GetStart() <= end) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100430 first_range_ = range_search_start_ = after_loop;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100431 // There are uses after the loop.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100432 first_range_->start_ = start;
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000433 } else {
434 // The use after the loop is after a lifetime hole.
435 DCHECK(last_in_loop != nullptr);
David Brazdil3fc992f2015-04-16 18:31:55 +0100436 first_range_ = range_search_start_ = last_in_loop;
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000437 first_range_->start_ = start;
438 first_range_->end_ = end;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100439 }
440 }
441
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100442 bool HasSpillSlot() const { return spill_slot_ != kNoSpillSlot; }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100443 void SetSpillSlot(int slot) {
444 DCHECK(!is_fixed_);
445 DCHECK(!is_temp_);
446 spill_slot_ = slot;
447 }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100448 int GetSpillSlot() const { return spill_slot_; }
449
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100450 void SetFrom(size_t from) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100451 if (first_range_ != nullptr) {
452 first_range_->start_ = from;
453 } else {
454 // Instruction without uses.
Vladimir Marko82b07402017-03-01 19:02:04 +0000455 DCHECK(uses_.empty());
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100456 DCHECK(from == defined_by_->GetLifetimePosition());
David Brazdil3fc992f2015-04-16 18:31:55 +0100457 first_range_ = last_range_ = range_search_start_ =
458 new (allocator_) LiveRange(from, from + 2, nullptr);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100459 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100460 }
461
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100462 LiveInterval* GetParent() const { return parent_; }
463
Nicolas Geoffray1ba19812015-04-21 09:12:40 +0100464 // Returns whether this interval is the parent interval, that is, the interval
465 // that starts where the HInstruction is defined.
466 bool IsParent() const { return parent_ == this; }
467
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100468 LiveRange* GetFirstRange() const { return first_range_; }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000469 LiveRange* GetLastRange() const { return last_range_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100470
471 int GetRegister() const { return register_; }
472 void SetRegister(int reg) { register_ = reg; }
473 void ClearRegister() { register_ = kNoRegister; }
474 bool HasRegister() const { return register_ != kNoRegister; }
475
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100476 bool IsDeadAt(size_t position) const {
David Brazdil241a4862015-04-16 17:59:03 +0100477 return GetEnd() <= position;
478 }
479
480 bool IsDefinedAt(size_t position) const {
481 return GetStart() <= position && !IsDeadAt(position);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100482 }
483
David Brazdil3fc992f2015-04-16 18:31:55 +0100484 // Returns true if the interval contains a LiveRange covering `position`.
485 // The range at or immediately after the current position of linear scan
486 // is cached for better performance. If `position` can be smaller than
487 // that, CoversSlow should be used instead.
David Brazdil5b8e6a52015-02-25 16:17:05 +0000488 bool Covers(size_t position) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100489 LiveRange* candidate = FindRangeAtOrAfter(position, range_search_start_);
490 range_search_start_ = candidate;
491 return (candidate != nullptr && candidate->GetStart() <= position);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100492 }
493
David Brazdil3fc992f2015-04-16 18:31:55 +0100494 // Same as Covers but always tests all ranges.
495 bool CoversSlow(size_t position) const {
496 LiveRange* candidate = FindRangeAtOrAfter(position, first_range_);
497 return candidate != nullptr && candidate->GetStart() <= position;
498 }
499
500 // Returns the first intersection of this interval with `current`, which
501 // must be the interval currently being allocated by linear scan.
502 size_t FirstIntersectionWith(LiveInterval* current) const {
503 // Find the first range after the start of `current`. We use the search
504 // cache to improve performance.
505 DCHECK(GetStart() <= current->GetStart() || IsFixed());
506 LiveRange* other_range = current->first_range_;
507 LiveRange* my_range = FindRangeAtOrAfter(other_range->GetStart(), range_search_start_);
508 if (my_range == nullptr) {
509 return kNoLifetime;
510 }
511
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100512 // Advance both intervals and find the first matching range start in
513 // this interval.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100514 do {
David Brazdil714e14f2015-02-25 11:57:05 +0000515 if (my_range->IsBefore(*other_range)) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100516 my_range = my_range->GetNext();
517 if (my_range == nullptr) {
518 return kNoLifetime;
519 }
David Brazdil714e14f2015-02-25 11:57:05 +0000520 } else if (other_range->IsBefore(*my_range)) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100521 other_range = other_range->GetNext();
522 if (other_range == nullptr) {
523 return kNoLifetime;
524 }
David Brazdil714e14f2015-02-25 11:57:05 +0000525 } else {
526 DCHECK(my_range->IntersectsWith(*other_range));
527 return std::max(my_range->GetStart(), other_range->GetStart());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100528 }
529 } while (true);
530 }
531
532 size_t GetStart() const {
533 return first_range_->GetStart();
534 }
535
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100536 size_t GetEnd() const {
537 return last_range_->GetEnd();
538 }
539
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700540 size_t GetLength() const {
541 return GetEnd() - GetStart();
542 }
543
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100544 size_t FirstRegisterUseAfter(size_t position) const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100545 if (is_temp_) {
546 return position == GetStart() ? position : kNoLifetime;
547 }
Nicolas Geoffray57902602015-04-21 14:28:41 +0100548
549 if (IsDefiningPosition(position) && DefinitionRequiresRegister()) {
550 return position;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100551 }
552
Nicolas Geoffrayde025a72014-06-19 17:06:46 +0100553 size_t end = GetEnd();
Vladimir Marko82b07402017-03-01 19:02:04 +0000554 for (const UsePosition& use : GetUses()) {
555 size_t use_position = use.GetPosition();
556 if (use_position > end) {
557 break;
558 }
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100559 if (use_position > position) {
Vladimir Marko82b07402017-03-01 19:02:04 +0000560 if (use.RequiresRegister()) {
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +0100561 return use_position;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100562 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100563 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100564 }
565 return kNoLifetime;
566 }
567
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700568 // Returns the location of the first register use for this live interval,
569 // including a register definition if applicable.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100570 size_t FirstRegisterUse() const {
571 return FirstRegisterUseAfter(GetStart());
572 }
573
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700574 // Whether the interval requires a register rather than a stack location.
575 // If needed for performance, this could be cached.
Matthew Gharrity2ccae4a2016-08-12 16:10:45 +0000576 bool RequiresRegister() const {
577 return !HasRegister() && FirstRegisterUse() != kNoLifetime;
578 }
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700579
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000580 size_t FirstUseAfter(size_t position) const {
581 if (is_temp_) {
582 return position == GetStart() ? position : kNoLifetime;
583 }
584
Nicolas Geoffray57902602015-04-21 14:28:41 +0100585 if (IsDefiningPosition(position)) {
586 DCHECK(defined_by_->GetLocations()->Out().IsValid());
587 return position;
Nicolas Geoffray1ba19812015-04-21 09:12:40 +0100588 }
589
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000590 size_t end = GetEnd();
Vladimir Marko82b07402017-03-01 19:02:04 +0000591 for (const UsePosition& use : GetUses()) {
592 size_t use_position = use.GetPosition();
593 if (use_position > end) {
594 break;
595 }
Nicolas Geoffray57902602015-04-21 14:28:41 +0100596 if (use_position > position) {
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100597 return use_position;
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000598 }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000599 }
600 return kNoLifetime;
601 }
602
Vladimir Marko82b07402017-03-01 19:02:04 +0000603 const UsePositionList& GetUses() const {
604 return parent_->uses_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100605 }
606
Vladimir Marko82b07402017-03-01 19:02:04 +0000607 const EnvUsePositionList& GetEnvironmentUses() const {
608 return parent_->env_uses_;
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100609 }
610
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100611 DataType::Type GetType() const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100612 return type_;
613 }
614
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100615 HInstruction* GetDefinedBy() const {
616 return defined_by_;
617 }
618
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100619 bool HasWillCallSafepoint() const {
620 for (SafepointPosition* safepoint = first_safepoint_;
621 safepoint != nullptr;
622 safepoint = safepoint->GetNext()) {
623 if (safepoint->GetLocations()->WillCall()) return true;
624 }
625 return false;
626 }
627
Nicolas Geoffray43af7282015-04-16 13:01:01 +0100628 SafepointPosition* FindSafepointJustBefore(size_t position) const {
629 for (SafepointPosition* safepoint = first_safepoint_, *previous = nullptr;
630 safepoint != nullptr;
631 previous = safepoint, safepoint = safepoint->GetNext()) {
632 if (safepoint->GetPosition() >= position) return previous;
633 }
634 return last_safepoint_;
635 }
636
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100637 /**
638 * Split this interval at `position`. This interval is changed to:
639 * [start ... position).
640 *
641 * The new interval covers:
642 * [position ... end)
643 */
644 LiveInterval* SplitAt(size_t position) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100645 DCHECK(!is_temp_);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100646 DCHECK(!is_fixed_);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100647 DCHECK_GT(position, GetStart());
648
David Brazdil241a4862015-04-16 17:59:03 +0100649 if (GetEnd() <= position) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100650 // This range dies before `position`, no need to split.
651 return nullptr;
652 }
653
654 LiveInterval* new_interval = new (allocator_) LiveInterval(allocator_, type_);
Nicolas Geoffray43af7282015-04-16 13:01:01 +0100655 SafepointPosition* new_last_safepoint = FindSafepointJustBefore(position);
656 if (new_last_safepoint == nullptr) {
657 new_interval->first_safepoint_ = first_safepoint_;
658 new_interval->last_safepoint_ = last_safepoint_;
659 first_safepoint_ = last_safepoint_ = nullptr;
660 } else if (last_safepoint_ != new_last_safepoint) {
661 new_interval->last_safepoint_ = last_safepoint_;
662 new_interval->first_safepoint_ = new_last_safepoint->GetNext();
663 DCHECK(new_interval->first_safepoint_ != nullptr);
664 last_safepoint_ = new_last_safepoint;
665 last_safepoint_->SetNext(nullptr);
666 }
667
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100668 new_interval->next_sibling_ = next_sibling_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100669 next_sibling_ = new_interval;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100670 new_interval->parent_ = parent_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100671
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100672 LiveRange* current = first_range_;
673 LiveRange* previous = nullptr;
674 // Iterate over the ranges, and either find a range that covers this position, or
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +0000675 // two ranges in between this position (that is, the position is in a lifetime hole).
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100676 do {
677 if (position >= current->GetEnd()) {
678 // Move to next range.
679 previous = current;
680 current = current->next_;
681 } else if (position <= current->GetStart()) {
682 // If the previous range did not cover this position, we know position is in
683 // a lifetime hole. We can just break the first_range_ and last_range_ links
684 // and return the new interval.
685 DCHECK(previous != nullptr);
686 DCHECK(current != first_range_);
687 new_interval->last_range_ = last_range_;
688 last_range_ = previous;
689 previous->next_ = nullptr;
690 new_interval->first_range_ = current;
David Brazdil3fc992f2015-04-16 18:31:55 +0100691 if (range_search_start_ != nullptr && range_search_start_->GetEnd() >= current->GetEnd()) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700692 // Search start point is inside `new_interval`. Change it to null
David Brazdil3fc992f2015-04-16 18:31:55 +0100693 // (i.e. the end of the interval) in the original interval.
694 range_search_start_ = nullptr;
695 }
696 new_interval->range_search_start_ = new_interval->first_range_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100697 return new_interval;
698 } else {
699 // This range covers position. We create a new last_range_ for this interval
700 // that covers last_range_->Start() and position. We also shorten the current
701 // range and make it the first range of the new interval.
702 DCHECK(position < current->GetEnd() && position > current->GetStart());
703 new_interval->last_range_ = last_range_;
704 last_range_ = new (allocator_) LiveRange(current->start_, position, nullptr);
705 if (previous != nullptr) {
706 previous->next_ = last_range_;
707 } else {
708 first_range_ = last_range_;
709 }
710 new_interval->first_range_ = current;
711 current->start_ = position;
David Brazdil3fc992f2015-04-16 18:31:55 +0100712 if (range_search_start_ != nullptr && range_search_start_->GetEnd() >= current->GetEnd()) {
713 // Search start point is inside `new_interval`. Change it to `last_range`
714 // in the original interval. This is conservative but always correct.
715 range_search_start_ = last_range_;
716 }
717 new_interval->range_search_start_ = new_interval->first_range_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100718 return new_interval;
719 }
720 } while (current != nullptr);
721
722 LOG(FATAL) << "Unreachable";
723 return nullptr;
724 }
725
Nicolas Geoffray76905622014-09-25 14:39:26 +0100726 bool StartsBeforeOrAt(LiveInterval* other) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100727 return GetStart() <= other->GetStart();
728 }
729
730 bool StartsAfter(LiveInterval* other) const {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100731 return GetStart() > other->GetStart();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100732 }
733
734 void Dump(std::ostream& stream) const {
735 stream << "ranges: { ";
736 LiveRange* current = first_range_;
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000737 while (current != nullptr) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100738 current->Dump(stream);
739 stream << " ";
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000740 current = current->GetNext();
741 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100742 stream << "}, uses: { ";
Vladimir Marko82b07402017-03-01 19:02:04 +0000743 for (const UsePosition& use : GetUses()) {
744 use.Dump(stream);
745 stream << " ";
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100746 }
Nicolas Geoffray57902602015-04-21 14:28:41 +0100747 stream << "}, { ";
Vladimir Marko82b07402017-03-01 19:02:04 +0000748 for (const EnvUsePosition& env_use : GetEnvironmentUses()) {
749 env_use.Dump(stream);
750 stream << " ";
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100751 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100752 stream << "}";
Mingyao Yang296bd602014-10-06 16:47:28 -0700753 stream << " is_fixed: " << is_fixed_ << ", is_split: " << IsSplit();
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000754 stream << " is_low: " << IsLowInterval();
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100755 stream << " is_high: " << IsHighInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100756 }
757
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700758 // Same as Dump, but adds context such as the instruction defining this interval, and
759 // the register currently assigned to this interval.
760 void DumpWithContext(std::ostream& stream, const CodeGenerator& codegen) const;
761
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100762 LiveInterval* GetNextSibling() const { return next_sibling_; }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000763 LiveInterval* GetLastSibling() {
764 LiveInterval* result = this;
765 while (result->next_sibling_ != nullptr) {
766 result = result->next_sibling_;
767 }
768 return result;
769 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100770
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100771 // Returns the first register hint that is at least free before
772 // the value contained in `free_until`. If none is found, returns
773 // `kNoRegister`.
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +0100774 int FindFirstRegisterHint(size_t* free_until, const SsaLivenessAnalysis& liveness) const;
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100775
776 // If there is enough at the definition site to find a register (for example
777 // it uses the same input as the first input), returns the register as a hint.
778 // Returns kNoRegister otherwise.
779 int FindHintAtDefinition() const;
780
Aart Bikcc895252017-03-21 10:55:15 -0700781 // Returns the number of required spilling slots (measured as a multiple of the
782 // Dex virtual register size `kVRegSize`).
783 size_t NumberOfSpillSlotsNeeded() const;
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100784
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100785 bool IsFloatingPoint() const {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100786 return type_ == DataType::Type::kFloat32 || type_ == DataType::Type::kFloat64;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100787 }
788
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100789 // Converts the location of the interval to a `Location` object.
790 Location ToLocation() const;
791
792 // Returns the location of the interval following its siblings at `position`.
David Brazdil5b8e6a52015-02-25 16:17:05 +0000793 Location GetLocationAt(size_t position);
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100794
David Brazdil241a4862015-04-16 17:59:03 +0100795 // Finds the sibling that is defined at `position`.
796 LiveInterval* GetSiblingAt(size_t position);
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100797
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100798 // Returns whether `other` and `this` share the same kind of register.
799 bool SameRegisterKind(Location other) const;
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000800 bool SameRegisterKind(const LiveInterval& other) const {
801 return IsFloatingPoint() == other.IsFloatingPoint();
802 }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100803
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000804 bool HasHighInterval() const {
Nicolas Geoffray3747b482015-01-19 17:17:16 +0000805 return IsLowInterval();
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000806 }
807
808 bool HasLowInterval() const {
809 return IsHighInterval();
810 }
811
812 LiveInterval* GetLowInterval() const {
813 DCHECK(HasLowInterval());
814 return high_or_low_interval_;
815 }
816
817 LiveInterval* GetHighInterval() const {
818 DCHECK(HasHighInterval());
819 return high_or_low_interval_;
820 }
821
822 bool IsHighInterval() const {
823 return GetParent()->is_high_interval_;
824 }
825
826 bool IsLowInterval() const {
827 return !IsHighInterval() && (GetParent()->high_or_low_interval_ != nullptr);
828 }
829
830 void SetLowInterval(LiveInterval* low) {
831 DCHECK(IsHighInterval());
832 high_or_low_interval_ = low;
833 }
834
835 void SetHighInterval(LiveInterval* high) {
836 DCHECK(IsLowInterval());
837 high_or_low_interval_ = high;
838 }
839
840 void AddHighInterval(bool is_temp = false) {
Nicolas Geoffray1ba19812015-04-21 09:12:40 +0100841 DCHECK(IsParent());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000842 DCHECK(!HasHighInterval());
843 DCHECK(!HasLowInterval());
844 high_or_low_interval_ = new (allocator_) LiveInterval(
Vladimir Marko70e97462016-08-09 11:04:26 +0100845 allocator_, type_, defined_by_, false, kNoRegister, is_temp, true);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000846 high_or_low_interval_->high_or_low_interval_ = this;
847 if (first_range_ != nullptr) {
848 high_or_low_interval_->first_range_ = first_range_->Dup(allocator_);
David Brazdilc08675c2015-04-17 15:49:51 +0100849 high_or_low_interval_->last_range_ = high_or_low_interval_->first_range_->GetLastRange();
David Brazdil3fc992f2015-04-16 18:31:55 +0100850 high_or_low_interval_->range_search_start_ = high_or_low_interval_->first_range_;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000851 }
Vladimir Marko82b07402017-03-01 19:02:04 +0000852 auto pos = high_or_low_interval_->uses_.before_begin();
853 for (const UsePosition& use : uses_) {
854 UsePosition* new_use = use.Clone(allocator_);
855 pos = high_or_low_interval_->uses_.insert_after(pos, *new_use);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000856 }
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100857
Vladimir Marko82b07402017-03-01 19:02:04 +0000858 auto env_pos = high_or_low_interval_->env_uses_.before_begin();
859 for (const EnvUsePosition& env_use : env_uses_) {
860 EnvUsePosition* new_env_use = env_use.Clone(allocator_);
861 env_pos = high_or_low_interval_->env_uses_.insert_after(env_pos, *new_env_use);
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100862 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000863 }
864
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000865 // Returns whether an interval, when it is non-split, is using
866 // the same register of one of its input.
867 bool IsUsingInputRegister() const {
David Brazdil3fc992f2015-04-16 18:31:55 +0100868 CHECK(kIsDebugBuild) << "Function should be used only for DCHECKs";
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000869 if (defined_by_ != nullptr && !IsSplit()) {
Vladimir Marko372f10e2016-05-17 16:30:10 +0100870 for (const HInstruction* input : defined_by_->GetInputs()) {
871 LiveInterval* interval = input->GetLiveInterval();
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000872
David Brazdil3fc992f2015-04-16 18:31:55 +0100873 // Find the interval that covers `defined_by`_. Calls to this function
874 // are made outside the linear scan, hence we need to use CoversSlow.
875 while (interval != nullptr && !interval->CoversSlow(defined_by_->GetLifetimePosition())) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000876 interval = interval->GetNextSibling();
877 }
878
879 // Check if both intervals have the same register of the same kind.
880 if (interval != nullptr
881 && interval->SameRegisterKind(*this)
882 && interval->GetRegister() == GetRegister()) {
883 return true;
884 }
885 }
886 }
887 return false;
888 }
889
890 // Returns whether an interval, when it is non-split, can safely use
891 // the same register of one of its input. Note that this method requires
892 // IsUsingInputRegister() to be true.
893 bool CanUseInputRegister() const {
David Brazdil3fc992f2015-04-16 18:31:55 +0100894 CHECK(kIsDebugBuild) << "Function should be used only for DCHECKs";
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000895 DCHECK(IsUsingInputRegister());
896 if (defined_by_ != nullptr && !IsSplit()) {
897 LocationSummary* locations = defined_by_->GetLocations();
898 if (locations->OutputCanOverlapWithInputs()) {
899 return false;
900 }
Vladimir Marko372f10e2016-05-17 16:30:10 +0100901 for (const HInstruction* input : defined_by_->GetInputs()) {
902 LiveInterval* interval = input->GetLiveInterval();
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000903
David Brazdil3fc992f2015-04-16 18:31:55 +0100904 // Find the interval that covers `defined_by`_. Calls to this function
905 // are made outside the linear scan, hence we need to use CoversSlow.
906 while (interval != nullptr && !interval->CoversSlow(defined_by_->GetLifetimePosition())) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000907 interval = interval->GetNextSibling();
908 }
909
910 if (interval != nullptr
911 && interval->SameRegisterKind(*this)
912 && interval->GetRegister() == GetRegister()) {
913 // We found the input that has the same register. Check if it is live after
914 // `defined_by`_.
David Brazdil3fc992f2015-04-16 18:31:55 +0100915 return !interval->CoversSlow(defined_by_->GetLifetimePosition() + 1);
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000916 }
917 }
918 }
919 LOG(FATAL) << "Unreachable";
920 UNREACHABLE();
921 }
922
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100923 void AddSafepoint(HInstruction* instruction) {
924 SafepointPosition* safepoint = new (allocator_) SafepointPosition(instruction);
925 if (first_safepoint_ == nullptr) {
926 first_safepoint_ = last_safepoint_ = safepoint;
927 } else {
928 DCHECK_LT(last_safepoint_->GetPosition(), safepoint->GetPosition());
929 last_safepoint_->SetNext(safepoint);
930 last_safepoint_ = safepoint;
931 }
932 }
933
934 SafepointPosition* GetFirstSafepoint() const {
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100935 return first_safepoint_;
936 }
937
David Brazdil3fc992f2015-04-16 18:31:55 +0100938 // Resets the starting point for range-searching queries to the first range.
939 // Intervals must be reset prior to starting a new linear scan over them.
940 void ResetSearchCache() {
941 range_search_start_ = first_range_;
942 }
943
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700944 bool DefinitionRequiresRegister() const {
945 DCHECK(IsParent());
946 LocationSummary* locations = defined_by_->GetLocations();
947 Location location = locations->Out();
948 // This interval is the first interval of the instruction. If the output
949 // of the instruction requires a register, we return the position of that instruction
950 // as the first register use.
951 if (location.IsUnallocated()) {
952 if ((location.GetPolicy() == Location::kRequiresRegister)
953 || (location.GetPolicy() == Location::kSameAsFirstInput
954 && (locations->InAt(0).IsRegister()
955 || locations->InAt(0).IsRegisterPair()
956 || locations->InAt(0).GetPolicy() == Location::kRequiresRegister))) {
957 return true;
958 } else if ((location.GetPolicy() == Location::kRequiresFpuRegister)
959 || (location.GetPolicy() == Location::kSameAsFirstInput
960 && (locations->InAt(0).IsFpuRegister()
961 || locations->InAt(0).IsFpuRegisterPair()
962 || locations->InAt(0).GetPolicy() == Location::kRequiresFpuRegister))) {
963 return true;
964 }
965 } else if (location.IsRegister() || location.IsRegisterPair()) {
966 return true;
967 }
968 return false;
969 }
970
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100971 private:
Mingyao Yang296bd602014-10-06 16:47:28 -0700972 LiveInterval(ArenaAllocator* allocator,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100973 DataType::Type type,
Mingyao Yang296bd602014-10-06 16:47:28 -0700974 HInstruction* defined_by = nullptr,
975 bool is_fixed = false,
976 int reg = kNoRegister,
977 bool is_temp = false,
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000978 bool is_high_interval = false)
Mingyao Yang296bd602014-10-06 16:47:28 -0700979 : allocator_(allocator),
980 first_range_(nullptr),
981 last_range_(nullptr),
David Brazdil3fc992f2015-04-16 18:31:55 +0100982 range_search_start_(nullptr),
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100983 first_safepoint_(nullptr),
984 last_safepoint_(nullptr),
Vladimir Marko82b07402017-03-01 19:02:04 +0000985 uses_(),
986 env_uses_(),
Mingyao Yang296bd602014-10-06 16:47:28 -0700987 type_(type),
988 next_sibling_(nullptr),
989 parent_(this),
990 register_(reg),
991 spill_slot_(kNoSpillSlot),
992 is_fixed_(is_fixed),
993 is_temp_(is_temp),
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000994 is_high_interval_(is_high_interval),
995 high_or_low_interval_(nullptr),
Mingyao Yang296bd602014-10-06 16:47:28 -0700996 defined_by_(defined_by) {}
997
David Brazdil3fc992f2015-04-16 18:31:55 +0100998 // Searches for a LiveRange that either covers the given position or is the
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700999 // first next LiveRange. Returns null if no such LiveRange exists. Ranges
David Brazdil3fc992f2015-04-16 18:31:55 +01001000 // known to end before `position` can be skipped with `search_start`.
1001 LiveRange* FindRangeAtOrAfter(size_t position, LiveRange* search_start) const {
David Brazdil5b8e6a52015-02-25 16:17:05 +00001002 if (kIsDebugBuild) {
David Brazdil3fc992f2015-04-16 18:31:55 +01001003 if (search_start != first_range_) {
1004 // If we are not searching the entire list of ranges, make sure we do
1005 // not skip the range we are searching for.
1006 if (search_start == nullptr) {
1007 DCHECK(IsDeadAt(position));
1008 } else if (search_start->GetStart() > position) {
1009 DCHECK_EQ(search_start, FindRangeAtOrAfter(position, first_range_));
1010 }
David Brazdil5b8e6a52015-02-25 16:17:05 +00001011 }
1012 }
1013
David Brazdil3fc992f2015-04-16 18:31:55 +01001014 LiveRange* range;
1015 for (range = search_start;
1016 range != nullptr && range->GetEnd() <= position;
1017 range = range->GetNext()) {
1018 continue;
David Brazdil5b8e6a52015-02-25 16:17:05 +00001019 }
David Brazdil3fc992f2015-04-16 18:31:55 +01001020 return range;
David Brazdil5b8e6a52015-02-25 16:17:05 +00001021 }
1022
Nicolas Geoffray57902602015-04-21 14:28:41 +01001023 bool IsDefiningPosition(size_t position) const {
1024 return IsParent() && (position == GetStart());
1025 }
1026
1027 bool HasSynthesizeUseAt(size_t position) const {
Vladimir Marko82b07402017-03-01 19:02:04 +00001028 for (const UsePosition& use : GetUses()) {
1029 size_t use_position = use.GetPosition();
1030 if ((use_position == position) && use.IsSynthesized()) {
Nicolas Geoffray57902602015-04-21 14:28:41 +01001031 return true;
1032 }
1033 if (use_position > position) break;
Nicolas Geoffray57902602015-04-21 14:28:41 +01001034 }
1035 return false;
1036 }
1037
1038 void AddBackEdgeUses(const HBasicBlock& block_at_use) {
1039 DCHECK(block_at_use.IsInLoop());
David Brazdil07b35102016-04-27 15:33:22 +01001040 if (block_at_use.GetGraph()->HasIrreducibleLoops()) {
1041 // Linear order may not be well formed when irreducible loops are present,
1042 // i.e. loop blocks may not be adjacent and a back edge may not be last,
1043 // which violates assumptions made in this method.
1044 return;
1045 }
1046
Nicolas Geoffray57902602015-04-21 14:28:41 +01001047 // Add synthesized uses at the back edge of loops to help the register allocator.
1048 // Note that this method is called in decreasing liveness order, to faciliate adding
Vladimir Marko82b07402017-03-01 19:02:04 +00001049 // uses at the head of the `uses_` list. Because below
Nicolas Geoffray57902602015-04-21 14:28:41 +01001050 // we iterate from inner-most to outer-most, which is in increasing liveness order,
Vladimir Marko82b07402017-03-01 19:02:04 +00001051 // we need to add subsequent entries after the last inserted entry.
1052 const UsePositionList::iterator old_begin = uses_.begin();
1053 UsePositionList::iterator insert_pos = uses_.before_begin();
Nicolas Geoffray57902602015-04-21 14:28:41 +01001054 for (HLoopInformationOutwardIterator it(block_at_use);
1055 !it.Done();
1056 it.Advance()) {
1057 HLoopInformation* current = it.Current();
1058 if (GetDefinedBy()->GetLifetimePosition() >= current->GetHeader()->GetLifetimeStart()) {
1059 // This interval is defined in the loop. We can stop going outward.
1060 break;
1061 }
1062
Vladimir Marko82b07402017-03-01 19:02:04 +00001063 // We're only adding a synthesized use at the last back edge. Adding synthesized uses on
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001064 // all back edges is not necessary: anything used in the loop will have its use at the
1065 // last back edge. If we want branches in a loop to have better register allocation than
1066 // another branch, then it is the linear order we should change.
1067 size_t back_edge_use_position = current->GetLifetimeEnd();
Vladimir Marko82b07402017-03-01 19:02:04 +00001068 if ((old_begin != uses_.end()) && (old_begin->GetPosition() <= back_edge_use_position)) {
Nicolas Geoffray57902602015-04-21 14:28:41 +01001069 // There was a use already seen in this loop. Therefore the previous call to `AddUse`
1070 // already inserted the backedge use. We can stop going outward.
David Brazdil07b35102016-04-27 15:33:22 +01001071 DCHECK(HasSynthesizeUseAt(back_edge_use_position));
Nicolas Geoffray57902602015-04-21 14:28:41 +01001072 break;
1073 }
1074
Vladimir Marko82b07402017-03-01 19:02:04 +00001075 DCHECK(insert_pos != uses_.before_begin()
1076 ? back_edge_use_position > insert_pos->GetPosition()
1077 : current == block_at_use.GetLoopInformation())
1078 << std::distance(uses_.before_begin(), insert_pos);
Nicolas Geoffray57902602015-04-21 14:28:41 +01001079
Vladimir Marko356bd282017-03-01 12:01:11 +00001080 UsePosition* new_use = new (allocator_) UsePosition(back_edge_use_position);
Vladimir Marko82b07402017-03-01 19:02:04 +00001081 insert_pos = uses_.insert_after(insert_pos, *new_use);
Nicolas Geoffray57902602015-04-21 14:28:41 +01001082 }
1083 }
1084
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001085 ArenaAllocator* const allocator_;
1086
1087 // Ranges of this interval. We need a quick access to the last range to test
1088 // for liveness (see `IsDeadAt`).
1089 LiveRange* first_range_;
1090 LiveRange* last_range_;
1091
David Brazdil3fc992f2015-04-16 18:31:55 +01001092 // The first range at or after the current position of a linear scan. It is
1093 // used to optimize range-searching queries.
1094 LiveRange* range_search_start_;
1095
Nicolas Geoffray43af7282015-04-16 13:01:01 +01001096 // Safepoints where this interval is live.
Nicolas Geoffray5588e582015-04-14 14:10:59 +01001097 SafepointPosition* first_safepoint_;
1098 SafepointPosition* last_safepoint_;
1099
Vladimir Marko82b07402017-03-01 19:02:04 +00001100 // Uses of this interval. Only the parent interval keeps these lists.
1101 UsePositionList uses_;
1102 EnvUsePositionList env_uses_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001103
1104 // The instruction type this interval corresponds to.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001105 const DataType::Type type_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001106
1107 // Live interval that is the result of a split.
1108 LiveInterval* next_sibling_;
1109
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001110 // The first interval from which split intervals come from.
1111 LiveInterval* parent_;
1112
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001113 // The register allocated to this interval.
1114 int register_;
1115
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001116 // The spill slot allocated to this interval.
1117 int spill_slot_;
1118
1119 // Whether the interval is for a fixed register.
Nicolas Geoffray39468442014-09-02 15:17:15 +01001120 const bool is_fixed_;
1121
1122 // Whether the interval is for a temporary.
1123 const bool is_temp_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001124
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001125 // Whether this interval is a synthesized interval for register pair.
1126 const bool is_high_interval_;
1127
1128 // If this interval needs a register pair, the high or low equivalent.
1129 // `is_high_interval_` tells whether this holds the low or the high.
1130 LiveInterval* high_or_low_interval_;
1131
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001132 // The instruction represented by this interval.
1133 HInstruction* const defined_by_;
1134
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001135 static constexpr int kNoRegister = -1;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001136 static constexpr int kNoSpillSlot = -1;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001137
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00001138 ART_FRIEND_TEST(RegisterAllocatorTest, SpillInactive);
1139
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001140 DISALLOW_COPY_AND_ASSIGN(LiveInterval);
1141};
1142
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001143/**
1144 * Analysis that computes the liveness of instructions:
1145 *
1146 * (a) Non-environment uses of an instruction always make
1147 * the instruction live.
1148 * (b) Environment uses of an instruction whose type is
1149 * object (that is, non-primitive), make the instruction live.
1150 * This is due to having to keep alive objects that have
1151 * finalizers deleting native objects.
1152 * (c) When the graph has the debuggable property, environment uses
1153 * of an instruction that has a primitive type make the instruction live.
1154 * If the graph does not have the debuggable property, the environment
1155 * use has no effect, and may get a 'none' value after register allocation.
1156 *
1157 * (b) and (c) are implemented through SsaLivenessAnalysis::ShouldBeLiveForEnvironment.
1158 */
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001159class SsaLivenessAnalysis : public ValueObject {
1160 public:
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01001161 SsaLivenessAnalysis(HGraph* graph, CodeGenerator* codegen)
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001162 : graph_(graph),
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001163 codegen_(codegen),
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001164 block_infos_(graph->GetBlocks().size(),
1165 nullptr,
1166 graph->GetArena()->Adapter(kArenaAllocSsaLiveness)),
1167 instructions_from_ssa_index_(graph->GetArena()->Adapter(kArenaAllocSsaLiveness)),
1168 instructions_from_lifetime_position_(graph->GetArena()->Adapter(kArenaAllocSsaLiveness)),
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001169 number_of_ssa_values_(0) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001170 }
1171
1172 void Analyze();
1173
1174 BitVector* GetLiveInSet(const HBasicBlock& block) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001175 return &block_infos_[block.GetBlockId()]->live_in_;
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001176 }
1177
1178 BitVector* GetLiveOutSet(const HBasicBlock& block) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001179 return &block_infos_[block.GetBlockId()]->live_out_;
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001180 }
1181
1182 BitVector* GetKillSet(const HBasicBlock& block) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001183 return &block_infos_[block.GetBlockId()]->kill_;
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001184 }
1185
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001186 HInstruction* GetInstructionFromSsaIndex(size_t index) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001187 return instructions_from_ssa_index_[index];
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001188 }
1189
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001190 HInstruction* GetInstructionFromPosition(size_t index) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001191 return instructions_from_lifetime_position_[index];
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001192 }
1193
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001194 HBasicBlock* GetBlockFromPosition(size_t index) const {
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +01001195 HInstruction* instruction = GetInstructionFromPosition(index);
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001196 if (instruction == nullptr) {
1197 // If we are at a block boundary, get the block following.
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +01001198 instruction = GetInstructionFromPosition(index + 1);
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001199 }
1200 return instruction->GetBlock();
1201 }
1202
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +01001203 bool IsAtBlockBoundary(size_t index) const {
1204 return GetInstructionFromPosition(index) == nullptr;
1205 }
1206
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001207 HInstruction* GetTempUser(LiveInterval* temp) const {
1208 // A temporary shares the same lifetime start as the instruction that requires it.
1209 DCHECK(temp->IsTemp());
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +00001210 HInstruction* user = GetInstructionFromPosition(temp->GetStart() / 2);
Vladimir Marko82b07402017-03-01 19:02:04 +00001211 DCHECK_EQ(user, temp->GetUses().front().GetUser());
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +00001212 return user;
1213 }
1214
1215 size_t GetTempIndex(LiveInterval* temp) const {
1216 // We use the input index to store the index of the temporary in the user's temporary list.
1217 DCHECK(temp->IsTemp());
Vladimir Marko82b07402017-03-01 19:02:04 +00001218 return temp->GetUses().front().GetInputIndex();
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001219 }
1220
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001221 size_t GetMaxLifetimePosition() const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001222 return instructions_from_lifetime_position_.size() * 2 - 1;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001223 }
1224
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001225 size_t GetNumberOfSsaValues() const {
1226 return number_of_ssa_values_;
1227 }
1228
Andreas Gampe7c3952f2015-02-19 18:21:24 -08001229 static constexpr const char* kLivenessPassName = "liveness";
1230
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001231 private:
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001232 // Give an SSA number to each instruction that defines a value used by another instruction,
1233 // and setup the lifetime information of each instruction and block.
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001234 void NumberInstructions();
1235
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001236 // Compute live ranges of instructions, as well as live_in, live_out and kill sets.
1237 void ComputeLiveness();
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001238
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001239 // Compute the live ranges of instructions, as well as the initial live_in, live_out and
1240 // kill sets, that do not take into account backward branches.
1241 void ComputeLiveRanges();
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001242
1243 // After computing the initial sets, this method does a fixed point
1244 // calculation over the live_in and live_out set to take into account
1245 // backwards branches.
1246 void ComputeLiveInAndLiveOutSets();
1247
1248 // Update the live_in set of the block and returns whether it has changed.
1249 bool UpdateLiveIn(const HBasicBlock& block);
1250
1251 // Update the live_out set of the block and returns whether it has changed.
1252 bool UpdateLiveOut(const HBasicBlock& block);
1253
Mingyao Yang718493c2015-07-22 15:56:34 -07001254 // Returns whether `instruction` in an HEnvironment held by `env_holder`
1255 // should be kept live by the HEnvironment.
Vladimir Marko356bd282017-03-01 12:01:11 +00001256 static bool ShouldBeLiveForEnvironment(HInstruction* env_holder, HInstruction* instruction) {
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001257 if (instruction == nullptr) return false;
Mingyao Yang718493c2015-07-22 15:56:34 -07001258 // A value that's not live in compiled code may still be needed in interpreter,
1259 // due to code motion, etc.
1260 if (env_holder->IsDeoptimize()) return true;
David Brazdil77a48ae2015-09-15 12:34:04 +00001261 // A value live at a throwing instruction in a try block may be copied by
1262 // the exception handler to its location at the top of the catch block.
1263 if (env_holder->CanThrowIntoCatchBlock()) return true;
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001264 if (instruction->GetBlock()->GetGraph()->IsDebuggable()) return true;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001265 return instruction->GetType() == DataType::Type::kReference;
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001266 }
1267
Nicolas Geoffrayd7c2fdc2016-05-10 14:35:34 +01001268 void CheckNoLiveInIrreducibleLoop(const HBasicBlock& block) const {
1269 if (!block.IsLoopHeader() || !block.GetLoopInformation()->IsIrreducible()) {
1270 return;
1271 }
1272 BitVector* live_in = GetLiveInSet(block);
1273 // To satisfy our liveness algorithm, we need to ensure loop headers of
1274 // irreducible loops do not have any live-in instructions, except constants
1275 // and the current method, which can be trivially re-materialized.
1276 for (uint32_t idx : live_in->Indexes()) {
1277 HInstruction* instruction = GetInstructionFromSsaIndex(idx);
1278 DCHECK(instruction->GetBlock()->IsEntryBlock()) << instruction->DebugName();
1279 DCHECK(!instruction->IsParameterValue());
1280 DCHECK(instruction->IsCurrentMethod() || instruction->IsConstant())
1281 << instruction->DebugName();
1282 }
1283 }
1284
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01001285 HGraph* const graph_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001286 CodeGenerator* const codegen_;
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001287 ArenaVector<BlockInfo*> block_infos_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001288
1289 // Temporary array used when computing live_in, live_out, and kill sets.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001290 ArenaVector<HInstruction*> instructions_from_ssa_index_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001291
1292 // Temporary array used when inserting moves in the graph.
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001293 ArenaVector<HInstruction*> instructions_from_lifetime_position_;
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001294 size_t number_of_ssa_values_;
1295
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001296 ART_FRIEND_TEST(RegisterAllocatorTest, SpillInactive);
Nicolas Geoffray23a81882015-06-01 18:12:38 +01001297 ART_FRIEND_TEST(RegisterAllocatorTest, FreeUntil);
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001298
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001299 DISALLOW_COPY_AND_ASSIGN(SsaLivenessAnalysis);
1300};
1301
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001302} // namespace art
1303
1304#endif // ART_COMPILER_OPTIMIZING_SSA_LIVENESS_ANALYSIS_H_