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