blob: f83bb52b69cace5a82419747785711c03a66185d [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 Markoe764d2e2017-10-05 14:35:55 +010023#include "base/scoped_arena_allocator.h"
24#include "base/scoped_arena_containers.h"
Vladimir Marko356bd282017-03-01 12:01:11 +000025#include "nodes.h"
Vladimir Marko82b07402017-03-01 19:02:04 +000026#include "utils/intrusive_forward_list.h"
Vladimir Marko356bd282017-03-01 12:01:11 +000027
Nicolas Geoffray804d0932014-05-02 08:46:00 +010028namespace art {
29
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010030class CodeGenerator;
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +010031class SsaLivenessAnalysis;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010032
Nicolas Geoffray01ef3452014-10-01 11:32:17 +010033static constexpr int kNoRegister = -1;
34
Vladimir Marko5233f932015-09-29 19:01:15 +010035class BlockInfo : public ArenaObject<kArenaAllocSsaLiveness> {
Nicolas Geoffray804d0932014-05-02 08:46:00 +010036 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +010037 BlockInfo(ScopedArenaAllocator* allocator, const HBasicBlock& block, size_t number_of_ssa_values)
Nicolas Geoffray804d0932014-05-02 08:46:00 +010038 : block_(block),
Vladimir Markof6a35de2016-03-21 12:01:50 +000039 live_in_(allocator, number_of_ssa_values, false, kArenaAllocSsaLiveness),
40 live_out_(allocator, number_of_ssa_values, false, kArenaAllocSsaLiveness),
41 kill_(allocator, number_of_ssa_values, false, kArenaAllocSsaLiveness) {
Ian Rogerscf7f1912014-10-22 22:06:39 -070042 UNUSED(block_);
Nicolas Geoffray804d0932014-05-02 08:46:00 +010043 live_in_.ClearAllBits();
44 live_out_.ClearAllBits();
45 kill_.ClearAllBits();
46 }
47
48 private:
49 const HBasicBlock& block_;
50 ArenaBitVector live_in_;
51 ArenaBitVector live_out_;
52 ArenaBitVector kill_;
53
54 friend class SsaLivenessAnalysis;
55
56 DISALLOW_COPY_AND_ASSIGN(BlockInfo);
57};
58
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010059/**
Nicolas Geoffray39468442014-09-02 15:17:15 +010060 * A live range contains the start and end of a range where an instruction or a temporary
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010061 * is live.
62 */
Vladimir Marko5233f932015-09-29 19:01:15 +010063class LiveRange FINAL : public ArenaObject<kArenaAllocSsaLiveness> {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010064 public:
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010065 LiveRange(size_t start, size_t end, LiveRange* next) : start_(start), end_(end), next_(next) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010066 DCHECK_LT(start, end);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010067 DCHECK(next_ == nullptr || next_->GetStart() > GetEnd());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010068 }
69
70 size_t GetStart() const { return start_; }
71 size_t GetEnd() const { return end_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010072 LiveRange* GetNext() const { return next_; }
73
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070074 bool IntersectsWith(const LiveRange& other) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010075 return (start_ >= other.start_ && start_ < other.end_)
76 || (other.start_ >= start_ && other.start_ < end_);
77 }
78
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070079 bool IsBefore(const LiveRange& other) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010080 return end_ <= other.start_;
81 }
82
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070083 void Dump(std::ostream& stream) const {
David Brazdilc7a24852015-05-15 16:44:05 +010084 stream << "[" << start_ << "," << end_ << ")";
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010085 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010086
Vladimir Markoe764d2e2017-10-05 14:35:55 +010087 LiveRange* Dup(ScopedArenaAllocator* allocator) const {
Nicolas Geoffray840e5462015-01-07 16:01:24 +000088 return new (allocator) LiveRange(
89 start_, end_, next_ == nullptr ? nullptr : next_->Dup(allocator));
90 }
91
92 LiveRange* GetLastRange() {
93 return next_ == nullptr ? this : next_->GetLastRange();
94 }
95
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010096 private:
97 size_t start_;
Nicolas Geoffray76905622014-09-25 14:39:26 +010098 size_t end_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +010099 LiveRange* next_;
100
101 friend class LiveInterval;
102
103 DISALLOW_COPY_AND_ASSIGN(LiveRange);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100104};
105
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100106/**
107 * A use position represents a live interval use at a given position.
108 */
Vladimir Marko82b07402017-03-01 19:02:04 +0000109class UsePosition : public ArenaObject<kArenaAllocSsaLiveness>,
110 public IntrusiveForwardListNode<UsePosition> {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100111 public:
Vladimir Marko82b07402017-03-01 19:02:04 +0000112 UsePosition(HInstruction* user, size_t input_index, size_t position)
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100113 : user_(user),
114 input_index_(input_index),
Vladimir Marko82b07402017-03-01 19:02:04 +0000115 position_(position) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100116 }
117
Vladimir Marko356bd282017-03-01 12:01:11 +0000118 explicit UsePosition(size_t position)
119 : user_(nullptr),
120 input_index_(kNoInput),
Vladimir Marko82b07402017-03-01 19:02:04 +0000121 position_(dchecked_integral_cast<uint32_t>(position)) {
Vladimir Marko356bd282017-03-01 12:01:11 +0000122 }
Nicolas Geoffray57902602015-04-21 14:28:41 +0100123
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100124 size_t GetPosition() const { return position_; }
125
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100126 HInstruction* GetUser() const { return user_; }
127
Nicolas Geoffray57902602015-04-21 14:28:41 +0100128 bool IsSynthesized() const { return user_ == nullptr; }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100129
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_;
Nicolas Geoffray57902602015-04-21 14:28:41 +0100134 }
135
136 HLoopInformation* GetLoopInformation() const {
137 return user_->GetBlock()->GetLoopInformation();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100138 }
139
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100140 UsePosition* Clone(ScopedArenaAllocator* allocator) const {
Vladimir Marko82b07402017-03-01 19:02:04 +0000141 return new (allocator) UsePosition(user_, input_index_, position_);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000142 }
143
Nicolas Geoffray57902602015-04-21 14:28:41 +0100144 bool RequiresRegister() const {
Nicolas Geoffray57902602015-04-21 14:28:41 +0100145 if (IsSynthesized()) return false;
146 Location location = GetUser()->GetLocations()->InAt(GetInputIndex());
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700147 return location.IsUnallocated() && location.RequiresRegisterKind();
Nicolas Geoffray57902602015-04-21 14:28:41 +0100148 }
149
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100150 private:
Vladimir Marko356bd282017-03-01 12:01:11 +0000151 static constexpr uint32_t kNoInput = static_cast<uint32_t>(-1);
152
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100153 HInstruction* const user_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100154 const size_t input_index_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100155 const size_t position_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100156
157 DISALLOW_COPY_AND_ASSIGN(UsePosition);
158};
Vladimir Marko82b07402017-03-01 19:02:04 +0000159using UsePositionList = IntrusiveForwardList<UsePosition>;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100160
Vladimir Marko356bd282017-03-01 12:01:11 +0000161/**
162 * An environment use position represents a live interval for environment use at a given position.
163 */
Vladimir Marko82b07402017-03-01 19:02:04 +0000164class EnvUsePosition : public ArenaObject<kArenaAllocSsaLiveness>,
165 public IntrusiveForwardListNode<EnvUsePosition> {
Vladimir Marko356bd282017-03-01 12:01:11 +0000166 public:
167 EnvUsePosition(HEnvironment* environment,
168 size_t input_index,
Vladimir Marko82b07402017-03-01 19:02:04 +0000169 size_t position)
Vladimir Marko356bd282017-03-01 12:01:11 +0000170 : environment_(environment),
171 input_index_(input_index),
Vladimir Marko82b07402017-03-01 19:02:04 +0000172 position_(position) {
Vladimir Marko356bd282017-03-01 12:01:11 +0000173 DCHECK(environment != nullptr);
Vladimir Marko356bd282017-03-01 12:01:11 +0000174 }
175
176 size_t GetPosition() const { return position_; }
177
Vladimir Marko356bd282017-03-01 12:01:11 +0000178 HEnvironment* GetEnvironment() const { return environment_; }
179 size_t GetInputIndex() const { return input_index_; }
180
181 void Dump(std::ostream& stream) const {
182 stream << position_;
183 }
184
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100185 EnvUsePosition* Clone(ScopedArenaAllocator* allocator) const {
Vladimir Marko82b07402017-03-01 19:02:04 +0000186 return new (allocator) EnvUsePosition(environment_, input_index_, position_);
Vladimir Marko356bd282017-03-01 12:01:11 +0000187 }
188
189 private:
190 HEnvironment* const environment_;
191 const size_t input_index_;
192 const size_t position_;
Vladimir Marko356bd282017-03-01 12:01:11 +0000193
194 DISALLOW_COPY_AND_ASSIGN(EnvUsePosition);
195};
Vladimir Marko82b07402017-03-01 19:02:04 +0000196using EnvUsePositionList = IntrusiveForwardList<EnvUsePosition>;
197
198template <typename Iterator>
199inline Iterator FindUseAtOrAfterPosition(Iterator first, Iterator last, size_t position) {
200 using value_type = const typename Iterator::value_type;
201 static_assert(std::is_same<value_type, const UsePosition>::value ||
202 std::is_same<value_type, const EnvUsePosition>::value,
203 "Expecting value type UsePosition or EnvUsePosition.");
204 Iterator ret = std::find_if(
205 first, last, [position](const value_type& use) { return use.GetPosition() >= position; });
206 // Check that the processed range is sorted. Do not check the rest of the range to avoid
207 // increasing the complexity of callers from O(n) to O(n^2).
208 DCHECK(std::is_sorted(
209 first,
210 ret,
211 [](const value_type& lhs, const value_type& rhs) {
212 return lhs.GetPosition() < rhs.GetPosition();
213 }));
214 return ret;
215}
216
217template <typename Iterator>
218inline IterationRange<Iterator> FindMatchingUseRange(Iterator first,
219 Iterator last,
220 size_t position_begin,
221 size_t position_end) {
222 Iterator begin = FindUseAtOrAfterPosition(first, last, position_begin);
223 Iterator end = FindUseAtOrAfterPosition(begin, last, position_end);
224 return MakeIterationRange(begin, end);
225}
Vladimir Marko356bd282017-03-01 12:01:11 +0000226
Vladimir Marko5233f932015-09-29 19:01:15 +0100227class SafepointPosition : public ArenaObject<kArenaAllocSsaLiveness> {
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100228 public:
229 explicit SafepointPosition(HInstruction* instruction)
230 : instruction_(instruction),
231 next_(nullptr) {}
232
233 void SetNext(SafepointPosition* next) {
234 next_ = next;
235 }
236
237 size_t GetPosition() const {
238 return instruction_->GetLifetimePosition();
239 }
240
241 SafepointPosition* GetNext() const {
242 return next_;
243 }
244
245 LocationSummary* GetLocations() const {
246 return instruction_->GetLocations();
247 }
248
249 HInstruction* GetInstruction() const {
250 return instruction_;
251 }
252
253 private:
254 HInstruction* const instruction_;
255 SafepointPosition* next_;
256
257 DISALLOW_COPY_AND_ASSIGN(SafepointPosition);
258};
259
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100260/**
261 * An interval is a list of disjoint live ranges where an instruction is live.
262 * Each instruction that has uses gets an interval.
263 */
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100264class LiveInterval : public ArenaObject<kArenaAllocSsaLiveness> {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100265 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100266 static LiveInterval* MakeInterval(ScopedArenaAllocator* allocator,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100267 DataType::Type type,
Mingyao Yang296bd602014-10-06 16:47:28 -0700268 HInstruction* instruction = nullptr) {
269 return new (allocator) LiveInterval(allocator, type, instruction);
270 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100271
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100272 static LiveInterval* MakeFixedInterval(ScopedArenaAllocator* allocator,
273 int reg,
274 DataType::Type type) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100275 return new (allocator) LiveInterval(allocator, type, nullptr, true, reg, false);
276 }
277
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100278 static LiveInterval* MakeTempInterval(ScopedArenaAllocator* allocator, DataType::Type type) {
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100279 return new (allocator) LiveInterval(allocator, type, nullptr, false, kNoRegister, true);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100280 }
281
282 bool IsFixed() const { return is_fixed_; }
Mingyao Yang296bd602014-10-06 16:47:28 -0700283 bool IsTemp() const { return is_temp_; }
Mingyao Yang296bd602014-10-06 16:47:28 -0700284 // This interval is the result of a split.
285 bool IsSplit() const { return parent_ != this; }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100286
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000287 void AddTempUse(HInstruction* instruction, size_t temp_index) {
288 DCHECK(IsTemp());
Vladimir Marko82b07402017-03-01 19:02:04 +0000289 DCHECK(GetUses().empty()) << "A temporary can only have one user";
290 DCHECK(GetEnvironmentUses().empty()) << "A temporary cannot have environment user";
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000291 size_t position = instruction->GetLifetimePosition();
Vladimir Marko82b07402017-03-01 19:02:04 +0000292 UsePosition* new_use = new (allocator_) UsePosition(instruction, temp_index, position);
293 uses_.push_front(*new_use);
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +0000294 AddRange(position, position + 1);
295 }
296
David Brazdilb3e773e2016-01-26 11:28:37 +0000297 // Record use of an input. The use will be recorded as an environment use if
298 // `environment` is not null and as register use otherwise. If `actual_user`
299 // is specified, the use will be recorded at `actual_user`'s lifetime position.
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000300 void AddUse(HInstruction* instruction,
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100301 HEnvironment* environment,
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000302 size_t input_index,
David Brazdilb3e773e2016-01-26 11:28:37 +0000303 HInstruction* actual_user = nullptr,
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000304 bool keep_alive = false) {
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100305 bool is_environment = (environment != nullptr);
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000306 LocationSummary* locations = instruction->GetLocations();
David Brazdilb3e773e2016-01-26 11:28:37 +0000307 if (actual_user == nullptr) {
308 actual_user = instruction;
309 }
310
311 // Set the use within the instruction.
312 size_t position = actual_user->GetLifetimePosition() + 1;
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000313 if (!is_environment) {
314 if (locations->IsFixedInput(input_index) || locations->OutputUsesSameAs(input_index)) {
315 // For fixed inputs and output same as input, the register allocator
316 // requires to have inputs die at the instruction, so that input moves use the
317 // location of the input just before that instruction (and not potential moves due
318 // to splitting).
David Brazdilb3e773e2016-01-26 11:28:37 +0000319 DCHECK_EQ(instruction, actual_user);
320 position = actual_user->GetLifetimePosition();
Nicolas Geoffray57902602015-04-21 14:28:41 +0100321 } else if (!locations->InAt(input_index).IsValid()) {
322 return;
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000323 }
Nicolas Geoffray76905622014-09-25 14:39:26 +0100324 }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000325
Nicolas Geoffray57902602015-04-21 14:28:41 +0100326 if (!is_environment && instruction->IsInLoop()) {
327 AddBackEdgeUses(*instruction->GetBlock());
328 }
329
Vladimir Marko82b07402017-03-01 19:02:04 +0000330 if ((!uses_.empty()) &&
331 (uses_.front().GetUser() == actual_user) &&
332 (uses_.front().GetPosition() < position)) {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100333 // The user uses the instruction multiple times, and one use dies before the other.
334 // We update the use list so that the latter is first.
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000335 DCHECK(!is_environment);
Vladimir Marko82b07402017-03-01 19:02:04 +0000336 DCHECK(uses_.front().GetPosition() + 1 == position);
337 UsePositionList::iterator next_pos = uses_.begin();
338 UsePositionList::iterator insert_pos;
339 do {
340 insert_pos = next_pos;
341 ++next_pos;
342 } while (next_pos != uses_.end() && next_pos->GetPosition() < position);
343 UsePosition* new_use = new (allocator_) UsePosition(instruction, input_index, position);
344 uses_.insert_after(insert_pos, *new_use);
345 if (first_range_->GetEnd() == uses_.front().GetPosition()) {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100346 first_range_->end_ = position;
347 }
348 return;
349 }
350
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100351 if (is_environment) {
Vladimir Marko82b07402017-03-01 19:02:04 +0000352 DCHECK(env_uses_.empty() || position <= env_uses_.front().GetPosition());
353 EnvUsePosition* new_env_use =
354 new (allocator_) EnvUsePosition(environment, input_index, position);
355 env_uses_.push_front(*new_env_use);
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100356 } else {
Vladimir Marko82b07402017-03-01 19:02:04 +0000357 DCHECK(uses_.empty() || position <= uses_.front().GetPosition());
358 UsePosition* new_use = new (allocator_) UsePosition(instruction, input_index, position);
359 uses_.push_front(*new_use);
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100360 }
Nicolas Geoffrayd8126be2015-03-27 10:22:41 +0000361
362 if (is_environment && !keep_alive) {
363 // If this environment use does not keep the instruction live, it does not
364 // affect the live range of that instruction.
365 return;
366 }
367
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100368 size_t start_block_position = instruction->GetBlock()->GetLifetimeStart();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100369 if (first_range_ == nullptr) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100370 // First time we see a use of that interval.
David Brazdil3fc992f2015-04-16 18:31:55 +0100371 first_range_ = last_range_ = range_search_start_ =
372 new (allocator_) LiveRange(start_block_position, position, nullptr);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100373 } else if (first_range_->GetStart() == start_block_position) {
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100374 // There is a use later in the same block or in a following block.
375 // Note that in such a case, `AddRange` for the whole blocks has been called
376 // before arriving in this method, and this is the reason the start of
377 // `first_range_` is before the given `position`.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100378 DCHECK_LE(position, first_range_->GetEnd());
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100379 } else {
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100380 DCHECK(first_range_->GetStart() > position);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100381 // There is a hole in the interval. Create a new range.
Nicolas Geoffray8ddb00c2014-09-29 12:00:40 +0100382 // Note that the start of `first_range_` can be equal to `end`: two blocks
383 // having adjacent lifetime positions are not necessarily
384 // predecessor/successor. When two blocks are predecessor/successor, the
385 // liveness algorithm has called `AddRange` before arriving in this method,
386 // and the check line 205 would succeed.
David Brazdil3fc992f2015-04-16 18:31:55 +0100387 first_range_ = range_search_start_ =
388 new (allocator_) LiveRange(start_block_position, position, first_range_);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100389 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100390 }
391
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100392 void AddPhiUse(HInstruction* instruction, size_t input_index, HBasicBlock* block) {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100393 DCHECK(instruction->IsPhi());
Nicolas Geoffray57902602015-04-21 14:28:41 +0100394 if (block->IsInLoop()) {
395 AddBackEdgeUses(*block);
396 }
Vladimir Marko82b07402017-03-01 19:02:04 +0000397 UsePosition* new_use =
398 new (allocator_) UsePosition(instruction, input_index, block->GetLifetimeEnd());
399 uses_.push_front(*new_use);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100400 }
401
Mingyao Yang01b47b02017-02-03 12:09:57 -0800402 ALWAYS_INLINE void AddRange(size_t start, size_t end) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100403 if (first_range_ == nullptr) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100404 first_range_ = last_range_ = range_search_start_ =
405 new (allocator_) LiveRange(start, end, first_range_);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100406 } else if (first_range_->GetStart() == end) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100407 // There is a use in the following block.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100408 first_range_->start_ = start;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100409 } else if (first_range_->GetStart() == start && first_range_->GetEnd() == end) {
410 DCHECK(is_fixed_);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100411 } else {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100412 DCHECK_GT(first_range_->GetStart(), end);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100413 // There is a hole in the interval. Create a new range.
David Brazdil3fc992f2015-04-16 18:31:55 +0100414 first_range_ = range_search_start_ = new (allocator_) LiveRange(start, end, first_range_);
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100415 }
416 }
417
418 void AddLoopRange(size_t start, size_t end) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100419 DCHECK(first_range_ != nullptr);
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000420 DCHECK_LE(start, first_range_->GetStart());
421 // Find the range that covers the positions after the loop.
422 LiveRange* after_loop = first_range_;
423 LiveRange* last_in_loop = nullptr;
424 while (after_loop != nullptr && after_loop->GetEnd() < end) {
425 DCHECK_LE(start, after_loop->GetStart());
426 last_in_loop = after_loop;
427 after_loop = after_loop->GetNext();
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100428 }
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000429 if (after_loop == nullptr) {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100430 // Uses are only in the loop.
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700431 first_range_ = last_range_ = range_search_start_ =
432 new (allocator_) LiveRange(start, end, nullptr);
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000433 } else if (after_loop->GetStart() <= end) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100434 first_range_ = range_search_start_ = after_loop;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100435 // There are uses after the loop.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100436 first_range_->start_ = start;
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000437 } else {
438 // The use after the loop is after a lifetime hole.
439 DCHECK(last_in_loop != nullptr);
David Brazdil3fc992f2015-04-16 18:31:55 +0100440 first_range_ = range_search_start_ = last_in_loop;
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000441 first_range_->start_ = start;
442 first_range_->end_ = end;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100443 }
444 }
445
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100446 bool HasSpillSlot() const { return spill_slot_ != kNoSpillSlot; }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100447 void SetSpillSlot(int slot) {
448 DCHECK(!is_fixed_);
449 DCHECK(!is_temp_);
450 spill_slot_ = slot;
451 }
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100452 int GetSpillSlot() const { return spill_slot_; }
453
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100454 void SetFrom(size_t from) {
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100455 if (first_range_ != nullptr) {
456 first_range_->start_ = from;
457 } else {
458 // Instruction without uses.
Vladimir Marko82b07402017-03-01 19:02:04 +0000459 DCHECK(uses_.empty());
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100460 DCHECK(from == defined_by_->GetLifetimePosition());
David Brazdil3fc992f2015-04-16 18:31:55 +0100461 first_range_ = last_range_ = range_search_start_ =
462 new (allocator_) LiveRange(from, from + 2, nullptr);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100463 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100464 }
465
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100466 LiveInterval* GetParent() const { return parent_; }
467
Nicolas Geoffray1ba19812015-04-21 09:12:40 +0100468 // Returns whether this interval is the parent interval, that is, the interval
469 // that starts where the HInstruction is defined.
470 bool IsParent() const { return parent_ == this; }
471
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100472 LiveRange* GetFirstRange() const { return first_range_; }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000473 LiveRange* GetLastRange() const { return last_range_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100474
475 int GetRegister() const { return register_; }
476 void SetRegister(int reg) { register_ = reg; }
477 void ClearRegister() { register_ = kNoRegister; }
478 bool HasRegister() const { return register_ != kNoRegister; }
479
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100480 bool IsDeadAt(size_t position) const {
David Brazdil241a4862015-04-16 17:59:03 +0100481 return GetEnd() <= position;
482 }
483
484 bool IsDefinedAt(size_t position) const {
485 return GetStart() <= position && !IsDeadAt(position);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100486 }
487
David Brazdil3fc992f2015-04-16 18:31:55 +0100488 // Returns true if the interval contains a LiveRange covering `position`.
489 // The range at or immediately after the current position of linear scan
490 // is cached for better performance. If `position` can be smaller than
491 // that, CoversSlow should be used instead.
David Brazdil5b8e6a52015-02-25 16:17:05 +0000492 bool Covers(size_t position) {
David Brazdil3fc992f2015-04-16 18:31:55 +0100493 LiveRange* candidate = FindRangeAtOrAfter(position, range_search_start_);
494 range_search_start_ = candidate;
495 return (candidate != nullptr && candidate->GetStart() <= position);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100496 }
497
David Brazdil3fc992f2015-04-16 18:31:55 +0100498 // Same as Covers but always tests all ranges.
499 bool CoversSlow(size_t position) const {
500 LiveRange* candidate = FindRangeAtOrAfter(position, first_range_);
501 return candidate != nullptr && candidate->GetStart() <= position;
502 }
503
504 // Returns the first intersection of this interval with `current`, which
505 // must be the interval currently being allocated by linear scan.
506 size_t FirstIntersectionWith(LiveInterval* current) const {
507 // Find the first range after the start of `current`. We use the search
508 // cache to improve performance.
509 DCHECK(GetStart() <= current->GetStart() || IsFixed());
510 LiveRange* other_range = current->first_range_;
511 LiveRange* my_range = FindRangeAtOrAfter(other_range->GetStart(), range_search_start_);
512 if (my_range == nullptr) {
513 return kNoLifetime;
514 }
515
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100516 // Advance both intervals and find the first matching range start in
517 // this interval.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100518 do {
David Brazdil714e14f2015-02-25 11:57:05 +0000519 if (my_range->IsBefore(*other_range)) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100520 my_range = my_range->GetNext();
521 if (my_range == nullptr) {
522 return kNoLifetime;
523 }
David Brazdil714e14f2015-02-25 11:57:05 +0000524 } else if (other_range->IsBefore(*my_range)) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100525 other_range = other_range->GetNext();
526 if (other_range == nullptr) {
527 return kNoLifetime;
528 }
David Brazdil714e14f2015-02-25 11:57:05 +0000529 } else {
530 DCHECK(my_range->IntersectsWith(*other_range));
531 return std::max(my_range->GetStart(), other_range->GetStart());
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100532 }
533 } while (true);
534 }
535
536 size_t GetStart() const {
537 return first_range_->GetStart();
538 }
539
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100540 size_t GetEnd() const {
541 return last_range_->GetEnd();
542 }
543
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700544 size_t GetLength() const {
545 return GetEnd() - GetStart();
546 }
547
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100548 size_t FirstRegisterUseAfter(size_t position) const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100549 if (is_temp_) {
550 return position == GetStart() ? position : kNoLifetime;
551 }
Nicolas Geoffray57902602015-04-21 14:28:41 +0100552
553 if (IsDefiningPosition(position) && DefinitionRequiresRegister()) {
554 return position;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100555 }
556
Nicolas Geoffrayde025a72014-06-19 17:06:46 +0100557 size_t end = GetEnd();
Vladimir Marko82b07402017-03-01 19:02:04 +0000558 for (const UsePosition& use : GetUses()) {
559 size_t use_position = use.GetPosition();
560 if (use_position > end) {
561 break;
562 }
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100563 if (use_position > position) {
Vladimir Marko82b07402017-03-01 19:02:04 +0000564 if (use.RequiresRegister()) {
Nicolas Geoffrayc8147a72014-10-21 16:06:20 +0100565 return use_position;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100566 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100567 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100568 }
569 return kNoLifetime;
570 }
571
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700572 // Returns the location of the first register use for this live interval,
573 // including a register definition if applicable.
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100574 size_t FirstRegisterUse() const {
575 return FirstRegisterUseAfter(GetStart());
576 }
577
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700578 // Whether the interval requires a register rather than a stack location.
579 // If needed for performance, this could be cached.
Matthew Gharrity2ccae4a2016-08-12 16:10:45 +0000580 bool RequiresRegister() const {
581 return !HasRegister() && FirstRegisterUse() != kNoLifetime;
582 }
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700583
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000584 size_t FirstUseAfter(size_t position) const {
585 if (is_temp_) {
586 return position == GetStart() ? position : kNoLifetime;
587 }
588
Nicolas Geoffray57902602015-04-21 14:28:41 +0100589 if (IsDefiningPosition(position)) {
590 DCHECK(defined_by_->GetLocations()->Out().IsValid());
591 return position;
Nicolas Geoffray1ba19812015-04-21 09:12:40 +0100592 }
593
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000594 size_t end = GetEnd();
Vladimir Marko82b07402017-03-01 19:02:04 +0000595 for (const UsePosition& use : GetUses()) {
596 size_t use_position = use.GetPosition();
597 if (use_position > end) {
598 break;
599 }
Nicolas Geoffray57902602015-04-21 14:28:41 +0100600 if (use_position > position) {
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100601 return use_position;
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000602 }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000603 }
604 return kNoLifetime;
605 }
606
Vladimir Marko82b07402017-03-01 19:02:04 +0000607 const UsePositionList& GetUses() const {
608 return parent_->uses_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100609 }
610
Vladimir Marko82b07402017-03-01 19:02:04 +0000611 const EnvUsePositionList& GetEnvironmentUses() const {
612 return parent_->env_uses_;
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100613 }
614
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100615 DataType::Type GetType() const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100616 return type_;
617 }
618
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100619 HInstruction* GetDefinedBy() const {
620 return defined_by_;
621 }
622
Nicolas Geoffray8826f672015-04-17 09:15:11 +0100623 bool HasWillCallSafepoint() const {
624 for (SafepointPosition* safepoint = first_safepoint_;
625 safepoint != nullptr;
626 safepoint = safepoint->GetNext()) {
627 if (safepoint->GetLocations()->WillCall()) return true;
628 }
629 return false;
630 }
631
Nicolas Geoffray43af7282015-04-16 13:01:01 +0100632 SafepointPosition* FindSafepointJustBefore(size_t position) const {
633 for (SafepointPosition* safepoint = first_safepoint_, *previous = nullptr;
634 safepoint != nullptr;
635 previous = safepoint, safepoint = safepoint->GetNext()) {
636 if (safepoint->GetPosition() >= position) return previous;
637 }
638 return last_safepoint_;
639 }
640
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100641 /**
642 * Split this interval at `position`. This interval is changed to:
643 * [start ... position).
644 *
645 * The new interval covers:
646 * [position ... end)
647 */
648 LiveInterval* SplitAt(size_t position) {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100649 DCHECK(!is_temp_);
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100650 DCHECK(!is_fixed_);
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100651 DCHECK_GT(position, GetStart());
652
David Brazdil241a4862015-04-16 17:59:03 +0100653 if (GetEnd() <= position) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100654 // This range dies before `position`, no need to split.
655 return nullptr;
656 }
657
658 LiveInterval* new_interval = new (allocator_) LiveInterval(allocator_, type_);
Nicolas Geoffray43af7282015-04-16 13:01:01 +0100659 SafepointPosition* new_last_safepoint = FindSafepointJustBefore(position);
660 if (new_last_safepoint == nullptr) {
661 new_interval->first_safepoint_ = first_safepoint_;
662 new_interval->last_safepoint_ = last_safepoint_;
663 first_safepoint_ = last_safepoint_ = nullptr;
664 } else if (last_safepoint_ != new_last_safepoint) {
665 new_interval->last_safepoint_ = last_safepoint_;
666 new_interval->first_safepoint_ = new_last_safepoint->GetNext();
667 DCHECK(new_interval->first_safepoint_ != nullptr);
668 last_safepoint_ = new_last_safepoint;
669 last_safepoint_->SetNext(nullptr);
670 }
671
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100672 new_interval->next_sibling_ = next_sibling_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100673 next_sibling_ = new_interval;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +0100674 new_interval->parent_ = parent_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100675
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100676 LiveRange* current = first_range_;
677 LiveRange* previous = nullptr;
678 // Iterate over the ranges, and either find a range that covers this position, or
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +0000679 // two ranges in between this position (that is, the position is in a lifetime hole).
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100680 do {
681 if (position >= current->GetEnd()) {
682 // Move to next range.
683 previous = current;
684 current = current->next_;
685 } else if (position <= current->GetStart()) {
686 // If the previous range did not cover this position, we know position is in
687 // a lifetime hole. We can just break the first_range_ and last_range_ links
688 // and return the new interval.
689 DCHECK(previous != nullptr);
690 DCHECK(current != first_range_);
691 new_interval->last_range_ = last_range_;
692 last_range_ = previous;
693 previous->next_ = nullptr;
694 new_interval->first_range_ = current;
David Brazdil3fc992f2015-04-16 18:31:55 +0100695 if (range_search_start_ != nullptr && range_search_start_->GetEnd() >= current->GetEnd()) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700696 // Search start point is inside `new_interval`. Change it to null
David Brazdil3fc992f2015-04-16 18:31:55 +0100697 // (i.e. the end of the interval) in the original interval.
698 range_search_start_ = nullptr;
699 }
700 new_interval->range_search_start_ = new_interval->first_range_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100701 return new_interval;
702 } else {
703 // This range covers position. We create a new last_range_ for this interval
704 // that covers last_range_->Start() and position. We also shorten the current
705 // range and make it the first range of the new interval.
706 DCHECK(position < current->GetEnd() && position > current->GetStart());
707 new_interval->last_range_ = last_range_;
708 last_range_ = new (allocator_) LiveRange(current->start_, position, nullptr);
709 if (previous != nullptr) {
710 previous->next_ = last_range_;
711 } else {
712 first_range_ = last_range_;
713 }
714 new_interval->first_range_ = current;
715 current->start_ = position;
David Brazdil3fc992f2015-04-16 18:31:55 +0100716 if (range_search_start_ != nullptr && range_search_start_->GetEnd() >= current->GetEnd()) {
717 // Search start point is inside `new_interval`. Change it to `last_range`
718 // in the original interval. This is conservative but always correct.
719 range_search_start_ = last_range_;
720 }
721 new_interval->range_search_start_ = new_interval->first_range_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100722 return new_interval;
723 }
724 } while (current != nullptr);
725
726 LOG(FATAL) << "Unreachable";
727 return nullptr;
728 }
729
Nicolas Geoffray76905622014-09-25 14:39:26 +0100730 bool StartsBeforeOrAt(LiveInterval* other) const {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100731 return GetStart() <= other->GetStart();
732 }
733
734 bool StartsAfter(LiveInterval* other) const {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100735 return GetStart() > other->GetStart();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100736 }
737
738 void Dump(std::ostream& stream) const {
739 stream << "ranges: { ";
740 LiveRange* current = first_range_;
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000741 while (current != nullptr) {
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100742 current->Dump(stream);
743 stream << " ";
Nicolas Geoffrayaedc3282015-01-23 18:01:51 +0000744 current = current->GetNext();
745 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100746 stream << "}, uses: { ";
Vladimir Marko82b07402017-03-01 19:02:04 +0000747 for (const UsePosition& use : GetUses()) {
748 use.Dump(stream);
749 stream << " ";
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100750 }
Nicolas Geoffray57902602015-04-21 14:28:41 +0100751 stream << "}, { ";
Vladimir Marko82b07402017-03-01 19:02:04 +0000752 for (const EnvUsePosition& env_use : GetEnvironmentUses()) {
753 env_use.Dump(stream);
754 stream << " ";
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100755 }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100756 stream << "}";
Mingyao Yang296bd602014-10-06 16:47:28 -0700757 stream << " is_fixed: " << is_fixed_ << ", is_split: " << IsSplit();
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000758 stream << " is_low: " << IsLowInterval();
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100759 stream << " is_high: " << IsHighInterval();
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100760 }
761
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700762 // Same as Dump, but adds context such as the instruction defining this interval, and
763 // the register currently assigned to this interval.
764 void DumpWithContext(std::ostream& stream, const CodeGenerator& codegen) const;
765
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100766 LiveInterval* GetNextSibling() const { return next_sibling_; }
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000767 LiveInterval* GetLastSibling() {
768 LiveInterval* result = this;
769 while (result->next_sibling_ != nullptr) {
770 result = result->next_sibling_;
771 }
772 return result;
773 }
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100774
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100775 // Returns the first register hint that is at least free before
776 // the value contained in `free_until`. If none is found, returns
777 // `kNoRegister`.
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +0100778 int FindFirstRegisterHint(size_t* free_until, const SsaLivenessAnalysis& liveness) const;
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100779
780 // If there is enough at the definition site to find a register (for example
781 // it uses the same input as the first input), returns the register as a hint.
782 // Returns kNoRegister otherwise.
783 int FindHintAtDefinition() const;
784
Aart Bikcc895252017-03-21 10:55:15 -0700785 // Returns the number of required spilling slots (measured as a multiple of the
786 // Dex virtual register size `kVRegSize`).
787 size_t NumberOfSpillSlotsNeeded() const;
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100788
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100789 bool IsFloatingPoint() const {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100790 return type_ == DataType::Type::kFloat32 || type_ == DataType::Type::kFloat64;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100791 }
792
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100793 // Converts the location of the interval to a `Location` object.
794 Location ToLocation() const;
795
796 // Returns the location of the interval following its siblings at `position`.
David Brazdil5b8e6a52015-02-25 16:17:05 +0000797 Location GetLocationAt(size_t position);
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100798
David Brazdil241a4862015-04-16 17:59:03 +0100799 // Finds the sibling that is defined at `position`.
800 LiveInterval* GetSiblingAt(size_t position);
Nicolas Geoffray01ef3452014-10-01 11:32:17 +0100801
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100802 // Returns whether `other` and `this` share the same kind of register.
803 bool SameRegisterKind(Location other) const;
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000804 bool SameRegisterKind(const LiveInterval& other) const {
805 return IsFloatingPoint() == other.IsFloatingPoint();
806 }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100807
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000808 bool HasHighInterval() const {
Nicolas Geoffray3747b482015-01-19 17:17:16 +0000809 return IsLowInterval();
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000810 }
811
812 bool HasLowInterval() const {
813 return IsHighInterval();
814 }
815
816 LiveInterval* GetLowInterval() const {
817 DCHECK(HasLowInterval());
818 return high_or_low_interval_;
819 }
820
821 LiveInterval* GetHighInterval() const {
822 DCHECK(HasHighInterval());
823 return high_or_low_interval_;
824 }
825
826 bool IsHighInterval() const {
827 return GetParent()->is_high_interval_;
828 }
829
830 bool IsLowInterval() const {
831 return !IsHighInterval() && (GetParent()->high_or_low_interval_ != nullptr);
832 }
833
834 void SetLowInterval(LiveInterval* low) {
835 DCHECK(IsHighInterval());
836 high_or_low_interval_ = low;
837 }
838
839 void SetHighInterval(LiveInterval* high) {
840 DCHECK(IsLowInterval());
841 high_or_low_interval_ = high;
842 }
843
844 void AddHighInterval(bool is_temp = false) {
Nicolas Geoffray1ba19812015-04-21 09:12:40 +0100845 DCHECK(IsParent());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000846 DCHECK(!HasHighInterval());
847 DCHECK(!HasLowInterval());
848 high_or_low_interval_ = new (allocator_) LiveInterval(
Vladimir Marko70e97462016-08-09 11:04:26 +0100849 allocator_, type_, defined_by_, false, kNoRegister, is_temp, true);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000850 high_or_low_interval_->high_or_low_interval_ = this;
851 if (first_range_ != nullptr) {
852 high_or_low_interval_->first_range_ = first_range_->Dup(allocator_);
David Brazdilc08675c2015-04-17 15:49:51 +0100853 high_or_low_interval_->last_range_ = high_or_low_interval_->first_range_->GetLastRange();
David Brazdil3fc992f2015-04-16 18:31:55 +0100854 high_or_low_interval_->range_search_start_ = high_or_low_interval_->first_range_;
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000855 }
Vladimir Marko82b07402017-03-01 19:02:04 +0000856 auto pos = high_or_low_interval_->uses_.before_begin();
857 for (const UsePosition& use : uses_) {
858 UsePosition* new_use = use.Clone(allocator_);
859 pos = high_or_low_interval_->uses_.insert_after(pos, *new_use);
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000860 }
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100861
Vladimir Marko82b07402017-03-01 19:02:04 +0000862 auto env_pos = high_or_low_interval_->env_uses_.before_begin();
863 for (const EnvUsePosition& env_use : env_uses_) {
864 EnvUsePosition* new_env_use = env_use.Clone(allocator_);
865 env_pos = high_or_low_interval_->env_uses_.insert_after(env_pos, *new_env_use);
Nicolas Geoffray4ed947a2015-04-27 16:58:06 +0100866 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000867 }
868
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000869 // Returns whether an interval, when it is non-split, is using
870 // the same register of one of its input.
871 bool IsUsingInputRegister() const {
David Brazdil3fc992f2015-04-16 18:31:55 +0100872 CHECK(kIsDebugBuild) << "Function should be used only for DCHECKs";
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000873 if (defined_by_ != nullptr && !IsSplit()) {
Vladimir Marko372f10e2016-05-17 16:30:10 +0100874 for (const HInstruction* input : defined_by_->GetInputs()) {
875 LiveInterval* interval = input->GetLiveInterval();
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000876
David Brazdil3fc992f2015-04-16 18:31:55 +0100877 // Find the interval that covers `defined_by`_. Calls to this function
878 // are made outside the linear scan, hence we need to use CoversSlow.
879 while (interval != nullptr && !interval->CoversSlow(defined_by_->GetLifetimePosition())) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000880 interval = interval->GetNextSibling();
881 }
882
883 // Check if both intervals have the same register of the same kind.
884 if (interval != nullptr
885 && interval->SameRegisterKind(*this)
886 && interval->GetRegister() == GetRegister()) {
887 return true;
888 }
889 }
890 }
891 return false;
892 }
893
894 // Returns whether an interval, when it is non-split, can safely use
895 // the same register of one of its input. Note that this method requires
896 // IsUsingInputRegister() to be true.
897 bool CanUseInputRegister() const {
David Brazdil3fc992f2015-04-16 18:31:55 +0100898 CHECK(kIsDebugBuild) << "Function should be used only for DCHECKs";
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000899 DCHECK(IsUsingInputRegister());
900 if (defined_by_ != nullptr && !IsSplit()) {
901 LocationSummary* locations = defined_by_->GetLocations();
902 if (locations->OutputCanOverlapWithInputs()) {
903 return false;
904 }
Vladimir Marko372f10e2016-05-17 16:30:10 +0100905 for (const HInstruction* input : defined_by_->GetInputs()) {
906 LiveInterval* interval = input->GetLiveInterval();
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000907
David Brazdil3fc992f2015-04-16 18:31:55 +0100908 // Find the interval that covers `defined_by`_. Calls to this function
909 // are made outside the linear scan, hence we need to use CoversSlow.
910 while (interval != nullptr && !interval->CoversSlow(defined_by_->GetLifetimePosition())) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000911 interval = interval->GetNextSibling();
912 }
913
914 if (interval != nullptr
915 && interval->SameRegisterKind(*this)
916 && interval->GetRegister() == GetRegister()) {
917 // We found the input that has the same register. Check if it is live after
918 // `defined_by`_.
David Brazdil3fc992f2015-04-16 18:31:55 +0100919 return !interval->CoversSlow(defined_by_->GetLifetimePosition() + 1);
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000920 }
921 }
922 }
923 LOG(FATAL) << "Unreachable";
924 UNREACHABLE();
925 }
926
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100927 void AddSafepoint(HInstruction* instruction) {
928 SafepointPosition* safepoint = new (allocator_) SafepointPosition(instruction);
929 if (first_safepoint_ == nullptr) {
930 first_safepoint_ = last_safepoint_ = safepoint;
931 } else {
932 DCHECK_LT(last_safepoint_->GetPosition(), safepoint->GetPosition());
933 last_safepoint_->SetNext(safepoint);
934 last_safepoint_ = safepoint;
935 }
936 }
937
938 SafepointPosition* GetFirstSafepoint() const {
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100939 return first_safepoint_;
940 }
941
David Brazdil3fc992f2015-04-16 18:31:55 +0100942 // Resets the starting point for range-searching queries to the first range.
943 // Intervals must be reset prior to starting a new linear scan over them.
944 void ResetSearchCache() {
945 range_search_start_ = first_range_;
946 }
947
Matthew Gharrityd9ffd0d2016-06-22 10:27:55 -0700948 bool DefinitionRequiresRegister() const {
949 DCHECK(IsParent());
950 LocationSummary* locations = defined_by_->GetLocations();
951 Location location = locations->Out();
952 // This interval is the first interval of the instruction. If the output
953 // of the instruction requires a register, we return the position of that instruction
954 // as the first register use.
955 if (location.IsUnallocated()) {
956 if ((location.GetPolicy() == Location::kRequiresRegister)
957 || (location.GetPolicy() == Location::kSameAsFirstInput
958 && (locations->InAt(0).IsRegister()
959 || locations->InAt(0).IsRegisterPair()
960 || locations->InAt(0).GetPolicy() == Location::kRequiresRegister))) {
961 return true;
962 } else if ((location.GetPolicy() == Location::kRequiresFpuRegister)
963 || (location.GetPolicy() == Location::kSameAsFirstInput
964 && (locations->InAt(0).IsFpuRegister()
965 || locations->InAt(0).IsFpuRegisterPair()
966 || locations->InAt(0).GetPolicy() == Location::kRequiresFpuRegister))) {
967 return true;
968 }
969 } else if (location.IsRegister() || location.IsRegisterPair()) {
970 return true;
971 }
972 return false;
973 }
974
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100975 private:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100976 LiveInterval(ScopedArenaAllocator* allocator,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100977 DataType::Type type,
Mingyao Yang296bd602014-10-06 16:47:28 -0700978 HInstruction* defined_by = nullptr,
979 bool is_fixed = false,
980 int reg = kNoRegister,
981 bool is_temp = false,
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000982 bool is_high_interval = false)
Mingyao Yang296bd602014-10-06 16:47:28 -0700983 : allocator_(allocator),
984 first_range_(nullptr),
985 last_range_(nullptr),
David Brazdil3fc992f2015-04-16 18:31:55 +0100986 range_search_start_(nullptr),
Nicolas Geoffray5588e582015-04-14 14:10:59 +0100987 first_safepoint_(nullptr),
988 last_safepoint_(nullptr),
Vladimir Marko82b07402017-03-01 19:02:04 +0000989 uses_(),
990 env_uses_(),
Mingyao Yang296bd602014-10-06 16:47:28 -0700991 type_(type),
992 next_sibling_(nullptr),
993 parent_(this),
994 register_(reg),
995 spill_slot_(kNoSpillSlot),
996 is_fixed_(is_fixed),
997 is_temp_(is_temp),
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000998 is_high_interval_(is_high_interval),
999 high_or_low_interval_(nullptr),
Mingyao Yang296bd602014-10-06 16:47:28 -07001000 defined_by_(defined_by) {}
1001
David Brazdil3fc992f2015-04-16 18:31:55 +01001002 // Searches for a LiveRange that either covers the given position or is the
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001003 // first next LiveRange. Returns null if no such LiveRange exists. Ranges
David Brazdil3fc992f2015-04-16 18:31:55 +01001004 // known to end before `position` can be skipped with `search_start`.
1005 LiveRange* FindRangeAtOrAfter(size_t position, LiveRange* search_start) const {
David Brazdil5b8e6a52015-02-25 16:17:05 +00001006 if (kIsDebugBuild) {
David Brazdil3fc992f2015-04-16 18:31:55 +01001007 if (search_start != first_range_) {
1008 // If we are not searching the entire list of ranges, make sure we do
1009 // not skip the range we are searching for.
1010 if (search_start == nullptr) {
1011 DCHECK(IsDeadAt(position));
1012 } else if (search_start->GetStart() > position) {
1013 DCHECK_EQ(search_start, FindRangeAtOrAfter(position, first_range_));
1014 }
David Brazdil5b8e6a52015-02-25 16:17:05 +00001015 }
1016 }
1017
David Brazdil3fc992f2015-04-16 18:31:55 +01001018 LiveRange* range;
1019 for (range = search_start;
1020 range != nullptr && range->GetEnd() <= position;
1021 range = range->GetNext()) {
1022 continue;
David Brazdil5b8e6a52015-02-25 16:17:05 +00001023 }
David Brazdil3fc992f2015-04-16 18:31:55 +01001024 return range;
David Brazdil5b8e6a52015-02-25 16:17:05 +00001025 }
1026
Nicolas Geoffray57902602015-04-21 14:28:41 +01001027 bool IsDefiningPosition(size_t position) const {
1028 return IsParent() && (position == GetStart());
1029 }
1030
1031 bool HasSynthesizeUseAt(size_t position) const {
Vladimir Marko82b07402017-03-01 19:02:04 +00001032 for (const UsePosition& use : GetUses()) {
1033 size_t use_position = use.GetPosition();
1034 if ((use_position == position) && use.IsSynthesized()) {
Nicolas Geoffray57902602015-04-21 14:28:41 +01001035 return true;
1036 }
1037 if (use_position > position) break;
Nicolas Geoffray57902602015-04-21 14:28:41 +01001038 }
1039 return false;
1040 }
1041
1042 void AddBackEdgeUses(const HBasicBlock& block_at_use) {
1043 DCHECK(block_at_use.IsInLoop());
David Brazdil07b35102016-04-27 15:33:22 +01001044 if (block_at_use.GetGraph()->HasIrreducibleLoops()) {
1045 // Linear order may not be well formed when irreducible loops are present,
1046 // i.e. loop blocks may not be adjacent and a back edge may not be last,
1047 // which violates assumptions made in this method.
1048 return;
1049 }
1050
Nicolas Geoffray57902602015-04-21 14:28:41 +01001051 // Add synthesized uses at the back edge of loops to help the register allocator.
1052 // Note that this method is called in decreasing liveness order, to faciliate adding
Vladimir Marko82b07402017-03-01 19:02:04 +00001053 // uses at the head of the `uses_` list. Because below
Nicolas Geoffray57902602015-04-21 14:28:41 +01001054 // we iterate from inner-most to outer-most, which is in increasing liveness order,
Vladimir Marko82b07402017-03-01 19:02:04 +00001055 // we need to add subsequent entries after the last inserted entry.
1056 const UsePositionList::iterator old_begin = uses_.begin();
1057 UsePositionList::iterator insert_pos = uses_.before_begin();
Nicolas Geoffray57902602015-04-21 14:28:41 +01001058 for (HLoopInformationOutwardIterator it(block_at_use);
1059 !it.Done();
1060 it.Advance()) {
1061 HLoopInformation* current = it.Current();
1062 if (GetDefinedBy()->GetLifetimePosition() >= current->GetHeader()->GetLifetimeStart()) {
1063 // This interval is defined in the loop. We can stop going outward.
1064 break;
1065 }
1066
Vladimir Marko82b07402017-03-01 19:02:04 +00001067 // We're only adding a synthesized use at the last back edge. Adding synthesized uses on
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001068 // all back edges is not necessary: anything used in the loop will have its use at the
1069 // last back edge. If we want branches in a loop to have better register allocation than
1070 // another branch, then it is the linear order we should change.
1071 size_t back_edge_use_position = current->GetLifetimeEnd();
Vladimir Marko82b07402017-03-01 19:02:04 +00001072 if ((old_begin != uses_.end()) && (old_begin->GetPosition() <= back_edge_use_position)) {
Nicolas Geoffray57902602015-04-21 14:28:41 +01001073 // There was a use already seen in this loop. Therefore the previous call to `AddUse`
1074 // already inserted the backedge use. We can stop going outward.
David Brazdil07b35102016-04-27 15:33:22 +01001075 DCHECK(HasSynthesizeUseAt(back_edge_use_position));
Nicolas Geoffray57902602015-04-21 14:28:41 +01001076 break;
1077 }
1078
Vladimir Marko82b07402017-03-01 19:02:04 +00001079 DCHECK(insert_pos != uses_.before_begin()
1080 ? back_edge_use_position > insert_pos->GetPosition()
1081 : current == block_at_use.GetLoopInformation())
1082 << std::distance(uses_.before_begin(), insert_pos);
Nicolas Geoffray57902602015-04-21 14:28:41 +01001083
Vladimir Marko356bd282017-03-01 12:01:11 +00001084 UsePosition* new_use = new (allocator_) UsePosition(back_edge_use_position);
Vladimir Marko82b07402017-03-01 19:02:04 +00001085 insert_pos = uses_.insert_after(insert_pos, *new_use);
Nicolas Geoffray57902602015-04-21 14:28:41 +01001086 }
1087 }
1088
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001089 ScopedArenaAllocator* const allocator_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001090
1091 // Ranges of this interval. We need a quick access to the last range to test
1092 // for liveness (see `IsDeadAt`).
1093 LiveRange* first_range_;
1094 LiveRange* last_range_;
1095
David Brazdil3fc992f2015-04-16 18:31:55 +01001096 // The first range at or after the current position of a linear scan. It is
1097 // used to optimize range-searching queries.
1098 LiveRange* range_search_start_;
1099
Nicolas Geoffray43af7282015-04-16 13:01:01 +01001100 // Safepoints where this interval is live.
Nicolas Geoffray5588e582015-04-14 14:10:59 +01001101 SafepointPosition* first_safepoint_;
1102 SafepointPosition* last_safepoint_;
1103
Vladimir Marko82b07402017-03-01 19:02:04 +00001104 // Uses of this interval. Only the parent interval keeps these lists.
1105 UsePositionList uses_;
1106 EnvUsePositionList env_uses_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001107
1108 // The instruction type this interval corresponds to.
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001109 const DataType::Type type_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001110
1111 // Live interval that is the result of a split.
1112 LiveInterval* next_sibling_;
1113
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001114 // The first interval from which split intervals come from.
1115 LiveInterval* parent_;
1116
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001117 // The register allocated to this interval.
1118 int register_;
1119
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001120 // The spill slot allocated to this interval.
1121 int spill_slot_;
1122
1123 // Whether the interval is for a fixed register.
Nicolas Geoffray39468442014-09-02 15:17:15 +01001124 const bool is_fixed_;
1125
1126 // Whether the interval is for a temporary.
1127 const bool is_temp_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001128
Nicolas Geoffray840e5462015-01-07 16:01:24 +00001129 // Whether this interval is a synthesized interval for register pair.
1130 const bool is_high_interval_;
1131
1132 // If this interval needs a register pair, the high or low equivalent.
1133 // `is_high_interval_` tells whether this holds the low or the high.
1134 LiveInterval* high_or_low_interval_;
1135
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001136 // The instruction represented by this interval.
1137 HInstruction* const defined_by_;
1138
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001139 static constexpr int kNoRegister = -1;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001140 static constexpr int kNoSpillSlot = -1;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001141
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00001142 ART_FRIEND_TEST(RegisterAllocatorTest, SpillInactive);
1143
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001144 DISALLOW_COPY_AND_ASSIGN(LiveInterval);
1145};
1146
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001147/**
1148 * Analysis that computes the liveness of instructions:
1149 *
1150 * (a) Non-environment uses of an instruction always make
1151 * the instruction live.
1152 * (b) Environment uses of an instruction whose type is
1153 * object (that is, non-primitive), make the instruction live.
1154 * This is due to having to keep alive objects that have
1155 * finalizers deleting native objects.
1156 * (c) When the graph has the debuggable property, environment uses
1157 * of an instruction that has a primitive type make the instruction live.
1158 * If the graph does not have the debuggable property, the environment
1159 * use has no effect, and may get a 'none' value after register allocation.
1160 *
1161 * (b) and (c) are implemented through SsaLivenessAnalysis::ShouldBeLiveForEnvironment.
1162 */
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001163class SsaLivenessAnalysis : public ValueObject {
1164 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001165 SsaLivenessAnalysis(HGraph* graph, CodeGenerator* codegen, ScopedArenaAllocator* allocator)
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001166 : graph_(graph),
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001167 codegen_(codegen),
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001168 allocator_(allocator),
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001169 block_infos_(graph->GetBlocks().size(),
1170 nullptr,
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001171 allocator_->Adapter(kArenaAllocSsaLiveness)),
1172 instructions_from_ssa_index_(allocator_->Adapter(kArenaAllocSsaLiveness)),
1173 instructions_from_lifetime_position_(allocator_->Adapter(kArenaAllocSsaLiveness)),
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001174 number_of_ssa_values_(0) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001175 }
1176
1177 void Analyze();
1178
1179 BitVector* GetLiveInSet(const HBasicBlock& block) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001180 return &block_infos_[block.GetBlockId()]->live_in_;
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001181 }
1182
1183 BitVector* GetLiveOutSet(const HBasicBlock& block) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001184 return &block_infos_[block.GetBlockId()]->live_out_;
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001185 }
1186
1187 BitVector* GetKillSet(const HBasicBlock& block) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001188 return &block_infos_[block.GetBlockId()]->kill_;
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001189 }
1190
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001191 HInstruction* GetInstructionFromSsaIndex(size_t index) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001192 return instructions_from_ssa_index_[index];
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001193 }
1194
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001195 HInstruction* GetInstructionFromPosition(size_t index) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001196 return instructions_from_lifetime_position_[index];
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001197 }
1198
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001199 HBasicBlock* GetBlockFromPosition(size_t index) const {
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +01001200 HInstruction* instruction = GetInstructionFromPosition(index);
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001201 if (instruction == nullptr) {
1202 // If we are at a block boundary, get the block following.
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +01001203 instruction = GetInstructionFromPosition(index + 1);
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001204 }
1205 return instruction->GetBlock();
1206 }
1207
Nicolas Geoffrayfbda5f32015-04-29 14:16:00 +01001208 bool IsAtBlockBoundary(size_t index) const {
1209 return GetInstructionFromPosition(index) == nullptr;
1210 }
1211
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001212 HInstruction* GetTempUser(LiveInterval* temp) const {
1213 // A temporary shares the same lifetime start as the instruction that requires it.
1214 DCHECK(temp->IsTemp());
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +00001215 HInstruction* user = GetInstructionFromPosition(temp->GetStart() / 2);
Vladimir Marko82b07402017-03-01 19:02:04 +00001216 DCHECK_EQ(user, temp->GetUses().front().GetUser());
Nicolas Geoffrayf01d3442015-03-27 17:15:49 +00001217 return user;
1218 }
1219
1220 size_t GetTempIndex(LiveInterval* temp) const {
1221 // We use the input index to store the index of the temporary in the user's temporary list.
1222 DCHECK(temp->IsTemp());
Vladimir Marko82b07402017-03-01 19:02:04 +00001223 return temp->GetUses().front().GetInputIndex();
Nicolas Geoffray01ef3452014-10-01 11:32:17 +01001224 }
1225
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001226 size_t GetMaxLifetimePosition() const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +01001227 return instructions_from_lifetime_position_.size() * 2 - 1;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001228 }
1229
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001230 size_t GetNumberOfSsaValues() const {
1231 return number_of_ssa_values_;
1232 }
1233
Andreas Gampe7c3952f2015-02-19 18:21:24 -08001234 static constexpr const char* kLivenessPassName = "liveness";
1235
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001236 private:
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001237 // Give an SSA number to each instruction that defines a value used by another instruction,
1238 // and setup the lifetime information of each instruction and block.
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001239 void NumberInstructions();
1240
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001241 // Compute live ranges of instructions, as well as live_in, live_out and kill sets.
1242 void ComputeLiveness();
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001243
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001244 // Compute the live ranges of instructions, as well as the initial live_in, live_out and
1245 // kill sets, that do not take into account backward branches.
1246 void ComputeLiveRanges();
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001247
1248 // After computing the initial sets, this method does a fixed point
1249 // calculation over the live_in and live_out set to take into account
1250 // backwards branches.
1251 void ComputeLiveInAndLiveOutSets();
1252
1253 // Update the live_in set of the block and returns whether it has changed.
1254 bool UpdateLiveIn(const HBasicBlock& block);
1255
1256 // Update the live_out set of the block and returns whether it has changed.
1257 bool UpdateLiveOut(const HBasicBlock& block);
1258
Mingyao Yang718493c2015-07-22 15:56:34 -07001259 // Returns whether `instruction` in an HEnvironment held by `env_holder`
1260 // should be kept live by the HEnvironment.
Vladimir Marko356bd282017-03-01 12:01:11 +00001261 static bool ShouldBeLiveForEnvironment(HInstruction* env_holder, HInstruction* instruction) {
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001262 if (instruction == nullptr) return false;
Mingyao Yang718493c2015-07-22 15:56:34 -07001263 // A value that's not live in compiled code may still be needed in interpreter,
1264 // due to code motion, etc.
1265 if (env_holder->IsDeoptimize()) return true;
David Brazdil77a48ae2015-09-15 12:34:04 +00001266 // A value live at a throwing instruction in a try block may be copied by
1267 // the exception handler to its location at the top of the catch block.
1268 if (env_holder->CanThrowIntoCatchBlock()) return true;
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001269 if (instruction->GetBlock()->GetGraph()->IsDebuggable()) return true;
Vladimir Marko0ebe0d82017-09-21 22:50:39 +01001270 return instruction->GetType() == DataType::Type::kReference;
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001271 }
1272
Nicolas Geoffrayd7c2fdc2016-05-10 14:35:34 +01001273 void CheckNoLiveInIrreducibleLoop(const HBasicBlock& block) const {
1274 if (!block.IsLoopHeader() || !block.GetLoopInformation()->IsIrreducible()) {
1275 return;
1276 }
1277 BitVector* live_in = GetLiveInSet(block);
1278 // To satisfy our liveness algorithm, we need to ensure loop headers of
1279 // irreducible loops do not have any live-in instructions, except constants
1280 // and the current method, which can be trivially re-materialized.
1281 for (uint32_t idx : live_in->Indexes()) {
1282 HInstruction* instruction = GetInstructionFromSsaIndex(idx);
1283 DCHECK(instruction->GetBlock()->IsEntryBlock()) << instruction->DebugName();
1284 DCHECK(!instruction->IsParameterValue());
1285 DCHECK(instruction->IsCurrentMethod() || instruction->IsConstant())
1286 << instruction->DebugName();
1287 }
1288 }
1289
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01001290 HGraph* const graph_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001291 CodeGenerator* const codegen_;
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001292
1293 // Use a local ScopedArenaAllocator for allocating memory.
1294 // This allocator must remain alive while doing register allocation.
Vladimir Marko69d310e2017-10-09 14:12:23 +01001295 ScopedArenaAllocator* const allocator_;
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001296
1297 ScopedArenaVector<BlockInfo*> block_infos_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001298
1299 // Temporary array used when computing live_in, live_out, and kill sets.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001300 ScopedArenaVector<HInstruction*> instructions_from_ssa_index_;
Nicolas Geoffray31d76b42014-06-09 15:02:22 +01001301
1302 // Temporary array used when inserting moves in the graph.
Vladimir Markoe764d2e2017-10-05 14:35:55 +01001303 ScopedArenaVector<HInstruction*> instructions_from_lifetime_position_;
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001304 size_t number_of_ssa_values_;
1305
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001306 ART_FRIEND_TEST(RegisterAllocatorTest, SpillInactive);
Nicolas Geoffray23a81882015-06-01 18:12:38 +01001307 ART_FRIEND_TEST(RegisterAllocatorTest, FreeUntil);
Nicolas Geoffray8cbab3c2015-04-23 15:14:36 +01001308
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001309 DISALLOW_COPY_AND_ASSIGN(SsaLivenessAnalysis);
1310};
1311
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001312} // namespace art
1313
1314#endif // ART_COMPILER_OPTIMIZING_SSA_LIVENESS_ANALYSIS_H_