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