blob: 1ff26d914ca58ece03476f0b756f27fb258e3617 [file] [log] [blame]
Nicolas Geoffray76716a62014-05-23 10:14:19 +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_LOCATIONS_H_
18#define ART_COMPILER_OPTIMIZING_LOCATIONS_H_
19
20#include "base/bit_field.h"
Nicolas Geoffray39468442014-09-02 15:17:15 +010021#include "base/bit_vector.h"
Ian Rogers0279ebb2014-10-08 17:27:48 -070022#include "base/value_object.h"
23#include "utils/arena_object.h"
Nicolas Geoffray76716a62014-05-23 10:14:19 +010024#include "utils/growable_array.h"
Nicolas Geoffray76716a62014-05-23 10:14:19 +010025
26namespace art {
27
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010028class HConstant;
Nicolas Geoffray76716a62014-05-23 10:14:19 +010029class HInstruction;
Nicolas Geoffray424f6762014-11-03 14:51:25 +000030class Location;
31
32std::ostream& operator<<(std::ostream& os, const Location& location);
Nicolas Geoffray76716a62014-05-23 10:14:19 +010033
34/**
35 * A Location is an abstraction over the potential location
36 * of an instruction. It could be in register or stack.
37 */
38class Location : public ValueObject {
39 public:
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +010040 static constexpr bool kNoOutputOverlap = false;
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +010041
Nicolas Geoffray76716a62014-05-23 10:14:19 +010042 enum Kind {
43 kInvalid = 0,
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010044 kConstant = 1,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010045 kStackSlot = 2, // 32bit stack slot.
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010046 kDoubleStackSlot = 3, // 64bit stack slot.
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010047
48 kRegister = 4, // Core register.
49
50 // We do not use the value 5 because it conflicts with kLocationConstantMask.
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010051 kDoNotUse5 = 5,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010052
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000053 kFpuRegister = 6, // Float register.
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010054
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000055 kRegisterPair = 7, // Long register.
56
57 kFpuRegisterPair = 8, // Double register.
58
59 // We do not use the value 9 because it conflicts with kLocationConstantMask.
60 kDoNotUse9 = 9,
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010061
Nicolas Geoffray76716a62014-05-23 10:14:19 +010062 // On 32bits architectures, quick can pass a long where the
63 // low bits are in the last parameter register, and the high
64 // bits are in a stack slot. The kQuickParameter kind is for
65 // handling this special case.
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000066 kQuickParameter = 10,
Nicolas Geoffray76716a62014-05-23 10:14:19 +010067
68 // Unallocated location represents a location that is not fixed and can be
69 // allocated by a register allocator. Each unallocated location has
70 // a policy that specifies what kind of location is suitable. Payload
71 // contains register allocation policy.
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000072 kUnallocated = 11,
Nicolas Geoffray76716a62014-05-23 10:14:19 +010073 };
74
75 Location() : value_(kInvalid) {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010076 // Verify that non-constant location kinds do not interfere with kConstant.
Andreas Gampe785d2f22014-11-03 22:57:30 -080077 static_assert((kInvalid & kLocationConstantMask) != kConstant, "TagError");
78 static_assert((kUnallocated & kLocationConstantMask) != kConstant, "TagError");
79 static_assert((kStackSlot & kLocationConstantMask) != kConstant, "TagError");
80 static_assert((kDoubleStackSlot & kLocationConstantMask) != kConstant, "TagError");
81 static_assert((kRegister & kLocationConstantMask) != kConstant, "TagError");
82 static_assert((kQuickParameter & kLocationConstantMask) != kConstant, "TagError");
83 static_assert((kFpuRegister & kLocationConstantMask) != kConstant, "TagError");
84 static_assert((kRegisterPair & kLocationConstantMask) != kConstant, "TagError");
85 static_assert((kFpuRegisterPair & kLocationConstantMask) != kConstant, "TagError");
86 static_assert((kConstant & kLocationConstantMask) == kConstant, "TagError");
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010087
Nicolas Geoffray76716a62014-05-23 10:14:19 +010088 DCHECK(!IsValid());
89 }
90
91 Location(const Location& other) : ValueObject(), value_(other.value_) {}
92
93 Location& operator=(const Location& other) {
94 value_ = other.value_;
95 return *this;
96 }
97
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010098 bool IsConstant() const {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010099 return (value_ & kLocationConstantMask) == kConstant;
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100100 }
101
102 static Location ConstantLocation(HConstant* constant) {
103 DCHECK(constant != nullptr);
Ian Rogers13735952014-10-08 12:43:28 -0700104 return Location(kConstant | reinterpret_cast<uintptr_t>(constant));
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100105 }
106
107 HConstant* GetConstant() const {
108 DCHECK(IsConstant());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100109 return reinterpret_cast<HConstant*>(value_ & ~kLocationConstantMask);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100110 }
111
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100112 bool IsValid() const {
113 return value_ != kInvalid;
114 }
115
116 bool IsInvalid() const {
117 return !IsValid();
118 }
119
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100120 // Empty location. Used if there the location should be ignored.
121 static Location NoLocation() {
122 return Location();
123 }
124
125 // Register locations.
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100126 static Location RegisterLocation(int reg) {
127 return Location(kRegister, reg);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100128 }
129
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100130 static Location FpuRegisterLocation(int reg) {
131 return Location(kFpuRegister, reg);
132 }
133
134 static Location RegisterPairLocation(int low, int high) {
135 return Location(kRegisterPair, low << 16 | high);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100136 }
137
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000138 static Location FpuRegisterPairLocation(int low, int high) {
139 return Location(kFpuRegisterPair, low << 16 | high);
140 }
141
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100142 bool IsRegister() const {
143 return GetKind() == kRegister;
144 }
145
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100146 bool IsFpuRegister() const {
147 return GetKind() == kFpuRegister;
148 }
149
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100150 bool IsRegisterPair() const {
151 return GetKind() == kRegisterPair;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100152 }
153
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000154 bool IsFpuRegisterPair() const {
155 return GetKind() == kFpuRegisterPair;
156 }
157
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100158 int reg() const {
159 DCHECK(IsRegister() || IsFpuRegister());
160 return GetPayload();
161 }
162
163 template <typename T>
Roland Levillain271ab9c2014-11-27 15:23:57 +0000164 T AsRegister() const {
165 DCHECK(IsRegister());
166 return static_cast<T>(reg());
167 }
168
169 template <typename T>
170 T AsFpuRegister() const {
171 DCHECK(IsFpuRegister());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100172 return static_cast<T>(reg());
173 }
174
175 template <typename T>
176 T AsRegisterPairLow() const {
177 DCHECK(IsRegisterPair());
178 return static_cast<T>(GetPayload() >> 16);
179 }
180
181 template <typename T>
182 T AsRegisterPairHigh() const {
183 DCHECK(IsRegisterPair());
184 return static_cast<T>(GetPayload() & 0xFFFF);
185 }
186
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000187 template <typename T>
188 T AsFpuRegisterPairLow() const {
189 DCHECK(IsFpuRegisterPair());
190 return static_cast<T>(GetPayload() >> 16);
191 }
192
193 template <typename T>
194 T AsFpuRegisterPairHigh() const {
195 DCHECK(IsFpuRegisterPair());
196 return static_cast<T>(GetPayload() & 0xFFFF);
197 }
198
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100199 static uintptr_t EncodeStackIndex(intptr_t stack_index) {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100200 DCHECK(-kStackIndexBias <= stack_index);
201 DCHECK(stack_index < kStackIndexBias);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100202 return static_cast<uintptr_t>(kStackIndexBias + stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100203 }
204
205 static Location StackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700206 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100207 Location loc(kStackSlot, payload);
208 // Ensure that sign is preserved.
209 DCHECK_EQ(loc.GetStackIndex(), stack_index);
210 return loc;
211 }
212
213 bool IsStackSlot() const {
214 return GetKind() == kStackSlot;
215 }
216
217 static Location DoubleStackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700218 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100219 Location loc(kDoubleStackSlot, payload);
220 // Ensure that sign is preserved.
221 DCHECK_EQ(loc.GetStackIndex(), stack_index);
222 return loc;
223 }
224
225 bool IsDoubleStackSlot() const {
226 return GetKind() == kDoubleStackSlot;
227 }
228
229 intptr_t GetStackIndex() const {
230 DCHECK(IsStackSlot() || IsDoubleStackSlot());
231 // Decode stack index manually to preserve sign.
232 return GetPayload() - kStackIndexBias;
233 }
234
235 intptr_t GetHighStackIndex(uintptr_t word_size) const {
236 DCHECK(IsDoubleStackSlot());
237 // Decode stack index manually to preserve sign.
238 return GetPayload() - kStackIndexBias + word_size;
239 }
240
Nicolas Geoffray0a6c4592014-10-30 16:37:57 +0000241 static Location QuickParameter(uint16_t register_index, uint16_t stack_index) {
242 return Location(kQuickParameter, register_index << 16 | stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100243 }
244
Nicolas Geoffray0a6c4592014-10-30 16:37:57 +0000245 uint32_t GetQuickParameterRegisterIndex() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100246 DCHECK(IsQuickParameter());
Nicolas Geoffray0a6c4592014-10-30 16:37:57 +0000247 return GetPayload() >> 16;
248 }
249
250 uint32_t GetQuickParameterStackIndex() const {
251 DCHECK(IsQuickParameter());
252 return GetPayload() & 0xFFFF;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100253 }
254
255 bool IsQuickParameter() const {
256 return GetKind() == kQuickParameter;
257 }
258
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100259 Kind GetKind() const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100260 return IsConstant() ? kConstant : KindField::Decode(value_);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100261 }
262
263 bool Equals(Location other) const {
264 return value_ == other.value_;
265 }
266
267 const char* DebugString() const {
268 switch (GetKind()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100269 case kInvalid: return "I";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100270 case kRegister: return "R";
271 case kStackSlot: return "S";
272 case kDoubleStackSlot: return "DS";
273 case kQuickParameter: return "Q";
274 case kUnallocated: return "U";
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100275 case kConstant: return "C";
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100276 case kFpuRegister: return "F";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100277 case kRegisterPair: return "RP";
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000278 case kFpuRegisterPair: return "FP";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100279 case kDoNotUse5: // fall-through
280 case kDoNotUse9:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100281 LOG(FATAL) << "Should not use this location kind";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100282 }
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100283 UNREACHABLE();
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100284 return "?";
285 }
286
287 // Unallocated locations.
288 enum Policy {
289 kAny,
290 kRequiresRegister,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100291 kRequiresFpuRegister,
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100292 kSameAsFirstInput,
293 };
294
295 bool IsUnallocated() const {
296 return GetKind() == kUnallocated;
297 }
298
299 static Location UnallocatedLocation(Policy policy) {
300 return Location(kUnallocated, PolicyField::Encode(policy));
301 }
302
303 // Any free register is suitable to replace this unallocated location.
304 static Location Any() {
305 return UnallocatedLocation(kAny);
306 }
307
308 static Location RequiresRegister() {
309 return UnallocatedLocation(kRequiresRegister);
310 }
311
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100312 static Location RequiresFpuRegister() {
313 return UnallocatedLocation(kRequiresFpuRegister);
314 }
315
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100316 static Location RegisterOrConstant(HInstruction* instruction);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100317 static Location ByteRegisterOrConstant(int reg, HInstruction* instruction);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100318
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100319 // The location of the first input to the instruction will be
320 // used to replace this unallocated location.
321 static Location SameAsFirstInput() {
322 return UnallocatedLocation(kSameAsFirstInput);
323 }
324
325 Policy GetPolicy() const {
326 DCHECK(IsUnallocated());
327 return PolicyField::Decode(GetPayload());
328 }
329
Ian Rogers13735952014-10-08 12:43:28 -0700330 uintptr_t GetEncoding() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100331 return GetPayload();
332 }
333
334 private:
335 // Number of bits required to encode Kind value.
336 static constexpr uint32_t kBitsForKind = 4;
Ian Rogers13735952014-10-08 12:43:28 -0700337 static constexpr uint32_t kBitsForPayload = kBitsPerIntPtrT - kBitsForKind;
338 static constexpr uintptr_t kLocationConstantMask = 0x3;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100339
Ian Rogers13735952014-10-08 12:43:28 -0700340 explicit Location(uintptr_t value) : value_(value) {}
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100341
Ian Rogers13735952014-10-08 12:43:28 -0700342 Location(Kind kind, uintptr_t payload)
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100343 : value_(KindField::Encode(kind) | PayloadField::Encode(payload)) {}
344
Ian Rogers13735952014-10-08 12:43:28 -0700345 uintptr_t GetPayload() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100346 return PayloadField::Decode(value_);
347 }
348
349 typedef BitField<Kind, 0, kBitsForKind> KindField;
Ian Rogers13735952014-10-08 12:43:28 -0700350 typedef BitField<uintptr_t, kBitsForKind, kBitsForPayload> PayloadField;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100351
352 // Layout for kUnallocated locations payload.
353 typedef BitField<Policy, 0, 3> PolicyField;
354
355 // Layout for stack slots.
356 static const intptr_t kStackIndexBias =
357 static_cast<intptr_t>(1) << (kBitsForPayload - 1);
358
359 // Location either contains kind and payload fields or a tagged handle for
360 // a constant locations. Values of enumeration Kind are selected in such a
361 // way that none of them can be interpreted as a kConstant tag.
Ian Rogers13735952014-10-08 12:43:28 -0700362 uintptr_t value_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100363};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700364std::ostream& operator<<(std::ostream& os, const Location::Kind& rhs);
365std::ostream& operator<<(std::ostream& os, const Location::Policy& rhs);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100366
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100367class RegisterSet : public ValueObject {
368 public:
369 RegisterSet() : core_registers_(0), floating_point_registers_(0) {}
370
371 void Add(Location loc) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100372 if (loc.IsRegister()) {
373 core_registers_ |= (1 << loc.reg());
374 } else {
375 DCHECK(loc.IsFpuRegister());
376 floating_point_registers_ |= (1 << loc.reg());
377 }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100378 }
379
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100380 void Remove(Location loc) {
381 if (loc.IsRegister()) {
382 core_registers_ &= ~(1 << loc.reg());
383 } else {
Nicolas Geoffray424f6762014-11-03 14:51:25 +0000384 DCHECK(loc.IsFpuRegister()) << loc;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100385 floating_point_registers_ &= ~(1 << loc.reg());
386 }
387 }
388
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100389 bool ContainsCoreRegister(uint32_t id) {
390 return Contains(core_registers_, id);
391 }
392
393 bool ContainsFloatingPointRegister(uint32_t id) {
394 return Contains(floating_point_registers_, id);
395 }
396
397 static bool Contains(uint32_t register_set, uint32_t reg) {
398 return (register_set & (1 << reg)) != 0;
399 }
400
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000401 size_t GetNumberOfRegisters() const {
402 return __builtin_popcount(core_registers_) + __builtin_popcount(floating_point_registers_);
403 }
404
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100405 private:
406 uint32_t core_registers_;
407 uint32_t floating_point_registers_;
408
409 DISALLOW_COPY_AND_ASSIGN(RegisterSet);
410};
411
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100412/**
413 * The code generator computes LocationSummary for each instruction so that
414 * the instruction itself knows what code to generate: where to find the inputs
415 * and where to place the result.
416 *
417 * The intent is to have the code for generating the instruction independent of
418 * register allocation. A register allocator just has to provide a LocationSummary.
419 */
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700420class LocationSummary : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100421 public:
Nicolas Geoffray39468442014-09-02 15:17:15 +0100422 enum CallKind {
423 kNoCall,
424 kCallOnSlowPath,
425 kCall
426 };
427
Roland Levillain5799fc02014-09-25 12:15:20 +0100428 LocationSummary(HInstruction* instruction, CallKind call_kind = kNoCall);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100429
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100430 void SetInAt(uint32_t at, Location location) {
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000431 DCHECK(inputs_.Get(at).IsUnallocated() || inputs_.Get(at).IsInvalid());
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100432 inputs_.Put(at, location);
433 }
434
435 Location InAt(uint32_t at) const {
436 return inputs_.Get(at);
437 }
438
439 size_t GetInputCount() const {
440 return inputs_.Size();
441 }
442
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100443 void SetOut(Location location, bool overlaps = true) {
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000444 DCHECK(output_.IsUnallocated() || output_.IsInvalid());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100445 output_overlaps_ = overlaps;
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000446 output_ = location;
447 }
448
449 void UpdateOut(Location location) {
450 // The only reason for updating an output is for parameters where
451 // we only know the exact stack slot after doing full register
452 // allocation.
453 DCHECK(output_.IsStackSlot() || output_.IsDoubleStackSlot());
454 output_ = location;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100455 }
456
457 void AddTemp(Location location) {
458 temps_.Add(location);
459 }
460
461 Location GetTemp(uint32_t at) const {
462 return temps_.Get(at);
463 }
464
465 void SetTempAt(uint32_t at, Location location) {
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000466 DCHECK(temps_.Get(at).IsUnallocated() || temps_.Get(at).IsInvalid());
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100467 temps_.Put(at, location);
468 }
469
470 size_t GetTempCount() const {
471 return temps_.Size();
472 }
473
Nicolas Geoffray39468442014-09-02 15:17:15 +0100474 void SetEnvironmentAt(uint32_t at, Location location) {
475 environment_.Put(at, location);
476 }
477
478 Location GetEnvironmentAt(uint32_t at) const {
479 return environment_.Get(at);
480 }
481
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100482 Location Out() const { return output_; }
483
Nicolas Geoffray39468442014-09-02 15:17:15 +0100484 bool CanCall() const { return call_kind_ != kNoCall; }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100485 bool WillCall() const { return call_kind_ == kCall; }
486 bool OnlyCallsOnSlowPath() const { return call_kind_ == kCallOnSlowPath; }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100487 bool NeedsSafepoint() const { return CanCall(); }
488
489 void SetStackBit(uint32_t index) {
490 stack_mask_->SetBit(index);
491 }
492
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100493 void ClearStackBit(uint32_t index) {
494 stack_mask_->ClearBit(index);
495 }
496
Nicolas Geoffray39468442014-09-02 15:17:15 +0100497 void SetRegisterBit(uint32_t reg_id) {
498 register_mask_ |= (1 << reg_id);
499 }
500
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100501 bool RegisterContainsObject(uint32_t reg_id) {
502 return RegisterSet::Contains(register_mask_, reg_id);
503 }
504
505 void AddLiveRegister(Location location) {
506 live_registers_.Add(location);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100507 }
508
509 BitVector* GetStackMask() const {
510 return stack_mask_;
511 }
512
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100513 RegisterSet* GetLiveRegisters() {
514 return &live_registers_;
515 }
516
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000517 size_t GetNumberOfLiveRegisters() const {
518 return live_registers_.GetNumberOfRegisters();
519 }
520
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100521 bool InputOverlapsWithOutputOrTemp(uint32_t input_index, bool is_environment) const {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100522 if (is_environment) return true;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100523 if ((input_index == 0)
524 && output_.IsUnallocated()
525 && (output_.GetPolicy() == Location::kSameAsFirstInput)) {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100526 return false;
527 }
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100528 if (inputs_.Get(input_index).IsRegister() || inputs_.Get(input_index).IsFpuRegister()) {
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +0100529 return false;
530 }
Nicolas Geoffray76905622014-09-25 14:39:26 +0100531 return true;
532 }
533
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100534 bool OutputOverlapsWithInputs() const {
535 return output_overlaps_;
536 }
537
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100538 private:
539 GrowableArray<Location> inputs_;
540 GrowableArray<Location> temps_;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100541 GrowableArray<Location> environment_;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100542 // Whether the output overlaps with any of the inputs. If it overlaps, then it cannot
543 // share the same register as the inputs.
544 bool output_overlaps_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100545 Location output_;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100546 const CallKind call_kind_;
547
548 // Mask of objects that live in the stack.
549 BitVector* stack_mask_;
550
551 // Mask of objects that live in register.
552 uint32_t register_mask_;
553
554 // Registers that are in use at this position.
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100555 RegisterSet live_registers_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100556
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000557 ART_FRIEND_TEST(RegisterAllocatorTest, ExpectedInRegisterHint);
558 ART_FRIEND_TEST(RegisterAllocatorTest, SameAsFirstInputHint);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100559 DISALLOW_COPY_AND_ASSIGN(LocationSummary);
560};
561
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100562} // namespace art
563
564#endif // ART_COMPILER_OPTIMIZING_LOCATIONS_H_