locations.h revision 9cf35523764d829ae0470dae2d5dd99be469c841
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/bit_field.h" 21#include "utils/allocation.h" 22#include "utils/growable_array.h" 23#include "utils/managed_register.h" 24 25namespace art { 26 27class HInstruction; 28 29/** 30 * A Location is an abstraction over the potential location 31 * of an instruction. It could be in register or stack. 32 */ 33class Location : public ValueObject { 34 public: 35 enum Kind { 36 kInvalid = 0, 37 kStackSlot = 1, // Word size slot. 38 kDoubleStackSlot = 2, // 64bit stack slot. 39 kRegister = 3, 40 // On 32bits architectures, quick can pass a long where the 41 // low bits are in the last parameter register, and the high 42 // bits are in a stack slot. The kQuickParameter kind is for 43 // handling this special case. 44 kQuickParameter = 4, 45 46 // Unallocated location represents a location that is not fixed and can be 47 // allocated by a register allocator. Each unallocated location has 48 // a policy that specifies what kind of location is suitable. Payload 49 // contains register allocation policy. 50 kUnallocated = 5, 51 }; 52 53 Location() : value_(kInvalid) { 54 DCHECK(!IsValid()); 55 } 56 57 Location(const Location& other) : ValueObject(), value_(other.value_) {} 58 59 Location& operator=(const Location& other) { 60 value_ = other.value_; 61 return *this; 62 } 63 64 bool IsValid() const { 65 return value_ != kInvalid; 66 } 67 68 bool IsInvalid() const { 69 return !IsValid(); 70 } 71 72 bool IsConstant() const { 73 // TODO: support constants. 74 return false; 75 } 76 77 // Empty location. Used if there the location should be ignored. 78 static Location NoLocation() { 79 return Location(); 80 } 81 82 // Register locations. 83 static Location RegisterLocation(ManagedRegister reg) { 84 return Location(kRegister, reg.RegId()); 85 } 86 87 bool IsRegister() const { 88 return GetKind() == kRegister; 89 } 90 91 ManagedRegister reg() const { 92 DCHECK(IsRegister()); 93 return static_cast<ManagedRegister>(GetPayload()); 94 } 95 96 static uword EncodeStackIndex(intptr_t stack_index) { 97 DCHECK(-kStackIndexBias <= stack_index); 98 DCHECK(stack_index < kStackIndexBias); 99 return static_cast<uword>(kStackIndexBias + stack_index); 100 } 101 102 static Location StackSlot(intptr_t stack_index) { 103 uword payload = EncodeStackIndex(stack_index); 104 Location loc(kStackSlot, payload); 105 // Ensure that sign is preserved. 106 DCHECK_EQ(loc.GetStackIndex(), stack_index); 107 return loc; 108 } 109 110 bool IsStackSlot() const { 111 return GetKind() == kStackSlot; 112 } 113 114 static Location DoubleStackSlot(intptr_t stack_index) { 115 uword payload = EncodeStackIndex(stack_index); 116 Location loc(kDoubleStackSlot, payload); 117 // Ensure that sign is preserved. 118 DCHECK_EQ(loc.GetStackIndex(), stack_index); 119 return loc; 120 } 121 122 bool IsDoubleStackSlot() const { 123 return GetKind() == kDoubleStackSlot; 124 } 125 126 intptr_t GetStackIndex() const { 127 DCHECK(IsStackSlot() || IsDoubleStackSlot()); 128 // Decode stack index manually to preserve sign. 129 return GetPayload() - kStackIndexBias; 130 } 131 132 intptr_t GetHighStackIndex(uintptr_t word_size) const { 133 DCHECK(IsDoubleStackSlot()); 134 // Decode stack index manually to preserve sign. 135 return GetPayload() - kStackIndexBias + word_size; 136 } 137 138 static Location QuickParameter(uint32_t parameter_index) { 139 return Location(kQuickParameter, parameter_index); 140 } 141 142 uint32_t GetQuickParameterIndex() const { 143 DCHECK(IsQuickParameter()); 144 return GetPayload(); 145 } 146 147 bool IsQuickParameter() const { 148 return GetKind() == kQuickParameter; 149 } 150 151 arm::ArmManagedRegister AsArm() const; 152 x86::X86ManagedRegister AsX86() const; 153 x86_64::X86_64ManagedRegister AsX86_64() const; 154 155 Kind GetKind() const { 156 return KindField::Decode(value_); 157 } 158 159 bool Equals(Location other) const { 160 return value_ == other.value_; 161 } 162 163 const char* DebugString() const { 164 switch (GetKind()) { 165 case kInvalid: return "?"; 166 case kRegister: return "R"; 167 case kStackSlot: return "S"; 168 case kDoubleStackSlot: return "DS"; 169 case kQuickParameter: return "Q"; 170 case kUnallocated: return "U"; 171 } 172 return "?"; 173 } 174 175 // Unallocated locations. 176 enum Policy { 177 kAny, 178 kRequiresRegister, 179 kSameAsFirstInput, 180 }; 181 182 bool IsUnallocated() const { 183 return GetKind() == kUnallocated; 184 } 185 186 static Location UnallocatedLocation(Policy policy) { 187 return Location(kUnallocated, PolicyField::Encode(policy)); 188 } 189 190 // Any free register is suitable to replace this unallocated location. 191 static Location Any() { 192 return UnallocatedLocation(kAny); 193 } 194 195 static Location RequiresRegister() { 196 return UnallocatedLocation(kRequiresRegister); 197 } 198 199 // The location of the first input to the instruction will be 200 // used to replace this unallocated location. 201 static Location SameAsFirstInput() { 202 return UnallocatedLocation(kSameAsFirstInput); 203 } 204 205 Policy GetPolicy() const { 206 DCHECK(IsUnallocated()); 207 return PolicyField::Decode(GetPayload()); 208 } 209 210 uword GetEncoding() const { 211 return GetPayload(); 212 } 213 214 private: 215 // Number of bits required to encode Kind value. 216 static constexpr uint32_t kBitsForKind = 4; 217 static constexpr uint32_t kBitsForPayload = kWordSize * kBitsPerByte - kBitsForKind; 218 219 explicit Location(uword value) : value_(value) {} 220 221 Location(Kind kind, uword payload) 222 : value_(KindField::Encode(kind) | PayloadField::Encode(payload)) {} 223 224 uword GetPayload() const { 225 return PayloadField::Decode(value_); 226 } 227 228 typedef BitField<Kind, 0, kBitsForKind> KindField; 229 typedef BitField<uword, kBitsForKind, kBitsForPayload> PayloadField; 230 231 // Layout for kUnallocated locations payload. 232 typedef BitField<Policy, 0, 3> PolicyField; 233 234 // Layout for stack slots. 235 static const intptr_t kStackIndexBias = 236 static_cast<intptr_t>(1) << (kBitsForPayload - 1); 237 238 // Location either contains kind and payload fields or a tagged handle for 239 // a constant locations. Values of enumeration Kind are selected in such a 240 // way that none of them can be interpreted as a kConstant tag. 241 uword value_; 242}; 243 244/** 245 * The code generator computes LocationSummary for each instruction so that 246 * the instruction itself knows what code to generate: where to find the inputs 247 * and where to place the result. 248 * 249 * The intent is to have the code for generating the instruction independent of 250 * register allocation. A register allocator just has to provide a LocationSummary. 251 */ 252class LocationSummary : public ArenaObject { 253 public: 254 explicit LocationSummary(HInstruction* instruction); 255 256 void SetInAt(uint32_t at, Location location) { 257 inputs_.Put(at, location); 258 } 259 260 Location InAt(uint32_t at) const { 261 return inputs_.Get(at); 262 } 263 264 size_t GetInputCount() const { 265 return inputs_.Size(); 266 } 267 268 void SetOut(Location location) { 269 output_ = Location(location); 270 } 271 272 void AddTemp(Location location) { 273 temps_.Add(location); 274 } 275 276 Location GetTemp(uint32_t at) const { 277 return temps_.Get(at); 278 } 279 280 void SetTempAt(uint32_t at, Location location) { 281 temps_.Put(at, location); 282 } 283 284 size_t GetTempCount() const { 285 return temps_.Size(); 286 } 287 288 Location Out() const { return output_; } 289 290 private: 291 GrowableArray<Location> inputs_; 292 GrowableArray<Location> temps_; 293 Location output_; 294 295 DISALLOW_COPY_AND_ASSIGN(LocationSummary); 296}; 297 298} // namespace art 299 300#endif // ART_COMPILER_OPTIMIZING_LOCATIONS_H_ 301