Home | History | Annotate | Download | only in codegen
      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     LOGE("================================================");
     75     for (i=0; i < numRegs; i++ ){
     76         LOGE("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     LOGE("================================================");
     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     LOGE("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         LOGE("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     LOGE("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             LOGE("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     LOGE("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     LOGE("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