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 target independent register alloction support.
     19  */
     20 
     21 #include "compiler/CompilerUtility.h"
     22 #include "compiler/CompilerIR.h"
     23 #include "compiler/Dataflow.h"
     24 #include "compiler/codegen/arm/ArmLIR.h"
     25 
     26 /*
     27  * Return most flexible allowed register class based on size.
     28  * Bug: 2813841
     29  * Must use a core register for data types narrower than word (due
     30  * to possible unaligned load/store.
     31  */
     32 static inline RegisterClass dvmCompilerRegClassBySize(OpSize size)
     33 {
     34     return (size == kUnsignedHalf ||
     35             size == kSignedHalf ||
     36             size == kUnsignedByte ||
     37             size == kSignedByte ) ? kCoreReg : kAnyReg;
     38 }
     39 
     40 static inline int dvmCompilerS2VReg(CompilationUnit *cUnit, int sReg)
     41 {
     42     assert(sReg != INVALID_SREG);
     43     return DECODE_REG(dvmConvertSSARegToDalvik(cUnit, sReg));
     44 }
     45 
     46 /* Reset the tracker to unknown state */
     47 static inline void dvmCompilerResetNullCheck(CompilationUnit *cUnit)
     48 {
     49     dvmClearAllBits(cUnit->regPool->nullCheckedRegs);
     50 }
     51 
     52 /*
     53  * Get the "real" sreg number associated with an sReg slot.  In general,
     54  * sReg values passed through codegen are the SSA names created by
     55  * dataflow analysis and refer to slot numbers in the cUnit->regLocation
     56  * array.  However, renaming is accomplished by simply replacing RegLocation
     57  * entries in the cUnit->reglocation[] array.  Therefore, when location
     58  * records for operands are first created, we need to ask the locRecord
     59  * identified by the dataflow pass what it's new name is.
     60  */
     61 
     62 static inline int dvmCompilerSRegHi(int lowSreg) {
     63     return (lowSreg == INVALID_SREG) ? INVALID_SREG : lowSreg + 1;
     64 }
     65 
     66 
     67 static inline bool dvmCompilerLiveOut(CompilationUnit *cUnit, int sReg)
     68 {
     69     //TODO: fully implement
     70     return true;
     71 }
     72 
     73 static inline int dvmCompilerSSASrc(MIR *mir, int num)
     74 {
     75     assert(mir->ssaRep->numUses > num);
     76     return mir->ssaRep->uses[num];
     77 }
     78 
     79 extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
     80                                       int regClass, bool update);
     81 /* Mark a temp register as dead.  Does not affect allocation state. */
     82 extern void dvmCompilerClobber(CompilationUnit *cUnit, int reg);
     83 
     84 extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit,
     85                                         RegLocation loc);
     86 
     87 /* see comments for updateLoc */
     88 extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
     89                                             RegLocation loc);
     90 
     91 /* Clobber all of the temps that might be used by a handler. */
     92 extern void dvmCompilerClobberHandlerRegs(CompilationUnit *cUnit);
     93 
     94 extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg);
     95 
     96 extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg);
     97 
     98 extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg,
     99                                 int highReg);
    100 
    101 extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg);
    102 
    103 extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg);
    104 
    105 extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl);
    106 
    107 /* Set up temp & preserved register pools specialized by target */
    108 extern void dvmCompilerInitPool(RegisterInfo *regs, int *regNums, int num);
    109 
    110 /*
    111  * Mark the beginning and end LIR of a def sequence.  Note that
    112  * on entry start points to the LIR prior to the beginning of the
    113  * sequence.
    114  */
    115 extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
    116                                LIR *start, LIR *finish);
    117 /*
    118  * Mark the beginning and end LIR of a def sequence.  Note that
    119  * on entry start points to the LIR prior to the beginning of the
    120  * sequence.
    121  */
    122 extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
    123                                    LIR *start, LIR *finish);
    124 
    125 extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
    126                                          int low, int high);
    127 
    128 extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
    129                                           int low, int high);
    130 // Get the LocRecord associated with an SSA name use.
    131 extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num);
    132 
    133 // Get the LocRecord associated with an SSA name def.
    134 extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
    135                                       int num);
    136 
    137 extern RegLocation dvmCompilerGetReturnWide(CompilationUnit *cUnit);
    138 
    139 /* Clobber all regs that might be used by an external C call */
    140 extern void dvmCompilerClobberCallRegs(CompilationUnit *cUnit);
    141 
    142 extern RegisterInfo *dvmCompilerIsTemp(CompilationUnit *cUnit, int reg);
    143 
    144 extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg);
    145 
    146 extern int dvmCompilerAllocTemp(CompilationUnit *cUnit);
    147 
    148 extern int dvmCompilerAllocTempFloat(CompilationUnit *cUnit);
    149 
    150 //REDO: too many assumptions.
    151 extern int dvmCompilerAllocTempDouble(CompilationUnit *cUnit);
    152 
    153 extern void dvmCompilerFreeTemp(CompilationUnit *cUnit, int reg);
    154 
    155 extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl);
    156 
    157 extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit);
    158 
    159 /* Kill the corresponding bit in the null-checked register list */
    160 extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
    161                                           RegLocation loc);
    162 
    163 //FIXME - this needs to also check the preserved pool.
    164 extern RegisterInfo *dvmCompilerIsLive(CompilationUnit *cUnit, int reg);
    165 
    166 /* To be used when explicitly managing register use */
    167 extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit);
    168 
    169 extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit);
    170 
    171 extern RegLocation dvmCompilerGetReturnWideAlt(CompilationUnit *cUnit);
    172 
    173 extern RegLocation dvmCompilerGetReturn(CompilationUnit *cUnit);
    174 
    175 extern RegLocation dvmCompilerGetReturnAlt(CompilationUnit *cUnit);
    176 
    177 /* Clobber any temp associated with an sReg.  Could be in either class */
    178 extern void dvmCompilerClobberSReg(CompilationUnit *cUnit, int sReg);
    179 
    180 /* Return a temp if one is available, -1 otherwise */
    181 extern int dvmCompilerAllocFreeTemp(CompilationUnit *cUnit);
    182 
    183 /*
    184  * Similar to dvmCompilerAllocTemp(), but forces the allocation of a specific
    185  * register.  No check is made to see if the register was previously
    186  * allocated.  Use with caution.
    187  */
    188 extern void dvmCompilerLockTemp(CompilationUnit *cUnit, int reg);
    189 
    190 extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
    191                                            RegLocation rl);
    192 
    193 /*
    194  * Free all allocated temps in the temp pools.  Note that this does
    195  * not affect the "liveness" of a temp register, which will stay
    196  * live until it is either explicitly killed or reallocated.
    197  */
    198 extern void dvmCompilerResetRegPool(CompilationUnit *cUnit);
    199 
    200 extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit);
    201 
    202 extern void dvmCompilerFlushRegWide(CompilationUnit *cUnit, int reg1, int reg2);
    203 
    204 extern void dvmCompilerFlushReg(CompilationUnit *cUnit, int reg);
    205 
    206 /*
    207  * Architecture-dependent register allocation routines implemented in
    208  * ${TARGET_ARCH}/${TARGET_ARCH_VARIANT}/Ralloc.c
    209  */
    210 extern int dvmCompilerAllocTypedTempPair(CompilationUnit *cUnit,
    211                                          bool fpHint, int regClass);
    212 
    213 extern int dvmCompilerAllocTypedTemp(CompilationUnit *cUnit, bool fpHint,
    214                                      int regClass);
    215 
    216 extern ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
    217 
    218 extern void dvmCompilerRegCopyWide(CompilationUnit *cUnit, int destLo,
    219                                    int destHi, int srcLo, int srcHi);
    220 
    221 extern void dvmCompilerFlushRegImpl(CompilationUnit *cUnit, int rBase,
    222                                     int displacement, int rSrc, OpSize size);
    223 
    224 extern void dvmCompilerFlushRegWideImpl(CompilationUnit *cUnit, int rBase,
    225                                         int displacement, int rSrcLo,
    226                                         int rSrcHi);
    227