blob: c3a99150c4e0a8b676461a5ddcc4f3404905b026 [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
Mathieu Chartierb666f482015-02-18 14:33:14 -080020#include "base/arena_object.h"
Nicolas Geoffray76716a62014-05-23 10:14:19 +010021#include "base/bit_field.h"
Nicolas Geoffray39468442014-09-02 15:17:15 +010022#include "base/bit_vector.h"
Ian Rogers0279ebb2014-10-08 17:27:48 -070023#include "base/value_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 Geoffray6c2dff82015-01-21 14:56:54 +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 // 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.
Mark Mendell3e6a3bf2015-01-19 14:09:22 -050069 kUnallocated = 10,
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.
Andreas Gampe785d2f22014-11-03 22:57:30 -080074 static_assert((kInvalid & kLocationConstantMask) != kConstant, "TagError");
75 static_assert((kUnallocated & kLocationConstantMask) != kConstant, "TagError");
76 static_assert((kStackSlot & kLocationConstantMask) != kConstant, "TagError");
77 static_assert((kDoubleStackSlot & kLocationConstantMask) != kConstant, "TagError");
78 static_assert((kRegister & kLocationConstantMask) != kConstant, "TagError");
Andreas Gampe785d2f22014-11-03 22:57:30 -080079 static_assert((kFpuRegister & kLocationConstantMask) != kConstant, "TagError");
80 static_assert((kRegisterPair & kLocationConstantMask) != kConstant, "TagError");
81 static_assert((kFpuRegisterPair & kLocationConstantMask) != kConstant, "TagError");
82 static_assert((kConstant & kLocationConstantMask) == kConstant, "TagError");
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010083
Nicolas Geoffray76716a62014-05-23 10:14:19 +010084 DCHECK(!IsValid());
85 }
86
87 Location(const Location& other) : ValueObject(), value_(other.value_) {}
88
89 Location& operator=(const Location& other) {
90 value_ = other.value_;
91 return *this;
92 }
93
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010094 bool IsConstant() const {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010095 return (value_ & kLocationConstantMask) == kConstant;
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010096 }
97
98 static Location ConstantLocation(HConstant* constant) {
99 DCHECK(constant != nullptr);
Ian Rogers13735952014-10-08 12:43:28 -0700100 return Location(kConstant | reinterpret_cast<uintptr_t>(constant));
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100101 }
102
103 HConstant* GetConstant() const {
104 DCHECK(IsConstant());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100105 return reinterpret_cast<HConstant*>(value_ & ~kLocationConstantMask);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100106 }
107
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100108 bool IsValid() const {
109 return value_ != kInvalid;
110 }
111
112 bool IsInvalid() const {
113 return !IsValid();
114 }
115
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100116 // Empty location. Used if there the location should be ignored.
117 static Location NoLocation() {
118 return Location();
119 }
120
121 // Register locations.
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100122 static Location RegisterLocation(int reg) {
123 return Location(kRegister, reg);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100124 }
125
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100126 static Location FpuRegisterLocation(int reg) {
127 return Location(kFpuRegister, reg);
128 }
129
130 static Location RegisterPairLocation(int low, int high) {
131 return Location(kRegisterPair, low << 16 | high);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100132 }
133
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000134 static Location FpuRegisterPairLocation(int low, int high) {
135 return Location(kFpuRegisterPair, low << 16 | high);
136 }
137
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100138 bool IsRegister() const {
139 return GetKind() == kRegister;
140 }
141
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100142 bool IsFpuRegister() const {
143 return GetKind() == kFpuRegister;
144 }
145
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100146 bool IsRegisterPair() const {
147 return GetKind() == kRegisterPair;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100148 }
149
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000150 bool IsFpuRegisterPair() const {
151 return GetKind() == kFpuRegisterPair;
152 }
153
Nicolas Geoffrayda02afe2015-02-11 02:29:42 +0000154 bool IsRegisterKind() const {
155 return IsRegister() || IsFpuRegister() || IsRegisterPair() || IsFpuRegisterPair();
156 }
157
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100158 int reg() const {
159 DCHECK(IsRegister() || IsFpuRegister());
160 return GetPayload();
161 }
162
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000163 int low() const {
164 DCHECK(IsPair());
165 return GetPayload() >> 16;
166 }
167
168 int high() const {
169 DCHECK(IsPair());
170 return GetPayload() & 0xFFFF;
171 }
172
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100173 template <typename T>
Roland Levillain271ab9c2014-11-27 15:23:57 +0000174 T AsRegister() const {
175 DCHECK(IsRegister());
176 return static_cast<T>(reg());
177 }
178
179 template <typename T>
180 T AsFpuRegister() const {
181 DCHECK(IsFpuRegister());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100182 return static_cast<T>(reg());
183 }
184
185 template <typename T>
186 T AsRegisterPairLow() const {
187 DCHECK(IsRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000188 return static_cast<T>(low());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100189 }
190
191 template <typename T>
192 T AsRegisterPairHigh() const {
193 DCHECK(IsRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000194 return static_cast<T>(high());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100195 }
196
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000197 template <typename T>
198 T AsFpuRegisterPairLow() const {
199 DCHECK(IsFpuRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000200 return static_cast<T>(low());
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000201 }
202
203 template <typename T>
204 T AsFpuRegisterPairHigh() const {
205 DCHECK(IsFpuRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000206 return static_cast<T>(high());
207 }
208
209 bool IsPair() const {
210 return IsRegisterPair() || IsFpuRegisterPair();
211 }
212
213 Location ToLow() const {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000214 if (IsRegisterPair()) {
215 return Location::RegisterLocation(low());
216 } else if (IsFpuRegisterPair()) {
217 return Location::FpuRegisterLocation(low());
218 } else {
219 DCHECK(IsDoubleStackSlot());
220 return Location::StackSlot(GetStackIndex());
221 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000222 }
223
224 Location ToHigh() const {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000225 if (IsRegisterPair()) {
226 return Location::RegisterLocation(high());
227 } else if (IsFpuRegisterPair()) {
228 return Location::FpuRegisterLocation(high());
229 } else {
230 DCHECK(IsDoubleStackSlot());
231 return Location::StackSlot(GetHighStackIndex(4));
232 }
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000233 }
234
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100235 static uintptr_t EncodeStackIndex(intptr_t stack_index) {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100236 DCHECK(-kStackIndexBias <= stack_index);
237 DCHECK(stack_index < kStackIndexBias);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100238 return static_cast<uintptr_t>(kStackIndexBias + stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100239 }
240
241 static Location StackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700242 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100243 Location loc(kStackSlot, payload);
244 // Ensure that sign is preserved.
245 DCHECK_EQ(loc.GetStackIndex(), stack_index);
246 return loc;
247 }
248
249 bool IsStackSlot() const {
250 return GetKind() == kStackSlot;
251 }
252
253 static Location DoubleStackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700254 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100255 Location loc(kDoubleStackSlot, payload);
256 // Ensure that sign is preserved.
257 DCHECK_EQ(loc.GetStackIndex(), stack_index);
258 return loc;
259 }
260
261 bool IsDoubleStackSlot() const {
262 return GetKind() == kDoubleStackSlot;
263 }
264
265 intptr_t GetStackIndex() const {
266 DCHECK(IsStackSlot() || IsDoubleStackSlot());
267 // Decode stack index manually to preserve sign.
268 return GetPayload() - kStackIndexBias;
269 }
270
271 intptr_t GetHighStackIndex(uintptr_t word_size) const {
272 DCHECK(IsDoubleStackSlot());
273 // Decode stack index manually to preserve sign.
274 return GetPayload() - kStackIndexBias + word_size;
275 }
276
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100277 Kind GetKind() const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100278 return IsConstant() ? kConstant : KindField::Decode(value_);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100279 }
280
281 bool Equals(Location other) const {
282 return value_ == other.value_;
283 }
284
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000285 bool Contains(Location other) const {
286 if (Equals(other)) {
287 return true;
Zheng Xuad4450e2015-04-17 18:48:56 +0800288 } else if (IsPair() || IsDoubleStackSlot()) {
289 return ToLow().Equals(other) || ToHigh().Equals(other);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000290 }
291 return false;
292 }
293
Zheng Xuad4450e2015-04-17 18:48:56 +0800294 bool OverlapsWith(Location other) const {
295 // Only check the overlapping case that can happen with our register allocation algorithm.
296 bool overlap = Contains(other) || other.Contains(*this);
297 if (kIsDebugBuild && !overlap) {
298 // Note: These are also overlapping cases. But we are not able to handle them in
299 // ParallelMoveResolverWithSwap. Make sure that we do not meet such case with our compiler.
300 if ((IsPair() && other.IsPair()) || (IsDoubleStackSlot() && other.IsDoubleStackSlot())) {
301 DCHECK(!Contains(other.ToLow()));
302 DCHECK(!Contains(other.ToHigh()));
303 }
304 }
305 return overlap;
306 }
307
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100308 const char* DebugString() const {
309 switch (GetKind()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100310 case kInvalid: return "I";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100311 case kRegister: return "R";
312 case kStackSlot: return "S";
313 case kDoubleStackSlot: return "DS";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100314 case kUnallocated: return "U";
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100315 case kConstant: return "C";
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100316 case kFpuRegister: return "F";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100317 case kRegisterPair: return "RP";
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000318 case kFpuRegisterPair: return "FP";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100319 case kDoNotUse5: // fall-through
320 case kDoNotUse9:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100321 LOG(FATAL) << "Should not use this location kind";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100322 }
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100323 UNREACHABLE();
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100324 return "?";
325 }
326
327 // Unallocated locations.
328 enum Policy {
329 kAny,
330 kRequiresRegister,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100331 kRequiresFpuRegister,
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100332 kSameAsFirstInput,
333 };
334
335 bool IsUnallocated() const {
336 return GetKind() == kUnallocated;
337 }
338
339 static Location UnallocatedLocation(Policy policy) {
340 return Location(kUnallocated, PolicyField::Encode(policy));
341 }
342
343 // Any free register is suitable to replace this unallocated location.
344 static Location Any() {
345 return UnallocatedLocation(kAny);
346 }
347
348 static Location RequiresRegister() {
349 return UnallocatedLocation(kRequiresRegister);
350 }
351
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100352 static Location RequiresFpuRegister() {
353 return UnallocatedLocation(kRequiresFpuRegister);
354 }
355
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100356 static Location RegisterOrConstant(HInstruction* instruction);
Mark Mendell3f6c7f62015-03-13 13:47:53 -0400357 static Location RegisterOrInt32LongConstant(HInstruction* instruction);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100358 static Location ByteRegisterOrConstant(int reg, HInstruction* instruction);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100359
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100360 // The location of the first input to the instruction will be
361 // used to replace this unallocated location.
362 static Location SameAsFirstInput() {
363 return UnallocatedLocation(kSameAsFirstInput);
364 }
365
366 Policy GetPolicy() const {
367 DCHECK(IsUnallocated());
368 return PolicyField::Decode(GetPayload());
369 }
370
Ian Rogers13735952014-10-08 12:43:28 -0700371 uintptr_t GetEncoding() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100372 return GetPayload();
373 }
374
375 private:
376 // Number of bits required to encode Kind value.
377 static constexpr uint32_t kBitsForKind = 4;
Ian Rogers13735952014-10-08 12:43:28 -0700378 static constexpr uint32_t kBitsForPayload = kBitsPerIntPtrT - kBitsForKind;
379 static constexpr uintptr_t kLocationConstantMask = 0x3;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100380
Ian Rogers13735952014-10-08 12:43:28 -0700381 explicit Location(uintptr_t value) : value_(value) {}
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100382
Ian Rogers13735952014-10-08 12:43:28 -0700383 Location(Kind kind, uintptr_t payload)
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100384 : value_(KindField::Encode(kind) | PayloadField::Encode(payload)) {}
385
Ian Rogers13735952014-10-08 12:43:28 -0700386 uintptr_t GetPayload() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100387 return PayloadField::Decode(value_);
388 }
389
390 typedef BitField<Kind, 0, kBitsForKind> KindField;
Ian Rogers13735952014-10-08 12:43:28 -0700391 typedef BitField<uintptr_t, kBitsForKind, kBitsForPayload> PayloadField;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100392
393 // Layout for kUnallocated locations payload.
394 typedef BitField<Policy, 0, 3> PolicyField;
395
396 // Layout for stack slots.
397 static const intptr_t kStackIndexBias =
398 static_cast<intptr_t>(1) << (kBitsForPayload - 1);
399
400 // Location either contains kind and payload fields or a tagged handle for
401 // a constant locations. Values of enumeration Kind are selected in such a
402 // way that none of them can be interpreted as a kConstant tag.
Ian Rogers13735952014-10-08 12:43:28 -0700403 uintptr_t value_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100404};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700405std::ostream& operator<<(std::ostream& os, const Location::Kind& rhs);
406std::ostream& operator<<(std::ostream& os, const Location::Policy& rhs);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100407
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100408class RegisterSet : public ValueObject {
409 public:
410 RegisterSet() : core_registers_(0), floating_point_registers_(0) {}
411
412 void Add(Location loc) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100413 if (loc.IsRegister()) {
414 core_registers_ |= (1 << loc.reg());
415 } else {
416 DCHECK(loc.IsFpuRegister());
417 floating_point_registers_ |= (1 << loc.reg());
418 }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100419 }
420
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100421 void Remove(Location loc) {
422 if (loc.IsRegister()) {
423 core_registers_ &= ~(1 << loc.reg());
424 } else {
Nicolas Geoffray424f6762014-11-03 14:51:25 +0000425 DCHECK(loc.IsFpuRegister()) << loc;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100426 floating_point_registers_ &= ~(1 << loc.reg());
427 }
428 }
429
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100430 bool ContainsCoreRegister(uint32_t id) {
431 return Contains(core_registers_, id);
432 }
433
434 bool ContainsFloatingPointRegister(uint32_t id) {
435 return Contains(floating_point_registers_, id);
436 }
437
438 static bool Contains(uint32_t register_set, uint32_t reg) {
439 return (register_set & (1 << reg)) != 0;
440 }
441
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000442 size_t GetNumberOfRegisters() const {
443 return __builtin_popcount(core_registers_) + __builtin_popcount(floating_point_registers_);
444 }
445
Nicolas Geoffray98893962015-01-21 12:32:32 +0000446 uint32_t GetCoreRegisters() const {
447 return core_registers_;
448 }
449
450 uint32_t GetFloatingPointRegisters() const {
451 return floating_point_registers_;
452 }
453
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100454 private:
455 uint32_t core_registers_;
456 uint32_t floating_point_registers_;
457
458 DISALLOW_COPY_AND_ASSIGN(RegisterSet);
459};
460
Andreas Gampe878d58c2015-01-15 23:24:00 -0800461static constexpr bool kIntrinsified = true;
462
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100463/**
464 * The code generator computes LocationSummary for each instruction so that
465 * the instruction itself knows what code to generate: where to find the inputs
466 * and where to place the result.
467 *
468 * The intent is to have the code for generating the instruction independent of
469 * register allocation. A register allocator just has to provide a LocationSummary.
470 */
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700471class LocationSummary : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100472 public:
Nicolas Geoffray39468442014-09-02 15:17:15 +0100473 enum CallKind {
474 kNoCall,
475 kCallOnSlowPath,
476 kCall
477 };
478
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800479 LocationSummary(HInstruction* instruction,
480 CallKind call_kind = kNoCall,
481 bool intrinsified = false);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100482
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100483 void SetInAt(uint32_t at, Location location) {
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000484 DCHECK(inputs_.Get(at).IsUnallocated() || inputs_.Get(at).IsInvalid());
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100485 inputs_.Put(at, location);
486 }
487
488 Location InAt(uint32_t at) const {
489 return inputs_.Get(at);
490 }
491
492 size_t GetInputCount() const {
493 return inputs_.Size();
494 }
495
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000496 void SetOut(Location location, Location::OutputOverlap overlaps = Location::kOutputOverlap) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000497 DCHECK(output_.IsInvalid());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100498 output_overlaps_ = overlaps;
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000499 output_ = location;
500 }
501
502 void UpdateOut(Location location) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000503 // There are two reasons for updating an output:
504 // 1) Parameters, where we only know the exact stack slot after
505 // doing full register allocation.
506 // 2) Unallocated location.
507 DCHECK(output_.IsStackSlot() || output_.IsDoubleStackSlot() || output_.IsUnallocated());
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000508 output_ = location;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100509 }
510
511 void AddTemp(Location location) {
512 temps_.Add(location);
513 }
514
515 Location GetTemp(uint32_t at) const {
516 return temps_.Get(at);
517 }
518
519 void SetTempAt(uint32_t at, Location location) {
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000520 DCHECK(temps_.Get(at).IsUnallocated() || temps_.Get(at).IsInvalid());
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100521 temps_.Put(at, location);
522 }
523
524 size_t GetTempCount() const {
525 return temps_.Size();
526 }
527
Nicolas Geoffray39468442014-09-02 15:17:15 +0100528 void SetEnvironmentAt(uint32_t at, Location location) {
529 environment_.Put(at, location);
530 }
531
532 Location GetEnvironmentAt(uint32_t at) const {
533 return environment_.Get(at);
534 }
535
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100536 Location Out() const { return output_; }
537
Nicolas Geoffray39468442014-09-02 15:17:15 +0100538 bool CanCall() const { return call_kind_ != kNoCall; }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100539 bool WillCall() const { return call_kind_ == kCall; }
540 bool OnlyCallsOnSlowPath() const { return call_kind_ == kCallOnSlowPath; }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100541 bool NeedsSafepoint() const { return CanCall(); }
542
543 void SetStackBit(uint32_t index) {
544 stack_mask_->SetBit(index);
545 }
546
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100547 void ClearStackBit(uint32_t index) {
548 stack_mask_->ClearBit(index);
549 }
550
Nicolas Geoffray39468442014-09-02 15:17:15 +0100551 void SetRegisterBit(uint32_t reg_id) {
552 register_mask_ |= (1 << reg_id);
553 }
554
Nicolas Geoffray98893962015-01-21 12:32:32 +0000555 uint32_t GetRegisterMask() const {
556 return register_mask_;
557 }
558
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100559 bool RegisterContainsObject(uint32_t reg_id) {
560 return RegisterSet::Contains(register_mask_, reg_id);
561 }
562
563 void AddLiveRegister(Location location) {
564 live_registers_.Add(location);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100565 }
566
567 BitVector* GetStackMask() const {
568 return stack_mask_;
569 }
570
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100571 RegisterSet* GetLiveRegisters() {
572 return &live_registers_;
573 }
574
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000575 size_t GetNumberOfLiveRegisters() const {
576 return live_registers_.GetNumberOfRegisters();
577 }
578
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000579 bool OutputUsesSameAs(uint32_t input_index) const {
580 return (input_index == 0)
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100581 && output_.IsUnallocated()
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000582 && (output_.GetPolicy() == Location::kSameAsFirstInput);
583 }
584
585 bool IsFixedInput(uint32_t input_index) const {
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000586 Location input = inputs_.Get(input_index);
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000587 return input.IsRegister()
Nicolas Geoffray98893962015-01-21 12:32:32 +0000588 || input.IsFpuRegister()
589 || input.IsPair()
590 || input.IsStackSlot()
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000591 || input.IsDoubleStackSlot();
Nicolas Geoffray76905622014-09-25 14:39:26 +0100592 }
593
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000594 bool OutputCanOverlapWithInputs() const {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000595 return output_overlaps_ == Location::kOutputOverlap;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100596 }
597
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800598 bool Intrinsified() const {
599 return intrinsified_;
600 }
601
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100602 private:
603 GrowableArray<Location> inputs_;
604 GrowableArray<Location> temps_;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100605 GrowableArray<Location> environment_;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100606 // Whether the output overlaps with any of the inputs. If it overlaps, then it cannot
607 // share the same register as the inputs.
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000608 Location::OutputOverlap output_overlaps_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100609 Location output_;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100610 const CallKind call_kind_;
611
612 // Mask of objects that live in the stack.
613 BitVector* stack_mask_;
614
615 // Mask of objects that live in register.
616 uint32_t register_mask_;
617
618 // Registers that are in use at this position.
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100619 RegisterSet live_registers_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100620
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800621 // Whether these are locations for an intrinsified call.
622 const bool intrinsified_;
623
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000624 ART_FRIEND_TEST(RegisterAllocatorTest, ExpectedInRegisterHint);
625 ART_FRIEND_TEST(RegisterAllocatorTest, SameAsFirstInputHint);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100626 DISALLOW_COPY_AND_ASSIGN(LocationSummary);
627};
628
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100629} // namespace art
630
631#endif // ART_COMPILER_OPTIMIZING_LOCATIONS_H_