blob: 3f27c911be52910403a88c55ed7d6309306d1ab6 [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
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 */
Vladimir Marko76c92ac2015-09-17 15:39:16 +010038class Location : public ValueObject {
Nicolas Geoffray76716a62014-05-23 10:14:19 +010039 public:
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +000040 enum OutputOverlap {
Roland Levillain3d312422016-06-23 13:53:42 +010041 // The liveness of the output overlaps the liveness of one or
42 // several input(s); the register allocator cannot reuse an
43 // input's location for the output's location.
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +000044 kOutputOverlap,
Roland Levillain3d312422016-06-23 13:53:42 +010045 // The liveness of the output does not overlap the liveness of any
46 // input; the register allocator is allowed to reuse an input's
47 // location for the output's location.
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +000048 kNoOutputOverlap
49 };
Nicolas Geoffray9ae0daa2014-09-30 22:40:23 +010050
Nicolas Geoffray76716a62014-05-23 10:14:19 +010051 enum Kind {
52 kInvalid = 0,
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010053 kConstant = 1,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010054 kStackSlot = 2, // 32bit stack slot.
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010055 kDoubleStackSlot = 3, // 64bit stack slot.
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010056
57 kRegister = 4, // Core register.
58
59 // We do not use the value 5 because it conflicts with kLocationConstantMask.
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010060 kDoNotUse5 = 5,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010061
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000062 kFpuRegister = 6, // Float register.
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +010063
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000064 kRegisterPair = 7, // Long register.
65
66 kFpuRegisterPair = 8, // Double register.
67
68 // We do not use the value 9 because it conflicts with kLocationConstantMask.
69 kDoNotUse9 = 9,
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +010070
Nicolas Geoffray76716a62014-05-23 10:14:19 +010071 // 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.
Mark Mendell3e6a3bf2015-01-19 14:09:22 -050075 kUnallocated = 10,
Nicolas Geoffray76716a62014-05-23 10:14:19 +010076 };
77
Vladimir Marko76c92ac2015-09-17 15:39:16 +010078 Location() : ValueObject(), 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");
Andreas Gampe785d2f22014-11-03 22:57:30 -080085 static_assert((kFpuRegister & kLocationConstantMask) != kConstant, "TagError");
86 static_assert((kRegisterPair & kLocationConstantMask) != kConstant, "TagError");
87 static_assert((kFpuRegisterPair & kLocationConstantMask) != kConstant, "TagError");
88 static_assert((kConstant & kLocationConstantMask) == kConstant, "TagError");
Nicolas Geoffray96f89a22014-07-11 10:57:49 +010089
Nicolas Geoffray76716a62014-05-23 10:14:19 +010090 DCHECK(!IsValid());
91 }
92
Vladimir Markofa6b93c2015-09-15 10:15:55 +010093 Location(const Location& other) : value_(other.value_) {}
Nicolas Geoffray76716a62014-05-23 10:14:19 +010094
95 Location& operator=(const Location& other) {
96 value_ = other.value_;
97 return *this;
98 }
99
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100100 bool IsConstant() const {
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100101 return (value_ & kLocationConstantMask) == kConstant;
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100102 }
103
104 static Location ConstantLocation(HConstant* constant) {
105 DCHECK(constant != nullptr);
Ian Rogers13735952014-10-08 12:43:28 -0700106 return Location(kConstant | reinterpret_cast<uintptr_t>(constant));
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100107 }
108
109 HConstant* GetConstant() const {
110 DCHECK(IsConstant());
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100111 return reinterpret_cast<HConstant*>(value_ & ~kLocationConstantMask);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100112 }
113
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100114 bool IsValid() const {
115 return value_ != kInvalid;
116 }
117
118 bool IsInvalid() const {
119 return !IsValid();
120 }
121
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100122 // Empty location. Used if there the location should be ignored.
123 static Location NoLocation() {
124 return Location();
125 }
126
127 // Register locations.
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100128 static Location RegisterLocation(int reg) {
129 return Location(kRegister, reg);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100130 }
131
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100132 static Location FpuRegisterLocation(int reg) {
133 return Location(kFpuRegister, reg);
134 }
135
136 static Location RegisterPairLocation(int low, int high) {
137 return Location(kRegisterPair, low << 16 | high);
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100138 }
139
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000140 static Location FpuRegisterPairLocation(int low, int high) {
141 return Location(kFpuRegisterPair, low << 16 | high);
142 }
143
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100144 bool IsRegister() const {
145 return GetKind() == kRegister;
146 }
147
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100148 bool IsFpuRegister() const {
149 return GetKind() == kFpuRegister;
150 }
151
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100152 bool IsRegisterPair() const {
153 return GetKind() == kRegisterPair;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100154 }
155
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000156 bool IsFpuRegisterPair() const {
157 return GetKind() == kFpuRegisterPair;
158 }
159
Nicolas Geoffrayda02afe2015-02-11 02:29:42 +0000160 bool IsRegisterKind() const {
161 return IsRegister() || IsFpuRegister() || IsRegisterPair() || IsFpuRegisterPair();
162 }
163
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100164 int reg() const {
165 DCHECK(IsRegister() || IsFpuRegister());
166 return GetPayload();
167 }
168
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000169 int low() const {
170 DCHECK(IsPair());
171 return GetPayload() >> 16;
172 }
173
174 int high() const {
175 DCHECK(IsPair());
176 return GetPayload() & 0xFFFF;
177 }
178
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100179 template <typename T>
Roland Levillain271ab9c2014-11-27 15:23:57 +0000180 T AsRegister() const {
181 DCHECK(IsRegister());
182 return static_cast<T>(reg());
183 }
184
185 template <typename T>
186 T AsFpuRegister() const {
187 DCHECK(IsFpuRegister());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100188 return static_cast<T>(reg());
189 }
190
191 template <typename T>
192 T AsRegisterPairLow() const {
193 DCHECK(IsRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000194 return static_cast<T>(low());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100195 }
196
197 template <typename T>
198 T AsRegisterPairHigh() const {
199 DCHECK(IsRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000200 return static_cast<T>(high());
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100201 }
202
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000203 template <typename T>
204 T AsFpuRegisterPairLow() const {
205 DCHECK(IsFpuRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000206 return static_cast<T>(low());
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000207 }
208
209 template <typename T>
210 T AsFpuRegisterPairHigh() const {
211 DCHECK(IsFpuRegisterPair());
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000212 return static_cast<T>(high());
213 }
214
215 bool IsPair() const {
216 return IsRegisterPair() || IsFpuRegisterPair();
217 }
218
219 Location ToLow() const {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000220 if (IsRegisterPair()) {
221 return Location::RegisterLocation(low());
222 } else if (IsFpuRegisterPair()) {
223 return Location::FpuRegisterLocation(low());
224 } else {
225 DCHECK(IsDoubleStackSlot());
226 return Location::StackSlot(GetStackIndex());
227 }
Nicolas Geoffray840e5462015-01-07 16:01:24 +0000228 }
229
230 Location ToHigh() const {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +0000231 if (IsRegisterPair()) {
232 return Location::RegisterLocation(high());
233 } else if (IsFpuRegisterPair()) {
234 return Location::FpuRegisterLocation(high());
235 } else {
236 DCHECK(IsDoubleStackSlot());
237 return Location::StackSlot(GetHighStackIndex(4));
238 }
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000239 }
240
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100241 static uintptr_t EncodeStackIndex(intptr_t stack_index) {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100242 DCHECK(-kStackIndexBias <= stack_index);
243 DCHECK(stack_index < kStackIndexBias);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100244 return static_cast<uintptr_t>(kStackIndexBias + stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100245 }
246
247 static Location StackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700248 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100249 Location loc(kStackSlot, payload);
250 // Ensure that sign is preserved.
251 DCHECK_EQ(loc.GetStackIndex(), stack_index);
252 return loc;
253 }
254
255 bool IsStackSlot() const {
256 return GetKind() == kStackSlot;
257 }
258
259 static Location DoubleStackSlot(intptr_t stack_index) {
Ian Rogers13735952014-10-08 12:43:28 -0700260 uintptr_t payload = EncodeStackIndex(stack_index);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100261 Location loc(kDoubleStackSlot, payload);
262 // Ensure that sign is preserved.
263 DCHECK_EQ(loc.GetStackIndex(), stack_index);
264 return loc;
265 }
266
267 bool IsDoubleStackSlot() const {
268 return GetKind() == kDoubleStackSlot;
269 }
270
271 intptr_t GetStackIndex() const {
272 DCHECK(IsStackSlot() || IsDoubleStackSlot());
273 // Decode stack index manually to preserve sign.
274 return GetPayload() - kStackIndexBias;
275 }
276
277 intptr_t GetHighStackIndex(uintptr_t word_size) const {
278 DCHECK(IsDoubleStackSlot());
279 // Decode stack index manually to preserve sign.
280 return GetPayload() - kStackIndexBias + word_size;
281 }
282
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100283 Kind GetKind() const {
Nicolas Geoffray39468442014-09-02 15:17:15 +0100284 return IsConstant() ? kConstant : KindField::Decode(value_);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100285 }
286
287 bool Equals(Location other) const {
288 return value_ == other.value_;
289 }
290
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000291 bool Contains(Location other) const {
292 if (Equals(other)) {
293 return true;
Zheng Xuad4450e2015-04-17 18:48:56 +0800294 } else if (IsPair() || IsDoubleStackSlot()) {
295 return ToLow().Equals(other) || ToHigh().Equals(other);
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +0000296 }
297 return false;
298 }
299
Zheng Xuad4450e2015-04-17 18:48:56 +0800300 bool OverlapsWith(Location other) const {
301 // Only check the overlapping case that can happen with our register allocation algorithm.
302 bool overlap = Contains(other) || other.Contains(*this);
303 if (kIsDebugBuild && !overlap) {
304 // Note: These are also overlapping cases. But we are not able to handle them in
305 // ParallelMoveResolverWithSwap. Make sure that we do not meet such case with our compiler.
306 if ((IsPair() && other.IsPair()) || (IsDoubleStackSlot() && other.IsDoubleStackSlot())) {
307 DCHECK(!Contains(other.ToLow()));
308 DCHECK(!Contains(other.ToHigh()));
309 }
310 }
311 return overlap;
312 }
313
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100314 const char* DebugString() const {
315 switch (GetKind()) {
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100316 case kInvalid: return "I";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100317 case kRegister: return "R";
318 case kStackSlot: return "S";
319 case kDoubleStackSlot: return "DS";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100320 case kUnallocated: return "U";
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100321 case kConstant: return "C";
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100322 case kFpuRegister: return "F";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100323 case kRegisterPair: return "RP";
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +0000324 case kFpuRegisterPair: return "FP";
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100325 case kDoNotUse5: // fall-through
326 case kDoNotUse9:
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100327 LOG(FATAL) << "Should not use this location kind";
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100328 }
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100329 UNREACHABLE();
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100330 return "?";
331 }
332
333 // Unallocated locations.
334 enum Policy {
335 kAny,
336 kRequiresRegister,
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100337 kRequiresFpuRegister,
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100338 kSameAsFirstInput,
339 };
340
341 bool IsUnallocated() const {
342 return GetKind() == kUnallocated;
343 }
344
345 static Location UnallocatedLocation(Policy policy) {
346 return Location(kUnallocated, PolicyField::Encode(policy));
347 }
348
349 // Any free register is suitable to replace this unallocated location.
350 static Location Any() {
351 return UnallocatedLocation(kAny);
352 }
353
354 static Location RequiresRegister() {
355 return UnallocatedLocation(kRequiresRegister);
356 }
357
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100358 static Location RequiresFpuRegister() {
359 return UnallocatedLocation(kRequiresFpuRegister);
360 }
361
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100362 static Location RegisterOrConstant(HInstruction* instruction);
Mark Mendellea5af682015-10-22 17:35:49 -0400363 static Location RegisterOrInt32Constant(HInstruction* instruction);
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100364 static Location ByteRegisterOrConstant(int reg, HInstruction* instruction);
Mark Mendellea5af682015-10-22 17:35:49 -0400365 static Location FpuRegisterOrConstant(HInstruction* instruction);
366 static Location FpuRegisterOrInt32Constant(HInstruction* instruction);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100367
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100368 // The location of the first input to the instruction will be
369 // used to replace this unallocated location.
370 static Location SameAsFirstInput() {
371 return UnallocatedLocation(kSameAsFirstInput);
372 }
373
374 Policy GetPolicy() const {
375 DCHECK(IsUnallocated());
376 return PolicyField::Decode(GetPayload());
377 }
378
Ian Rogers13735952014-10-08 12:43:28 -0700379 uintptr_t GetEncoding() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100380 return GetPayload();
381 }
382
383 private:
384 // Number of bits required to encode Kind value.
385 static constexpr uint32_t kBitsForKind = 4;
Ian Rogers13735952014-10-08 12:43:28 -0700386 static constexpr uint32_t kBitsForPayload = kBitsPerIntPtrT - kBitsForKind;
387 static constexpr uintptr_t kLocationConstantMask = 0x3;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100388
Ian Rogers13735952014-10-08 12:43:28 -0700389 explicit Location(uintptr_t value) : value_(value) {}
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100390
Ian Rogers13735952014-10-08 12:43:28 -0700391 Location(Kind kind, uintptr_t payload)
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100392 : value_(KindField::Encode(kind) | PayloadField::Encode(payload)) {}
393
Ian Rogers13735952014-10-08 12:43:28 -0700394 uintptr_t GetPayload() const {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100395 return PayloadField::Decode(value_);
396 }
397
398 typedef BitField<Kind, 0, kBitsForKind> KindField;
Ian Rogers13735952014-10-08 12:43:28 -0700399 typedef BitField<uintptr_t, kBitsForKind, kBitsForPayload> PayloadField;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100400
401 // Layout for kUnallocated locations payload.
402 typedef BitField<Policy, 0, 3> PolicyField;
403
404 // Layout for stack slots.
405 static const intptr_t kStackIndexBias =
406 static_cast<intptr_t>(1) << (kBitsForPayload - 1);
407
408 // Location either contains kind and payload fields or a tagged handle for
409 // a constant locations. Values of enumeration Kind are selected in such a
410 // way that none of them can be interpreted as a kConstant tag.
Ian Rogers13735952014-10-08 12:43:28 -0700411 uintptr_t value_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100412};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700413std::ostream& operator<<(std::ostream& os, const Location::Kind& rhs);
414std::ostream& operator<<(std::ostream& os, const Location::Policy& rhs);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100415
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100416class RegisterSet : public ValueObject {
417 public:
418 RegisterSet() : core_registers_(0), floating_point_registers_(0) {}
419
420 void Add(Location loc) {
Nicolas Geoffray56b9ee62014-10-09 11:47:51 +0100421 if (loc.IsRegister()) {
422 core_registers_ |= (1 << loc.reg());
423 } else {
424 DCHECK(loc.IsFpuRegister());
425 floating_point_registers_ |= (1 << loc.reg());
426 }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100427 }
428
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100429 void Remove(Location loc) {
430 if (loc.IsRegister()) {
431 core_registers_ &= ~(1 << loc.reg());
432 } else {
Nicolas Geoffray424f6762014-11-03 14:51:25 +0000433 DCHECK(loc.IsFpuRegister()) << loc;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100434 floating_point_registers_ &= ~(1 << loc.reg());
435 }
436 }
437
Nicolas Geoffray45b83af2015-07-06 15:12:53 +0000438 bool ContainsCoreRegister(uint32_t id) const {
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100439 return Contains(core_registers_, id);
440 }
441
Nicolas Geoffray45b83af2015-07-06 15:12:53 +0000442 bool ContainsFloatingPointRegister(uint32_t id) const {
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100443 return Contains(floating_point_registers_, id);
444 }
445
446 static bool Contains(uint32_t register_set, uint32_t reg) {
447 return (register_set & (1 << reg)) != 0;
448 }
449
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000450 size_t GetNumberOfRegisters() const {
451 return __builtin_popcount(core_registers_) + __builtin_popcount(floating_point_registers_);
452 }
453
Nicolas Geoffray98893962015-01-21 12:32:32 +0000454 uint32_t GetCoreRegisters() const {
455 return core_registers_;
456 }
457
458 uint32_t GetFloatingPointRegisters() const {
459 return floating_point_registers_;
460 }
461
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100462 private:
463 uint32_t core_registers_;
464 uint32_t floating_point_registers_;
465
466 DISALLOW_COPY_AND_ASSIGN(RegisterSet);
467};
468
Andreas Gampe878d58c2015-01-15 23:24:00 -0800469static constexpr bool kIntrinsified = true;
470
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100471/**
472 * The code generator computes LocationSummary for each instruction so that
473 * the instruction itself knows what code to generate: where to find the inputs
474 * and where to place the result.
475 *
476 * The intent is to have the code for generating the instruction independent of
477 * register allocation. A register allocator just has to provide a LocationSummary.
478 */
Vladimir Marko5233f932015-09-29 19:01:15 +0100479class LocationSummary : public ArenaObject<kArenaAllocLocationSummary> {
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100480 public:
Nicolas Geoffray39468442014-09-02 15:17:15 +0100481 enum CallKind {
482 kNoCall,
483 kCallOnSlowPath,
484 kCall
485 };
486
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800487 LocationSummary(HInstruction* instruction,
488 CallKind call_kind = kNoCall,
489 bool intrinsified = false);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100490
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100491 void SetInAt(uint32_t at, Location location) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100492 inputs_[at] = location;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100493 }
494
495 Location InAt(uint32_t at) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100496 return inputs_[at];
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100497 }
498
499 size_t GetInputCount() const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100500 return inputs_.size();
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100501 }
502
Roland Levillain3d312422016-06-23 13:53:42 +0100503 // Set the output location. Argument `overlaps` tells whether the
504 // output overlaps any of the inputs (if so, it cannot share the
505 // same register as one of the inputs); it is set to
506 // `Location::kOutputOverlap` by default for safety.
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000507 void SetOut(Location location, Location::OutputOverlap overlaps = Location::kOutputOverlap) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000508 DCHECK(output_.IsInvalid());
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100509 output_overlaps_ = overlaps;
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000510 output_ = location;
511 }
512
513 void UpdateOut(Location location) {
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000514 // There are two reasons for updating an output:
515 // 1) Parameters, where we only know the exact stack slot after
516 // doing full register allocation.
517 // 2) Unallocated location.
518 DCHECK(output_.IsStackSlot() || output_.IsDoubleStackSlot() || output_.IsUnallocated());
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000519 output_ = location;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100520 }
521
522 void AddTemp(Location location) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100523 temps_.push_back(location);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100524 }
525
526 Location GetTemp(uint32_t at) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100527 return temps_[at];
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100528 }
529
530 void SetTempAt(uint32_t at, Location location) {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100531 DCHECK(temps_[at].IsUnallocated() || temps_[at].IsInvalid());
532 temps_[at] = location;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100533 }
534
535 size_t GetTempCount() const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100536 return temps_.size();
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100537 }
538
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100539 bool HasTemps() const { return !temps_.empty(); }
Nicolas Geoffray94015b92015-06-04 18:21:04 +0100540
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100541 Location Out() const { return output_; }
542
Nicolas Geoffray39468442014-09-02 15:17:15 +0100543 bool CanCall() const { return call_kind_ != kNoCall; }
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100544 bool WillCall() const { return call_kind_ == kCall; }
545 bool OnlyCallsOnSlowPath() const { return call_kind_ == kCallOnSlowPath; }
Nicolas Geoffray39468442014-09-02 15:17:15 +0100546 bool NeedsSafepoint() const { return CanCall(); }
547
548 void SetStackBit(uint32_t index) {
549 stack_mask_->SetBit(index);
550 }
551
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100552 void ClearStackBit(uint32_t index) {
553 stack_mask_->ClearBit(index);
554 }
555
Nicolas Geoffray39468442014-09-02 15:17:15 +0100556 void SetRegisterBit(uint32_t reg_id) {
557 register_mask_ |= (1 << reg_id);
558 }
559
Nicolas Geoffray98893962015-01-21 12:32:32 +0000560 uint32_t GetRegisterMask() const {
561 return register_mask_;
562 }
563
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100564 bool RegisterContainsObject(uint32_t reg_id) {
565 return RegisterSet::Contains(register_mask_, reg_id);
566 }
567
568 void AddLiveRegister(Location location) {
569 live_registers_.Add(location);
Nicolas Geoffray39468442014-09-02 15:17:15 +0100570 }
571
572 BitVector* GetStackMask() const {
573 return stack_mask_;
574 }
575
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100576 RegisterSet* GetLiveRegisters() {
577 return &live_registers_;
578 }
579
Nicolas Geoffray87d03762014-11-19 15:17:56 +0000580 size_t GetNumberOfLiveRegisters() const {
581 return live_registers_.GetNumberOfRegisters();
582 }
583
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000584 bool OutputUsesSameAs(uint32_t input_index) const {
585 return (input_index == 0)
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100586 && output_.IsUnallocated()
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000587 && (output_.GetPolicy() == Location::kSameAsFirstInput);
588 }
589
590 bool IsFixedInput(uint32_t input_index) const {
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100591 Location input = inputs_[input_index];
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000592 return input.IsRegister()
Nicolas Geoffray98893962015-01-21 12:32:32 +0000593 || input.IsFpuRegister()
594 || input.IsPair()
595 || input.IsStackSlot()
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000596 || input.IsDoubleStackSlot();
Nicolas Geoffray76905622014-09-25 14:39:26 +0100597 }
598
Nicolas Geoffray829280c2015-01-28 10:20:37 +0000599 bool OutputCanOverlapWithInputs() const {
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000600 return output_overlaps_ == Location::kOutputOverlap;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100601 }
602
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800603 bool Intrinsified() const {
604 return intrinsified_;
605 }
606
Roland Levillain0d5a2812015-11-13 10:07:31 +0000607 void SetIntrinsified(bool intrinsified) {
608 intrinsified_ = intrinsified;
609 }
610
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100611 private:
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100612 ArenaVector<Location> inputs_;
613 ArenaVector<Location> temps_;
Nicolas Geoffray8e3964b2014-10-17 11:06:38 +0100614 // Whether the output overlaps with any of the inputs. If it overlaps, then it cannot
615 // share the same register as the inputs.
Nicolas Geoffray6c2dff82015-01-21 14:56:54 +0000616 Location::OutputOverlap output_overlaps_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100617 Location output_;
Nicolas Geoffray39468442014-09-02 15:17:15 +0100618 const CallKind call_kind_;
619
620 // Mask of objects that live in the stack.
621 BitVector* stack_mask_;
622
623 // Mask of objects that live in register.
624 uint32_t register_mask_;
625
626 // Registers that are in use at this position.
Nicolas Geoffray3bca0df2014-09-19 11:01:00 +0100627 RegisterSet live_registers_;
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100628
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800629 // Whether these are locations for an intrinsified call.
Roland Levillain0d5a2812015-11-13 10:07:31 +0000630 bool intrinsified_;
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800631
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +0000632 ART_FRIEND_TEST(RegisterAllocatorTest, ExpectedInRegisterHint);
633 ART_FRIEND_TEST(RegisterAllocatorTest, SameAsFirstInputHint);
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100634 DISALLOW_COPY_AND_ASSIGN(LocationSummary);
635};
636
Nicolas Geoffray76716a62014-05-23 10:14:19 +0100637} // namespace art
638
639#endif // ART_COMPILER_OPTIMIZING_LOCATIONS_H_