1 /* 2 * Copyright (C) 2009 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 /* 18 * This file contains register alloction support and is intended to be 19 * included by: 20 * 21 * Codegen-$(TARGET_ARCH_VARIANT).c 22 * 23 */ 24 25 #include "compiler/CompilerUtility.h" 26 #include "compiler/CompilerIR.h" 27 #include "compiler/Dataflow.h" 28 #include "Ralloc.h" 29 30 #define SREG(c, s) ((c)->regLocation[(s)].sRegLow) 31 /* 32 * Get the "real" sreg number associated with an sReg slot. In general, 33 * sReg values passed through codegen are the SSA names created by 34 * dataflow analysis and refer to slot numbers in the cUnit->regLocation 35 * array. However, renaming is accomplished by simply replacing RegLocation 36 * entries in the cUnit->reglocation[] array. Therefore, when location 37 * records for operands are first created, we need to ask the locRecord 38 * identified by the dataflow pass what it's new name is. 39 */ 40 41 /* 42 * Free all allocated temps in the temp pools. Note that this does 43 * not affect the "liveness" of a temp register, which will stay 44 * live until it is either explicitly killed or reallocated. 45 */ 46 extern void dvmCompilerResetRegPool(CompilationUnit *cUnit) 47 { 48 int i; 49 for (i=0; i < cUnit->regPool->numCoreTemps; i++) { 50 cUnit->regPool->coreTemps[i].inUse = false; 51 } 52 for (i=0; i < cUnit->regPool->numFPTemps; i++) { 53 cUnit->regPool->FPTemps[i].inUse = false; 54 } 55 } 56 57 /* Set up temp & preserved register pools specialized by target */ 58 extern void dvmCompilerInitPool(RegisterInfo *regs, int *regNums, int num) 59 { 60 int i; 61 for (i=0; i < num; i++) { 62 regs[i].reg = regNums[i]; 63 regs[i].inUse = false; 64 regs[i].pair = false; 65 regs[i].live = false; 66 regs[i].dirty = false; 67 regs[i].sReg = INVALID_SREG; 68 } 69 } 70 71 static void dumpRegPool(RegisterInfo *p, int numRegs) 72 { 73 int i; 74 ALOGE("================================================"); 75 for (i=0; i < numRegs; i++ ){ 76 ALOGE("R[%d]: U:%d, P:%d, part:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x", 77 p[i].reg, p[i].inUse, p[i].pair, p[i].partner, p[i].live, 78 p[i].dirty, p[i].sReg,(int)p[i].defStart, (int)p[i].defEnd); 79 } 80 ALOGE("================================================"); 81 } 82 83 static RegisterInfo *getRegInfo(CompilationUnit *cUnit, int reg) 84 { 85 int numTemps = cUnit->regPool->numCoreTemps; 86 RegisterInfo *p = cUnit->regPool->coreTemps; 87 int i; 88 for (i=0; i< numTemps; i++) { 89 if (p[i].reg == reg) { 90 return &p[i]; 91 } 92 } 93 p = cUnit->regPool->FPTemps; 94 numTemps = cUnit->regPool->numFPTemps; 95 for (i=0; i< numTemps; i++) { 96 if (p[i].reg == reg) { 97 return &p[i]; 98 } 99 } 100 ALOGE("Tried to get info on a non-existant temp: r%d",reg); 101 dvmCompilerAbort(cUnit); 102 return NULL; 103 } 104 105 void dvmCompilerFlushRegWide(CompilationUnit *cUnit, int reg1, int reg2) 106 { 107 RegisterInfo *info1 = getRegInfo(cUnit, reg1); 108 RegisterInfo *info2 = getRegInfo(cUnit, reg2); 109 assert(info1 && info2 && info1->pair && info2->pair && 110 (info1->partner == info2->reg) && 111 (info2->partner == info1->reg)); 112 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) { 113 info1->dirty = false; 114 info2->dirty = false; 115 if (dvmCompilerS2VReg(cUnit, info2->sReg) < 116 dvmCompilerS2VReg(cUnit, info1->sReg)) 117 info1 = info2; 118 dvmCompilerFlushRegWideImpl(cUnit, rFP, 119 dvmCompilerS2VReg(cUnit, info1->sReg) << 2, 120 info1->reg, info1->partner); 121 } 122 } 123 124 void dvmCompilerFlushReg(CompilationUnit *cUnit, int reg) 125 { 126 RegisterInfo *info = getRegInfo(cUnit, reg); 127 if (info->live && info->dirty) { 128 info->dirty = false; 129 dvmCompilerFlushRegImpl(cUnit, rFP, 130 dvmCompilerS2VReg(cUnit, info->sReg) << 2, 131 reg, kWord); 132 } 133 } 134 135 /* return true if found reg to clobber */ 136 static bool clobberRegBody(CompilationUnit *cUnit, RegisterInfo *p, 137 int numTemps, int reg) 138 { 139 int i; 140 for (i=0; i< numTemps; i++) { 141 if (p[i].reg == reg) { 142 if (p[i].live && p[i].dirty) { 143 if (p[i].pair) { 144 dvmCompilerFlushRegWide(cUnit, p[i].reg, p[i].partner); 145 } else { 146 dvmCompilerFlushReg(cUnit, p[i].reg); 147 } 148 } 149 p[i].live = false; 150 p[i].sReg = INVALID_SREG; 151 p[i].defStart = NULL; 152 p[i].defEnd = NULL; 153 if (p[i].pair) { 154 p[i].pair = false; 155 /* partners should be in same pool */ 156 clobberRegBody(cUnit, p, numTemps, p[i].partner); 157 } 158 return true; 159 } 160 } 161 return false; 162 } 163 164 /* Mark a temp register as dead. Does not affect allocation state. */ 165 void dvmCompilerClobber(CompilationUnit *cUnit, int reg) 166 { 167 if (!clobberRegBody(cUnit, cUnit->regPool->coreTemps, 168 cUnit->regPool->numCoreTemps, reg)) { 169 clobberRegBody(cUnit, cUnit->regPool->FPTemps, 170 cUnit->regPool->numFPTemps, reg); 171 } 172 } 173 174 static void clobberSRegBody(RegisterInfo *p, int numTemps, int sReg) 175 { 176 int i; 177 for (i=0; i< numTemps; i++) { 178 if (p[i].sReg == sReg) { 179 p[i].live = false; 180 p[i].defStart = NULL; 181 p[i].defEnd = NULL; 182 } 183 } 184 } 185 186 /* Clobber any temp associated with an sReg. Could be in either class */ 187 extern void dvmCompilerClobberSReg(CompilationUnit *cUnit, int sReg) 188 { 189 clobberSRegBody(cUnit->regPool->coreTemps, cUnit->regPool->numCoreTemps, 190 sReg); 191 clobberSRegBody(cUnit->regPool->FPTemps, cUnit->regPool->numFPTemps, 192 sReg); 193 } 194 195 static int allocTempBody(CompilationUnit *cUnit, RegisterInfo *p, int numTemps, 196 int *nextTemp, bool required) 197 { 198 int i; 199 int next = *nextTemp; 200 for (i=0; i< numTemps; i++) { 201 if (next >= numTemps) 202 next = 0; 203 if (!p[next].inUse && !p[next].live) { 204 dvmCompilerClobber(cUnit, p[next].reg); 205 p[next].inUse = true; 206 p[next].pair = false; 207 *nextTemp = next + 1; 208 return p[next].reg; 209 } 210 next++; 211 } 212 next = *nextTemp; 213 for (i=0; i< numTemps; i++) { 214 if (next >= numTemps) 215 next = 0; 216 if (!p[next].inUse) { 217 dvmCompilerClobber(cUnit, p[next].reg); 218 p[next].inUse = true; 219 p[next].pair = false; 220 *nextTemp = next + 1; 221 return p[next].reg; 222 } 223 next++; 224 } 225 if (required) { 226 ALOGE("No free temp registers"); 227 dvmCompilerAbort(cUnit); 228 } 229 return -1; // No register available 230 } 231 232 //REDO: too many assumptions. 233 extern int dvmCompilerAllocTempDouble(CompilationUnit *cUnit) 234 { 235 RegisterInfo *p = cUnit->regPool->FPTemps; 236 int numTemps = cUnit->regPool->numFPTemps; 237 int next = cUnit->regPool->nextFPTemp; 238 int i; 239 240 for (i=0; i < numTemps; i+=2) { 241 /* Cleanup - not all targets need aligned regs */ 242 if (next & 1) 243 next++; 244 if (next >= numTemps) 245 next = 0; 246 if ((!p[next].inUse && !p[next].live) && 247 (!p[next+1].inUse && !p[next+1].live)) { 248 dvmCompilerClobber(cUnit, p[next].reg); 249 dvmCompilerClobber(cUnit, p[next+1].reg); 250 p[next].inUse = true; 251 p[next+1].inUse = true; 252 assert((p[next].reg+1) == p[next+1].reg); 253 assert((p[next].reg & 0x1) == 0); 254 cUnit->regPool->nextFPTemp += 2; 255 return p[next].reg; 256 } 257 next += 2; 258 } 259 next = cUnit->regPool->nextFPTemp; 260 for (i=0; i < numTemps; i+=2) { 261 if (next >= numTemps) 262 next = 0; 263 if (!p[next].inUse && !p[next+1].inUse) { 264 dvmCompilerClobber(cUnit, p[next].reg); 265 dvmCompilerClobber(cUnit, p[next+1].reg); 266 p[next].inUse = true; 267 p[next+1].inUse = true; 268 assert((p[next].reg+1) == p[next+1].reg); 269 assert((p[next].reg & 0x1) == 0); 270 cUnit->regPool->nextFPTemp += 2; 271 return p[next].reg; 272 } 273 next += 2; 274 } 275 ALOGE("No free temp registers"); 276 dvmCompilerAbort(cUnit); 277 return -1; 278 } 279 280 /* Return a temp if one is available, -1 otherwise */ 281 extern int dvmCompilerAllocFreeTemp(CompilationUnit *cUnit) 282 { 283 return allocTempBody(cUnit, cUnit->regPool->coreTemps, 284 cUnit->regPool->numCoreTemps, 285 &cUnit->regPool->nextCoreTemp, true); 286 } 287 288 extern int dvmCompilerAllocTemp(CompilationUnit *cUnit) 289 { 290 return allocTempBody(cUnit, cUnit->regPool->coreTemps, 291 cUnit->regPool->numCoreTemps, 292 &cUnit->regPool->nextCoreTemp, true); 293 } 294 295 extern int dvmCompilerAllocTempFloat(CompilationUnit *cUnit) 296 { 297 return allocTempBody(cUnit, cUnit->regPool->FPTemps, 298 cUnit->regPool->numFPTemps, 299 &cUnit->regPool->nextFPTemp, true); 300 } 301 302 static RegisterInfo *allocLiveBody(RegisterInfo *p, int numTemps, int sReg) 303 { 304 int i; 305 if (sReg == -1) 306 return NULL; 307 for (i=0; i < numTemps; i++) { 308 if (p[i].live && (p[i].sReg == sReg)) { 309 p[i].inUse = true; 310 return &p[i]; 311 } 312 } 313 return NULL; 314 } 315 316 static RegisterInfo *allocLive(CompilationUnit *cUnit, int sReg, 317 int regClass) 318 { 319 RegisterInfo *res = NULL; 320 switch(regClass) { 321 case kAnyReg: 322 res = allocLiveBody(cUnit->regPool->FPTemps, 323 cUnit->regPool->numFPTemps, sReg); 324 if (res) 325 break; 326 /* Intentional fallthrough */ 327 case kCoreReg: 328 res = allocLiveBody(cUnit->regPool->coreTemps, 329 cUnit->regPool->numCoreTemps, sReg); 330 break; 331 case kFPReg: 332 res = allocLiveBody(cUnit->regPool->FPTemps, 333 cUnit->regPool->numFPTemps, sReg); 334 break; 335 default: 336 ALOGE("Invalid register type"); 337 dvmCompilerAbort(cUnit); 338 } 339 return res; 340 } 341 342 extern void dvmCompilerFreeTemp(CompilationUnit *cUnit, int reg) 343 { 344 RegisterInfo *p = cUnit->regPool->coreTemps; 345 int numTemps = cUnit->regPool->numCoreTemps; 346 int i; 347 for (i=0; i< numTemps; i++) { 348 if (p[i].reg == reg) { 349 p[i].inUse = false; 350 p[i].pair = false; 351 return; 352 } 353 } 354 p = cUnit->regPool->FPTemps; 355 numTemps = cUnit->regPool->numFPTemps; 356 for (i=0; i< numTemps; i++) { 357 if (p[i].reg == reg) { 358 p[i].inUse = false; 359 p[i].pair = false; 360 return; 361 } 362 } 363 ALOGE("Tried to free a non-existant temp: r%d",reg); 364 dvmCompilerAbort(cUnit); 365 } 366 367 extern RegisterInfo *dvmCompilerIsLive(CompilationUnit *cUnit, int reg) 368 { 369 RegisterInfo *p = cUnit->regPool->coreTemps; 370 int numTemps = cUnit->regPool->numCoreTemps; 371 int i; 372 for (i=0; i< numTemps; i++) { 373 if (p[i].reg == reg) { 374 return p[i].live ? &p[i] : NULL; 375 } 376 } 377 p = cUnit->regPool->FPTemps; 378 numTemps = cUnit->regPool->numFPTemps; 379 for (i=0; i< numTemps; i++) { 380 if (p[i].reg == reg) { 381 return p[i].live ? &p[i] : NULL; 382 } 383 } 384 return NULL; 385 } 386 387 extern RegisterInfo *dvmCompilerIsTemp(CompilationUnit *cUnit, int reg) 388 { 389 RegisterInfo *p = cUnit->regPool->coreTemps; 390 int numTemps = cUnit->regPool->numCoreTemps; 391 int i; 392 for (i=0; i< numTemps; i++) { 393 if (p[i].reg == reg) { 394 return &p[i]; 395 } 396 } 397 p = cUnit->regPool->FPTemps; 398 numTemps = cUnit->regPool->numFPTemps; 399 for (i=0; i< numTemps; i++) { 400 if (p[i].reg == reg) { 401 return &p[i]; 402 } 403 } 404 return NULL; 405 } 406 407 /* 408 * Similar to dvmCompilerAllocTemp(), but forces the allocation of a specific 409 * register. No check is made to see if the register was previously 410 * allocated. Use with caution. 411 */ 412 extern void dvmCompilerLockTemp(CompilationUnit *cUnit, int reg) 413 { 414 RegisterInfo *p = cUnit->regPool->coreTemps; 415 int numTemps = cUnit->regPool->numCoreTemps; 416 int i; 417 for (i=0; i< numTemps; i++) { 418 if (p[i].reg == reg) { 419 p[i].inUse = true; 420 p[i].live = false; 421 return; 422 } 423 } 424 p = cUnit->regPool->FPTemps; 425 numTemps = cUnit->regPool->numFPTemps; 426 for (i=0; i< numTemps; i++) { 427 if (p[i].reg == reg) { 428 p[i].inUse = true; 429 p[i].live = false; 430 return; 431 } 432 } 433 ALOGE("Tried to lock a non-existant temp: r%d",reg); 434 dvmCompilerAbort(cUnit); 435 } 436 437 extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg) 438 { 439 RegisterInfo *p = getRegInfo(cUnit, reg); 440 p->defStart = NULL; 441 p->defEnd = NULL; 442 } 443 444 static void nullifyRange(CompilationUnit *cUnit, LIR *start, LIR *finish, 445 int sReg1, int sReg2) 446 { 447 if (start && finish) { 448 LIR *p; 449 assert(sReg1 == sReg2); 450 for (p = start; ;p = p->next) { 451 ((ArmLIR *)p)->flags.isNop = true; 452 if (p == finish) 453 break; 454 } 455 } 456 } 457 458 /* 459 * Mark the beginning and end LIR of a def sequence. Note that 460 * on entry start points to the LIR prior to the beginning of the 461 * sequence. 462 */ 463 extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl, 464 LIR *start, LIR *finish) 465 { 466 assert(!rl.wide); 467 assert(start && start->next); 468 assert(finish); 469 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg); 470 p->defStart = start->next; 471 p->defEnd = finish; 472 } 473 474 /* 475 * Mark the beginning and end LIR of a def sequence. Note that 476 * on entry start points to the LIR prior to the beginning of the 477 * sequence. 478 */ 479 extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl, 480 LIR *start, LIR *finish) 481 { 482 assert(rl.wide); 483 assert(start && start->next); 484 assert(finish); 485 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg); 486 dvmCompilerResetDef(cUnit, rl.highReg); // Only track low of pair 487 p->defStart = start->next; 488 p->defEnd = finish; 489 } 490 491 extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit, 492 RegLocation rl) 493 { 494 assert(rl.wide); 495 if (rl.location == kLocPhysReg) { 496 RegisterInfo *infoLo = getRegInfo(cUnit, rl.lowReg); 497 RegisterInfo *infoHi = getRegInfo(cUnit, rl.highReg); 498 if (!infoLo->pair) { 499 dumpRegPool(cUnit->regPool->coreTemps, 500 cUnit->regPool->numCoreTemps); 501 assert(infoLo->pair); 502 } 503 if (!infoHi->pair) { 504 dumpRegPool(cUnit->regPool->coreTemps, 505 cUnit->regPool->numCoreTemps); 506 assert(infoHi->pair); 507 } 508 assert(infoLo->pair); 509 assert(infoHi->pair); 510 assert(infoLo->partner == infoHi->reg); 511 assert(infoHi->partner == infoLo->reg); 512 infoLo->pair = false; 513 infoHi->pair = false; 514 infoLo->defStart = NULL; 515 infoLo->defEnd = NULL; 516 infoHi->defStart = NULL; 517 infoHi->defEnd = NULL; 518 } 519 rl.wide = false; 520 return rl; 521 } 522 523 extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl) 524 { 525 assert(!rl.wide); 526 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) { 527 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg); 528 assert(!p->pair); 529 nullifyRange(cUnit, p->defStart, p->defEnd, 530 p->sReg, rl.sRegLow); 531 } 532 dvmCompilerResetDef(cUnit, rl.lowReg); 533 } 534 535 extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl) 536 { 537 assert(rl.wide); 538 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) { 539 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg); 540 assert(p->pair); 541 nullifyRange(cUnit, p->defStart, p->defEnd, 542 p->sReg, rl.sRegLow); 543 } 544 dvmCompilerResetDef(cUnit, rl.lowReg); 545 dvmCompilerResetDef(cUnit, rl.highReg); 546 } 547 548 extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit) 549 { 550 int i; 551 for (i=0; i< cUnit->regPool->numCoreTemps; i++) { 552 dvmCompilerResetDef(cUnit, cUnit->regPool->coreTemps[i].reg); 553 } 554 for (i=0; i< cUnit->regPool->numFPTemps; i++) { 555 dvmCompilerResetDef(cUnit, cUnit->regPool->FPTemps[i].reg); 556 } 557 } 558 559 extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit) 560 { 561 int i; 562 for (i=0; i< cUnit->regPool->numCoreTemps; i++) { 563 dvmCompilerClobber(cUnit, cUnit->regPool->coreTemps[i].reg); 564 } 565 for (i=0; i< cUnit->regPool->numFPTemps; i++) { 566 dvmCompilerClobber(cUnit, cUnit->regPool->FPTemps[i].reg); 567 } 568 } 569 570 /* To be used when explicitly managing register use */ 571 extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit) 572 { 573 int i; 574 for (i=0; i< cUnit->regPool->numCoreTemps; i++) { 575 dvmCompilerLockTemp(cUnit, cUnit->regPool->coreTemps[i].reg); 576 } 577 } 578 579 // Make sure nothing is live and dirty 580 static void flushAllRegsBody(CompilationUnit *cUnit, RegisterInfo *info, 581 int numRegs) 582 { 583 int i; 584 for (i=0; i < numRegs; i++) { 585 if (info[i].live && info[i].dirty) { 586 if (info[i].pair) { 587 dvmCompilerFlushRegWide(cUnit, info[i].reg, info[i].partner); 588 } else { 589 dvmCompilerFlushReg(cUnit, info[i].reg); 590 } 591 } 592 } 593 } 594 595 extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit) 596 { 597 flushAllRegsBody(cUnit, cUnit->regPool->coreTemps, 598 cUnit->regPool->numCoreTemps); 599 flushAllRegsBody(cUnit, cUnit->regPool->FPTemps, 600 cUnit->regPool->numFPTemps); 601 dvmCompilerClobberAllRegs(cUnit); 602 } 603 604 605 //TUNING: rewrite all of this reg stuff. Probably use an attribute table 606 static bool regClassMatches(int regClass, int reg) 607 { 608 if (regClass == kAnyReg) { 609 return true; 610 } else if (regClass == kCoreReg) { 611 return !FPREG(reg); 612 } else { 613 return FPREG(reg); 614 } 615 } 616 617 extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg) 618 { 619 RegisterInfo *info = getRegInfo(cUnit, reg); 620 if ((info->reg == reg) && (info->sReg == sReg) && info->live) { 621 return; /* already live */ 622 } else if (sReg != INVALID_SREG) { 623 dvmCompilerClobberSReg(cUnit, sReg); 624 info->live = true; 625 } else { 626 /* Can't be live if no associated sReg */ 627 info->live = false; 628 } 629 info->sReg = sReg; 630 } 631 632 extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg, int highReg) 633 { 634 RegisterInfo *infoLo = getRegInfo(cUnit, lowReg); 635 RegisterInfo *infoHi = getRegInfo(cUnit, highReg); 636 infoLo->pair = infoHi->pair = true; 637 infoLo->partner = highReg; 638 infoHi->partner = lowReg; 639 } 640 641 extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg) 642 { 643 RegisterInfo *info = getRegInfo(cUnit, reg); 644 info->dirty = false; 645 } 646 647 extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg) 648 { 649 RegisterInfo *info = getRegInfo(cUnit, reg); 650 info->dirty = true; 651 } 652 653 extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg) 654 { 655 RegisterInfo *info = getRegInfo(cUnit, reg); 656 info->inUse = true; 657 } 658 659 static void copyRegInfo(CompilationUnit *cUnit, int newReg, int oldReg) 660 { 661 RegisterInfo *newInfo = getRegInfo(cUnit, newReg); 662 RegisterInfo *oldInfo = getRegInfo(cUnit, oldReg); 663 *newInfo = *oldInfo; 664 newInfo->reg = newReg; 665 } 666 667 /* 668 * Return an updated location record with current in-register status. 669 * If the value lives in live temps, reflect that fact. No code 670 * is generated. The the live value is part of an older pair, 671 * clobber both low and high. 672 * TUNING: clobbering both is a bit heavy-handed, but the alternative 673 * is a bit complex when dealing with FP regs. Examine code to see 674 * if it's worthwhile trying to be more clever here. 675 */ 676 extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit, RegLocation loc) 677 { 678 assert(!loc.wide); 679 if (loc.location == kLocDalvikFrame) { 680 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg); 681 if (infoLo) { 682 if (infoLo->pair) { 683 dvmCompilerClobber(cUnit, infoLo->reg); 684 dvmCompilerClobber(cUnit, infoLo->partner); 685 } else { 686 loc.lowReg = infoLo->reg; 687 loc.location = kLocPhysReg; 688 } 689 } 690 } 691 692 return loc; 693 } 694 695 /* see comments for updateLoc */ 696 extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit, 697 RegLocation loc) 698 { 699 assert(loc.wide); 700 if (loc.location == kLocDalvikFrame) { 701 // Are the dalvik regs already live in physical registers? 702 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg); 703 RegisterInfo *infoHi = allocLive(cUnit, 704 dvmCompilerSRegHi(loc.sRegLow), kAnyReg); 705 bool match = true; 706 match = match && (infoLo != NULL); 707 match = match && (infoHi != NULL); 708 // Are they both core or both FP? 709 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg)); 710 // If a pair of floating point singles, are they properly aligned? 711 if (match && FPREG(infoLo->reg)) { 712 match &= ((infoLo->reg & 0x1) == 0); 713 match &= ((infoHi->reg - infoLo->reg) == 1); 714 } 715 // If previously used as a pair, it is the same pair? 716 if (match && (infoLo->pair || infoHi->pair)) { 717 match = (infoLo->pair == infoHi->pair); 718 match &= ((infoLo->reg == infoHi->partner) && 719 (infoHi->reg == infoLo->partner)); 720 } 721 if (match) { 722 // Can reuse - update the register usage info 723 loc.lowReg = infoLo->reg; 724 loc.highReg = infoHi->reg; 725 loc.location = kLocPhysReg; 726 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg); 727 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0)); 728 return loc; 729 } 730 // Can't easily reuse - clobber any overlaps 731 if (infoLo) { 732 dvmCompilerClobber(cUnit, infoLo->reg); 733 if (infoLo->pair) 734 dvmCompilerClobber(cUnit, infoLo->partner); 735 } 736 if (infoHi) { 737 dvmCompilerClobber(cUnit, infoHi->reg); 738 if (infoHi->pair) 739 dvmCompilerClobber(cUnit, infoHi->partner); 740 } 741 } 742 743 return loc; 744 } 745 746 static RegLocation evalLocWide(CompilationUnit *cUnit, RegLocation loc, 747 int regClass, bool update) 748 { 749 assert(loc.wide); 750 int newRegs; 751 int lowReg; 752 int highReg; 753 754 loc = dvmCompilerUpdateLocWide(cUnit, loc); 755 756 /* If already in registers, we can assume proper form. Right reg class? */ 757 if (loc.location == kLocPhysReg) { 758 assert(FPREG(loc.lowReg) == FPREG(loc.highReg)); 759 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0)); 760 if (!regClassMatches(regClass, loc.lowReg)) { 761 /* Wrong register class. Reallocate and copy */ 762 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass); 763 lowReg = newRegs & 0xff; 764 highReg = (newRegs >> 8) & 0xff; 765 dvmCompilerRegCopyWide(cUnit, lowReg, highReg, loc.lowReg, 766 loc.highReg); 767 copyRegInfo(cUnit, lowReg, loc.lowReg); 768 copyRegInfo(cUnit, highReg, loc.highReg); 769 dvmCompilerClobber(cUnit, loc.lowReg); 770 dvmCompilerClobber(cUnit, loc.highReg); 771 loc.lowReg = lowReg; 772 loc.highReg = highReg; 773 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg); 774 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0)); 775 } 776 return loc; 777 } 778 779 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG)); 780 assert((loc.location != kLocRetval) || 781 (dvmCompilerSRegHi(loc.sRegLow) == INVALID_SREG)); 782 783 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass); 784 loc.lowReg = newRegs & 0xff; 785 loc.highReg = (newRegs >> 8) & 0xff; 786 787 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg); 788 if (update) { 789 loc.location = kLocPhysReg; 790 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow); 791 dvmCompilerMarkLive(cUnit, loc.highReg, dvmCompilerSRegHi(loc.sRegLow)); 792 } 793 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0)); 794 return loc; 795 } 796 797 extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc, 798 int regClass, bool update) 799 { 800 int newReg; 801 if (loc.wide) 802 return evalLocWide(cUnit, loc, regClass, update); 803 loc = dvmCompilerUpdateLoc(cUnit, loc); 804 805 if (loc.location == kLocPhysReg) { 806 if (!regClassMatches(regClass, loc.lowReg)) { 807 /* Wrong register class. Realloc, copy and transfer ownership */ 808 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass); 809 dvmCompilerRegCopy(cUnit, newReg, loc.lowReg); 810 copyRegInfo(cUnit, newReg, loc.lowReg); 811 dvmCompilerClobber(cUnit, loc.lowReg); 812 loc.lowReg = newReg; 813 } 814 return loc; 815 } 816 817 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG)); 818 819 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass); 820 loc.lowReg = newReg; 821 822 if (update) { 823 loc.location = kLocPhysReg; 824 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow); 825 } 826 return loc; 827 } 828 829 static inline int getDestSSAName(MIR *mir, int num) 830 { 831 assert(mir->ssaRep->numDefs > num); 832 return mir->ssaRep->defs[num]; 833 } 834 835 // Get the LocRecord associated with an SSA name use. 836 extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num) 837 { 838 RegLocation loc = cUnit->regLocation[ 839 SREG(cUnit, dvmCompilerSSASrc(mir, num))]; 840 loc.fp = cUnit->regLocation[dvmCompilerSSASrc(mir, num)].fp; 841 loc.wide = false; 842 return loc; 843 } 844 845 // Get the LocRecord associated with an SSA name def. 846 extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir, 847 int num) 848 { 849 RegLocation loc = cUnit->regLocation[SREG(cUnit, getDestSSAName(mir, num))]; 850 loc.fp = cUnit->regLocation[getDestSSAName(mir, num)].fp; 851 loc.wide = false; 852 return loc; 853 } 854 855 static RegLocation getLocWide(CompilationUnit *cUnit, MIR *mir, 856 int low, int high, bool isSrc) 857 { 858 RegLocation lowLoc; 859 RegLocation highLoc; 860 /* Copy loc record for low word and patch in data from high word */ 861 if (isSrc) { 862 lowLoc = dvmCompilerGetSrc(cUnit, mir, low); 863 highLoc = dvmCompilerGetSrc(cUnit, mir, high); 864 } else { 865 lowLoc = dvmCompilerGetDest(cUnit, mir, low); 866 highLoc = dvmCompilerGetDest(cUnit, mir, high); 867 } 868 /* Avoid this case by either promoting both or neither. */ 869 assert(lowLoc.location == highLoc.location); 870 if (lowLoc.location == kLocPhysReg) { 871 /* This case shouldn't happen if we've named correctly */ 872 assert(lowLoc.fp == highLoc.fp); 873 } 874 lowLoc.wide = true; 875 lowLoc.highReg = highLoc.lowReg; 876 return lowLoc; 877 } 878 879 extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir, 880 int low, int high) 881 { 882 return getLocWide(cUnit, mir, low, high, false); 883 } 884 885 extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir, 886 int low, int high) 887 { 888 return getLocWide(cUnit, mir, low, high, true); 889 } 890 891 /* Kill the corresponding bit in the null-checked register list */ 892 extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit, 893 RegLocation loc) 894 { 895 if (loc.location != kLocRetval) { 896 assert(loc.sRegLow != INVALID_SREG); 897 dvmClearBit(cUnit->regPool->nullCheckedRegs, loc.sRegLow); 898 if (loc.wide) { 899 assert(dvmCompilerSRegHi(loc.sRegLow) != INVALID_SREG); 900 dvmClearBit(cUnit->regPool->nullCheckedRegs, 901 dvmCompilerSRegHi(loc.sRegLow)); 902 } 903 } 904 } 905