blob: dda6c94a3d4456b83332b5e993bf6c30bfe89fe0 [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 Geoffray41aedbb2015-01-14 10:49:16 +000040 enum OutputOverlap {
41 kOutputOverlap,
42 kNoOutputOverlap
43 };
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +010044
Nicolas Geoffray76716a62014-05-23 10:14:19 +010045 enum Kind {
46 kInvalid = 0,
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010047 kConstant = 1,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010048 kStackSlot = 2, // 32bit stack slot.
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010049 kDoubleStackSlot = 3, // 64bit stack slot.
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010050
51 kRegister = 4, // Core register.
52
53 // We do not use the value 5 because it conflicts with kLocationConstantMask.
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010054 kDoNotUse5 = 5,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010055
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000056 kFpuRegister = 6, // Float register.
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010057
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000058 kRegisterPair = 7, // Long register.
59
60 kFpuRegisterPair = 8, // Double register.
61
62 // We do not use the value 9 because it conflicts with kLocationConstantMask.
63 kDoNotUse9 = 9,
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010064
Nicolas Geoffray76716a62014-05-23 10:14:19 +010065 // On 32bits architectures, quick can pass a long where the
66 // low bits are in the last parameter register, and the high
67 // bits are in a stack slot. The kQuickParameter kind is for
68 // handling this special case.
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000069 kQuickParameter = 10,
Nicolas Geoffray76716a62014-05-23 10:14:19 +010070
71 // Unallocated location represents a location that is not fixed and can be
72 // allocated by a register allocator. Each unallocated location has
73 // a policy that specifies what kind of location is suitable. Payload
74 // contains register allocation policy.
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000075 kUnallocated = 11,
Nicolas Geoffray76716a62014-05-23 10:14:19 +010076 };
77
78 Location() : value_(kInvalid) {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010079 // Verify that non-constant location kinds do not interfere with kConstant.
Andreas Gampe785d2f22014-11-03 22:57:30 -080080 static_assert((kInvalid & kLocationConstantMask) != kConstant, "TagError");
81 static_assert((kUnallocated & kLocationConstantMask) != kConstant, "TagError");
82 static_assert((kStackSlot & kLocationConstantMask) != kConstant, "TagError");
83 static_assert((kDoubleStackSlot & kLocationConstantMask) != kConstant, "TagError");
84 static_assert((kRegister & kLocationConstantMask) != kConstant, "TagError");
85 static_assert((kQuickParameter & kLocationConstantMask) != kConstant, "TagError");
86 static_assert((kFpuRegister & kLocationConstantMask) != kConstant, "TagError");
87 static_assert((kRegisterPair & kLocationConstantMask) != kConstant, "TagError");
88 static_assert((kFpuRegisterPair & kLocationConstantMask) != kConstant, "TagError");
89 static_assert((kConstant & kLocationConstantMask) == kConstant, "TagError");
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010090
Nicolas Geoffray76716a62014-05-23 10:14:19 +010091 DCHECK(!IsValid());
92 }
93
94 Location(const Location& other) : ValueObject(), value_(other.value_) {}
95
96 Location& operator=(const Location& other) {
97 value_ = other.value_;
98 return *this;
99 }
100
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100101 bool IsConstant() const {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100102 return (value_ & kLocationConstantMask) == kConstant;
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100103 }
104
105 static Location ConstantLocation(HConstant* constant) {
106 DCHECK(constant != nullptr);
Ian Rogers13735952014-10-08 12:43:28 -0700107 return Location(kConstant | reinterpret_cast<uintptr_t>(constant));
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100108 }
109
110 HConstant* GetConstant() const {
111 DCHECK(IsConstant());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100112 return reinterpret_cast<HConstant*>(value_ & ~kLocationConstantMask);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100113 }
114
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100115 bool IsValid() const {
116 return value_ != kInvalid;
117 }
118
119 bool IsInvalid() const {
120 return !IsValid();
121 }
122
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100123 // Empty location. Used if there the location should be ignored.
124 static Location NoLocation() {
125 return Location();
126 }
127
128 // Register locations.
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100129 static Location RegisterLocation(int reg) {
130 return Location(kRegister, reg);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100131 }
132
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100133 static Location FpuRegisterLocation(int reg) {
134 return Location(kFpuRegister, reg);
135 }
136
137 static Location RegisterPairLocation(int low, int high) {
138 return Location(kRegisterPair, low << 16 | high);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100139 }
140
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000141 static Location FpuRegisterPairLocation(int low, int high) {
142 return Location(kFpuRegisterPair, low << 16 | high);
143 }
144
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100145 bool IsRegister() const {
146 return GetKind() == kRegister;
147 }
148
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100149 bool IsFpuRegister() const {
150 return GetKind() == kFpuRegister;
151 }
152
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100153 bool IsRegisterPair() const {
154 return GetKind() == kRegisterPair;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100155 }
156
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000157 bool IsFpuRegisterPair() const {
158 return GetKind() == kFpuRegisterPair;
159 }
160
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100161 int reg() const {
162 DCHECK(IsRegister() || IsFpuRegister());
163 return GetPayload();
164 }
165
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000166 int low() const {
167 DCHECK(IsPair());
168 return GetPayload() >> 16;
169 }
170
171 int high() const {
172 DCHECK(IsPair());
173 return GetPayload() & 0xFFFF;
174 }
175
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100176 template <typename T>
Roland Levillain271ab9c2014-11-27 15:23:57 +0000177 T AsRegister() const {
178 DCHECK(IsRegister());
179 return static_cast<T>(reg());
180 }
181
182 template <typename T>
183 T AsFpuRegister() const {
184 DCHECK(IsFpuRegister());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100185 return static_cast<T>(reg());
186 }
187
188 template <typename T>
189 T AsRegisterPairLow() const {
190 DCHECK(IsRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000191 return static_cast<T>(low());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100192 }
193
194 template <typename T>
195 T AsRegisterPairHigh() const {
196 DCHECK(IsRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000197 return static_cast<T>(high());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100198 }
199
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000200 template <typename T>
201 T AsFpuRegisterPairLow() const {
202 DCHECK(IsFpuRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000203 return static_cast<T>(low());
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000204 }
205
206 template <typename T>
207 T AsFpuRegisterPairHigh() const {
208 DCHECK(IsFpuRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000209 return static_cast<T>(high());
210 }
211
212 bool IsPair() const {
213 return IsRegisterPair() || IsFpuRegisterPair();
214 }
215
216 Location ToLow() const {
217 return IsRegisterPair()
218 ? Location::RegisterLocation(low())
219 : Location::FpuRegisterLocation(low());
220 }
221
222 Location ToHigh() const {
223 return IsRegisterPair()
224 ? Location::RegisterLocation(high())
225 : Location::FpuRegisterLocation(high());
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000226 }
227
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100228 static uintptr_t EncodeStackIndex(intptr_t stack_index) {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100229 DCHECK(-kStackIndexBias <= stack_index);
230 DCHECK(stack_index < kStackIndexBias);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100231 return static_cast<uintptr_t>(kStackIndexBias + stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100232 }
233
234 static Location StackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700235 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100236 Location loc(kStackSlot, payload);
237 // Ensure that sign is preserved.
238 DCHECK_EQ(loc.GetStackIndex(), stack_index);
239 return loc;
240 }
241
242 bool IsStackSlot() const {
243 return GetKind() == kStackSlot;
244 }
245
246 static Location DoubleStackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700247 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100248 Location loc(kDoubleStackSlot, payload);
249 // Ensure that sign is preserved.
250 DCHECK_EQ(loc.GetStackIndex(), stack_index);
251 return loc;
252 }
253
254 bool IsDoubleStackSlot() const {
255 return GetKind() == kDoubleStackSlot;
256 }
257
258 intptr_t GetStackIndex() const {
259 DCHECK(IsStackSlot() || IsDoubleStackSlot());
260 // Decode stack index manually to preserve sign.
261 return GetPayload() - kStackIndexBias;
262 }
263
264 intptr_t GetHighStackIndex(uintptr_t word_size) const {
265 DCHECK(IsDoubleStackSlot());
266 // Decode stack index manually to preserve sign.
267 return GetPayload() - kStackIndexBias + word_size;
268 }
269
Nicolas Geoffray0a6c4592014-10-30 16:37:57 +0000270 static Location QuickParameter(uint16_t register_index, uint16_t stack_index) {
271 return Location(kQuickParameter, register_index << 16 | stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100272 }
273
Nicolas Geoffray0a6c4592014-10-30 16:37:57 +0000274 uint32_t GetQuickParameterRegisterIndex() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100275 DCHECK(IsQuickParameter());
Nicolas Geoffray0a6c4592014-10-30 16:37:57 +0000276 return GetPayload() >> 16;
277 }
278
279 uint32_t GetQuickParameterStackIndex() const {
280 DCHECK(IsQuickParameter());
281 return GetPayload() & 0xFFFF;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100282 }
283
284 bool IsQuickParameter() const {
285 return GetKind() == kQuickParameter;
286 }
287
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100288 Kind GetKind() const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100289 return IsConstant() ? kConstant : KindField::Decode(value_);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100290 }
291
292 bool Equals(Location other) const {
293 return value_ == other.value_;
294 }
295
296 const char* DebugString() const {
297 switch (GetKind()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100298 case kInvalid: return "I";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100299 case kRegister: return "R";
300 case kStackSlot: return "S";
301 case kDoubleStackSlot: return "DS";
302 case kQuickParameter: return "Q";
303 case kUnallocated: return "U";
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100304 case kConstant: return "C";
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100305 case kFpuRegister: return "F";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100306 case kRegisterPair: return "RP";
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000307 case kFpuRegisterPair: return "FP";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100308 case kDoNotUse5: // fall-through
309 case kDoNotUse9:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100310 LOG(FATAL) << "Should not use this location kind";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100311 }
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100312 UNREACHABLE();
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100313 return "?";
314 }
315
316 // Unallocated locations.
317 enum Policy {
318 kAny,
319 kRequiresRegister,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100320 kRequiresFpuRegister,
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100321 kSameAsFirstInput,
322 };
323
324 bool IsUnallocated() const {
325 return GetKind() == kUnallocated;
326 }
327
328 static Location UnallocatedLocation(Policy policy) {
329 return Location(kUnallocated, PolicyField::Encode(policy));
330 }
331
332 // Any free register is suitable to replace this unallocated location.
333 static Location Any() {
334 return UnallocatedLocation(kAny);
335 }
336
337 static Location RequiresRegister() {
338 return UnallocatedLocation(kRequiresRegister);
339 }
340
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100341 static Location RequiresFpuRegister() {
342 return UnallocatedLocation(kRequiresFpuRegister);
343 }
344
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100345 static Location RegisterOrConstant(HInstruction* instruction);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100346 static Location ByteRegisterOrConstant(int reg, HInstruction* instruction);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100347
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100348 // The location of the first input to the instruction will be
349 // used to replace this unallocated location.
350 static Location SameAsFirstInput() {
351 return UnallocatedLocation(kSameAsFirstInput);
352 }
353
354 Policy GetPolicy() const {
355 DCHECK(IsUnallocated());
356 return PolicyField::Decode(GetPayload());
357 }
358
Ian Rogers13735952014-10-08 12:43:28 -0700359 uintptr_t GetEncoding() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100360 return GetPayload();
361 }
362
363 private:
364 // Number of bits required to encode Kind value.
365 static constexpr uint32_t kBitsForKind = 4;
Ian Rogers13735952014-10-08 12:43:28 -0700366 static constexpr uint32_t kBitsForPayload = kBitsPerIntPtrT - kBitsForKind;
367 static constexpr uintptr_t kLocationConstantMask = 0x3;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100368
Ian Rogers13735952014-10-08 12:43:28 -0700369 explicit Location(uintptr_t value) : value_(value) {}
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100370
Ian Rogers13735952014-10-08 12:43:28 -0700371 Location(Kind kind, uintptr_t payload)
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100372 : value_(KindField::Encode(kind) | PayloadField::Encode(payload)) {}
373
Ian Rogers13735952014-10-08 12:43:28 -0700374 uintptr_t GetPayload() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100375 return PayloadField::Decode(value_);
376 }
377
378 typedef BitField<Kind, 0, kBitsForKind> KindField;
Ian Rogers13735952014-10-08 12:43:28 -0700379 typedef BitField<uintptr_t, kBitsForKind, kBitsForPayload> PayloadField;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100380
381 // Layout for kUnallocated locations payload.
382 typedef BitField<Policy, 0, 3> PolicyField;
383
384 // Layout for stack slots.
385 static const intptr_t kStackIndexBias =
386 static_cast<intptr_t>(1) << (kBitsForPayload - 1);
387
388 // Location either contains kind and payload fields or a tagged handle for
389 // a constant locations. Values of enumeration Kind are selected in such a
390 // way that none of them can be interpreted as a kConstant tag.
Ian Rogers13735952014-10-08 12:43:28 -0700391 uintptr_t value_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100392};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700393std::ostream& operator<<(std::ostream& os, const Location::Kind& rhs);
394std::ostream& operator<<(std::ostream& os, const Location::Policy& rhs);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100395
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100396class RegisterSet : public ValueObject {
397 public:
398 RegisterSet() : core_registers_(0), floating_point_registers_(0) {}
399
400 void Add(Location loc) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100401 if (loc.IsRegister()) {
402 core_registers_ |= (1 << loc.reg());
403 } else {
404 DCHECK(loc.IsFpuRegister());
405 floating_point_registers_ |= (1 << loc.reg());
406 }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100407 }
408
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100409 void Remove(Location loc) {
410 if (loc.IsRegister()) {
411 core_registers_ &= ~(1 << loc.reg());
412 } else {
Nicolas Geoffray424f6762014-11-03 14:51:25 +0000413 DCHECK(loc.IsFpuRegister()) << loc;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100414 floating_point_registers_ &= ~(1 << loc.reg());
415 }
416 }
417
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100418 bool ContainsCoreRegister(uint32_t id) {
419 return Contains(core_registers_, id);
420 }
421
422 bool ContainsFloatingPointRegister(uint32_t id) {
423 return Contains(floating_point_registers_, id);
424 }
425
426 static bool Contains(uint32_t register_set, uint32_t reg) {
427 return (register_set & (1 << reg)) != 0;
428 }
429
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000430 size_t GetNumberOfRegisters() const {
431 return __builtin_popcount(core_registers_) + __builtin_popcount(floating_point_registers_);
432 }
433
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100434 private:
435 uint32_t core_registers_;
436 uint32_t floating_point_registers_;
437
438 DISALLOW_COPY_AND_ASSIGN(RegisterSet);
439};
440
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100441/**
442 * The code generator computes LocationSummary for each instruction so that
443 * the instruction itself knows what code to generate: where to find the inputs
444 * and where to place the result.
445 *
446 * The intent is to have the code for generating the instruction independent of
447 * register allocation. A register allocator just has to provide a LocationSummary.
448 */
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700449class LocationSummary : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100450 public:
Nicolas Geoffray39468442014-09-02 15:17:15 +0100451 enum CallKind {
452 kNoCall,
453 kCallOnSlowPath,
454 kCall
455 };
456
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800457 LocationSummary(HInstruction* instruction,
458 CallKind call_kind = kNoCall,
459 bool intrinsified = false);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100460
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100461 void SetInAt(uint32_t at, Location location) {
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000462 DCHECK(inputs_.Get(at).IsUnallocated() || inputs_.Get(at).IsInvalid());
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100463 inputs_.Put(at, location);
464 }
465
466 Location InAt(uint32_t at) const {
467 return inputs_.Get(at);
468 }
469
470 size_t GetInputCount() const {
471 return inputs_.Size();
472 }
473
Nicolas Geoffray41aedbb2015-01-14 10:49:16 +0000474 void SetOut(Location location, Location::OutputOverlap overlaps = Location::kOutputOverlap) {
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000475 DCHECK(output_.IsUnallocated() || output_.IsInvalid());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100476 output_overlaps_ = overlaps;
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000477 output_ = location;
478 }
479
480 void UpdateOut(Location location) {
481 // The only reason for updating an output is for parameters where
482 // we only know the exact stack slot after doing full register
483 // allocation.
484 DCHECK(output_.IsStackSlot() || output_.IsDoubleStackSlot());
485 output_ = location;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100486 }
487
488 void AddTemp(Location location) {
489 temps_.Add(location);
490 }
491
492 Location GetTemp(uint32_t at) const {
493 return temps_.Get(at);
494 }
495
496 void SetTempAt(uint32_t at, Location location) {
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000497 DCHECK(temps_.Get(at).IsUnallocated() || temps_.Get(at).IsInvalid());
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100498 temps_.Put(at, location);
499 }
500
501 size_t GetTempCount() const {
502 return temps_.Size();
503 }
504
Nicolas Geoffray39468442014-09-02 15:17:15 +0100505 void SetEnvironmentAt(uint32_t at, Location location) {
506 environment_.Put(at, location);
507 }
508
509 Location GetEnvironmentAt(uint32_t at) const {
510 return environment_.Get(at);
511 }
512
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100513 Location Out() const { return output_; }
514
Nicolas Geoffray39468442014-09-02 15:17:15 +0100515 bool CanCall() const { return call_kind_ != kNoCall; }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100516 bool WillCall() const { return call_kind_ == kCall; }
517 bool OnlyCallsOnSlowPath() const { return call_kind_ == kCallOnSlowPath; }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100518 bool NeedsSafepoint() const { return CanCall(); }
519
520 void SetStackBit(uint32_t index) {
521 stack_mask_->SetBit(index);
522 }
523
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100524 void ClearStackBit(uint32_t index) {
525 stack_mask_->ClearBit(index);
526 }
527
Nicolas Geoffray39468442014-09-02 15:17:15 +0100528 void SetRegisterBit(uint32_t reg_id) {
529 register_mask_ |= (1 << reg_id);
530 }
531
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100532 bool RegisterContainsObject(uint32_t reg_id) {
533 return RegisterSet::Contains(register_mask_, reg_id);
534 }
535
536 void AddLiveRegister(Location location) {
537 live_registers_.Add(location);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100538 }
539
540 BitVector* GetStackMask() const {
541 return stack_mask_;
542 }
543
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100544 RegisterSet* GetLiveRegisters() {
545 return &live_registers_;
546 }
547
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000548 size_t GetNumberOfLiveRegisters() const {
549 return live_registers_.GetNumberOfRegisters();
550 }
551
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100552 bool InputOverlapsWithOutputOrTemp(uint32_t input_index, bool is_environment) const {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100553 if (is_environment) return true;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100554 if ((input_index == 0)
555 && output_.IsUnallocated()
556 && (output_.GetPolicy() == Location::kSameAsFirstInput)) {
Nicolas Geoffray76905622014-09-25 14:39:26 +0100557 return false;
558 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000559 Location input = inputs_.Get(input_index);
560 if (input.IsRegister() || input.IsFpuRegister() || input.IsPair()) {
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +0100561 return false;
562 }
Nicolas Geoffray76905622014-09-25 14:39:26 +0100563 return true;
564 }
565
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100566 bool OutputOverlapsWithInputs() const {
Nicolas Geoffray41aedbb2015-01-14 10:49:16 +0000567 return output_overlaps_ == Location::kOutputOverlap;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100568 }
569
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800570 bool Intrinsified() const {
571 return intrinsified_;
572 }
573
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100574 private:
575 GrowableArray<Location> inputs_;
576 GrowableArray<Location> temps_;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100577 GrowableArray<Location> environment_;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100578 // Whether the output overlaps with any of the inputs. If it overlaps, then it cannot
579 // share the same register as the inputs.
Nicolas Geoffray41aedbb2015-01-14 10:49:16 +0000580 Location::OutputOverlap output_overlaps_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100581 Location output_;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100582 const CallKind call_kind_;
583
584 // Mask of objects that live in the stack.
585 BitVector* stack_mask_;
586
587 // Mask of objects that live in register.
588 uint32_t register_mask_;
589
590 // Registers that are in use at this position.
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100591 RegisterSet live_registers_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100592
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800593 // Whether these are locations for an intrinsified call.
594 const bool intrinsified_;
595
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000596 ART_FRIEND_TEST(RegisterAllocatorTest, ExpectedInRegisterHint);
597 ART_FRIEND_TEST(RegisterAllocatorTest, SameAsFirstInputHint);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100598 DISALLOW_COPY_AND_ASSIGN(LocationSummary);
599};
600
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100601} // namespace art
602
603#endif // ART_COMPILER_OPTIMIZING_LOCATIONS_H_