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); } } }
/* 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]); } } }
/* Setup a new SSA register for a given Dalvik register */ static void handleSSADef(CompilationUnit *cUnit, int *defs, int dalvikReg, int regIndex) { int encodedValue = cUnit->dalvikToSSAMap[dalvikReg]; int ssaReg = cUnit->numSSARegs++; /* Bump up the subscript */ int dalvikSub = DECODE_SUB(encodedValue) + 1; int newD2SMapping = ENCODE_REG_SUB(ssaReg, dalvikSub); cUnit->dalvikToSSAMap[dalvikReg] = newD2SMapping; int newS2DMapping = ENCODE_REG_SUB(dalvikReg, dalvikSub); dvmInsertGrowableList(cUnit->ssaToDalvikMap, (void *) newS2DMapping); LOG("the insert newS2DMapping is %x\n", newS2DMapping); defs[regIndex] = ssaReg; }
/* * 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; }