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