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 
GetStackIndex()284   intptr_t GetStackIndex() const {
285     DCHECK(IsStackSlot() || IsDoubleStackSlot() || IsSIMDStackSlot());
286     // Decode stack index manually to preserve sign.
287     return GetPayload() - kStackIndexBias;
288   }
289 
GetHighStackIndex(uintptr_t word_size)290   intptr_t GetHighStackIndex(uintptr_t word_size) const {
291     DCHECK(IsDoubleStackSlot());
292     // Decode stack index manually to preserve sign.
293     return GetPayload() - kStackIndexBias + word_size;
294   }
295 
GetKind()296   Kind GetKind() const {
297     return IsConstant() ? kConstant : KindField::Decode(value_);
298   }
299 
Equals(Location other)300   bool Equals(Location other) const {
301     return value_ == other.value_;
302   }
303 
Contains(Location other)304   bool Contains(Location other) const {
305     if (Equals(other)) {
306       return true;
307     } else if (IsPair() || IsDoubleStackSlot()) {
308       return ToLow().Equals(other) || ToHigh().Equals(other);
309     }
310     return false;
311   }
312 
OverlapsWith(Location other)313   bool OverlapsWith(Location other) const {
314     // Only check the overlapping case that can happen with our register allocation algorithm.
315     bool overlap = Contains(other) || other.Contains(*this);
316     if (kIsDebugBuild && !overlap) {
317       // Note: These are also overlapping cases. But we are not able to handle them in
318       // ParallelMoveResolverWithSwap. Make sure that we do not meet such case with our compiler.
319       if ((IsPair() && other.IsPair()) || (IsDoubleStackSlot() && other.IsDoubleStackSlot())) {
320         DCHECK(!Contains(other.ToLow()));
321         DCHECK(!Contains(other.ToHigh()));
322       }
323     }
324     return overlap;
325   }
326 
DebugString()327   const char* DebugString() const {
328     switch (GetKind()) {
329       case kInvalid: return "I";
330       case kRegister: return "R";
331       case kStackSlot: return "S";
332       case kDoubleStackSlot: return "DS";
333       case kSIMDStackSlot: return "SIMD";
334       case kUnallocated: return "U";
335       case kConstant: return "C";
336       case kFpuRegister: return "F";
337       case kRegisterPair: return "RP";
338       case kFpuRegisterPair: return "FP";
339       case kDoNotUse5:  // fall-through
340       case kDoNotUse9:
341         LOG(FATAL) << "Should not use this location kind";
342     }
343     UNREACHABLE();
344   }
345 
346   // Unallocated locations.
347   enum Policy {
348     kAny,
349     kRequiresRegister,
350     kRequiresFpuRegister,
351     kSameAsFirstInput,
352   };
353 
IsUnallocated()354   bool IsUnallocated() const {
355     return GetKind() == kUnallocated;
356   }
357 
UnallocatedLocation(Policy policy)358   static Location UnallocatedLocation(Policy policy) {
359     return Location(kUnallocated, PolicyField::Encode(policy));
360   }
361 
362   // Any free register is suitable to replace this unallocated location.
Any()363   static Location Any() {
364     return UnallocatedLocation(kAny);
365   }
366 
RequiresRegister()367   static Location RequiresRegister() {
368     return UnallocatedLocation(kRequiresRegister);
369   }
370 
RequiresFpuRegister()371   static Location RequiresFpuRegister() {
372     return UnallocatedLocation(kRequiresFpuRegister);
373   }
374 
375   static Location RegisterOrConstant(HInstruction* instruction);
376   static Location RegisterOrInt32Constant(HInstruction* instruction);
377   static Location ByteRegisterOrConstant(int reg, HInstruction* instruction);
378   static Location FpuRegisterOrConstant(HInstruction* instruction);
379   static Location FpuRegisterOrInt32Constant(HInstruction* instruction);
380 
381   // The location of the first input to the instruction will be
382   // used to replace this unallocated location.
SameAsFirstInput()383   static Location SameAsFirstInput() {
384     return UnallocatedLocation(kSameAsFirstInput);
385   }
386 
GetPolicy()387   Policy GetPolicy() const {
388     DCHECK(IsUnallocated());
389     return PolicyField::Decode(GetPayload());
390   }
391 
RequiresRegisterKind()392   bool RequiresRegisterKind() const {
393     return GetPolicy() == kRequiresRegister || GetPolicy() == kRequiresFpuRegister;
394   }
395 
GetEncoding()396   uintptr_t GetEncoding() const {
397     return GetPayload();
398   }
399 
400  private:
401   // Number of bits required to encode Kind value.
402   static constexpr uint32_t kBitsForKind = 4;
403   static constexpr uint32_t kBitsForPayload = kBitsPerIntPtrT - kBitsForKind;
404   static constexpr uintptr_t kLocationConstantMask = 0x3;
405 
Location(uintptr_t value)406   explicit Location(uintptr_t value) : value_(value) {}
407 
Location(Kind kind,uintptr_t payload)408   Location(Kind kind, uintptr_t payload)
409       : value_(KindField::Encode(kind) | PayloadField::Encode(payload)) {}
410 
GetPayload()411   uintptr_t GetPayload() const {
412     return PayloadField::Decode(value_);
413   }
414 
415   typedef BitField<Kind, 0, kBitsForKind> KindField;
416   typedef BitField<uintptr_t, kBitsForKind, kBitsForPayload> PayloadField;
417 
418   // Layout for kUnallocated locations payload.
419   typedef BitField<Policy, 0, 3> PolicyField;
420 
421   // Layout for stack slots.
422   static const intptr_t kStackIndexBias =
423       static_cast<intptr_t>(1) << (kBitsForPayload - 1);
424 
425   // Location either contains kind and payload fields or a tagged handle for
426   // a constant locations. Values of enumeration Kind are selected in such a
427   // way that none of them can be interpreted as a kConstant tag.
428   uintptr_t value_;
429 };
430 std::ostream& operator<<(std::ostream& os, const Location::Kind& rhs);
431 std::ostream& operator<<(std::ostream& os, const Location::Policy& rhs);
432 
433 class RegisterSet : public ValueObject {
434  public:
Empty()435   static RegisterSet Empty() { return RegisterSet(); }
AllFpu()436   static RegisterSet AllFpu() { return RegisterSet(0, -1); }
437 
Add(Location loc)438   void Add(Location loc) {
439     if (loc.IsRegister()) {
440       core_registers_ |= (1 << loc.reg());
441     } else {
442       DCHECK(loc.IsFpuRegister());
443       floating_point_registers_ |= (1 << loc.reg());
444     }
445   }
446 
Remove(Location loc)447   void Remove(Location loc) {
448     if (loc.IsRegister()) {
449       core_registers_ &= ~(1 << loc.reg());
450     } else {
451       DCHECK(loc.IsFpuRegister()) << loc;
452       floating_point_registers_ &= ~(1 << loc.reg());
453     }
454   }
455 
ContainsCoreRegister(uint32_t id)456   bool ContainsCoreRegister(uint32_t id) const {
457     return Contains(core_registers_, id);
458   }
459 
ContainsFloatingPointRegister(uint32_t id)460   bool ContainsFloatingPointRegister(uint32_t id) const {
461     return Contains(floating_point_registers_, id);
462   }
463 
Contains(uint32_t register_set,uint32_t reg)464   static bool Contains(uint32_t register_set, uint32_t reg) {
465     return (register_set & (1 << reg)) != 0;
466   }
467 
GetNumberOfRegisters()468   size_t GetNumberOfRegisters() const {
469     return POPCOUNT(core_registers_) + POPCOUNT(floating_point_registers_);
470   }
471 
GetCoreRegisters()472   uint32_t GetCoreRegisters() const {
473     return core_registers_;
474   }
475 
GetFloatingPointRegisters()476   uint32_t GetFloatingPointRegisters() const {
477     return floating_point_registers_;
478   }
479 
480  private:
RegisterSet()481   RegisterSet() : core_registers_(0), floating_point_registers_(0) {}
RegisterSet(uint32_t core,uint32_t fp)482   RegisterSet(uint32_t core, uint32_t fp) : core_registers_(core), floating_point_registers_(fp) {}
483 
484   uint32_t core_registers_;
485   uint32_t floating_point_registers_;
486 };
487 
488 static constexpr bool kIntrinsified = true;
489 
490 /**
491  * The code generator computes LocationSummary for each instruction so that
492  * the instruction itself knows what code to generate: where to find the inputs
493  * and where to place the result.
494  *
495  * The intent is to have the code for generating the instruction independent of
496  * register allocation. A register allocator just has to provide a LocationSummary.
497  */
498 class LocationSummary : public ArenaObject<kArenaAllocLocationSummary> {
499  public:
500   enum CallKind {
501     kNoCall,
502     kCallOnMainAndSlowPath,
503     kCallOnSlowPath,
504     kCallOnMainOnly
505   };
506 
507   explicit LocationSummary(HInstruction* instruction,
508                            CallKind call_kind = kNoCall,
509                            bool intrinsified = false);
510 
SetInAt(uint32_t at,Location location)511   void SetInAt(uint32_t at, Location location) {
512     inputs_[at] = location;
513   }
514 
InAt(uint32_t at)515   Location InAt(uint32_t at) const {
516     return inputs_[at];
517   }
518 
GetInputCount()519   size_t GetInputCount() const {
520     return inputs_.size();
521   }
522 
523   // Set the output location.  Argument `overlaps` tells whether the
524   // output overlaps any of the inputs (if so, it cannot share the
525   // same register as one of the inputs); it is set to
526   // `Location::kOutputOverlap` by default for safety.
527   void SetOut(Location location, Location::OutputOverlap overlaps = Location::kOutputOverlap) {
528     DCHECK(output_.IsInvalid());
529     output_overlaps_ = overlaps;
530     output_ = location;
531   }
532 
UpdateOut(Location location)533   void UpdateOut(Location location) {
534     // There are two reasons for updating an output:
535     // 1) Parameters, where we only know the exact stack slot after
536     //    doing full register allocation.
537     // 2) Unallocated location.
538     DCHECK(output_.IsStackSlot() || output_.IsDoubleStackSlot() || output_.IsUnallocated());
539     output_ = location;
540   }
541 
AddTemp(Location location)542   void AddTemp(Location location) {
543     temps_.push_back(location);
544   }
545 
AddRegisterTemps(size_t count)546   void AddRegisterTemps(size_t count) {
547     for (size_t i = 0; i < count; ++i) {
548       AddTemp(Location::RequiresRegister());
549     }
550   }
551 
GetTemp(uint32_t at)552   Location GetTemp(uint32_t at) const {
553     return temps_[at];
554   }
555 
SetTempAt(uint32_t at,Location location)556   void SetTempAt(uint32_t at, Location location) {
557     DCHECK(temps_[at].IsUnallocated() || temps_[at].IsInvalid());
558     temps_[at] = location;
559   }
560 
GetTempCount()561   size_t GetTempCount() const {
562     return temps_.size();
563   }
564 
HasTemps()565   bool HasTemps() const { return !temps_.empty(); }
566 
Out()567   Location Out() const { return output_; }
568 
CanCall()569   bool CanCall() const {
570     return call_kind_ != kNoCall;
571   }
572 
WillCall()573   bool WillCall() const {
574     return call_kind_ == kCallOnMainOnly || call_kind_ == kCallOnMainAndSlowPath;
575   }
576 
CallsOnSlowPath()577   bool CallsOnSlowPath() const {
578     return call_kind_ == kCallOnSlowPath || call_kind_ == kCallOnMainAndSlowPath;
579   }
580 
OnlyCallsOnSlowPath()581   bool OnlyCallsOnSlowPath() const {
582     return call_kind_ == kCallOnSlowPath;
583   }
584 
CallsOnMainAndSlowPath()585   bool CallsOnMainAndSlowPath() const {
586     return call_kind_ == kCallOnMainAndSlowPath;
587   }
588 
NeedsSafepoint()589   bool NeedsSafepoint() const {
590     return CanCall();
591   }
592 
SetCustomSlowPathCallerSaves(const RegisterSet & caller_saves)593   void SetCustomSlowPathCallerSaves(const RegisterSet& caller_saves) {
594     DCHECK(OnlyCallsOnSlowPath());
595     has_custom_slow_path_calling_convention_ = true;
596     custom_slow_path_caller_saves_ = caller_saves;
597   }
598 
HasCustomSlowPathCallingConvention()599   bool HasCustomSlowPathCallingConvention() const {
600     return has_custom_slow_path_calling_convention_;
601   }
602 
GetCustomSlowPathCallerSaves()603   const RegisterSet& GetCustomSlowPathCallerSaves() const {
604     DCHECK(HasCustomSlowPathCallingConvention());
605     return custom_slow_path_caller_saves_;
606   }
607 
SetStackBit(uint32_t index)608   void SetStackBit(uint32_t index) {
609     stack_mask_->SetBit(index);
610   }
611 
ClearStackBit(uint32_t index)612   void ClearStackBit(uint32_t index) {
613     stack_mask_->ClearBit(index);
614   }
615 
SetRegisterBit(uint32_t reg_id)616   void SetRegisterBit(uint32_t reg_id) {
617     register_mask_ |= (1 << reg_id);
618   }
619 
GetRegisterMask()620   uint32_t GetRegisterMask() const {
621     return register_mask_;
622   }
623 
RegisterContainsObject(uint32_t reg_id)624   bool RegisterContainsObject(uint32_t reg_id) {
625     return RegisterSet::Contains(register_mask_, reg_id);
626   }
627 
AddLiveRegister(Location location)628   void AddLiveRegister(Location location) {
629     live_registers_.Add(location);
630   }
631 
GetStackMask()632   BitVector* GetStackMask() const {
633     return stack_mask_;
634   }
635 
GetLiveRegisters()636   RegisterSet* GetLiveRegisters() {
637     return &live_registers_;
638   }
639 
GetNumberOfLiveRegisters()640   size_t GetNumberOfLiveRegisters() const {
641     return live_registers_.GetNumberOfRegisters();
642   }
643 
OutputUsesSameAs(uint32_t input_index)644   bool OutputUsesSameAs(uint32_t input_index) const {
645     return (input_index == 0)
646         && output_.IsUnallocated()
647         && (output_.GetPolicy() == Location::kSameAsFirstInput);
648   }
649 
IsFixedInput(uint32_t input_index)650   bool IsFixedInput(uint32_t input_index) const {
651     Location input = inputs_[input_index];
652     return input.IsRegister()
653         || input.IsFpuRegister()
654         || input.IsPair()
655         || input.IsStackSlot()
656         || input.IsDoubleStackSlot();
657   }
658 
OutputCanOverlapWithInputs()659   bool OutputCanOverlapWithInputs() const {
660     return output_overlaps_ == Location::kOutputOverlap;
661   }
662 
Intrinsified()663   bool Intrinsified() const {
664     return intrinsified_;
665   }
666 
667  private:
668   ArenaVector<Location> inputs_;
669   ArenaVector<Location> temps_;
670   const CallKind call_kind_;
671   // Whether these are locations for an intrinsified call.
672   const bool intrinsified_;
673   // Whether the slow path has default or custom calling convention.
674   bool has_custom_slow_path_calling_convention_;
675   // Whether the output overlaps with any of the inputs. If it overlaps, then it cannot
676   // share the same register as the inputs.
677   Location::OutputOverlap output_overlaps_;
678   Location output_;
679 
680   // Mask of objects that live in the stack.
681   BitVector* stack_mask_;
682 
683   // Mask of objects that live in register.
684   uint32_t register_mask_;
685 
686   // Registers that are in use at this position.
687   RegisterSet live_registers_;
688 
689   // Custom slow path caller saves. Valid only if indicated by slow_path_calling_convention_.
690   RegisterSet custom_slow_path_caller_saves_;
691 
692   friend class RegisterAllocatorTest;
693   DISALLOW_COPY_AND_ASSIGN(LocationSummary);
694 };
695 
696 }  // namespace art
697 
698 #endif  // ART_COMPILER_OPTIMIZING_LOCATIONS_H_
699