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