static void dumpIVList(CompilationUnit *cUnit) { unsigned int i; GrowableList *ivList = cUnit->loopAnalysis->ivList; for (i = 0; i < ivList->numUsed; i++) { InductionVariableInfo *ivInfo = (InductionVariableInfo *) ivList->elemList[i]; int iv = dvmConvertSSARegToDalvik(cUnit, ivInfo->ssaReg); /* Basic IV */ if (ivInfo->ssaReg == ivInfo->basicSSAReg) { LOGE("BIV %d: s%d(v%d_%d) + %d", i, ivInfo->ssaReg, DECODE_REG(iv), DECODE_SUB(iv), ivInfo->inc); /* Dependent IV */ } else { int biv = dvmConvertSSARegToDalvik(cUnit, ivInfo->basicSSAReg); LOGE("DIV %d: s%d(v%d_%d) = %d * s%d(v%d_%d) + %d", i, ivInfo->ssaReg, DECODE_REG(iv), DECODE_SUB(iv), ivInfo->m, ivInfo->basicSSAReg, DECODE_REG(biv), DECODE_SUB(biv), ivInfo->c); } } }
static void dumpHoistedChecks(CompilationUnit *cUnit) { LoopAnalysis *loopAnalysis = cUnit->loopAnalysis; unsigned int i; for (i = 0; i < loopAnalysis->arrayAccessInfo->numUsed; i++) { ArrayAccessInfo *arrayAccessInfo = GET_ELEM_N(loopAnalysis->arrayAccessInfo, ArrayAccessInfo*, i); int arrayReg = DECODE_REG( dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->arrayReg)); int idxReg = DECODE_REG( dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->ivReg)); LOGE("Array access %d", i); LOGE(" arrayReg %d", arrayReg); LOGE(" idxReg %d", idxReg); LOGE(" endReg %d", loopAnalysis->endConditionReg); LOGE(" maxC %d", arrayAccessInfo->maxC); LOGE(" minC %d", arrayAccessInfo->minC); LOGE(" opcode %d", loopAnalysis->loopBranchOpcode); } }
/* Debugging routines */ static void dumpConstants(CompilationUnit *cUnit) { int i; LOGE("LOOP starting offset: %x", cUnit->entryBlock->startOffset); for (i = 0; i < cUnit->numSSARegs; i++) { if (dvmIsBitSet(cUnit->isConstantV, i)) { int subNReg = dvmConvertSSARegToDalvik(cUnit, i); LOGE("CONST: s%d(v%d_%d) has %d", i, DECODE_REG(subNReg), DECODE_SUB(subNReg), cUnit->constantValues[i]); } } }
void dvmCompilerRegAlloc(CompilationUnit *cUnit) { int i; int seqNum = 0; LiveRange *ranges; RegLocation *loc; int *ssaToDalvikMap = (int *) cUnit->ssaToDalvikMap->elemList; /* Allocate the location map */ loc = (RegLocation*)dvmCompilerNew(cUnit->numSSARegs * sizeof(*loc), true); for (i=0; i< cUnit->numSSARegs; i++) { loc[i] = freshLoc; loc[i].sRegLow = i; } cUnit->regLocation = loc; /* Do type inference pass */ for (i=0; i < cUnit->numBlocks; i++) { inferTypes(cUnit, cUnit->blockList[i]); } if (simpleTrace(cUnit)) { /* * Just rename everything back to subscript 0 names and don't do * any explicit promotion. Local allocator will opportunistically * promote on the fly. */ for (i=0; i < cUnit->numSSARegs; i++) { cUnit->regLocation[i].sRegLow = DECODE_REG(dvmConvertSSARegToDalvik(cUnit, loc[i].sRegLow)); } } else { // Compute live ranges ranges = dvmCompilerNew(cUnit->numSSARegs * sizeof(*ranges), true); for (i=0; i < cUnit->numSSARegs; i++) ranges[i].active = false; seqNum = computeLiveRange(ranges, cUnit->blockList[i], seqNum); //TODO: phi squash & linear scan promotion } }
/* * A loop is considered optimizable if: * 1) It has one basic induction variable. * 2) The loop back branch compares the BIV with a constant. * 3) We need to normalize the loop exit condition so that the loop is exited * via the taken path. * 4) If it is a count-up loop, the condition is GE/GT. Otherwise it is * LE/LT/LEZ/LTZ for a count-down loop. * * Return false for loops that fail the above tests. */ static bool isSimpleCountedLoop(CompilationUnit *cUnit) { unsigned int i; BasicBlock *loopBackBlock = cUnit->entryBlock->fallThrough; LoopAnalysis *loopAnalysis = cUnit->loopAnalysis; if (loopAnalysis->numBasicIV != 1) return false; for (i = 0; i < loopAnalysis->ivList->numUsed; i++) { InductionVariableInfo *ivInfo; ivInfo = GET_ELEM_N(loopAnalysis->ivList, InductionVariableInfo*, i); /* Count up or down loop? */ if (ivInfo->ssaReg == ivInfo->basicSSAReg) { /* Infinite loop */ if (ivInfo->inc == 0) { return false; } loopAnalysis->isCountUpLoop = ivInfo->inc > 0; break; } } /* Find the block that ends with a branch to exit the loop */ while (true) { loopBackBlock = findPredecessorBlock(cUnit, loopBackBlock); /* Loop structure not recognized as counted blocks */ if (loopBackBlock == NULL) { return false; } /* Unconditional goto - continue to trace up the predecessor chain */ if (loopBackBlock->taken == NULL) { continue; } break; } MIR *branch = loopBackBlock->lastMIRInsn; Opcode opcode = branch->dalvikInsn.opcode; /* Last instruction is not a conditional branch - bail */ if (dexGetFlagsFromOpcode(opcode) != (kInstrCanContinue|kInstrCanBranch)) { return false; } int endSSAReg; int endDalvikReg; /* reg/reg comparison */ if (branch->ssaRep->numUses == 2) { if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) { endSSAReg = branch->ssaRep->uses[1]; } else if (branch->ssaRep->uses[1] == loopAnalysis->ssaBIV) { endSSAReg = branch->ssaRep->uses[0]; opcode = negateOpcode(opcode); } else { return false; } endDalvikReg = dvmConvertSSARegToDalvik(cUnit, endSSAReg); /* * If the comparison is not between the BIV and a loop invariant, * return false. endDalvikReg is loop invariant if one of the * following is true: * - It is not defined in the loop (ie DECODE_SUB returns 0) * - It is reloaded with a constant */ if ((DECODE_SUB(endDalvikReg) != 0) && !dvmIsBitSet(cUnit->isConstantV, endSSAReg)) { return false; } /* Compare against zero */ } else if (branch->ssaRep->numUses == 1) { if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) { /* Keep the compiler happy */ endDalvikReg = -1; } else { return false; } } else { return false; } /* Normalize the loop exit check as "if (iv op end) exit;" */ if (loopBackBlock->taken->blockType == kDalvikByteCode) { opcode = negateOpcode(opcode); } if (loopAnalysis->isCountUpLoop) { /* * If the normalized condition op is not > or >=, this is not an * optimization candidate. */ switch (opcode) { case OP_IF_GT: case OP_IF_GE: break; default: return false; } loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg); } else { /* * If the normalized condition op is not < or <=, this is not an * optimization candidate. */ switch (opcode) { case OP_IF_LT: case OP_IF_LE: loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg); break; case OP_IF_LTZ: case OP_IF_LEZ: break; default: return false; } } /* * Remember the normalized opcode, which will be used to determine the end * value used for the yanked range checks. */ loopAnalysis->loopBranchOpcode = opcode; return true; }