1 /* 2 * Copyright (C) 2011 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 /* This file contains register alloction support. */ 18 19 #include "dex/compiler_ir.h" 20 #include "dex/compiler_internals.h" 21 #include "mir_to_lir-inl.h" 22 23 namespace art { 24 25 /* 26 * Free all allocated temps in the temp pools. Note that this does 27 * not affect the "liveness" of a temp register, which will stay 28 * live until it is either explicitly killed or reallocated. 29 */ 30 void Mir2Lir::ResetRegPool() { 31 for (int i = 0; i < reg_pool_->num_core_regs; i++) { 32 if (reg_pool_->core_regs[i].is_temp) 33 reg_pool_->core_regs[i].in_use = false; 34 } 35 for (int i = 0; i < reg_pool_->num_fp_regs; i++) { 36 if (reg_pool_->FPRegs[i].is_temp) 37 reg_pool_->FPRegs[i].in_use = false; 38 } 39 // Reset temp tracking sanity check. 40 if (kIsDebugBuild) { 41 live_sreg_ = INVALID_SREG; 42 } 43 } 44 45 /* 46 * Set up temp & preserved register pools specialized by target. 47 * Note: num_regs may be zero. 48 */ 49 void Mir2Lir::CompilerInitPool(RegisterInfo* regs, int* reg_nums, int num) { 50 for (int i = 0; i < num; i++) { 51 regs[i].reg = reg_nums[i]; 52 regs[i].in_use = false; 53 regs[i].is_temp = false; 54 regs[i].pair = false; 55 regs[i].live = false; 56 regs[i].dirty = false; 57 regs[i].s_reg = INVALID_SREG; 58 } 59 } 60 61 void Mir2Lir::DumpRegPool(RegisterInfo* p, int num_regs) { 62 LOG(INFO) << "================================================"; 63 for (int i = 0; i < num_regs; i++) { 64 LOG(INFO) << StringPrintf( 65 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x", 66 p[i].reg, p[i].is_temp, p[i].in_use, p[i].pair, p[i].partner, 67 p[i].live, p[i].dirty, p[i].s_reg, reinterpret_cast<uintptr_t>(p[i].def_start), 68 reinterpret_cast<uintptr_t>(p[i].def_end)); 69 } 70 LOG(INFO) << "================================================"; 71 } 72 73 void Mir2Lir::DumpCoreRegPool() { 74 DumpRegPool(reg_pool_->core_regs, reg_pool_->num_core_regs); 75 } 76 77 void Mir2Lir::DumpFpRegPool() { 78 DumpRegPool(reg_pool_->FPRegs, reg_pool_->num_fp_regs); 79 } 80 81 void Mir2Lir::ClobberSRegBody(RegisterInfo* p, int num_regs, int s_reg) { 82 for (int i = 0; i< num_regs; i++) { 83 if (p[i].s_reg == s_reg) { 84 if (p[i].is_temp) { 85 p[i].live = false; 86 } 87 p[i].def_start = NULL; 88 p[i].def_end = NULL; 89 } 90 } 91 } 92 93 /* 94 * Break the association between a Dalvik vreg and a physical temp register of either register 95 * class. 96 * TODO: Ideally, the public version of this code should not exist. Besides its local usage 97 * in the register utilities, is is also used by code gen routines to work around a deficiency in 98 * local register allocation, which fails to distinguish between the "in" and "out" identities 99 * of Dalvik vregs. This can result in useless register copies when the same Dalvik vreg 100 * is used both as the source and destination register of an operation in which the type 101 * changes (for example: INT_TO_FLOAT v1, v1). Revisit when improved register allocation is 102 * addressed. 103 */ 104 void Mir2Lir::ClobberSReg(int s_reg) { 105 /* Reset live temp tracking sanity checker */ 106 if (kIsDebugBuild) { 107 if (s_reg == live_sreg_) { 108 live_sreg_ = INVALID_SREG; 109 } 110 } 111 ClobberSRegBody(reg_pool_->core_regs, reg_pool_->num_core_regs, s_reg); 112 ClobberSRegBody(reg_pool_->FPRegs, reg_pool_->num_fp_regs, s_reg); 113 } 114 115 /* 116 * SSA names associated with the initial definitions of Dalvik 117 * registers are the same as the Dalvik register number (and 118 * thus take the same position in the promotion_map. However, 119 * the special Method* and compiler temp resisters use negative 120 * v_reg numbers to distinguish them and can have an arbitrary 121 * ssa name (above the last original Dalvik register). This function 122 * maps SSA names to positions in the promotion_map array. 123 */ 124 int Mir2Lir::SRegToPMap(int s_reg) { 125 DCHECK_LT(s_reg, mir_graph_->GetNumSSARegs()); 126 DCHECK_GE(s_reg, 0); 127 int v_reg = mir_graph_->SRegToVReg(s_reg); 128 if (v_reg >= 0) { 129 DCHECK_LT(v_reg, cu_->num_dalvik_registers); 130 return v_reg; 131 } else { 132 int pos = std::abs(v_reg) - std::abs(SSA_METHOD_BASEREG); 133 DCHECK_LE(pos, cu_->num_compiler_temps); 134 return cu_->num_dalvik_registers + pos; 135 } 136 } 137 138 void Mir2Lir::RecordCorePromotion(int reg, int s_reg) { 139 int p_map_idx = SRegToPMap(s_reg); 140 int v_reg = mir_graph_->SRegToVReg(s_reg); 141 GetRegInfo(reg)->in_use = true; 142 core_spill_mask_ |= (1 << reg); 143 // Include reg for later sort 144 core_vmap_table_.push_back(reg << VREG_NUM_WIDTH | (v_reg & ((1 << VREG_NUM_WIDTH) - 1))); 145 num_core_spills_++; 146 promotion_map_[p_map_idx].core_location = kLocPhysReg; 147 promotion_map_[p_map_idx].core_reg = reg; 148 } 149 150 /* Reserve a callee-save register. Return -1 if none available */ 151 int Mir2Lir::AllocPreservedCoreReg(int s_reg) { 152 int res = -1; 153 RegisterInfo* core_regs = reg_pool_->core_regs; 154 for (int i = 0; i < reg_pool_->num_core_regs; i++) { 155 if (!core_regs[i].is_temp && !core_regs[i].in_use) { 156 res = core_regs[i].reg; 157 RecordCorePromotion(res, s_reg); 158 break; 159 } 160 } 161 return res; 162 } 163 164 void Mir2Lir::RecordFpPromotion(int reg, int s_reg) { 165 int p_map_idx = SRegToPMap(s_reg); 166 int v_reg = mir_graph_->SRegToVReg(s_reg); 167 GetRegInfo(reg)->in_use = true; 168 MarkPreservedSingle(v_reg, reg); 169 promotion_map_[p_map_idx].fp_location = kLocPhysReg; 170 promotion_map_[p_map_idx].FpReg = reg; 171 } 172 173 /* 174 * Reserve a callee-save fp single register. Try to fullfill request for 175 * even/odd allocation, but go ahead and allocate anything if not 176 * available. If nothing's available, return -1. 177 */ 178 int Mir2Lir::AllocPreservedSingle(int s_reg, bool even) { 179 int res = -1; 180 RegisterInfo* FPRegs = reg_pool_->FPRegs; 181 for (int i = 0; i < reg_pool_->num_fp_regs; i++) { 182 if (!FPRegs[i].is_temp && !FPRegs[i].in_use && 183 ((FPRegs[i].reg & 0x1) == 0) == even) { 184 res = FPRegs[i].reg; 185 RecordFpPromotion(res, s_reg); 186 break; 187 } 188 } 189 return res; 190 } 191 192 /* 193 * Somewhat messy code here. We want to allocate a pair of contiguous 194 * physical single-precision floating point registers starting with 195 * an even numbered reg. It is possible that the paired s_reg (s_reg+1) 196 * has already been allocated - try to fit if possible. Fail to 197 * allocate if we can't meet the requirements for the pair of 198 * s_reg<=sX[even] & (s_reg+1)<= sX+1. 199 */ 200 int Mir2Lir::AllocPreservedDouble(int s_reg) { 201 int res = -1; // Assume failure 202 int v_reg = mir_graph_->SRegToVReg(s_reg); 203 int p_map_idx = SRegToPMap(s_reg); 204 if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) { 205 // Upper reg is already allocated. Can we fit? 206 int high_reg = promotion_map_[p_map_idx+1].FpReg; 207 if ((high_reg & 1) == 0) { 208 // High reg is even - fail. 209 return res; 210 } 211 // Is the low reg of the pair free? 212 RegisterInfo* p = GetRegInfo(high_reg-1); 213 if (p->in_use || p->is_temp) { 214 // Already allocated or not preserved - fail. 215 return res; 216 } 217 // OK - good to go. 218 res = p->reg; 219 p->in_use = true; 220 DCHECK_EQ((res & 1), 0); 221 MarkPreservedSingle(v_reg, res); 222 } else { 223 RegisterInfo* FPRegs = reg_pool_->FPRegs; 224 for (int i = 0; i < reg_pool_->num_fp_regs; i++) { 225 if (!FPRegs[i].is_temp && !FPRegs[i].in_use && 226 ((FPRegs[i].reg & 0x1) == 0x0) && 227 !FPRegs[i+1].is_temp && !FPRegs[i+1].in_use && 228 ((FPRegs[i+1].reg & 0x1) == 0x1) && 229 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) { 230 res = FPRegs[i].reg; 231 FPRegs[i].in_use = true; 232 MarkPreservedSingle(v_reg, res); 233 FPRegs[i+1].in_use = true; 234 DCHECK_EQ(res + 1, FPRegs[i+1].reg); 235 MarkPreservedSingle(v_reg+1, res+1); 236 break; 237 } 238 } 239 } 240 if (res != -1) { 241 promotion_map_[p_map_idx].fp_location = kLocPhysReg; 242 promotion_map_[p_map_idx].FpReg = res; 243 promotion_map_[p_map_idx+1].fp_location = kLocPhysReg; 244 promotion_map_[p_map_idx+1].FpReg = res + 1; 245 } 246 return res; 247 } 248 249 250 /* 251 * Reserve a callee-save fp register. If this register can be used 252 * as the first of a double, attempt to allocate an even pair of fp 253 * single regs (but if can't still attempt to allocate a single, preferring 254 * first to allocate an odd register. 255 */ 256 int Mir2Lir::AllocPreservedFPReg(int s_reg, bool double_start) { 257 int res = -1; 258 if (double_start) { 259 res = AllocPreservedDouble(s_reg); 260 } 261 if (res == -1) { 262 res = AllocPreservedSingle(s_reg, false /* try odd # */); 263 } 264 if (res == -1) 265 res = AllocPreservedSingle(s_reg, true /* try even # */); 266 return res; 267 } 268 269 int Mir2Lir::AllocTempBody(RegisterInfo* p, int num_regs, int* next_temp, 270 bool required) { 271 int next = *next_temp; 272 for (int i = 0; i< num_regs; i++) { 273 if (next >= num_regs) 274 next = 0; 275 if (p[next].is_temp && !p[next].in_use && !p[next].live) { 276 Clobber(p[next].reg); 277 p[next].in_use = true; 278 p[next].pair = false; 279 *next_temp = next + 1; 280 return p[next].reg; 281 } 282 next++; 283 } 284 next = *next_temp; 285 for (int i = 0; i< num_regs; i++) { 286 if (next >= num_regs) 287 next = 0; 288 if (p[next].is_temp && !p[next].in_use) { 289 Clobber(p[next].reg); 290 p[next].in_use = true; 291 p[next].pair = false; 292 *next_temp = next + 1; 293 return p[next].reg; 294 } 295 next++; 296 } 297 if (required) { 298 CodegenDump(); 299 DumpRegPool(reg_pool_->core_regs, 300 reg_pool_->num_core_regs); 301 LOG(FATAL) << "No free temp registers"; 302 } 303 return -1; // No register available 304 } 305 306 // REDO: too many assumptions. 307 int Mir2Lir::AllocTempDouble() { 308 RegisterInfo* p = reg_pool_->FPRegs; 309 int num_regs = reg_pool_->num_fp_regs; 310 /* Start looking at an even reg */ 311 int next = reg_pool_->next_fp_reg & ~0x1; 312 313 // First try to avoid allocating live registers 314 for (int i = 0; i < num_regs; i+=2) { 315 if (next >= num_regs) 316 next = 0; 317 if ((p[next].is_temp && !p[next].in_use && !p[next].live) && 318 (p[next+1].is_temp && !p[next+1].in_use && !p[next+1].live)) { 319 Clobber(p[next].reg); 320 Clobber(p[next+1].reg); 321 p[next].in_use = true; 322 p[next+1].in_use = true; 323 DCHECK_EQ((p[next].reg+1), p[next+1].reg); 324 DCHECK_EQ((p[next].reg & 0x1), 0); 325 reg_pool_->next_fp_reg = next + 2; 326 if (reg_pool_->next_fp_reg >= num_regs) { 327 reg_pool_->next_fp_reg = 0; 328 } 329 return p[next].reg; 330 } 331 next += 2; 332 } 333 next = reg_pool_->next_fp_reg & ~0x1; 334 335 // No choice - find a pair and kill it. 336 for (int i = 0; i < num_regs; i+=2) { 337 if (next >= num_regs) 338 next = 0; 339 if (p[next].is_temp && !p[next].in_use && p[next+1].is_temp && 340 !p[next+1].in_use) { 341 Clobber(p[next].reg); 342 Clobber(p[next+1].reg); 343 p[next].in_use = true; 344 p[next+1].in_use = true; 345 DCHECK_EQ((p[next].reg+1), p[next+1].reg); 346 DCHECK_EQ((p[next].reg & 0x1), 0); 347 reg_pool_->next_fp_reg = next + 2; 348 if (reg_pool_->next_fp_reg >= num_regs) { 349 reg_pool_->next_fp_reg = 0; 350 } 351 return p[next].reg; 352 } 353 next += 2; 354 } 355 LOG(FATAL) << "No free temp registers (pair)"; 356 return -1; 357 } 358 359 /* Return a temp if one is available, -1 otherwise */ 360 int Mir2Lir::AllocFreeTemp() { 361 return AllocTempBody(reg_pool_->core_regs, 362 reg_pool_->num_core_regs, 363 ®_pool_->next_core_reg, true); 364 } 365 366 int Mir2Lir::AllocTemp() { 367 return AllocTempBody(reg_pool_->core_regs, 368 reg_pool_->num_core_regs, 369 ®_pool_->next_core_reg, true); 370 } 371 372 int Mir2Lir::AllocTempFloat() { 373 return AllocTempBody(reg_pool_->FPRegs, 374 reg_pool_->num_fp_regs, 375 ®_pool_->next_fp_reg, true); 376 } 377 378 Mir2Lir::RegisterInfo* Mir2Lir::AllocLiveBody(RegisterInfo* p, int num_regs, int s_reg) { 379 if (s_reg == -1) 380 return NULL; 381 for (int i = 0; i < num_regs; i++) { 382 if (p[i].live && (p[i].s_reg == s_reg)) { 383 if (p[i].is_temp) 384 p[i].in_use = true; 385 return &p[i]; 386 } 387 } 388 return NULL; 389 } 390 391 Mir2Lir::RegisterInfo* Mir2Lir::AllocLive(int s_reg, int reg_class) { 392 RegisterInfo* res = NULL; 393 switch (reg_class) { 394 case kAnyReg: 395 res = AllocLiveBody(reg_pool_->FPRegs, 396 reg_pool_->num_fp_regs, s_reg); 397 if (res) 398 break; 399 /* Intentional fallthrough */ 400 case kCoreReg: 401 res = AllocLiveBody(reg_pool_->core_regs, 402 reg_pool_->num_core_regs, s_reg); 403 break; 404 case kFPReg: 405 res = AllocLiveBody(reg_pool_->FPRegs, 406 reg_pool_->num_fp_regs, s_reg); 407 break; 408 default: 409 LOG(FATAL) << "Invalid register type"; 410 } 411 return res; 412 } 413 414 void Mir2Lir::FreeTemp(int reg) { 415 RegisterInfo* p = reg_pool_->core_regs; 416 int num_regs = reg_pool_->num_core_regs; 417 for (int i = 0; i< num_regs; i++) { 418 if (p[i].reg == reg) { 419 if (p[i].is_temp) { 420 p[i].in_use = false; 421 } 422 p[i].pair = false; 423 return; 424 } 425 } 426 p = reg_pool_->FPRegs; 427 num_regs = reg_pool_->num_fp_regs; 428 for (int i = 0; i< num_regs; i++) { 429 if (p[i].reg == reg) { 430 if (p[i].is_temp) { 431 p[i].in_use = false; 432 } 433 p[i].pair = false; 434 return; 435 } 436 } 437 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg; 438 } 439 440 Mir2Lir::RegisterInfo* Mir2Lir::IsLive(int reg) { 441 RegisterInfo* p = reg_pool_->core_regs; 442 int num_regs = reg_pool_->num_core_regs; 443 for (int i = 0; i< num_regs; i++) { 444 if (p[i].reg == reg) { 445 return p[i].live ? &p[i] : NULL; 446 } 447 } 448 p = reg_pool_->FPRegs; 449 num_regs = reg_pool_->num_fp_regs; 450 for (int i = 0; i< num_regs; i++) { 451 if (p[i].reg == reg) { 452 return p[i].live ? &p[i] : NULL; 453 } 454 } 455 return NULL; 456 } 457 458 Mir2Lir::RegisterInfo* Mir2Lir::IsTemp(int reg) { 459 RegisterInfo* p = GetRegInfo(reg); 460 return (p->is_temp) ? p : NULL; 461 } 462 463 Mir2Lir::RegisterInfo* Mir2Lir::IsPromoted(int reg) { 464 RegisterInfo* p = GetRegInfo(reg); 465 return (p->is_temp) ? NULL : p; 466 } 467 468 bool Mir2Lir::IsDirty(int reg) { 469 RegisterInfo* p = GetRegInfo(reg); 470 return p->dirty; 471 } 472 473 /* 474 * Similar to AllocTemp(), but forces the allocation of a specific 475 * register. No check is made to see if the register was previously 476 * allocated. Use with caution. 477 */ 478 void Mir2Lir::LockTemp(int reg) { 479 RegisterInfo* p = reg_pool_->core_regs; 480 int num_regs = reg_pool_->num_core_regs; 481 for (int i = 0; i< num_regs; i++) { 482 if (p[i].reg == reg) { 483 DCHECK(p[i].is_temp); 484 p[i].in_use = true; 485 p[i].live = false; 486 return; 487 } 488 } 489 p = reg_pool_->FPRegs; 490 num_regs = reg_pool_->num_fp_regs; 491 for (int i = 0; i< num_regs; i++) { 492 if (p[i].reg == reg) { 493 DCHECK(p[i].is_temp); 494 p[i].in_use = true; 495 p[i].live = false; 496 return; 497 } 498 } 499 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg; 500 } 501 502 void Mir2Lir::ResetDef(int reg) { 503 ResetDefBody(GetRegInfo(reg)); 504 } 505 506 void Mir2Lir::NullifyRange(LIR *start, LIR *finish, int s_reg1, int s_reg2) { 507 if (start && finish) { 508 LIR *p; 509 DCHECK_EQ(s_reg1, s_reg2); 510 for (p = start; ; p = p->next) { 511 NopLIR(p); 512 if (p == finish) 513 break; 514 } 515 } 516 } 517 518 /* 519 * Mark the beginning and end LIR of a def sequence. Note that 520 * on entry start points to the LIR prior to the beginning of the 521 * sequence. 522 */ 523 void Mir2Lir::MarkDef(RegLocation rl, LIR *start, LIR *finish) { 524 DCHECK(!rl.wide); 525 DCHECK(start && start->next); 526 DCHECK(finish); 527 RegisterInfo* p = GetRegInfo(rl.low_reg); 528 p->def_start = start->next; 529 p->def_end = finish; 530 } 531 532 /* 533 * Mark the beginning and end LIR of a def sequence. Note that 534 * on entry start points to the LIR prior to the beginning of the 535 * sequence. 536 */ 537 void Mir2Lir::MarkDefWide(RegLocation rl, LIR *start, LIR *finish) { 538 DCHECK(rl.wide); 539 DCHECK(start && start->next); 540 DCHECK(finish); 541 RegisterInfo* p = GetRegInfo(rl.low_reg); 542 ResetDef(rl.high_reg); // Only track low of pair 543 p->def_start = start->next; 544 p->def_end = finish; 545 } 546 547 RegLocation Mir2Lir::WideToNarrow(RegLocation rl) { 548 DCHECK(rl.wide); 549 if (rl.location == kLocPhysReg) { 550 RegisterInfo* info_lo = GetRegInfo(rl.low_reg); 551 RegisterInfo* info_hi = GetRegInfo(rl.high_reg); 552 if (info_lo->is_temp) { 553 info_lo->pair = false; 554 info_lo->def_start = NULL; 555 info_lo->def_end = NULL; 556 } 557 if (info_hi->is_temp) { 558 info_hi->pair = false; 559 info_hi->def_start = NULL; 560 info_hi->def_end = NULL; 561 } 562 } 563 rl.wide = false; 564 return rl; 565 } 566 567 void Mir2Lir::ResetDefLoc(RegLocation rl) { 568 DCHECK(!rl.wide); 569 RegisterInfo* p = IsTemp(rl.low_reg); 570 if (p && !(cu_->disable_opt & (1 << kSuppressLoads))) { 571 DCHECK(!p->pair); 572 NullifyRange(p->def_start, p->def_end, p->s_reg, rl.s_reg_low); 573 } 574 ResetDef(rl.low_reg); 575 } 576 577 void Mir2Lir::ResetDefLocWide(RegLocation rl) { 578 DCHECK(rl.wide); 579 RegisterInfo* p_low = IsTemp(rl.low_reg); 580 RegisterInfo* p_high = IsTemp(rl.high_reg); 581 if (p_low && !(cu_->disable_opt & (1 << kSuppressLoads))) { 582 DCHECK(p_low->pair); 583 NullifyRange(p_low->def_start, p_low->def_end, p_low->s_reg, rl.s_reg_low); 584 } 585 if (p_high && !(cu_->disable_opt & (1 << kSuppressLoads))) { 586 DCHECK(p_high->pair); 587 } 588 ResetDef(rl.low_reg); 589 ResetDef(rl.high_reg); 590 } 591 592 void Mir2Lir::ResetDefTracking() { 593 for (int i = 0; i< reg_pool_->num_core_regs; i++) { 594 ResetDefBody(®_pool_->core_regs[i]); 595 } 596 for (int i = 0; i< reg_pool_->num_fp_regs; i++) { 597 ResetDefBody(®_pool_->FPRegs[i]); 598 } 599 } 600 601 void Mir2Lir::ClobberAllRegs() { 602 for (int i = 0; i< reg_pool_->num_core_regs; i++) { 603 ClobberBody(®_pool_->core_regs[i]); 604 } 605 for (int i = 0; i< reg_pool_->num_fp_regs; i++) { 606 ClobberBody(®_pool_->FPRegs[i]); 607 } 608 } 609 610 // Make sure nothing is live and dirty 611 void Mir2Lir::FlushAllRegsBody(RegisterInfo* info, int num_regs) { 612 for (int i = 0; i < num_regs; i++) { 613 if (info[i].live && info[i].dirty) { 614 if (info[i].pair) { 615 FlushRegWide(info[i].reg, info[i].partner); 616 } else { 617 FlushReg(info[i].reg); 618 } 619 } 620 } 621 } 622 623 void Mir2Lir::FlushAllRegs() { 624 FlushAllRegsBody(reg_pool_->core_regs, 625 reg_pool_->num_core_regs); 626 FlushAllRegsBody(reg_pool_->FPRegs, 627 reg_pool_->num_fp_regs); 628 ClobberAllRegs(); 629 } 630 631 632 // TUNING: rewrite all of this reg stuff. Probably use an attribute table 633 bool Mir2Lir::RegClassMatches(int reg_class, int reg) { 634 if (reg_class == kAnyReg) { 635 return true; 636 } else if (reg_class == kCoreReg) { 637 return !IsFpReg(reg); 638 } else { 639 return IsFpReg(reg); 640 } 641 } 642 643 void Mir2Lir::MarkLive(int reg, int s_reg) { 644 RegisterInfo* info = GetRegInfo(reg); 645 if ((info->reg == reg) && (info->s_reg == s_reg) && info->live) { 646 return; /* already live */ 647 } else if (s_reg != INVALID_SREG) { 648 ClobberSReg(s_reg); 649 if (info->is_temp) { 650 info->live = true; 651 } 652 } else { 653 /* Can't be live if no associated s_reg */ 654 DCHECK(info->is_temp); 655 info->live = false; 656 } 657 info->s_reg = s_reg; 658 } 659 660 void Mir2Lir::MarkTemp(int reg) { 661 RegisterInfo* info = GetRegInfo(reg); 662 info->is_temp = true; 663 } 664 665 void Mir2Lir::UnmarkTemp(int reg) { 666 RegisterInfo* info = GetRegInfo(reg); 667 info->is_temp = false; 668 } 669 670 void Mir2Lir::MarkPair(int low_reg, int high_reg) { 671 RegisterInfo* info_lo = GetRegInfo(low_reg); 672 RegisterInfo* info_hi = GetRegInfo(high_reg); 673 info_lo->pair = info_hi->pair = true; 674 info_lo->partner = high_reg; 675 info_hi->partner = low_reg; 676 } 677 678 void Mir2Lir::MarkClean(RegLocation loc) { 679 RegisterInfo* info = GetRegInfo(loc.low_reg); 680 info->dirty = false; 681 if (loc.wide) { 682 info = GetRegInfo(loc.high_reg); 683 info->dirty = false; 684 } 685 } 686 687 void Mir2Lir::MarkDirty(RegLocation loc) { 688 if (loc.home) { 689 // If already home, can't be dirty 690 return; 691 } 692 RegisterInfo* info = GetRegInfo(loc.low_reg); 693 info->dirty = true; 694 if (loc.wide) { 695 info = GetRegInfo(loc.high_reg); 696 info->dirty = true; 697 } 698 } 699 700 void Mir2Lir::MarkInUse(int reg) { 701 RegisterInfo* info = GetRegInfo(reg); 702 info->in_use = true; 703 } 704 705 void Mir2Lir::CopyRegInfo(int new_reg, int old_reg) { 706 RegisterInfo* new_info = GetRegInfo(new_reg); 707 RegisterInfo* old_info = GetRegInfo(old_reg); 708 // Target temp status must not change 709 bool is_temp = new_info->is_temp; 710 *new_info = *old_info; 711 // Restore target's temp status 712 new_info->is_temp = is_temp; 713 new_info->reg = new_reg; 714 } 715 716 bool Mir2Lir::CheckCorePoolSanity() { 717 for (static int i = 0; i < reg_pool_->num_core_regs; i++) { 718 if (reg_pool_->core_regs[i].pair) { 719 static int my_reg = reg_pool_->core_regs[i].reg; 720 static int my_sreg = reg_pool_->core_regs[i].s_reg; 721 static int partner_reg = reg_pool_->core_regs[i].partner; 722 static RegisterInfo* partner = GetRegInfo(partner_reg); 723 DCHECK(partner != NULL); 724 DCHECK(partner->pair); 725 DCHECK_EQ(my_reg, partner->partner); 726 static int partner_sreg = partner->s_reg; 727 if (my_sreg == INVALID_SREG) { 728 DCHECK_EQ(partner_sreg, INVALID_SREG); 729 } else { 730 int diff = my_sreg - partner_sreg; 731 DCHECK((diff == -1) || (diff == 1)); 732 } 733 } 734 if (!reg_pool_->core_regs[i].live) { 735 DCHECK(reg_pool_->core_regs[i].def_start == NULL); 736 DCHECK(reg_pool_->core_regs[i].def_end == NULL); 737 } 738 } 739 return true; 740 } 741 742 /* 743 * Return an updated location record with current in-register status. 744 * If the value lives in live temps, reflect that fact. No code 745 * is generated. If the live value is part of an older pair, 746 * clobber both low and high. 747 * TUNING: clobbering both is a bit heavy-handed, but the alternative 748 * is a bit complex when dealing with FP regs. Examine code to see 749 * if it's worthwhile trying to be more clever here. 750 */ 751 752 RegLocation Mir2Lir::UpdateLoc(RegLocation loc) { 753 DCHECK(!loc.wide); 754 DCHECK(CheckCorePoolSanity()); 755 if (loc.location != kLocPhysReg) { 756 DCHECK((loc.location == kLocDalvikFrame) || 757 (loc.location == kLocCompilerTemp)); 758 RegisterInfo* info_lo = AllocLive(loc.s_reg_low, kAnyReg); 759 if (info_lo) { 760 if (info_lo->pair) { 761 Clobber(info_lo->reg); 762 Clobber(info_lo->partner); 763 FreeTemp(info_lo->reg); 764 } else { 765 loc.low_reg = info_lo->reg; 766 loc.location = kLocPhysReg; 767 } 768 } 769 } 770 771 return loc; 772 } 773 774 /* see comments for update_loc */ 775 RegLocation Mir2Lir::UpdateLocWide(RegLocation loc) { 776 DCHECK(loc.wide); 777 DCHECK(CheckCorePoolSanity()); 778 if (loc.location != kLocPhysReg) { 779 DCHECK((loc.location == kLocDalvikFrame) || 780 (loc.location == kLocCompilerTemp)); 781 // Are the dalvik regs already live in physical registers? 782 RegisterInfo* info_lo = AllocLive(loc.s_reg_low, kAnyReg); 783 RegisterInfo* info_hi = AllocLive(GetSRegHi(loc.s_reg_low), kAnyReg); 784 bool match = true; 785 match = match && (info_lo != NULL); 786 match = match && (info_hi != NULL); 787 // Are they both core or both FP? 788 match = match && (IsFpReg(info_lo->reg) == IsFpReg(info_hi->reg)); 789 // If a pair of floating point singles, are they properly aligned? 790 if (match && IsFpReg(info_lo->reg)) { 791 match &= ((info_lo->reg & 0x1) == 0); 792 match &= ((info_hi->reg - info_lo->reg) == 1); 793 } 794 // If previously used as a pair, it is the same pair? 795 if (match && (info_lo->pair || info_hi->pair)) { 796 match = (info_lo->pair == info_hi->pair); 797 match &= ((info_lo->reg == info_hi->partner) && 798 (info_hi->reg == info_lo->partner)); 799 } 800 if (match) { 801 // Can reuse - update the register usage info 802 loc.low_reg = info_lo->reg; 803 loc.high_reg = info_hi->reg; 804 loc.location = kLocPhysReg; 805 MarkPair(loc.low_reg, loc.high_reg); 806 DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); 807 return loc; 808 } 809 // Can't easily reuse - clobber and free any overlaps 810 if (info_lo) { 811 Clobber(info_lo->reg); 812 FreeTemp(info_lo->reg); 813 if (info_lo->pair) 814 Clobber(info_lo->partner); 815 } 816 if (info_hi) { 817 Clobber(info_hi->reg); 818 FreeTemp(info_hi->reg); 819 if (info_hi->pair) 820 Clobber(info_hi->partner); 821 } 822 } 823 return loc; 824 } 825 826 827 /* For use in cases we don't know (or care) width */ 828 RegLocation Mir2Lir::UpdateRawLoc(RegLocation loc) { 829 if (loc.wide) 830 return UpdateLocWide(loc); 831 else 832 return UpdateLoc(loc); 833 } 834 835 RegLocation Mir2Lir::EvalLocWide(RegLocation loc, int reg_class, bool update) { 836 DCHECK(loc.wide); 837 int new_regs; 838 int low_reg; 839 int high_reg; 840 841 loc = UpdateLocWide(loc); 842 843 /* If already in registers, we can assume proper form. Right reg class? */ 844 if (loc.location == kLocPhysReg) { 845 DCHECK_EQ(IsFpReg(loc.low_reg), IsFpReg(loc.high_reg)); 846 DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); 847 if (!RegClassMatches(reg_class, loc.low_reg)) { 848 /* Wrong register class. Reallocate and copy */ 849 new_regs = AllocTypedTempPair(loc.fp, reg_class); 850 low_reg = new_regs & 0xff; 851 high_reg = (new_regs >> 8) & 0xff; 852 OpRegCopyWide(low_reg, high_reg, loc.low_reg, loc.high_reg); 853 CopyRegInfo(low_reg, loc.low_reg); 854 CopyRegInfo(high_reg, loc.high_reg); 855 Clobber(loc.low_reg); 856 Clobber(loc.high_reg); 857 loc.low_reg = low_reg; 858 loc.high_reg = high_reg; 859 MarkPair(loc.low_reg, loc.high_reg); 860 DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); 861 } 862 return loc; 863 } 864 865 DCHECK_NE(loc.s_reg_low, INVALID_SREG); 866 DCHECK_NE(GetSRegHi(loc.s_reg_low), INVALID_SREG); 867 868 new_regs = AllocTypedTempPair(loc.fp, reg_class); 869 loc.low_reg = new_regs & 0xff; 870 loc.high_reg = (new_regs >> 8) & 0xff; 871 872 MarkPair(loc.low_reg, loc.high_reg); 873 if (update) { 874 loc.location = kLocPhysReg; 875 MarkLive(loc.low_reg, loc.s_reg_low); 876 MarkLive(loc.high_reg, GetSRegHi(loc.s_reg_low)); 877 } 878 DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0)); 879 return loc; 880 } 881 882 RegLocation Mir2Lir::EvalLoc(RegLocation loc, int reg_class, bool update) { 883 int new_reg; 884 885 if (loc.wide) 886 return EvalLocWide(loc, reg_class, update); 887 888 loc = UpdateLoc(loc); 889 890 if (loc.location == kLocPhysReg) { 891 if (!RegClassMatches(reg_class, loc.low_reg)) { 892 /* Wrong register class. Realloc, copy and transfer ownership */ 893 new_reg = AllocTypedTemp(loc.fp, reg_class); 894 OpRegCopy(new_reg, loc.low_reg); 895 CopyRegInfo(new_reg, loc.low_reg); 896 Clobber(loc.low_reg); 897 loc.low_reg = new_reg; 898 } 899 return loc; 900 } 901 902 DCHECK_NE(loc.s_reg_low, INVALID_SREG); 903 904 new_reg = AllocTypedTemp(loc.fp, reg_class); 905 loc.low_reg = new_reg; 906 907 if (update) { 908 loc.location = kLocPhysReg; 909 MarkLive(loc.low_reg, loc.s_reg_low); 910 } 911 return loc; 912 } 913 914 /* USE SSA names to count references of base Dalvik v_regs. */ 915 void Mir2Lir::CountRefs(RefCounts* core_counts, RefCounts* fp_counts) { 916 for (int i = 0; i < mir_graph_->GetNumSSARegs(); i++) { 917 RegLocation loc = mir_graph_->reg_location_[i]; 918 RefCounts* counts = loc.fp ? fp_counts : core_counts; 919 int p_map_idx = SRegToPMap(loc.s_reg_low); 920 // Don't count easily regenerated immediates 921 if (loc.fp || !IsInexpensiveConstant(loc)) { 922 counts[p_map_idx].count += mir_graph_->GetUseCount(i); 923 } 924 if (loc.wide && loc.fp && !loc.high_word) { 925 counts[p_map_idx].double_start = true; 926 } 927 } 928 } 929 930 /* qsort callback function, sort descending */ 931 static int SortCounts(const void *val1, const void *val2) { 932 const Mir2Lir::RefCounts* op1 = reinterpret_cast<const Mir2Lir::RefCounts*>(val1); 933 const Mir2Lir::RefCounts* op2 = reinterpret_cast<const Mir2Lir::RefCounts*>(val2); 934 // Note that we fall back to sorting on reg so we get stable output 935 // on differing qsort implementations (such as on host and target or 936 // between local host and build servers). 937 return (op1->count == op2->count) 938 ? (op1->s_reg - op2->s_reg) 939 : (op1->count < op2->count ? 1 : -1); 940 } 941 942 void Mir2Lir::DumpCounts(const RefCounts* arr, int size, const char* msg) { 943 LOG(INFO) << msg; 944 for (int i = 0; i < size; i++) { 945 LOG(INFO) << "s_reg[" << arr[i].s_reg << "]: " << arr[i].count; 946 } 947 } 948 949 /* 950 * Note: some portions of this code required even if the kPromoteRegs 951 * optimization is disabled. 952 */ 953 void Mir2Lir::DoPromotion() { 954 int reg_bias = cu_->num_compiler_temps + 1; 955 int dalvik_regs = cu_->num_dalvik_registers; 956 int num_regs = dalvik_regs + reg_bias; 957 const int promotion_threshold = 1; 958 959 // Allow target code to add any special registers 960 AdjustSpillMask(); 961 962 /* 963 * Simple register promotion. Just do a static count of the uses 964 * of Dalvik registers. Note that we examine the SSA names, but 965 * count based on original Dalvik register name. Count refs 966 * separately based on type in order to give allocation 967 * preference to fp doubles - which must be allocated sequential 968 * physical single fp registers started with an even-numbered 969 * reg. 970 * TUNING: replace with linear scan once we have the ability 971 * to describe register live ranges for GC. 972 */ 973 RefCounts *core_regs = 974 static_cast<RefCounts*>(arena_->Alloc(sizeof(RefCounts) * num_regs, 975 ArenaAllocator::kAllocRegAlloc)); 976 RefCounts *FpRegs = 977 static_cast<RefCounts *>(arena_->Alloc(sizeof(RefCounts) * num_regs, 978 ArenaAllocator::kAllocRegAlloc)); 979 // Set ssa names for original Dalvik registers 980 for (int i = 0; i < dalvik_regs; i++) { 981 core_regs[i].s_reg = FpRegs[i].s_reg = i; 982 } 983 // Set ssa name for Method* 984 core_regs[dalvik_regs].s_reg = mir_graph_->GetMethodSReg(); 985 FpRegs[dalvik_regs].s_reg = mir_graph_->GetMethodSReg(); // For consistecy 986 // Set ssa names for compiler_temps 987 for (int i = 1; i <= cu_->num_compiler_temps; i++) { 988 CompilerTemp* ct = mir_graph_->compiler_temps_.Get(i); 989 core_regs[dalvik_regs + i].s_reg = ct->s_reg; 990 FpRegs[dalvik_regs + i].s_reg = ct->s_reg; 991 } 992 993 // Sum use counts of SSA regs by original Dalvik vreg. 994 CountRefs(core_regs, FpRegs); 995 996 /* 997 * Ideally, we'd allocate doubles starting with an even-numbered 998 * register. Bias the counts to try to allocate any vreg that's 999 * used as the start of a pair first. 1000 */ 1001 for (int i = 0; i < num_regs; i++) { 1002 if (FpRegs[i].double_start) { 1003 FpRegs[i].count *= 2; 1004 } 1005 } 1006 1007 // Sort the count arrays 1008 qsort(core_regs, num_regs, sizeof(RefCounts), SortCounts); 1009 qsort(FpRegs, num_regs, sizeof(RefCounts), SortCounts); 1010 1011 if (cu_->verbose) { 1012 DumpCounts(core_regs, num_regs, "Core regs after sort"); 1013 DumpCounts(FpRegs, num_regs, "Fp regs after sort"); 1014 } 1015 1016 if (!(cu_->disable_opt & (1 << kPromoteRegs))) { 1017 // Promote FpRegs 1018 for (int i = 0; (i < num_regs) && (FpRegs[i].count >= promotion_threshold); i++) { 1019 int p_map_idx = SRegToPMap(FpRegs[i].s_reg); 1020 if (promotion_map_[p_map_idx].fp_location != kLocPhysReg) { 1021 int reg = AllocPreservedFPReg(FpRegs[i].s_reg, 1022 FpRegs[i].double_start); 1023 if (reg < 0) { 1024 break; // No more left 1025 } 1026 } 1027 } 1028 1029 // Promote core regs 1030 for (int i = 0; (i < num_regs) && 1031 (core_regs[i].count >= promotion_threshold); i++) { 1032 int p_map_idx = SRegToPMap(core_regs[i].s_reg); 1033 if (promotion_map_[p_map_idx].core_location != 1034 kLocPhysReg) { 1035 int reg = AllocPreservedCoreReg(core_regs[i].s_reg); 1036 if (reg < 0) { 1037 break; // No more left 1038 } 1039 } 1040 } 1041 } 1042 1043 // Now, update SSA names to new home locations 1044 for (int i = 0; i < mir_graph_->GetNumSSARegs(); i++) { 1045 RegLocation *curr = &mir_graph_->reg_location_[i]; 1046 int p_map_idx = SRegToPMap(curr->s_reg_low); 1047 if (!curr->wide) { 1048 if (curr->fp) { 1049 if (promotion_map_[p_map_idx].fp_location == kLocPhysReg) { 1050 curr->location = kLocPhysReg; 1051 curr->low_reg = promotion_map_[p_map_idx].FpReg; 1052 curr->home = true; 1053 } 1054 } else { 1055 if (promotion_map_[p_map_idx].core_location == kLocPhysReg) { 1056 curr->location = kLocPhysReg; 1057 curr->low_reg = promotion_map_[p_map_idx].core_reg; 1058 curr->home = true; 1059 } 1060 } 1061 curr->high_reg = INVALID_REG; 1062 } else { 1063 if (curr->high_word) { 1064 continue; 1065 } 1066 if (curr->fp) { 1067 if ((promotion_map_[p_map_idx].fp_location == kLocPhysReg) && 1068 (promotion_map_[p_map_idx+1].fp_location == 1069 kLocPhysReg)) { 1070 int low_reg = promotion_map_[p_map_idx].FpReg; 1071 int high_reg = promotion_map_[p_map_idx+1].FpReg; 1072 // Doubles require pair of singles starting at even reg 1073 if (((low_reg & 0x1) == 0) && ((low_reg + 1) == high_reg)) { 1074 curr->location = kLocPhysReg; 1075 curr->low_reg = low_reg; 1076 curr->high_reg = high_reg; 1077 curr->home = true; 1078 } 1079 } 1080 } else { 1081 if ((promotion_map_[p_map_idx].core_location == kLocPhysReg) 1082 && (promotion_map_[p_map_idx+1].core_location == 1083 kLocPhysReg)) { 1084 curr->location = kLocPhysReg; 1085 curr->low_reg = promotion_map_[p_map_idx].core_reg; 1086 curr->high_reg = promotion_map_[p_map_idx+1].core_reg; 1087 curr->home = true; 1088 } 1089 } 1090 } 1091 } 1092 if (cu_->verbose) { 1093 DumpPromotionMap(); 1094 } 1095 } 1096 1097 /* Returns sp-relative offset in bytes for a VReg */ 1098 int Mir2Lir::VRegOffset(int v_reg) { 1099 return StackVisitor::GetVRegOffset(cu_->code_item, core_spill_mask_, 1100 fp_spill_mask_, frame_size_, v_reg); 1101 } 1102 1103 /* Returns sp-relative offset in bytes for a SReg */ 1104 int Mir2Lir::SRegOffset(int s_reg) { 1105 return VRegOffset(mir_graph_->SRegToVReg(s_reg)); 1106 } 1107 1108 /* Mark register usage state and return long retloc */ 1109 RegLocation Mir2Lir::GetReturnWide(bool is_double) { 1110 RegLocation gpr_res = LocCReturnWide(); 1111 RegLocation fpr_res = LocCReturnDouble(); 1112 RegLocation res = is_double ? fpr_res : gpr_res; 1113 Clobber(res.low_reg); 1114 Clobber(res.high_reg); 1115 LockTemp(res.low_reg); 1116 LockTemp(res.high_reg); 1117 MarkPair(res.low_reg, res.high_reg); 1118 return res; 1119 } 1120 1121 RegLocation Mir2Lir::GetReturn(bool is_float) { 1122 RegLocation gpr_res = LocCReturn(); 1123 RegLocation fpr_res = LocCReturnFloat(); 1124 RegLocation res = is_float ? fpr_res : gpr_res; 1125 Clobber(res.low_reg); 1126 if (cu_->instruction_set == kMips) { 1127 MarkInUse(res.low_reg); 1128 } else { 1129 LockTemp(res.low_reg); 1130 } 1131 return res; 1132 } 1133 1134 void Mir2Lir::SimpleRegAlloc() { 1135 DoPromotion(); 1136 1137 if (cu_->verbose && !(cu_->disable_opt & (1 << kPromoteRegs))) { 1138 LOG(INFO) << "After Promotion"; 1139 mir_graph_->DumpRegLocTable(mir_graph_->reg_location_, mir_graph_->GetNumSSARegs()); 1140 } 1141 1142 /* Set the frame size */ 1143 frame_size_ = ComputeFrameSize(); 1144 } 1145 1146 /* 1147 * Get the "real" sreg number associated with an s_reg slot. In general, 1148 * s_reg values passed through codegen are the SSA names created by 1149 * dataflow analysis and refer to slot numbers in the mir_graph_->reg_location 1150 * array. However, renaming is accomplished by simply replacing RegLocation 1151 * entries in the reglocation[] array. Therefore, when location 1152 * records for operands are first created, we need to ask the locRecord 1153 * identified by the dataflow pass what it's new name is. 1154 */ 1155 int Mir2Lir::GetSRegHi(int lowSreg) { 1156 return (lowSreg == INVALID_SREG) ? INVALID_SREG : lowSreg + 1; 1157 } 1158 1159 bool Mir2Lir::oat_live_out(int s_reg) { 1160 // For now. 1161 return true; 1162 } 1163 1164 int Mir2Lir::oatSSASrc(MIR* mir, int num) { 1165 DCHECK_GT(mir->ssa_rep->num_uses, num); 1166 return mir->ssa_rep->uses[num]; 1167 } 1168 1169 } // namespace art 1170