blob: 2eeba18a4d383d487a314618ae882122a6dc9b76 [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
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010020#include "base/arena_containers.h"
Mathieu Chartierb666f482015-02-18 14:33:14 -080021#include "base/arena_object.h"
Nicolas Geoffray76716a62014-05-23 10:14:19 +010022#include "base/bit_field.h"
Nicolas Geoffray39468442014-09-02 15:17:15 +010023#include "base/bit_vector.h"
Ian Rogers0279ebb2014-10-08 17:27:48 -070024#include "base/value_object.h"
Nicolas Geoffray76716a62014-05-23 10:14:19 +010025#include "utils/growable_array.h"
Nicolas Geoffray76716a62014-05-23 10:14:19 +010026
27namespace art {
28
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010029class HConstant;
Nicolas Geoffray76716a62014-05-23 10:14:19 +010030class HInstruction;
Nicolas Geoffray424f6762014-11-03 14:51:25 +000031class Location;
32
33std::ostream& operator<<(std::ostream& os, const Location& location);
Nicolas Geoffray76716a62014-05-23 10:14:19 +010034
35/**
36 * A Location is an abstraction over the potential location
37 * of an instruction. It could be in register or stack.
38 */
Vladimir Marko76c92ac2015-09-17 15:39:16 +010039class Location : public ValueObject {
Nicolas Geoffray76716a62014-05-23 10:14:19 +010040 public:
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +000041 enum OutputOverlap {
42 kOutputOverlap,
43 kNoOutputOverlap
44 };
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +010045
Nicolas Geoffray76716a62014-05-23 10:14:19 +010046 enum Kind {
47 kInvalid = 0,
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010048 kConstant = 1,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010049 kStackSlot = 2, // 32bit stack slot.
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010050 kDoubleStackSlot = 3, // 64bit stack slot.
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010051
52 kRegister = 4, // Core register.
53
54 // We do not use the value 5 because it conflicts with kLocationConstantMask.
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010055 kDoNotUse5 = 5,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010056
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000057 kFpuRegister = 6, // Float register.
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010058
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000059 kRegisterPair = 7, // Long register.
60
61 kFpuRegisterPair = 8, // Double register.
62
63 // We do not use the value 9 because it conflicts with kLocationConstantMask.
64 kDoNotUse9 = 9,
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010065
Nicolas Geoffray76716a62014-05-23 10:14:19 +010066 // Unallocated location represents a location that is not fixed and can be
67 // allocated by a register allocator. Each unallocated location has
68 // a policy that specifies what kind of location is suitable. Payload
69 // contains register allocation policy.
Mark Mendell3e6a3bf2015-01-19 14:09:22 -050070 kUnallocated = 10,
Nicolas Geoffray76716a62014-05-23 10:14:19 +010071 };
72
Vladimir Marko76c92ac2015-09-17 15:39:16 +010073 Location() : ValueObject(), value_(kInvalid) {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010074 // Verify that non-constant location kinds do not interfere with kConstant.
Andreas Gampe785d2f22014-11-03 22:57:30 -080075 static_assert((kInvalid & kLocationConstantMask) != kConstant, "TagError");
76 static_assert((kUnallocated & kLocationConstantMask) != kConstant, "TagError");
77 static_assert((kStackSlot & kLocationConstantMask) != kConstant, "TagError");
78 static_assert((kDoubleStackSlot & kLocationConstantMask) != kConstant, "TagError");
79 static_assert((kRegister & kLocationConstantMask) != kConstant, "TagError");
Andreas Gampe785d2f22014-11-03 22:57:30 -080080 static_assert((kFpuRegister & kLocationConstantMask) != kConstant, "TagError");
81 static_assert((kRegisterPair & kLocationConstantMask) != kConstant, "TagError");
82 static_assert((kFpuRegisterPair & kLocationConstantMask) != kConstant, "TagError");
83 static_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
Vladimir Markofa6b93c2015-09-15 10:15:55 +010088 Location(const Location& other) : value_(other.value_) {}
Nicolas Geoffray76716a62014-05-23 10:14:19 +010089
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 Geoffrayda02afe2015-02-11 02:29:42 +0000155 bool IsRegisterKind() const {
156 return IsRegister() || IsFpuRegister() || IsRegisterPair() || IsFpuRegisterPair();
157 }
158
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100159 int reg() const {
160 DCHECK(IsRegister() || IsFpuRegister());
161 return GetPayload();
162 }
163
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000164 int low() const {
165 DCHECK(IsPair());
166 return GetPayload() >> 16;
167 }
168
169 int high() const {
170 DCHECK(IsPair());
171 return GetPayload() & 0xFFFF;
172 }
173
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100174 template <typename T>
Roland Levillain271ab9c2014-11-27 15:23:57 +0000175 T AsRegister() const {
176 DCHECK(IsRegister());
177 return static_cast<T>(reg());
178 }
179
180 template <typename T>
181 T AsFpuRegister() const {
182 DCHECK(IsFpuRegister());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100183 return static_cast<T>(reg());
184 }
185
186 template <typename T>
187 T AsRegisterPairLow() const {
188 DCHECK(IsRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000189 return static_cast<T>(low());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100190 }
191
192 template <typename T>
193 T AsRegisterPairHigh() const {
194 DCHECK(IsRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000195 return static_cast<T>(high());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100196 }
197
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000198 template <typename T>
199 T AsFpuRegisterPairLow() const {
200 DCHECK(IsFpuRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000201 return static_cast<T>(low());
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000202 }
203
204 template <typename T>
205 T AsFpuRegisterPairHigh() const {
206 DCHECK(IsFpuRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000207 return static_cast<T>(high());
208 }
209
210 bool IsPair() const {
211 return IsRegisterPair() || IsFpuRegisterPair();
212 }
213
214 Location ToLow() const {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000215 if (IsRegisterPair()) {
216 return Location::RegisterLocation(low());
217 } else if (IsFpuRegisterPair()) {
218 return Location::FpuRegisterLocation(low());
219 } else {
220 DCHECK(IsDoubleStackSlot());
221 return Location::StackSlot(GetStackIndex());
222 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000223 }
224
225 Location ToHigh() const {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000226 if (IsRegisterPair()) {
227 return Location::RegisterLocation(high());
228 } else if (IsFpuRegisterPair()) {
229 return Location::FpuRegisterLocation(high());
230 } else {
231 DCHECK(IsDoubleStackSlot());
232 return Location::StackSlot(GetHighStackIndex(4));
233 }
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000234 }
235
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100236 static uintptr_t EncodeStackIndex(intptr_t stack_index) {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100237 DCHECK(-kStackIndexBias <= stack_index);
238 DCHECK(stack_index < kStackIndexBias);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100239 return static_cast<uintptr_t>(kStackIndexBias + stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100240 }
241
242 static Location StackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700243 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100244 Location loc(kStackSlot, payload);
245 // Ensure that sign is preserved.
246 DCHECK_EQ(loc.GetStackIndex(), stack_index);
247 return loc;
248 }
249
250 bool IsStackSlot() const {
251 return GetKind() == kStackSlot;
252 }
253
254 static Location DoubleStackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700255 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100256 Location loc(kDoubleStackSlot, payload);
257 // Ensure that sign is preserved.
258 DCHECK_EQ(loc.GetStackIndex(), stack_index);
259 return loc;
260 }
261
262 bool IsDoubleStackSlot() const {
263 return GetKind() == kDoubleStackSlot;
264 }
265
266 intptr_t GetStackIndex() const {
267 DCHECK(IsStackSlot() || IsDoubleStackSlot());
268 // Decode stack index manually to preserve sign.
269 return GetPayload() - kStackIndexBias;
270 }
271
272 intptr_t GetHighStackIndex(uintptr_t word_size) const {
273 DCHECK(IsDoubleStackSlot());
274 // Decode stack index manually to preserve sign.
275 return GetPayload() - kStackIndexBias + word_size;
276 }
277
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100278 Kind GetKind() const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100279 return IsConstant() ? kConstant : KindField::Decode(value_);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100280 }
281
282 bool Equals(Location other) const {
283 return value_ == other.value_;
284 }
285
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000286 bool Contains(Location other) const {
287 if (Equals(other)) {
288 return true;
Zheng Xuad4450e2015-04-17 18:48:56 +0800289 } else if (IsPair() || IsDoubleStackSlot()) {
290 return ToLow().Equals(other) || ToHigh().Equals(other);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000291 }
292 return false;
293 }
294
Zheng Xuad4450e2015-04-17 18:48:56 +0800295 bool OverlapsWith(Location other) const {
296 // Only check the overlapping case that can happen with our register allocation algorithm.
297 bool overlap = Contains(other) || other.Contains(*this);
298 if (kIsDebugBuild && !overlap) {
299 // Note: These are also overlapping cases. But we are not able to handle them in
300 // ParallelMoveResolverWithSwap. Make sure that we do not meet such case with our compiler.
301 if ((IsPair() && other.IsPair()) || (IsDoubleStackSlot() && other.IsDoubleStackSlot())) {
302 DCHECK(!Contains(other.ToLow()));
303 DCHECK(!Contains(other.ToHigh()));
304 }
305 }
306 return overlap;
307 }
308
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100309 const char* DebugString() const {
310 switch (GetKind()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100311 case kInvalid: return "I";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100312 case kRegister: return "R";
313 case kStackSlot: return "S";
314 case kDoubleStackSlot: return "DS";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100315 case kUnallocated: return "U";
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100316 case kConstant: return "C";
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100317 case kFpuRegister: return "F";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100318 case kRegisterPair: return "RP";
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000319 case kFpuRegisterPair: return "FP";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100320 case kDoNotUse5: // fall-through
321 case kDoNotUse9:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100322 LOG(FATAL) << "Should not use this location kind";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100323 }
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100324 UNREACHABLE();
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100325 return "?";
326 }
327
328 // Unallocated locations.
329 enum Policy {
330 kAny,
331 kRequiresRegister,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100332 kRequiresFpuRegister,
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100333 kSameAsFirstInput,
334 };
335
336 bool IsUnallocated() const {
337 return GetKind() == kUnallocated;
338 }
339
340 static Location UnallocatedLocation(Policy policy) {
341 return Location(kUnallocated, PolicyField::Encode(policy));
342 }
343
344 // Any free register is suitable to replace this unallocated location.
345 static Location Any() {
346 return UnallocatedLocation(kAny);
347 }
348
349 static Location RequiresRegister() {
350 return UnallocatedLocation(kRequiresRegister);
351 }
352
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100353 static Location RequiresFpuRegister() {
354 return UnallocatedLocation(kRequiresFpuRegister);
355 }
356
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100357 static Location RegisterOrConstant(HInstruction* instruction);
Mark Mendell3f6c7f62015-03-13 13:47:53 -0400358 static Location RegisterOrInt32LongConstant(HInstruction* instruction);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100359 static Location ByteRegisterOrConstant(int reg, HInstruction* instruction);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100360
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100361 // The location of the first input to the instruction will be
362 // used to replace this unallocated location.
363 static Location SameAsFirstInput() {
364 return UnallocatedLocation(kSameAsFirstInput);
365 }
366
367 Policy GetPolicy() const {
368 DCHECK(IsUnallocated());
369 return PolicyField::Decode(GetPayload());
370 }
371
Ian Rogers13735952014-10-08 12:43:28 -0700372 uintptr_t GetEncoding() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100373 return GetPayload();
374 }
375
376 private:
377 // Number of bits required to encode Kind value.
378 static constexpr uint32_t kBitsForKind = 4;
Ian Rogers13735952014-10-08 12:43:28 -0700379 static constexpr uint32_t kBitsForPayload = kBitsPerIntPtrT - kBitsForKind;
380 static constexpr uintptr_t kLocationConstantMask = 0x3;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100381
Ian Rogers13735952014-10-08 12:43:28 -0700382 explicit Location(uintptr_t value) : value_(value) {}
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100383
Ian Rogers13735952014-10-08 12:43:28 -0700384 Location(Kind kind, uintptr_t payload)
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100385 : value_(KindField::Encode(kind) | PayloadField::Encode(payload)) {}
386
Ian Rogers13735952014-10-08 12:43:28 -0700387 uintptr_t GetPayload() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100388 return PayloadField::Decode(value_);
389 }
390
391 typedef BitField<Kind, 0, kBitsForKind> KindField;
Ian Rogers13735952014-10-08 12:43:28 -0700392 typedef BitField<uintptr_t, kBitsForKind, kBitsForPayload> PayloadField;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100393
394 // Layout for kUnallocated locations payload.
395 typedef BitField<Policy, 0, 3> PolicyField;
396
397 // Layout for stack slots.
398 static const intptr_t kStackIndexBias =
399 static_cast<intptr_t>(1) << (kBitsForPayload - 1);
400
401 // Location either contains kind and payload fields or a tagged handle for
402 // a constant locations. Values of enumeration Kind are selected in such a
403 // way that none of them can be interpreted as a kConstant tag.
Ian Rogers13735952014-10-08 12:43:28 -0700404 uintptr_t value_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100405};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700406std::ostream& operator<<(std::ostream& os, const Location::Kind& rhs);
407std::ostream& operator<<(std::ostream& os, const Location::Policy& rhs);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100408
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100409class RegisterSet : public ValueObject {
410 public:
411 RegisterSet() : core_registers_(0), floating_point_registers_(0) {}
412
413 void Add(Location loc) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100414 if (loc.IsRegister()) {
415 core_registers_ |= (1 << loc.reg());
416 } else {
417 DCHECK(loc.IsFpuRegister());
418 floating_point_registers_ |= (1 << loc.reg());
419 }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100420 }
421
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100422 void Remove(Location loc) {
423 if (loc.IsRegister()) {
424 core_registers_ &= ~(1 << loc.reg());
425 } else {
Nicolas Geoffray424f6762014-11-03 14:51:25 +0000426 DCHECK(loc.IsFpuRegister()) << loc;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100427 floating_point_registers_ &= ~(1 << loc.reg());
428 }
429 }
430
Nicolas Geoffray45b83af2015-07-06 15:12:53 +0000431 bool ContainsCoreRegister(uint32_t id) const {
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100432 return Contains(core_registers_, id);
433 }
434
Nicolas Geoffray45b83af2015-07-06 15:12:53 +0000435 bool ContainsFloatingPointRegister(uint32_t id) const {
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100436 return Contains(floating_point_registers_, id);
437 }
438
439 static bool Contains(uint32_t register_set, uint32_t reg) {
440 return (register_set & (1 << reg)) != 0;
441 }
442
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000443 size_t GetNumberOfRegisters() const {
444 return __builtin_popcount(core_registers_) + __builtin_popcount(floating_point_registers_);
445 }
446
Nicolas Geoffray98893962015-01-21 12:32:32 +0000447 uint32_t GetCoreRegisters() const {
448 return core_registers_;
449 }
450
451 uint32_t GetFloatingPointRegisters() const {
452 return floating_point_registers_;
453 }
454
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100455 private:
456 uint32_t core_registers_;
457 uint32_t floating_point_registers_;
458
459 DISALLOW_COPY_AND_ASSIGN(RegisterSet);
460};
461
Andreas Gampe878d58c2015-01-15 23:24:00 -0800462static constexpr bool kIntrinsified = true;
463
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100464/**
465 * The code generator computes LocationSummary for each instruction so that
466 * the instruction itself knows what code to generate: where to find the inputs
467 * and where to place the result.
468 *
469 * The intent is to have the code for generating the instruction independent of
470 * register allocation. A register allocator just has to provide a LocationSummary.
471 */
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700472class LocationSummary : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100473 public:
Nicolas Geoffray39468442014-09-02 15:17:15 +0100474 enum CallKind {
475 kNoCall,
476 kCallOnSlowPath,
477 kCall
478 };
479
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800480 LocationSummary(HInstruction* instruction,
481 CallKind call_kind = kNoCall,
482 bool intrinsified = false);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100483
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100484 void SetInAt(uint32_t at, Location location) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100485 DCHECK_LT(at, GetInputCount());
486 inputs_[at] = location;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100487 }
488
489 Location InAt(uint32_t at) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100490 DCHECK_LT(at, GetInputCount());
491 return inputs_[at];
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100492 }
493
494 size_t GetInputCount() const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100495 return inputs_.size();
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100496 }
497
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000498 void SetOut(Location location, Location::OutputOverlap overlaps = Location::kOutputOverlap) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000499 DCHECK(output_.IsInvalid());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100500 output_overlaps_ = overlaps;
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000501 output_ = location;
502 }
503
504 void UpdateOut(Location location) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000505 // There are two reasons for updating an output:
506 // 1) Parameters, where we only know the exact stack slot after
507 // doing full register allocation.
508 // 2) Unallocated location.
509 DCHECK(output_.IsStackSlot() || output_.IsDoubleStackSlot() || output_.IsUnallocated());
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000510 output_ = location;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100511 }
512
513 void AddTemp(Location location) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100514 temps_.push_back(location);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100515 }
516
517 Location GetTemp(uint32_t at) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100518 DCHECK_LT(at, GetTempCount());
519 return temps_[at];
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100520 }
521
522 void SetTempAt(uint32_t at, Location location) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100523 DCHECK_LT(at, GetTempCount());
524 DCHECK(temps_[at].IsUnallocated() || temps_[at].IsInvalid());
525 temps_[at] = location;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100526 }
527
528 size_t GetTempCount() const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100529 return temps_.size();
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100530 }
531
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100532 bool HasTemps() const { return !temps_.empty(); }
Nicolas Geoffray94015b92015-06-04 18:21:04 +0100533
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100534 Location Out() const { return output_; }
535
Nicolas Geoffray39468442014-09-02 15:17:15 +0100536 bool CanCall() const { return call_kind_ != kNoCall; }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100537 bool WillCall() const { return call_kind_ == kCall; }
538 bool OnlyCallsOnSlowPath() const { return call_kind_ == kCallOnSlowPath; }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100539 bool NeedsSafepoint() const { return CanCall(); }
540
541 void SetStackBit(uint32_t index) {
542 stack_mask_->SetBit(index);
543 }
544
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100545 void ClearStackBit(uint32_t index) {
546 stack_mask_->ClearBit(index);
547 }
548
Nicolas Geoffray39468442014-09-02 15:17:15 +0100549 void SetRegisterBit(uint32_t reg_id) {
550 register_mask_ |= (1 << reg_id);
551 }
552
Nicolas Geoffray98893962015-01-21 12:32:32 +0000553 uint32_t GetRegisterMask() const {
554 return register_mask_;
555 }
556
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100557 bool RegisterContainsObject(uint32_t reg_id) {
558 return RegisterSet::Contains(register_mask_, reg_id);
559 }
560
561 void AddLiveRegister(Location location) {
562 live_registers_.Add(location);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100563 }
564
565 BitVector* GetStackMask() const {
566 return stack_mask_;
567 }
568
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100569 RegisterSet* GetLiveRegisters() {
570 return &live_registers_;
571 }
572
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000573 size_t GetNumberOfLiveRegisters() const {
574 return live_registers_.GetNumberOfRegisters();
575 }
576
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000577 bool OutputUsesSameAs(uint32_t input_index) const {
578 return (input_index == 0)
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100579 && output_.IsUnallocated()
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000580 && (output_.GetPolicy() == Location::kSameAsFirstInput);
581 }
582
583 bool IsFixedInput(uint32_t input_index) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100584 Location input = inputs_[input_index];
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000585 return input.IsRegister()
Nicolas Geoffray98893962015-01-21 12:32:32 +0000586 || input.IsFpuRegister()
587 || input.IsPair()
588 || input.IsStackSlot()
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000589 || input.IsDoubleStackSlot();
Nicolas Geoffray76905622014-09-25 14:39:26 +0100590 }
591
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000592 bool OutputCanOverlapWithInputs() const {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000593 return output_overlaps_ == Location::kOutputOverlap;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100594 }
595
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800596 bool Intrinsified() const {
597 return intrinsified_;
598 }
599
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100600 private:
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100601 ArenaVector<Location> inputs_;
602 ArenaVector<Location> temps_;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100603 // Whether the output overlaps with any of the inputs. If it overlaps, then it cannot
604 // share the same register as the inputs.
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000605 Location::OutputOverlap output_overlaps_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100606 Location output_;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100607 const CallKind call_kind_;
608
609 // Mask of objects that live in the stack.
610 BitVector* stack_mask_;
611
612 // Mask of objects that live in register.
613 uint32_t register_mask_;
614
615 // Registers that are in use at this position.
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100616 RegisterSet live_registers_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100617
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800618 // Whether these are locations for an intrinsified call.
619 const bool intrinsified_;
620
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000621 ART_FRIEND_TEST(RegisterAllocatorTest, ExpectedInRegisterHint);
622 ART_FRIEND_TEST(RegisterAllocatorTest, SameAsFirstInputHint);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100623 DISALLOW_COPY_AND_ASSIGN(LocationSummary);
624};
625
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100626} // namespace art
627
628#endif // ART_COMPILER_OPTIMIZING_LOCATIONS_H_