xref: /aosp_15_r20/art/compiler/optimizing/locations.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_LOCATIONS_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_LOCATIONS_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "base/arena_containers.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/arena_object.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/bit_field.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/bit_vector.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/value_object.h"
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker class HConstant;
31*795d594fSAndroid Build Coastguard Worker class HInstruction;
32*795d594fSAndroid Build Coastguard Worker class Location;
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const Location& location);
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker /**
37*795d594fSAndroid Build Coastguard Worker  * A Location is an abstraction over the potential location
38*795d594fSAndroid Build Coastguard Worker  * of an instruction. It could be in register or stack.
39*795d594fSAndroid Build Coastguard Worker  */
40*795d594fSAndroid Build Coastguard Worker class Location : public ValueObject {
41*795d594fSAndroid Build Coastguard Worker  public:
42*795d594fSAndroid Build Coastguard Worker   enum OutputOverlap {
43*795d594fSAndroid Build Coastguard Worker     // The liveness of the output overlaps the liveness of one or
44*795d594fSAndroid Build Coastguard Worker     // several input(s); the register allocator cannot reuse an
45*795d594fSAndroid Build Coastguard Worker     // input's location for the output's location.
46*795d594fSAndroid Build Coastguard Worker     kOutputOverlap,
47*795d594fSAndroid Build Coastguard Worker     // The liveness of the output does not overlap the liveness of any
48*795d594fSAndroid Build Coastguard Worker     // input; the register allocator is allowed to reuse an input's
49*795d594fSAndroid Build Coastguard Worker     // location for the output's location.
50*795d594fSAndroid Build Coastguard Worker     kNoOutputOverlap
51*795d594fSAndroid Build Coastguard Worker   };
52*795d594fSAndroid Build Coastguard Worker 
53*795d594fSAndroid Build Coastguard Worker   enum Kind {
54*795d594fSAndroid Build Coastguard Worker     kInvalid = 0,
55*795d594fSAndroid Build Coastguard Worker     kConstant = 1,
56*795d594fSAndroid Build Coastguard Worker     kStackSlot = 2,  // 32bit stack slot.
57*795d594fSAndroid Build Coastguard Worker     kDoubleStackSlot = 3,  // 64bit stack slot.
58*795d594fSAndroid Build Coastguard Worker 
59*795d594fSAndroid Build Coastguard Worker     kRegister = 4,  // Core register.
60*795d594fSAndroid Build Coastguard Worker 
61*795d594fSAndroid Build Coastguard Worker     // We do not use the value 5 because it conflicts with kLocationConstantMask.
62*795d594fSAndroid Build Coastguard Worker     kDoNotUse5 = 5,
63*795d594fSAndroid Build Coastguard Worker 
64*795d594fSAndroid Build Coastguard Worker     kFpuRegister = 6,  // Float register.
65*795d594fSAndroid Build Coastguard Worker 
66*795d594fSAndroid Build Coastguard Worker     kRegisterPair = 7,  // Long register.
67*795d594fSAndroid Build Coastguard Worker 
68*795d594fSAndroid Build Coastguard Worker     kFpuRegisterPair = 8,  // Double register.
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker     // We do not use the value 9 because it conflicts with kLocationConstantMask.
71*795d594fSAndroid Build Coastguard Worker     kDoNotUse9 = 9,
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker     kSIMDStackSlot = 10,  // 128bit stack slot. TODO: generalize with encoded #bytes?
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker     // Unallocated location represents a location that is not fixed and can be
76*795d594fSAndroid Build Coastguard Worker     // allocated by a register allocator.  Each unallocated location has
77*795d594fSAndroid Build Coastguard Worker     // a policy that specifies what kind of location is suitable. Payload
78*795d594fSAndroid Build Coastguard Worker     // contains register allocation policy.
79*795d594fSAndroid Build Coastguard Worker     kUnallocated = 11,
80*795d594fSAndroid Build Coastguard Worker   };
81*795d594fSAndroid Build Coastguard Worker 
Location()82*795d594fSAndroid Build Coastguard Worker   constexpr Location() : ValueObject(), value_(kInvalid) {
83*795d594fSAndroid Build Coastguard Worker     // Verify that non-constant location kinds do not interfere with kConstant.
84*795d594fSAndroid Build Coastguard Worker     static_assert((kInvalid & kLocationConstantMask) != kConstant, "TagError");
85*795d594fSAndroid Build Coastguard Worker     static_assert((kUnallocated & kLocationConstantMask) != kConstant, "TagError");
86*795d594fSAndroid Build Coastguard Worker     static_assert((kStackSlot & kLocationConstantMask) != kConstant, "TagError");
87*795d594fSAndroid Build Coastguard Worker     static_assert((kDoubleStackSlot & kLocationConstantMask) != kConstant, "TagError");
88*795d594fSAndroid Build Coastguard Worker     static_assert((kSIMDStackSlot & kLocationConstantMask) != kConstant, "TagError");
89*795d594fSAndroid Build Coastguard Worker     static_assert((kRegister & kLocationConstantMask) != kConstant, "TagError");
90*795d594fSAndroid Build Coastguard Worker     static_assert((kFpuRegister & kLocationConstantMask) != kConstant, "TagError");
91*795d594fSAndroid Build Coastguard Worker     static_assert((kRegisterPair & kLocationConstantMask) != kConstant, "TagError");
92*795d594fSAndroid Build Coastguard Worker     static_assert((kFpuRegisterPair & kLocationConstantMask) != kConstant, "TagError");
93*795d594fSAndroid Build Coastguard Worker     static_assert((kConstant & kLocationConstantMask) == kConstant, "TagError");
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker     DCHECK(!IsValid());
96*795d594fSAndroid Build Coastguard Worker   }
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker   constexpr Location(const Location& other) = default;
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker   Location& operator=(const Location& other) = default;
101*795d594fSAndroid Build Coastguard Worker 
IsConstant()102*795d594fSAndroid Build Coastguard Worker   bool IsConstant() const {
103*795d594fSAndroid Build Coastguard Worker     return (value_ & kLocationConstantMask) == kConstant;
104*795d594fSAndroid Build Coastguard Worker   }
105*795d594fSAndroid Build Coastguard Worker 
ConstantLocation(HInstruction * constant)106*795d594fSAndroid Build Coastguard Worker   static Location ConstantLocation(HInstruction* constant) {
107*795d594fSAndroid Build Coastguard Worker     DCHECK(constant != nullptr);
108*795d594fSAndroid Build Coastguard Worker     if (kIsDebugBuild) {
109*795d594fSAndroid Build Coastguard Worker       // Call out-of-line helper to avoid circular dependency with `nodes.h`.
110*795d594fSAndroid Build Coastguard Worker       DCheckInstructionIsConstant(constant);
111*795d594fSAndroid Build Coastguard Worker     }
112*795d594fSAndroid Build Coastguard Worker     return Location(kConstant | reinterpret_cast<uintptr_t>(constant));
113*795d594fSAndroid Build Coastguard Worker   }
114*795d594fSAndroid Build Coastguard Worker 
GetConstant()115*795d594fSAndroid Build Coastguard Worker   HConstant* GetConstant() const {
116*795d594fSAndroid Build Coastguard Worker     DCHECK(IsConstant());
117*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<HConstant*>(value_ & ~kLocationConstantMask);
118*795d594fSAndroid Build Coastguard Worker   }
119*795d594fSAndroid Build Coastguard Worker 
IsValid()120*795d594fSAndroid Build Coastguard Worker   bool IsValid() const {
121*795d594fSAndroid Build Coastguard Worker     return value_ != kInvalid;
122*795d594fSAndroid Build Coastguard Worker   }
123*795d594fSAndroid Build Coastguard Worker 
IsInvalid()124*795d594fSAndroid Build Coastguard Worker   bool IsInvalid() const {
125*795d594fSAndroid Build Coastguard Worker     return !IsValid();
126*795d594fSAndroid Build Coastguard Worker   }
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker   // Empty location. Used if there the location should be ignored.
NoLocation()129*795d594fSAndroid Build Coastguard Worker   static constexpr Location NoLocation() {
130*795d594fSAndroid Build Coastguard Worker     return Location();
131*795d594fSAndroid Build Coastguard Worker   }
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker   // Register locations.
RegisterLocation(int reg)134*795d594fSAndroid Build Coastguard Worker   static constexpr Location RegisterLocation(int reg) {
135*795d594fSAndroid Build Coastguard Worker     return Location(kRegister, reg);
136*795d594fSAndroid Build Coastguard Worker   }
137*795d594fSAndroid Build Coastguard Worker 
FpuRegisterLocation(int reg)138*795d594fSAndroid Build Coastguard Worker   static constexpr Location FpuRegisterLocation(int reg) {
139*795d594fSAndroid Build Coastguard Worker     return Location(kFpuRegister, reg);
140*795d594fSAndroid Build Coastguard Worker   }
141*795d594fSAndroid Build Coastguard Worker 
RegisterPairLocation(int low,int high)142*795d594fSAndroid Build Coastguard Worker   static constexpr Location RegisterPairLocation(int low, int high) {
143*795d594fSAndroid Build Coastguard Worker     return Location(kRegisterPair, low << 16 | high);
144*795d594fSAndroid Build Coastguard Worker   }
145*795d594fSAndroid Build Coastguard Worker 
FpuRegisterPairLocation(int low,int high)146*795d594fSAndroid Build Coastguard Worker   static constexpr Location FpuRegisterPairLocation(int low, int high) {
147*795d594fSAndroid Build Coastguard Worker     return Location(kFpuRegisterPair, low << 16 | high);
148*795d594fSAndroid Build Coastguard Worker   }
149*795d594fSAndroid Build Coastguard Worker 
IsRegister()150*795d594fSAndroid Build Coastguard Worker   bool IsRegister() const {
151*795d594fSAndroid Build Coastguard Worker     return GetKind() == kRegister;
152*795d594fSAndroid Build Coastguard Worker   }
153*795d594fSAndroid Build Coastguard Worker 
IsFpuRegister()154*795d594fSAndroid Build Coastguard Worker   bool IsFpuRegister() const {
155*795d594fSAndroid Build Coastguard Worker     return GetKind() == kFpuRegister;
156*795d594fSAndroid Build Coastguard Worker   }
157*795d594fSAndroid Build Coastguard Worker 
IsRegisterPair()158*795d594fSAndroid Build Coastguard Worker   bool IsRegisterPair() const {
159*795d594fSAndroid Build Coastguard Worker     return GetKind() == kRegisterPair;
160*795d594fSAndroid Build Coastguard Worker   }
161*795d594fSAndroid Build Coastguard Worker 
IsFpuRegisterPair()162*795d594fSAndroid Build Coastguard Worker   bool IsFpuRegisterPair() const {
163*795d594fSAndroid Build Coastguard Worker     return GetKind() == kFpuRegisterPair;
164*795d594fSAndroid Build Coastguard Worker   }
165*795d594fSAndroid Build Coastguard Worker 
IsRegisterKind()166*795d594fSAndroid Build Coastguard Worker   bool IsRegisterKind() const {
167*795d594fSAndroid Build Coastguard Worker     return IsRegister() || IsFpuRegister() || IsRegisterPair() || IsFpuRegisterPair();
168*795d594fSAndroid Build Coastguard Worker   }
169*795d594fSAndroid Build Coastguard Worker 
reg()170*795d594fSAndroid Build Coastguard Worker   int reg() const {
171*795d594fSAndroid Build Coastguard Worker     DCHECK(IsRegister() || IsFpuRegister());
172*795d594fSAndroid Build Coastguard Worker     return GetPayload();
173*795d594fSAndroid Build Coastguard Worker   }
174*795d594fSAndroid Build Coastguard Worker 
low()175*795d594fSAndroid Build Coastguard Worker   int low() const {
176*795d594fSAndroid Build Coastguard Worker     DCHECK(IsPair());
177*795d594fSAndroid Build Coastguard Worker     return GetPayload() >> 16;
178*795d594fSAndroid Build Coastguard Worker   }
179*795d594fSAndroid Build Coastguard Worker 
high()180*795d594fSAndroid Build Coastguard Worker   int high() const {
181*795d594fSAndroid Build Coastguard Worker     DCHECK(IsPair());
182*795d594fSAndroid Build Coastguard Worker     return GetPayload() & 0xFFFF;
183*795d594fSAndroid Build Coastguard Worker   }
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker   template <typename T>
AsRegister()186*795d594fSAndroid Build Coastguard Worker   T AsRegister() const {
187*795d594fSAndroid Build Coastguard Worker     DCHECK(IsRegister());
188*795d594fSAndroid Build Coastguard Worker     return static_cast<T>(reg());
189*795d594fSAndroid Build Coastguard Worker   }
190*795d594fSAndroid Build Coastguard Worker 
191*795d594fSAndroid Build Coastguard Worker   template <typename T>
AsFpuRegister()192*795d594fSAndroid Build Coastguard Worker   T AsFpuRegister() const {
193*795d594fSAndroid Build Coastguard Worker     DCHECK(IsFpuRegister());
194*795d594fSAndroid Build Coastguard Worker     return static_cast<T>(reg());
195*795d594fSAndroid Build Coastguard Worker   }
196*795d594fSAndroid Build Coastguard Worker 
197*795d594fSAndroid Build Coastguard Worker   template <typename T>
AsRegisterPairLow()198*795d594fSAndroid Build Coastguard Worker   T AsRegisterPairLow() const {
199*795d594fSAndroid Build Coastguard Worker     DCHECK(IsRegisterPair());
200*795d594fSAndroid Build Coastguard Worker     return static_cast<T>(low());
201*795d594fSAndroid Build Coastguard Worker   }
202*795d594fSAndroid Build Coastguard Worker 
203*795d594fSAndroid Build Coastguard Worker   template <typename T>
AsRegisterPairHigh()204*795d594fSAndroid Build Coastguard Worker   T AsRegisterPairHigh() const {
205*795d594fSAndroid Build Coastguard Worker     DCHECK(IsRegisterPair());
206*795d594fSAndroid Build Coastguard Worker     return static_cast<T>(high());
207*795d594fSAndroid Build Coastguard Worker   }
208*795d594fSAndroid Build Coastguard Worker 
209*795d594fSAndroid Build Coastguard Worker   template <typename T>
AsFpuRegisterPairLow()210*795d594fSAndroid Build Coastguard Worker   T AsFpuRegisterPairLow() const {
211*795d594fSAndroid Build Coastguard Worker     DCHECK(IsFpuRegisterPair());
212*795d594fSAndroid Build Coastguard Worker     return static_cast<T>(low());
213*795d594fSAndroid Build Coastguard Worker   }
214*795d594fSAndroid Build Coastguard Worker 
215*795d594fSAndroid Build Coastguard Worker   template <typename T>
AsFpuRegisterPairHigh()216*795d594fSAndroid Build Coastguard Worker   T AsFpuRegisterPairHigh() const {
217*795d594fSAndroid Build Coastguard Worker     DCHECK(IsFpuRegisterPair());
218*795d594fSAndroid Build Coastguard Worker     return static_cast<T>(high());
219*795d594fSAndroid Build Coastguard Worker   }
220*795d594fSAndroid Build Coastguard Worker 
IsPair()221*795d594fSAndroid Build Coastguard Worker   bool IsPair() const {
222*795d594fSAndroid Build Coastguard Worker     return IsRegisterPair() || IsFpuRegisterPair();
223*795d594fSAndroid Build Coastguard Worker   }
224*795d594fSAndroid Build Coastguard Worker 
ToLow()225*795d594fSAndroid Build Coastguard Worker   Location ToLow() const {
226*795d594fSAndroid Build Coastguard Worker     if (IsRegisterPair()) {
227*795d594fSAndroid Build Coastguard Worker       return Location::RegisterLocation(low());
228*795d594fSAndroid Build Coastguard Worker     } else if (IsFpuRegisterPair()) {
229*795d594fSAndroid Build Coastguard Worker       return Location::FpuRegisterLocation(low());
230*795d594fSAndroid Build Coastguard Worker     } else {
231*795d594fSAndroid Build Coastguard Worker       DCHECK(IsDoubleStackSlot());
232*795d594fSAndroid Build Coastguard Worker       return Location::StackSlot(GetStackIndex());
233*795d594fSAndroid Build Coastguard Worker     }
234*795d594fSAndroid Build Coastguard Worker   }
235*795d594fSAndroid Build Coastguard Worker 
ToHigh()236*795d594fSAndroid Build Coastguard Worker   Location ToHigh() const {
237*795d594fSAndroid Build Coastguard Worker     if (IsRegisterPair()) {
238*795d594fSAndroid Build Coastguard Worker       return Location::RegisterLocation(high());
239*795d594fSAndroid Build Coastguard Worker     } else if (IsFpuRegisterPair()) {
240*795d594fSAndroid Build Coastguard Worker       return Location::FpuRegisterLocation(high());
241*795d594fSAndroid Build Coastguard Worker     } else {
242*795d594fSAndroid Build Coastguard Worker       DCHECK(IsDoubleStackSlot());
243*795d594fSAndroid Build Coastguard Worker       return Location::StackSlot(GetHighStackIndex(4));
244*795d594fSAndroid Build Coastguard Worker     }
245*795d594fSAndroid Build Coastguard Worker   }
246*795d594fSAndroid Build Coastguard Worker 
EncodeStackIndex(intptr_t stack_index)247*795d594fSAndroid Build Coastguard Worker   static uintptr_t EncodeStackIndex(intptr_t stack_index) {
248*795d594fSAndroid Build Coastguard Worker     DCHECK(-kStackIndexBias <= stack_index);
249*795d594fSAndroid Build Coastguard Worker     DCHECK(stack_index < kStackIndexBias);
250*795d594fSAndroid Build Coastguard Worker     return static_cast<uintptr_t>(kStackIndexBias + stack_index);
251*795d594fSAndroid Build Coastguard Worker   }
252*795d594fSAndroid Build Coastguard Worker 
StackSlot(intptr_t stack_index)253*795d594fSAndroid Build Coastguard Worker   static Location StackSlot(intptr_t stack_index) {
254*795d594fSAndroid Build Coastguard Worker     uintptr_t payload = EncodeStackIndex(stack_index);
255*795d594fSAndroid Build Coastguard Worker     Location loc(kStackSlot, payload);
256*795d594fSAndroid Build Coastguard Worker     // Ensure that sign is preserved.
257*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(loc.GetStackIndex(), stack_index);
258*795d594fSAndroid Build Coastguard Worker     return loc;
259*795d594fSAndroid Build Coastguard Worker   }
260*795d594fSAndroid Build Coastguard Worker 
IsStackSlot()261*795d594fSAndroid Build Coastguard Worker   bool IsStackSlot() const {
262*795d594fSAndroid Build Coastguard Worker     return GetKind() == kStackSlot;
263*795d594fSAndroid Build Coastguard Worker   }
264*795d594fSAndroid Build Coastguard Worker 
DoubleStackSlot(intptr_t stack_index)265*795d594fSAndroid Build Coastguard Worker   static Location DoubleStackSlot(intptr_t stack_index) {
266*795d594fSAndroid Build Coastguard Worker     uintptr_t payload = EncodeStackIndex(stack_index);
267*795d594fSAndroid Build Coastguard Worker     Location loc(kDoubleStackSlot, payload);
268*795d594fSAndroid Build Coastguard Worker     // Ensure that sign is preserved.
269*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(loc.GetStackIndex(), stack_index);
270*795d594fSAndroid Build Coastguard Worker     return loc;
271*795d594fSAndroid Build Coastguard Worker   }
272*795d594fSAndroid Build Coastguard Worker 
IsDoubleStackSlot()273*795d594fSAndroid Build Coastguard Worker   bool IsDoubleStackSlot() const {
274*795d594fSAndroid Build Coastguard Worker     return GetKind() == kDoubleStackSlot;
275*795d594fSAndroid Build Coastguard Worker   }
276*795d594fSAndroid Build Coastguard Worker 
SIMDStackSlot(intptr_t stack_index)277*795d594fSAndroid Build Coastguard Worker   static Location SIMDStackSlot(intptr_t stack_index) {
278*795d594fSAndroid Build Coastguard Worker     uintptr_t payload = EncodeStackIndex(stack_index);
279*795d594fSAndroid Build Coastguard Worker     Location loc(kSIMDStackSlot, payload);
280*795d594fSAndroid Build Coastguard Worker     // Ensure that sign is preserved.
281*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(loc.GetStackIndex(), stack_index);
282*795d594fSAndroid Build Coastguard Worker     return loc;
283*795d594fSAndroid Build Coastguard Worker   }
284*795d594fSAndroid Build Coastguard Worker 
IsSIMDStackSlot()285*795d594fSAndroid Build Coastguard Worker   bool IsSIMDStackSlot() const {
286*795d594fSAndroid Build Coastguard Worker     return GetKind() == kSIMDStackSlot;
287*795d594fSAndroid Build Coastguard Worker   }
288*795d594fSAndroid Build Coastguard Worker 
StackSlotByNumOfSlots(size_t num_of_slots,int spill_slot)289*795d594fSAndroid Build Coastguard Worker   static Location StackSlotByNumOfSlots(size_t num_of_slots, int spill_slot) {
290*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(num_of_slots, 0u);
291*795d594fSAndroid Build Coastguard Worker     switch (num_of_slots) {
292*795d594fSAndroid Build Coastguard Worker       case 1u:
293*795d594fSAndroid Build Coastguard Worker         return Location::StackSlot(spill_slot);
294*795d594fSAndroid Build Coastguard Worker       case 2u:
295*795d594fSAndroid Build Coastguard Worker         return Location::DoubleStackSlot(spill_slot);
296*795d594fSAndroid Build Coastguard Worker       default:
297*795d594fSAndroid Build Coastguard Worker         // Assume all other stack slot sizes correspond to SIMD slot size.
298*795d594fSAndroid Build Coastguard Worker         return Location::SIMDStackSlot(spill_slot);
299*795d594fSAndroid Build Coastguard Worker     }
300*795d594fSAndroid Build Coastguard Worker   }
301*795d594fSAndroid Build Coastguard Worker 
GetStackIndex()302*795d594fSAndroid Build Coastguard Worker   intptr_t GetStackIndex() const {
303*795d594fSAndroid Build Coastguard Worker     DCHECK(IsStackSlot() || IsDoubleStackSlot() || IsSIMDStackSlot());
304*795d594fSAndroid Build Coastguard Worker     // Decode stack index manually to preserve sign.
305*795d594fSAndroid Build Coastguard Worker     return GetPayload() - kStackIndexBias;
306*795d594fSAndroid Build Coastguard Worker   }
307*795d594fSAndroid Build Coastguard Worker 
GetHighStackIndex(uintptr_t word_size)308*795d594fSAndroid Build Coastguard Worker   intptr_t GetHighStackIndex(uintptr_t word_size) const {
309*795d594fSAndroid Build Coastguard Worker     DCHECK(IsDoubleStackSlot());
310*795d594fSAndroid Build Coastguard Worker     // Decode stack index manually to preserve sign.
311*795d594fSAndroid Build Coastguard Worker     return GetPayload() - kStackIndexBias + word_size;
312*795d594fSAndroid Build Coastguard Worker   }
313*795d594fSAndroid Build Coastguard Worker 
GetKind()314*795d594fSAndroid Build Coastguard Worker   Kind GetKind() const {
315*795d594fSAndroid Build Coastguard Worker     return IsConstant() ? kConstant : KindField::Decode(value_);
316*795d594fSAndroid Build Coastguard Worker   }
317*795d594fSAndroid Build Coastguard Worker 
Equals(Location other)318*795d594fSAndroid Build Coastguard Worker   bool Equals(Location other) const {
319*795d594fSAndroid Build Coastguard Worker     return value_ == other.value_;
320*795d594fSAndroid Build Coastguard Worker   }
321*795d594fSAndroid Build Coastguard Worker 
Contains(Location other)322*795d594fSAndroid Build Coastguard Worker   bool Contains(Location other) const {
323*795d594fSAndroid Build Coastguard Worker     if (Equals(other)) {
324*795d594fSAndroid Build Coastguard Worker       return true;
325*795d594fSAndroid Build Coastguard Worker     } else if (IsPair() || IsDoubleStackSlot()) {
326*795d594fSAndroid Build Coastguard Worker       return ToLow().Equals(other) || ToHigh().Equals(other);
327*795d594fSAndroid Build Coastguard Worker     }
328*795d594fSAndroid Build Coastguard Worker     return false;
329*795d594fSAndroid Build Coastguard Worker   }
330*795d594fSAndroid Build Coastguard Worker 
OverlapsWith(Location other)331*795d594fSAndroid Build Coastguard Worker   bool OverlapsWith(Location other) const {
332*795d594fSAndroid Build Coastguard Worker     // Only check the overlapping case that can happen with our register allocation algorithm.
333*795d594fSAndroid Build Coastguard Worker     bool overlap = Contains(other) || other.Contains(*this);
334*795d594fSAndroid Build Coastguard Worker     if (kIsDebugBuild && !overlap) {
335*795d594fSAndroid Build Coastguard Worker       // Note: These are also overlapping cases. But we are not able to handle them in
336*795d594fSAndroid Build Coastguard Worker       // ParallelMoveResolverWithSwap. Make sure that we do not meet such case with our compiler.
337*795d594fSAndroid Build Coastguard Worker       if ((IsPair() && other.IsPair()) || (IsDoubleStackSlot() && other.IsDoubleStackSlot())) {
338*795d594fSAndroid Build Coastguard Worker         DCHECK(!Contains(other.ToLow()));
339*795d594fSAndroid Build Coastguard Worker         DCHECK(!Contains(other.ToHigh()));
340*795d594fSAndroid Build Coastguard Worker       }
341*795d594fSAndroid Build Coastguard Worker     }
342*795d594fSAndroid Build Coastguard Worker     return overlap;
343*795d594fSAndroid Build Coastguard Worker   }
344*795d594fSAndroid Build Coastguard Worker 
DebugString()345*795d594fSAndroid Build Coastguard Worker   const char* DebugString() const {
346*795d594fSAndroid Build Coastguard Worker     switch (GetKind()) {
347*795d594fSAndroid Build Coastguard Worker       case kInvalid: return "I";
348*795d594fSAndroid Build Coastguard Worker       case kRegister: return "R";
349*795d594fSAndroid Build Coastguard Worker       case kStackSlot: return "S";
350*795d594fSAndroid Build Coastguard Worker       case kDoubleStackSlot: return "DS";
351*795d594fSAndroid Build Coastguard Worker       case kSIMDStackSlot: return "SIMD";
352*795d594fSAndroid Build Coastguard Worker       case kUnallocated: return "U";
353*795d594fSAndroid Build Coastguard Worker       case kConstant: return "C";
354*795d594fSAndroid Build Coastguard Worker       case kFpuRegister: return "F";
355*795d594fSAndroid Build Coastguard Worker       case kRegisterPair: return "RP";
356*795d594fSAndroid Build Coastguard Worker       case kFpuRegisterPair: return "FP";
357*795d594fSAndroid Build Coastguard Worker       case kDoNotUse5:  // fall-through
358*795d594fSAndroid Build Coastguard Worker       case kDoNotUse9:
359*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Should not use this location kind";
360*795d594fSAndroid Build Coastguard Worker     }
361*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
362*795d594fSAndroid Build Coastguard Worker   }
363*795d594fSAndroid Build Coastguard Worker 
364*795d594fSAndroid Build Coastguard Worker   // Unallocated locations.
365*795d594fSAndroid Build Coastguard Worker   enum Policy {
366*795d594fSAndroid Build Coastguard Worker     kAny,
367*795d594fSAndroid Build Coastguard Worker     kRequiresRegister,
368*795d594fSAndroid Build Coastguard Worker     kRequiresFpuRegister,
369*795d594fSAndroid Build Coastguard Worker     kSameAsFirstInput,
370*795d594fSAndroid Build Coastguard Worker   };
371*795d594fSAndroid Build Coastguard Worker 
IsUnallocated()372*795d594fSAndroid Build Coastguard Worker   bool IsUnallocated() const {
373*795d594fSAndroid Build Coastguard Worker     return GetKind() == kUnallocated;
374*795d594fSAndroid Build Coastguard Worker   }
375*795d594fSAndroid Build Coastguard Worker 
UnallocatedLocation(Policy policy)376*795d594fSAndroid Build Coastguard Worker   static Location UnallocatedLocation(Policy policy) {
377*795d594fSAndroid Build Coastguard Worker     return Location(kUnallocated, PolicyField::Encode(policy));
378*795d594fSAndroid Build Coastguard Worker   }
379*795d594fSAndroid Build Coastguard Worker 
380*795d594fSAndroid Build Coastguard Worker   // Any free register is suitable to replace this unallocated location.
Any()381*795d594fSAndroid Build Coastguard Worker   static Location Any() {
382*795d594fSAndroid Build Coastguard Worker     return UnallocatedLocation(kAny);
383*795d594fSAndroid Build Coastguard Worker   }
384*795d594fSAndroid Build Coastguard Worker 
RequiresRegister()385*795d594fSAndroid Build Coastguard Worker   static Location RequiresRegister() {
386*795d594fSAndroid Build Coastguard Worker     return UnallocatedLocation(kRequiresRegister);
387*795d594fSAndroid Build Coastguard Worker   }
388*795d594fSAndroid Build Coastguard Worker 
RequiresFpuRegister()389*795d594fSAndroid Build Coastguard Worker   static Location RequiresFpuRegister() {
390*795d594fSAndroid Build Coastguard Worker     return UnallocatedLocation(kRequiresFpuRegister);
391*795d594fSAndroid Build Coastguard Worker   }
392*795d594fSAndroid Build Coastguard Worker 
393*795d594fSAndroid Build Coastguard Worker   static Location RegisterOrConstant(HInstruction* instruction);
394*795d594fSAndroid Build Coastguard Worker   static Location RegisterOrInt32Constant(HInstruction* instruction);
395*795d594fSAndroid Build Coastguard Worker   static Location ByteRegisterOrConstant(int reg, HInstruction* instruction);
396*795d594fSAndroid Build Coastguard Worker   static Location FpuRegisterOrConstant(HInstruction* instruction);
397*795d594fSAndroid Build Coastguard Worker   static Location FpuRegisterOrInt32Constant(HInstruction* instruction);
398*795d594fSAndroid Build Coastguard Worker 
399*795d594fSAndroid Build Coastguard Worker   // The location of the first input to the instruction will be
400*795d594fSAndroid Build Coastguard Worker   // used to replace this unallocated location.
SameAsFirstInput()401*795d594fSAndroid Build Coastguard Worker   static Location SameAsFirstInput() {
402*795d594fSAndroid Build Coastguard Worker     return UnallocatedLocation(kSameAsFirstInput);
403*795d594fSAndroid Build Coastguard Worker   }
404*795d594fSAndroid Build Coastguard Worker 
GetPolicy()405*795d594fSAndroid Build Coastguard Worker   Policy GetPolicy() const {
406*795d594fSAndroid Build Coastguard Worker     DCHECK(IsUnallocated());
407*795d594fSAndroid Build Coastguard Worker     return PolicyField::Decode(GetPayload());
408*795d594fSAndroid Build Coastguard Worker   }
409*795d594fSAndroid Build Coastguard Worker 
RequiresRegisterKind()410*795d594fSAndroid Build Coastguard Worker   bool RequiresRegisterKind() const {
411*795d594fSAndroid Build Coastguard Worker     return GetPolicy() == kRequiresRegister || GetPolicy() == kRequiresFpuRegister;
412*795d594fSAndroid Build Coastguard Worker   }
413*795d594fSAndroid Build Coastguard Worker 
GetEncoding()414*795d594fSAndroid Build Coastguard Worker   uintptr_t GetEncoding() const {
415*795d594fSAndroid Build Coastguard Worker     return GetPayload();
416*795d594fSAndroid Build Coastguard Worker   }
417*795d594fSAndroid Build Coastguard Worker 
418*795d594fSAndroid Build Coastguard Worker  private:
419*795d594fSAndroid Build Coastguard Worker   // Number of bits required to encode Kind value.
420*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t kBitsForKind = 4;
421*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t kBitsForPayload = kBitsPerIntPtrT - kBitsForKind;
422*795d594fSAndroid Build Coastguard Worker   static constexpr uintptr_t kLocationConstantMask = 0x3;
423*795d594fSAndroid Build Coastguard Worker 
Location(uintptr_t value)424*795d594fSAndroid Build Coastguard Worker   explicit Location(uintptr_t value) : value_(value) {}
425*795d594fSAndroid Build Coastguard Worker 
Location(Kind kind,uintptr_t payload)426*795d594fSAndroid Build Coastguard Worker   constexpr Location(Kind kind, uintptr_t payload)
427*795d594fSAndroid Build Coastguard Worker       : value_(KindField::Encode(kind) | PayloadField::Encode(payload)) {}
428*795d594fSAndroid Build Coastguard Worker 
GetPayload()429*795d594fSAndroid Build Coastguard Worker   uintptr_t GetPayload() const {
430*795d594fSAndroid Build Coastguard Worker     return PayloadField::Decode(value_);
431*795d594fSAndroid Build Coastguard Worker   }
432*795d594fSAndroid Build Coastguard Worker 
433*795d594fSAndroid Build Coastguard Worker   static void DCheckInstructionIsConstant(HInstruction* instruction);
434*795d594fSAndroid Build Coastguard Worker 
435*795d594fSAndroid Build Coastguard Worker   using KindField = BitField<Kind, 0, kBitsForKind>;
436*795d594fSAndroid Build Coastguard Worker   using PayloadField = BitField<uintptr_t, kBitsForKind, kBitsForPayload>;
437*795d594fSAndroid Build Coastguard Worker 
438*795d594fSAndroid Build Coastguard Worker   // Layout for kUnallocated locations payload.
439*795d594fSAndroid Build Coastguard Worker   using PolicyField = BitField<Policy, 0, 3>;
440*795d594fSAndroid Build Coastguard Worker 
441*795d594fSAndroid Build Coastguard Worker   // Layout for stack slots.
442*795d594fSAndroid Build Coastguard Worker   static const intptr_t kStackIndexBias =
443*795d594fSAndroid Build Coastguard Worker       static_cast<intptr_t>(1) << (kBitsForPayload - 1);
444*795d594fSAndroid Build Coastguard Worker 
445*795d594fSAndroid Build Coastguard Worker   // Location either contains kind and payload fields or a tagged handle for
446*795d594fSAndroid Build Coastguard Worker   // a constant locations. Values of enumeration Kind are selected in such a
447*795d594fSAndroid Build Coastguard Worker   // way that none of them can be interpreted as a kConstant tag.
448*795d594fSAndroid Build Coastguard Worker   uintptr_t value_;
449*795d594fSAndroid Build Coastguard Worker };
450*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, Location::Kind rhs);
451*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, Location::Policy rhs);
452*795d594fSAndroid Build Coastguard Worker 
453*795d594fSAndroid Build Coastguard Worker class RegisterSet : public ValueObject {
454*795d594fSAndroid Build Coastguard Worker  public:
Empty()455*795d594fSAndroid Build Coastguard Worker   static RegisterSet Empty() { return RegisterSet(); }
AllFpu()456*795d594fSAndroid Build Coastguard Worker   static RegisterSet AllFpu() { return RegisterSet(0, -1); }
457*795d594fSAndroid Build Coastguard Worker 
Add(Location loc)458*795d594fSAndroid Build Coastguard Worker   void Add(Location loc) {
459*795d594fSAndroid Build Coastguard Worker     if (loc.IsRegister()) {
460*795d594fSAndroid Build Coastguard Worker       core_registers_ |= (1 << loc.reg());
461*795d594fSAndroid Build Coastguard Worker     } else {
462*795d594fSAndroid Build Coastguard Worker       DCHECK(loc.IsFpuRegister());
463*795d594fSAndroid Build Coastguard Worker       floating_point_registers_ |= (1 << loc.reg());
464*795d594fSAndroid Build Coastguard Worker     }
465*795d594fSAndroid Build Coastguard Worker   }
466*795d594fSAndroid Build Coastguard Worker 
Remove(Location loc)467*795d594fSAndroid Build Coastguard Worker   void Remove(Location loc) {
468*795d594fSAndroid Build Coastguard Worker     if (loc.IsRegister()) {
469*795d594fSAndroid Build Coastguard Worker       core_registers_ &= ~(1 << loc.reg());
470*795d594fSAndroid Build Coastguard Worker     } else {
471*795d594fSAndroid Build Coastguard Worker       DCHECK(loc.IsFpuRegister()) << loc;
472*795d594fSAndroid Build Coastguard Worker       floating_point_registers_ &= ~(1 << loc.reg());
473*795d594fSAndroid Build Coastguard Worker     }
474*795d594fSAndroid Build Coastguard Worker   }
475*795d594fSAndroid Build Coastguard Worker 
ContainsCoreRegister(uint32_t id)476*795d594fSAndroid Build Coastguard Worker   bool ContainsCoreRegister(uint32_t id) const {
477*795d594fSAndroid Build Coastguard Worker     return Contains(core_registers_, id);
478*795d594fSAndroid Build Coastguard Worker   }
479*795d594fSAndroid Build Coastguard Worker 
ContainsFloatingPointRegister(uint32_t id)480*795d594fSAndroid Build Coastguard Worker   bool ContainsFloatingPointRegister(uint32_t id) const {
481*795d594fSAndroid Build Coastguard Worker     return Contains(floating_point_registers_, id);
482*795d594fSAndroid Build Coastguard Worker   }
483*795d594fSAndroid Build Coastguard Worker 
Contains(uint32_t register_set,uint32_t reg)484*795d594fSAndroid Build Coastguard Worker   static bool Contains(uint32_t register_set, uint32_t reg) {
485*795d594fSAndroid Build Coastguard Worker     return (register_set & (1 << reg)) != 0;
486*795d594fSAndroid Build Coastguard Worker   }
487*795d594fSAndroid Build Coastguard Worker 
OverlapsRegisters(Location out)488*795d594fSAndroid Build Coastguard Worker   bool OverlapsRegisters(Location out) {
489*795d594fSAndroid Build Coastguard Worker     DCHECK(out.IsRegisterKind());
490*795d594fSAndroid Build Coastguard Worker     switch (out.GetKind()) {
491*795d594fSAndroid Build Coastguard Worker       case Location::Kind::kRegister:
492*795d594fSAndroid Build Coastguard Worker         return ContainsCoreRegister(out.reg());
493*795d594fSAndroid Build Coastguard Worker       case Location::Kind::kFpuRegister:
494*795d594fSAndroid Build Coastguard Worker         return ContainsFloatingPointRegister(out.reg());
495*795d594fSAndroid Build Coastguard Worker       case Location::Kind::kRegisterPair:
496*795d594fSAndroid Build Coastguard Worker         return ContainsCoreRegister(out.low()) || ContainsCoreRegister(out.high());
497*795d594fSAndroid Build Coastguard Worker       case Location::Kind::kFpuRegisterPair:
498*795d594fSAndroid Build Coastguard Worker         return ContainsFloatingPointRegister(out.low()) ||
499*795d594fSAndroid Build Coastguard Worker                ContainsFloatingPointRegister(out.high());
500*795d594fSAndroid Build Coastguard Worker       default:
501*795d594fSAndroid Build Coastguard Worker         return false;
502*795d594fSAndroid Build Coastguard Worker     }
503*795d594fSAndroid Build Coastguard Worker   }
504*795d594fSAndroid Build Coastguard Worker 
GetNumberOfRegisters()505*795d594fSAndroid Build Coastguard Worker   size_t GetNumberOfRegisters() const {
506*795d594fSAndroid Build Coastguard Worker     return POPCOUNT(core_registers_) + POPCOUNT(floating_point_registers_);
507*795d594fSAndroid Build Coastguard Worker   }
508*795d594fSAndroid Build Coastguard Worker 
GetCoreRegisters()509*795d594fSAndroid Build Coastguard Worker   uint32_t GetCoreRegisters() const {
510*795d594fSAndroid Build Coastguard Worker     return core_registers_;
511*795d594fSAndroid Build Coastguard Worker   }
512*795d594fSAndroid Build Coastguard Worker 
GetFloatingPointRegisters()513*795d594fSAndroid Build Coastguard Worker   uint32_t GetFloatingPointRegisters() const {
514*795d594fSAndroid Build Coastguard Worker     return floating_point_registers_;
515*795d594fSAndroid Build Coastguard Worker   }
516*795d594fSAndroid Build Coastguard Worker 
517*795d594fSAndroid Build Coastguard Worker  private:
RegisterSet()518*795d594fSAndroid Build Coastguard Worker   RegisterSet() : core_registers_(0), floating_point_registers_(0) {}
RegisterSet(uint32_t core,uint32_t fp)519*795d594fSAndroid Build Coastguard Worker   RegisterSet(uint32_t core, uint32_t fp) : core_registers_(core), floating_point_registers_(fp) {}
520*795d594fSAndroid Build Coastguard Worker 
521*795d594fSAndroid Build Coastguard Worker   uint32_t core_registers_;
522*795d594fSAndroid Build Coastguard Worker   uint32_t floating_point_registers_;
523*795d594fSAndroid Build Coastguard Worker };
524*795d594fSAndroid Build Coastguard Worker 
525*795d594fSAndroid Build Coastguard Worker static constexpr bool kIntrinsified = true;
526*795d594fSAndroid Build Coastguard Worker 
527*795d594fSAndroid Build Coastguard Worker /**
528*795d594fSAndroid Build Coastguard Worker  * The code generator computes LocationSummary for each instruction so that
529*795d594fSAndroid Build Coastguard Worker  * the instruction itself knows what code to generate: where to find the inputs
530*795d594fSAndroid Build Coastguard Worker  * and where to place the result.
531*795d594fSAndroid Build Coastguard Worker  *
532*795d594fSAndroid Build Coastguard Worker  * The intent is to have the code for generating the instruction independent of
533*795d594fSAndroid Build Coastguard Worker  * register allocation. A register allocator just has to provide a LocationSummary.
534*795d594fSAndroid Build Coastguard Worker  */
535*795d594fSAndroid Build Coastguard Worker class LocationSummary : public ArenaObject<kArenaAllocLocationSummary> {
536*795d594fSAndroid Build Coastguard Worker  public:
537*795d594fSAndroid Build Coastguard Worker   enum CallKind {
538*795d594fSAndroid Build Coastguard Worker     kNoCall,
539*795d594fSAndroid Build Coastguard Worker     kCallOnMainAndSlowPath,
540*795d594fSAndroid Build Coastguard Worker     kCallOnSlowPath,
541*795d594fSAndroid Build Coastguard Worker     kCallOnMainOnly
542*795d594fSAndroid Build Coastguard Worker   };
543*795d594fSAndroid Build Coastguard Worker 
544*795d594fSAndroid Build Coastguard Worker   explicit LocationSummary(HInstruction* instruction,
545*795d594fSAndroid Build Coastguard Worker                            CallKind call_kind = kNoCall,
546*795d594fSAndroid Build Coastguard Worker                            bool intrinsified = false);
547*795d594fSAndroid Build Coastguard Worker 
SetInAt(uint32_t at,Location location)548*795d594fSAndroid Build Coastguard Worker   void SetInAt(uint32_t at, Location location) {
549*795d594fSAndroid Build Coastguard Worker     inputs_[at] = location;
550*795d594fSAndroid Build Coastguard Worker   }
551*795d594fSAndroid Build Coastguard Worker 
InAt(uint32_t at)552*795d594fSAndroid Build Coastguard Worker   Location InAt(uint32_t at) const {
553*795d594fSAndroid Build Coastguard Worker     return inputs_[at];
554*795d594fSAndroid Build Coastguard Worker   }
555*795d594fSAndroid Build Coastguard Worker 
GetInputCount()556*795d594fSAndroid Build Coastguard Worker   size_t GetInputCount() const {
557*795d594fSAndroid Build Coastguard Worker     return inputs_.size();
558*795d594fSAndroid Build Coastguard Worker   }
559*795d594fSAndroid Build Coastguard Worker 
560*795d594fSAndroid Build Coastguard Worker   // Set the output location.  Argument `overlaps` tells whether the
561*795d594fSAndroid Build Coastguard Worker   // output overlaps any of the inputs (if so, it cannot share the
562*795d594fSAndroid Build Coastguard Worker   // same register as one of the inputs); it is set to
563*795d594fSAndroid Build Coastguard Worker   // `Location::kOutputOverlap` by default for safety.
564*795d594fSAndroid Build Coastguard Worker   void SetOut(Location location, Location::OutputOverlap overlaps = Location::kOutputOverlap) {
565*795d594fSAndroid Build Coastguard Worker     DCHECK(output_.IsInvalid());
566*795d594fSAndroid Build Coastguard Worker     output_overlaps_ = overlaps;
567*795d594fSAndroid Build Coastguard Worker     output_ = location;
568*795d594fSAndroid Build Coastguard Worker   }
569*795d594fSAndroid Build Coastguard Worker 
UpdateOut(Location location)570*795d594fSAndroid Build Coastguard Worker   void UpdateOut(Location location) {
571*795d594fSAndroid Build Coastguard Worker     // There are two reasons for updating an output:
572*795d594fSAndroid Build Coastguard Worker     // 1) Parameters, where we only know the exact stack slot after
573*795d594fSAndroid Build Coastguard Worker     //    doing full register allocation.
574*795d594fSAndroid Build Coastguard Worker     // 2) Unallocated location.
575*795d594fSAndroid Build Coastguard Worker     DCHECK(output_.IsStackSlot() || output_.IsDoubleStackSlot() || output_.IsUnallocated());
576*795d594fSAndroid Build Coastguard Worker     output_ = location;
577*795d594fSAndroid Build Coastguard Worker   }
578*795d594fSAndroid Build Coastguard Worker 
AddTemp(Location location)579*795d594fSAndroid Build Coastguard Worker   void AddTemp(Location location) {
580*795d594fSAndroid Build Coastguard Worker     temps_.push_back(location);
581*795d594fSAndroid Build Coastguard Worker   }
582*795d594fSAndroid Build Coastguard Worker 
AddRegisterTemps(size_t count)583*795d594fSAndroid Build Coastguard Worker   void AddRegisterTemps(size_t count) {
584*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < count; ++i) {
585*795d594fSAndroid Build Coastguard Worker       AddTemp(Location::RequiresRegister());
586*795d594fSAndroid Build Coastguard Worker     }
587*795d594fSAndroid Build Coastguard Worker   }
588*795d594fSAndroid Build Coastguard Worker 
GetTemp(uint32_t at)589*795d594fSAndroid Build Coastguard Worker   Location GetTemp(uint32_t at) const {
590*795d594fSAndroid Build Coastguard Worker     return temps_[at];
591*795d594fSAndroid Build Coastguard Worker   }
592*795d594fSAndroid Build Coastguard Worker 
SetTempAt(uint32_t at,Location location)593*795d594fSAndroid Build Coastguard Worker   void SetTempAt(uint32_t at, Location location) {
594*795d594fSAndroid Build Coastguard Worker     DCHECK(temps_[at].IsUnallocated() || temps_[at].IsInvalid());
595*795d594fSAndroid Build Coastguard Worker     temps_[at] = location;
596*795d594fSAndroid Build Coastguard Worker   }
597*795d594fSAndroid Build Coastguard Worker 
GetTempCount()598*795d594fSAndroid Build Coastguard Worker   size_t GetTempCount() const {
599*795d594fSAndroid Build Coastguard Worker     return temps_.size();
600*795d594fSAndroid Build Coastguard Worker   }
601*795d594fSAndroid Build Coastguard Worker 
HasTemps()602*795d594fSAndroid Build Coastguard Worker   bool HasTemps() const { return !temps_.empty(); }
603*795d594fSAndroid Build Coastguard Worker 
Out()604*795d594fSAndroid Build Coastguard Worker   Location Out() const { return output_; }
605*795d594fSAndroid Build Coastguard Worker 
CanCall()606*795d594fSAndroid Build Coastguard Worker   bool CanCall() const {
607*795d594fSAndroid Build Coastguard Worker     return call_kind_ != kNoCall;
608*795d594fSAndroid Build Coastguard Worker   }
609*795d594fSAndroid Build Coastguard Worker 
WillCall()610*795d594fSAndroid Build Coastguard Worker   bool WillCall() const {
611*795d594fSAndroid Build Coastguard Worker     return call_kind_ == kCallOnMainOnly || call_kind_ == kCallOnMainAndSlowPath;
612*795d594fSAndroid Build Coastguard Worker   }
613*795d594fSAndroid Build Coastguard Worker 
CallsOnSlowPath()614*795d594fSAndroid Build Coastguard Worker   bool CallsOnSlowPath() const {
615*795d594fSAndroid Build Coastguard Worker     return OnlyCallsOnSlowPath() || CallsOnMainAndSlowPath();
616*795d594fSAndroid Build Coastguard Worker   }
617*795d594fSAndroid Build Coastguard Worker 
OnlyCallsOnSlowPath()618*795d594fSAndroid Build Coastguard Worker   bool OnlyCallsOnSlowPath() const {
619*795d594fSAndroid Build Coastguard Worker     return call_kind_ == kCallOnSlowPath;
620*795d594fSAndroid Build Coastguard Worker   }
621*795d594fSAndroid Build Coastguard Worker 
NeedsSuspendCheckEntry()622*795d594fSAndroid Build Coastguard Worker   bool NeedsSuspendCheckEntry() const {
623*795d594fSAndroid Build Coastguard Worker     // Slow path calls do not need a SuspendCheck at method entry since they go into the runtime,
624*795d594fSAndroid Build Coastguard Worker     // which we expect to either do a suspend check or return quickly.
625*795d594fSAndroid Build Coastguard Worker     return WillCall();
626*795d594fSAndroid Build Coastguard Worker   }
627*795d594fSAndroid Build Coastguard Worker 
CallsOnMainAndSlowPath()628*795d594fSAndroid Build Coastguard Worker   bool CallsOnMainAndSlowPath() const {
629*795d594fSAndroid Build Coastguard Worker     return call_kind_ == kCallOnMainAndSlowPath;
630*795d594fSAndroid Build Coastguard Worker   }
631*795d594fSAndroid Build Coastguard Worker 
NeedsSafepoint()632*795d594fSAndroid Build Coastguard Worker   bool NeedsSafepoint() const {
633*795d594fSAndroid Build Coastguard Worker     return CanCall();
634*795d594fSAndroid Build Coastguard Worker   }
635*795d594fSAndroid Build Coastguard Worker 
SetCustomSlowPathCallerSaves(const RegisterSet & caller_saves)636*795d594fSAndroid Build Coastguard Worker   void SetCustomSlowPathCallerSaves(const RegisterSet& caller_saves) {
637*795d594fSAndroid Build Coastguard Worker     DCHECK(OnlyCallsOnSlowPath());
638*795d594fSAndroid Build Coastguard Worker     has_custom_slow_path_calling_convention_ = true;
639*795d594fSAndroid Build Coastguard Worker     custom_slow_path_caller_saves_ = caller_saves;
640*795d594fSAndroid Build Coastguard Worker   }
641*795d594fSAndroid Build Coastguard Worker 
HasCustomSlowPathCallingConvention()642*795d594fSAndroid Build Coastguard Worker   bool HasCustomSlowPathCallingConvention() const {
643*795d594fSAndroid Build Coastguard Worker     return has_custom_slow_path_calling_convention_;
644*795d594fSAndroid Build Coastguard Worker   }
645*795d594fSAndroid Build Coastguard Worker 
GetCustomSlowPathCallerSaves()646*795d594fSAndroid Build Coastguard Worker   const RegisterSet& GetCustomSlowPathCallerSaves() const {
647*795d594fSAndroid Build Coastguard Worker     DCHECK(HasCustomSlowPathCallingConvention());
648*795d594fSAndroid Build Coastguard Worker     return custom_slow_path_caller_saves_;
649*795d594fSAndroid Build Coastguard Worker   }
650*795d594fSAndroid Build Coastguard Worker 
SetStackBit(uint32_t index)651*795d594fSAndroid Build Coastguard Worker   void SetStackBit(uint32_t index) {
652*795d594fSAndroid Build Coastguard Worker     stack_mask_->SetBit(index);
653*795d594fSAndroid Build Coastguard Worker   }
654*795d594fSAndroid Build Coastguard Worker 
ClearStackBit(uint32_t index)655*795d594fSAndroid Build Coastguard Worker   void ClearStackBit(uint32_t index) {
656*795d594fSAndroid Build Coastguard Worker     stack_mask_->ClearBit(index);
657*795d594fSAndroid Build Coastguard Worker   }
658*795d594fSAndroid Build Coastguard Worker 
SetRegisterBit(uint32_t reg_id)659*795d594fSAndroid Build Coastguard Worker   void SetRegisterBit(uint32_t reg_id) {
660*795d594fSAndroid Build Coastguard Worker     register_mask_ |= (1 << reg_id);
661*795d594fSAndroid Build Coastguard Worker   }
662*795d594fSAndroid Build Coastguard Worker 
GetRegisterMask()663*795d594fSAndroid Build Coastguard Worker   uint32_t GetRegisterMask() const {
664*795d594fSAndroid Build Coastguard Worker     return register_mask_;
665*795d594fSAndroid Build Coastguard Worker   }
666*795d594fSAndroid Build Coastguard Worker 
RegisterContainsObject(uint32_t reg_id)667*795d594fSAndroid Build Coastguard Worker   bool RegisterContainsObject(uint32_t reg_id) {
668*795d594fSAndroid Build Coastguard Worker     return RegisterSet::Contains(register_mask_, reg_id);
669*795d594fSAndroid Build Coastguard Worker   }
670*795d594fSAndroid Build Coastguard Worker 
AddLiveRegister(Location location)671*795d594fSAndroid Build Coastguard Worker   void AddLiveRegister(Location location) {
672*795d594fSAndroid Build Coastguard Worker     live_registers_.Add(location);
673*795d594fSAndroid Build Coastguard Worker   }
674*795d594fSAndroid Build Coastguard Worker 
GetStackMask()675*795d594fSAndroid Build Coastguard Worker   BitVector* GetStackMask() const {
676*795d594fSAndroid Build Coastguard Worker     return stack_mask_;
677*795d594fSAndroid Build Coastguard Worker   }
678*795d594fSAndroid Build Coastguard Worker 
GetLiveRegisters()679*795d594fSAndroid Build Coastguard Worker   RegisterSet* GetLiveRegisters() {
680*795d594fSAndroid Build Coastguard Worker     return &live_registers_;
681*795d594fSAndroid Build Coastguard Worker   }
682*795d594fSAndroid Build Coastguard Worker 
GetNumberOfLiveRegisters()683*795d594fSAndroid Build Coastguard Worker   size_t GetNumberOfLiveRegisters() const {
684*795d594fSAndroid Build Coastguard Worker     return live_registers_.GetNumberOfRegisters();
685*795d594fSAndroid Build Coastguard Worker   }
686*795d594fSAndroid Build Coastguard Worker 
OutputUsesSameAs(uint32_t input_index)687*795d594fSAndroid Build Coastguard Worker   bool OutputUsesSameAs(uint32_t input_index) const {
688*795d594fSAndroid Build Coastguard Worker     return (input_index == 0)
689*795d594fSAndroid Build Coastguard Worker         && output_.IsUnallocated()
690*795d594fSAndroid Build Coastguard Worker         && (output_.GetPolicy() == Location::kSameAsFirstInput);
691*795d594fSAndroid Build Coastguard Worker   }
692*795d594fSAndroid Build Coastguard Worker 
IsFixedInput(uint32_t input_index)693*795d594fSAndroid Build Coastguard Worker   bool IsFixedInput(uint32_t input_index) const {
694*795d594fSAndroid Build Coastguard Worker     Location input = inputs_[input_index];
695*795d594fSAndroid Build Coastguard Worker     return input.IsRegister()
696*795d594fSAndroid Build Coastguard Worker         || input.IsFpuRegister()
697*795d594fSAndroid Build Coastguard Worker         || input.IsPair()
698*795d594fSAndroid Build Coastguard Worker         || input.IsStackSlot()
699*795d594fSAndroid Build Coastguard Worker         || input.IsDoubleStackSlot();
700*795d594fSAndroid Build Coastguard Worker   }
701*795d594fSAndroid Build Coastguard Worker 
OutputCanOverlapWithInputs()702*795d594fSAndroid Build Coastguard Worker   bool OutputCanOverlapWithInputs() const {
703*795d594fSAndroid Build Coastguard Worker     return output_overlaps_ == Location::kOutputOverlap;
704*795d594fSAndroid Build Coastguard Worker   }
705*795d594fSAndroid Build Coastguard Worker 
Intrinsified()706*795d594fSAndroid Build Coastguard Worker   bool Intrinsified() const {
707*795d594fSAndroid Build Coastguard Worker     return intrinsified_;
708*795d594fSAndroid Build Coastguard Worker   }
709*795d594fSAndroid Build Coastguard Worker 
710*795d594fSAndroid Build Coastguard Worker  private:
711*795d594fSAndroid Build Coastguard Worker   LocationSummary(HInstruction* instruction,
712*795d594fSAndroid Build Coastguard Worker                   CallKind call_kind,
713*795d594fSAndroid Build Coastguard Worker                   bool intrinsified,
714*795d594fSAndroid Build Coastguard Worker                   ArenaAllocator* allocator);
715*795d594fSAndroid Build Coastguard Worker 
716*795d594fSAndroid Build Coastguard Worker   ArenaVector<Location> inputs_;
717*795d594fSAndroid Build Coastguard Worker   ArenaVector<Location> temps_;
718*795d594fSAndroid Build Coastguard Worker   const CallKind call_kind_;
719*795d594fSAndroid Build Coastguard Worker   // Whether these are locations for an intrinsified call.
720*795d594fSAndroid Build Coastguard Worker   const bool intrinsified_;
721*795d594fSAndroid Build Coastguard Worker   // Whether the slow path has default or custom calling convention.
722*795d594fSAndroid Build Coastguard Worker   bool has_custom_slow_path_calling_convention_;
723*795d594fSAndroid Build Coastguard Worker   // Whether the output overlaps with any of the inputs. If it overlaps, then it cannot
724*795d594fSAndroid Build Coastguard Worker   // share the same register as the inputs.
725*795d594fSAndroid Build Coastguard Worker   Location::OutputOverlap output_overlaps_;
726*795d594fSAndroid Build Coastguard Worker   Location output_;
727*795d594fSAndroid Build Coastguard Worker 
728*795d594fSAndroid Build Coastguard Worker   // Mask of objects that live in the stack.
729*795d594fSAndroid Build Coastguard Worker   BitVector* stack_mask_;
730*795d594fSAndroid Build Coastguard Worker 
731*795d594fSAndroid Build Coastguard Worker   // Mask of objects that live in register.
732*795d594fSAndroid Build Coastguard Worker   uint32_t register_mask_;
733*795d594fSAndroid Build Coastguard Worker 
734*795d594fSAndroid Build Coastguard Worker   // Registers that are in use at this position.
735*795d594fSAndroid Build Coastguard Worker   RegisterSet live_registers_;
736*795d594fSAndroid Build Coastguard Worker 
737*795d594fSAndroid Build Coastguard Worker   // Custom slow path caller saves. Valid only if indicated by slow_path_calling_convention_.
738*795d594fSAndroid Build Coastguard Worker   RegisterSet custom_slow_path_caller_saves_;
739*795d594fSAndroid Build Coastguard Worker 
740*795d594fSAndroid Build Coastguard Worker   ART_FRIEND_TEST(RegisterAllocatorTest, ExpectedInRegisterHint);
741*795d594fSAndroid Build Coastguard Worker   ART_FRIEND_TEST(RegisterAllocatorTest, SameAsFirstInputHint);
742*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(LocationSummary);
743*795d594fSAndroid Build Coastguard Worker };
744*795d594fSAndroid Build Coastguard Worker 
745*795d594fSAndroid Build Coastguard Worker }  // namespace art
746*795d594fSAndroid Build Coastguard Worker 
747*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_LOCATIONS_H_
748