blob: 914a0c46cbbb674d0781bf00da89df02f2db479b [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;
30
31/**
32 * A Location is an abstraction over the potential location
33 * of an instruction. It could be in register or stack.
34 */
35class Location : public ValueObject {
36 public:
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +010037 static constexpr bool kNoOutputOverlap = false;
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +010038
Nicolas Geoffray76716a62014-05-23 10:14:19 +010039 enum Kind {
40 kInvalid = 0,
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010041 kConstant = 1,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010042 kStackSlot = 2, // 32bit stack slot.
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010043 kDoubleStackSlot = 3, // 64bit stack slot.
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010044
45 kRegister = 4, // Core register.
46
47 // We do not use the value 5 because it conflicts with kLocationConstantMask.
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010048 kDoNotUse5 = 5,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010049
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000050 kFpuRegister = 6, // Float register.
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010051
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000052 kRegisterPair = 7, // Long register.
53
54 kFpuRegisterPair = 8, // Double register.
55
56 // We do not use the value 9 because it conflicts with kLocationConstantMask.
57 kDoNotUse9 = 9,
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010058
Nicolas Geoffray76716a62014-05-23 10:14:19 +010059 // On 32bits architectures, quick can pass a long where the
60 // low bits are in the last parameter register, and the high
61 // bits are in a stack slot. The kQuickParameter kind is for
62 // handling this special case.
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000063 kQuickParameter = 10,
Nicolas Geoffray76716a62014-05-23 10:14:19 +010064
65 // Unallocated location represents a location that is not fixed and can be
66 // allocated by a register allocator. Each unallocated location has
67 // a policy that specifies what kind of location is suitable. Payload
68 // contains register allocation policy.
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000069 kUnallocated = 11,
Nicolas Geoffray76716a62014-05-23 10:14:19 +010070 };
71
72 Location() : value_(kInvalid) {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010073 // Verify that non-constant location kinds do not interfere with kConstant.
74 COMPILE_ASSERT((kInvalid & kLocationConstantMask) != kConstant, TagError);
75 COMPILE_ASSERT((kUnallocated & kLocationConstantMask) != kConstant, TagError);
76 COMPILE_ASSERT((kStackSlot & kLocationConstantMask) != kConstant, TagError);
77 COMPILE_ASSERT((kDoubleStackSlot & kLocationConstantMask) != kConstant, TagError);
78 COMPILE_ASSERT((kRegister & kLocationConstantMask) != kConstant, TagError);
79 COMPILE_ASSERT((kQuickParameter & kLocationConstantMask) != kConstant, TagError);
80 COMPILE_ASSERT((kFpuRegister & kLocationConstantMask) != kConstant, TagError);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010081 COMPILE_ASSERT((kRegisterPair & kLocationConstantMask) != kConstant, TagError);
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000082 COMPILE_ASSERT((kFpuRegisterPair & kLocationConstantMask) != kConstant, TagError);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010083 COMPILE_ASSERT((kConstant & kLocationConstantMask) == kConstant, TagError);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010084
Nicolas Geoffray76716a62014-05-23 10:14:19 +010085 DCHECK(!IsValid());
86 }
87
88 Location(const Location& other) : ValueObject(), value_(other.value_) {}
89
90 Location& operator=(const Location& other) {
91 value_ = other.value_;
92 return *this;
93 }
94
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010095 bool IsConstant() const {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010096 return (value_ & kLocationConstantMask) == kConstant;
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010097 }
98
99 static Location ConstantLocation(HConstant* constant) {
100 DCHECK(constant != nullptr);
Ian Rogers13735952014-10-08 12:43:28 -0700101 return Location(kConstant | reinterpret_cast<uintptr_t>(constant));
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100102 }
103
104 HConstant* GetConstant() const {
105 DCHECK(IsConstant());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100106 return reinterpret_cast<HConstant*>(value_ & ~kLocationConstantMask);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100107 }
108
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100109 bool IsValid() const {
110 return value_ != kInvalid;
111 }
112
113 bool IsInvalid() const {
114 return !IsValid();
115 }
116
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100117 // Empty location. Used if there the location should be ignored.
118 static Location NoLocation() {
119 return Location();
120 }
121
122 // Register locations.
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100123 static Location RegisterLocation(int reg) {
124 return Location(kRegister, reg);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100125 }
126
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100127 static Location FpuRegisterLocation(int reg) {
128 return Location(kFpuRegister, reg);
129 }
130
131 static Location RegisterPairLocation(int low, int high) {
132 return Location(kRegisterPair, low << 16 | high);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100133 }
134
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000135 static Location FpuRegisterPairLocation(int low, int high) {
136 return Location(kFpuRegisterPair, low << 16 | high);
137 }
138
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100139 bool IsRegister() const {
140 return GetKind() == kRegister;
141 }
142
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100143 bool IsFpuRegister() const {
144 return GetKind() == kFpuRegister;
145 }
146
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100147 bool IsRegisterPair() const {
148 return GetKind() == kRegisterPair;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100149 }
150
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000151 bool IsFpuRegisterPair() const {
152 return GetKind() == kFpuRegisterPair;
153 }
154
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100155 int reg() const {
156 DCHECK(IsRegister() || IsFpuRegister());
157 return GetPayload();
158 }
159
160 template <typename T>
161 T As() const {
162 return static_cast<T>(reg());
163 }
164
165 template <typename T>
166 T AsRegisterPairLow() const {
167 DCHECK(IsRegisterPair());
168 return static_cast<T>(GetPayload() >> 16);
169 }
170
171 template <typename T>
172 T AsRegisterPairHigh() const {
173 DCHECK(IsRegisterPair());
174 return static_cast<T>(GetPayload() & 0xFFFF);
175 }
176
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000177 template <typename T>
178 T AsFpuRegisterPairLow() const {
179 DCHECK(IsFpuRegisterPair());
180 return static_cast<T>(GetPayload() >> 16);
181 }
182
183 template <typename T>
184 T AsFpuRegisterPairHigh() const {
185 DCHECK(IsFpuRegisterPair());
186 return static_cast<T>(GetPayload() & 0xFFFF);
187 }
188
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100189 static uintptr_t EncodeStackIndex(intptr_t stack_index) {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100190 DCHECK(-kStackIndexBias <= stack_index);
191 DCHECK(stack_index < kStackIndexBias);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100192 return static_cast<uintptr_t>(kStackIndexBias + stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100193 }
194
195 static Location StackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700196 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100197 Location loc(kStackSlot, payload);
198 // Ensure that sign is preserved.
199 DCHECK_EQ(loc.GetStackIndex(), stack_index);
200 return loc;
201 }
202
203 bool IsStackSlot() const {
204 return GetKind() == kStackSlot;
205 }
206
207 static Location DoubleStackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700208 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100209 Location loc(kDoubleStackSlot, payload);
210 // Ensure that sign is preserved.
211 DCHECK_EQ(loc.GetStackIndex(), stack_index);
212 return loc;
213 }
214
215 bool IsDoubleStackSlot() const {
216 return GetKind() == kDoubleStackSlot;
217 }
218
219 intptr_t GetStackIndex() const {
220 DCHECK(IsStackSlot() || IsDoubleStackSlot());
221 // Decode stack index manually to preserve sign.
222 return GetPayload() - kStackIndexBias;
223 }
224
225 intptr_t GetHighStackIndex(uintptr_t word_size) const {
226 DCHECK(IsDoubleStackSlot());
227 // Decode stack index manually to preserve sign.
228 return GetPayload() - kStackIndexBias + word_size;
229 }
230
Nicolas Geoffray0a6c4592014-10-30 16:37:57 +0000231 static Location QuickParameter(uint16_t register_index, uint16_t stack_index) {
232 return Location(kQuickParameter, register_index << 16 | stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100233 }
234
Nicolas Geoffray0a6c4592014-10-30 16:37:57 +0000235 uint32_t GetQuickParameterRegisterIndex() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100236 DCHECK(IsQuickParameter());
Nicolas Geoffray0a6c4592014-10-30 16:37:57 +0000237 return GetPayload() >> 16;
238 }
239
240 uint32_t GetQuickParameterStackIndex() const {
241 DCHECK(IsQuickParameter());
242 return GetPayload() & 0xFFFF;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100243 }
244
245 bool IsQuickParameter() const {
246 return GetKind() == kQuickParameter;
247 }
248
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100249 Kind GetKind() const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100250 return IsConstant() ? kConstant : KindField::Decode(value_);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100251 }
252
253 bool Equals(Location other) const {
254 return value_ == other.value_;
255 }
256
257 const char* DebugString() const {
258 switch (GetKind()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100259 case kInvalid: return "I";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100260 case kRegister: return "R";
261 case kStackSlot: return "S";
262 case kDoubleStackSlot: return "DS";
263 case kQuickParameter: return "Q";
264 case kUnallocated: return "U";
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100265 case kConstant: return "C";
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100266 case kFpuRegister: return "F";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100267 case kRegisterPair: return "RP";
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000268 case kFpuRegisterPair: return "FP";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100269 case kDoNotUse5: // fall-through
270 case kDoNotUse9:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100271 LOG(FATAL) << "Should not use this location kind";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100272 }
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100273 UNREACHABLE();
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100274 return "?";
275 }
276
277 // Unallocated locations.
278 enum Policy {
279 kAny,
280 kRequiresRegister,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100281 kRequiresFpuRegister,
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100282 kSameAsFirstInput,
283 };
284
285 bool IsUnallocated() const {
286 return GetKind() == kUnallocated;
287 }
288
289 static Location UnallocatedLocation(Policy policy) {
290 return Location(kUnallocated, PolicyField::Encode(policy));
291 }
292
293 // Any free register is suitable to replace this unallocated location.
294 static Location Any() {
295 return UnallocatedLocation(kAny);
296 }
297
298 static Location RequiresRegister() {
299 return UnallocatedLocation(kRequiresRegister);
300 }
301
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100302 static Location RequiresFpuRegister() {
303 return UnallocatedLocation(kRequiresFpuRegister);
304 }
305
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100306 static Location RegisterOrConstant(HInstruction* instruction);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100307 static Location ByteRegisterOrConstant(int reg, HInstruction* instruction);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100308
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100309 // The location of the first input to the instruction will be
310 // used to replace this unallocated location.
311 static Location SameAsFirstInput() {
312 return UnallocatedLocation(kSameAsFirstInput);
313 }
314
315 Policy GetPolicy() const {
316 DCHECK(IsUnallocated());
317 return PolicyField::Decode(GetPayload());
318 }
319
Ian Rogers13735952014-10-08 12:43:28 -0700320 uintptr_t GetEncoding() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100321 return GetPayload();
322 }
323
324 private:
325 // Number of bits required to encode Kind value.
326 static constexpr uint32_t kBitsForKind = 4;
Ian Rogers13735952014-10-08 12:43:28 -0700327 static constexpr uint32_t kBitsForPayload = kBitsPerIntPtrT - kBitsForKind;
328 static constexpr uintptr_t kLocationConstantMask = 0x3;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100329
Ian Rogers13735952014-10-08 12:43:28 -0700330 explicit Location(uintptr_t value) : value_(value) {}
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100331
Ian Rogers13735952014-10-08 12:43:28 -0700332 Location(Kind kind, uintptr_t payload)
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100333 : value_(KindField::Encode(kind) | PayloadField::Encode(payload)) {}
334
Ian Rogers13735952014-10-08 12:43:28 -0700335 uintptr_t GetPayload() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100336 return PayloadField::Decode(value_);
337 }
338
339 typedef BitField<Kind, 0, kBitsForKind> KindField;
Ian Rogers13735952014-10-08 12:43:28 -0700340 typedef BitField<uintptr_t, kBitsForKind, kBitsForPayload> PayloadField;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100341
342 // Layout for kUnallocated locations payload.
343 typedef BitField<Policy, 0, 3> PolicyField;
344
345 // Layout for stack slots.
346 static const intptr_t kStackIndexBias =
347 static_cast<intptr_t>(1) << (kBitsForPayload - 1);
348
349 // Location either contains kind and payload fields or a tagged handle for
350 // a constant locations. Values of enumeration Kind are selected in such a
351 // way that none of them can be interpreted as a kConstant tag.
Ian Rogers13735952014-10-08 12:43:28 -0700352 uintptr_t value_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100353};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700354std::ostream& operator<<(std::ostream& os, const Location::Kind& rhs);
355std::ostream& operator<<(std::ostream& os, const Location::Policy& rhs);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100356
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100357class RegisterSet : public ValueObject {
358 public:
359 RegisterSet() : core_registers_(0), floating_point_registers_(0) {}
360
361 void Add(Location loc) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100362 if (loc.IsRegister()) {
363 core_registers_ |= (1 << loc.reg());
364 } else {
365 DCHECK(loc.IsFpuRegister());
366 floating_point_registers_ |= (1 << loc.reg());
367 }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100368 }
369
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100370 void Remove(Location loc) {
371 if (loc.IsRegister()) {
372 core_registers_ &= ~(1 << loc.reg());
373 } else {
374 DCHECK(loc.IsFpuRegister());
375 floating_point_registers_ &= ~(1 << loc.reg());
376 }
377 }
378
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100379 bool ContainsCoreRegister(uint32_t id) {
380 return Contains(core_registers_, id);
381 }
382
383 bool ContainsFloatingPointRegister(uint32_t id) {
384 return Contains(floating_point_registers_, id);
385 }
386
387 static bool Contains(uint32_t register_set, uint32_t reg) {
388 return (register_set & (1 << reg)) != 0;
389 }
390
391 private:
392 uint32_t core_registers_;
393 uint32_t floating_point_registers_;
394
395 DISALLOW_COPY_AND_ASSIGN(RegisterSet);
396};
397
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100398/**
399 * The code generator computes LocationSummary for each instruction so that
400 * the instruction itself knows what code to generate: where to find the inputs
401 * and where to place the result.
402 *
403 * The intent is to have the code for generating the instruction independent of
404 * register allocation. A register allocator just has to provide a LocationSummary.
405 */
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700406class LocationSummary : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100407 public:
Nicolas Geoffray39468442014-09-02 15:17:15 +0100408 enum CallKind {
409 kNoCall,
410 kCallOnSlowPath,
411 kCall
412 };
413
Roland Levillain5799fc02014-09-25 12:15:20 +0100414 LocationSummary(HInstruction* instruction, CallKind call_kind = kNoCall);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100415
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100416 void SetInAt(uint32_t at, Location location) {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100417 inputs_.Put(at, location);
418 }
419
420 Location InAt(uint32_t at) const {
421 return inputs_.Get(at);
422 }
423
424 size_t GetInputCount() const {
425 return inputs_.Size();
426 }
427
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100428 void SetOut(Location location, bool overlaps = true) {
429 output_overlaps_ = overlaps;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100430 output_ = Location(location);
431 }
432
433 void AddTemp(Location location) {
434 temps_.Add(location);
435 }
436
437 Location GetTemp(uint32_t at) const {
438 return temps_.Get(at);
439 }
440
441 void SetTempAt(uint32_t at, Location location) {
442 temps_.Put(at, location);
443 }
444
445 size_t GetTempCount() const {
446 return temps_.Size();
447 }
448
Nicolas Geoffray39468442014-09-02 15:17:15 +0100449 void SetEnvironmentAt(uint32_t at, Location location) {
450 environment_.Put(at, location);
451 }
452
453 Location GetEnvironmentAt(uint32_t at) const {
454 return environment_.Get(at);
455 }
456
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100457 Location Out() const { return output_; }
458
Nicolas Geoffray39468442014-09-02 15:17:15 +0100459 bool CanCall() const { return call_kind_ != kNoCall; }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100460 bool WillCall() const { return call_kind_ == kCall; }
461 bool OnlyCallsOnSlowPath() const { return call_kind_ == kCallOnSlowPath; }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100462 bool NeedsSafepoint() const { return CanCall(); }
463
464 void SetStackBit(uint32_t index) {
465 stack_mask_->SetBit(index);
466 }
467
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100468 void ClearStackBit(uint32_t index) {
469 stack_mask_->ClearBit(index);
470 }
471
Nicolas Geoffray39468442014-09-02 15:17:15 +0100472 void SetRegisterBit(uint32_t reg_id) {
473 register_mask_ |= (1 << reg_id);
474 }
475
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100476 bool RegisterContainsObject(uint32_t reg_id) {
477 return RegisterSet::Contains(register_mask_, reg_id);
478 }
479
480 void AddLiveRegister(Location location) {
481 live_registers_.Add(location);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100482 }
483
484 BitVector* GetStackMask() const {
485 return stack_mask_;
486 }
487
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100488 RegisterSet* GetLiveRegisters() {
489 return &live_registers_;
490 }
491
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100492 bool InputOverlapsWithOutputOrTemp(uint32_t input_index, bool is_environment) const {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100493 if (is_environment) return true;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100494 if ((input_index == 0)
495 && output_.IsUnallocated()
496 && (output_.GetPolicy() == Location::kSameAsFirstInput)) {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100497 return false;
498 }
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100499 if (inputs_.Get(input_index).IsRegister() || inputs_.Get(input_index).IsFpuRegister()) {
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +0100500 return false;
501 }
Nicolas Geoffray76905622014-09-25 14:39:26 +0100502 return true;
503 }
504
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100505 bool OutputOverlapsWithInputs() const {
506 return output_overlaps_;
507 }
508
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100509 private:
510 GrowableArray<Location> inputs_;
511 GrowableArray<Location> temps_;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100512 GrowableArray<Location> environment_;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100513 // Whether the output overlaps with any of the inputs. If it overlaps, then it cannot
514 // share the same register as the inputs.
515 bool output_overlaps_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100516 Location output_;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100517 const CallKind call_kind_;
518
519 // Mask of objects that live in the stack.
520 BitVector* stack_mask_;
521
522 // Mask of objects that live in register.
523 uint32_t register_mask_;
524
525 // Registers that are in use at this position.
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100526 RegisterSet live_registers_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100527
528 DISALLOW_COPY_AND_ASSIGN(LocationSummary);
529};
530
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +0100531std::ostream& operator<<(std::ostream& os, const Location& location);
532
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100533} // namespace art
534
535#endif // ART_COMPILER_OPTIMIZING_LOCATIONS_H_