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 #include "Dalvik.h" 18 #include "CompilerInternals.h" 19 #include "Dataflow.h" 20 #include "Loop.h" 21 22 #define DEBUG_LOOP(X) 23 24 #if 0 25 /* Debugging routines */ 26 static void dumpConstants(CompilationUnit *cUnit) 27 { 28 int i; 29 LOGE("LOOP starting offset: %x", cUnit->entryBlock->startOffset); 30 for (i = 0; i < cUnit->numSSARegs; i++) { 31 if (dvmIsBitSet(cUnit->isConstantV, i)) { 32 int subNReg = dvmConvertSSARegToDalvik(cUnit, i); 33 LOGE("CONST: s%d(v%d_%d) has %d", i, 34 DECODE_REG(subNReg), DECODE_SUB(subNReg), 35 cUnit->constantValues[i]); 36 } 37 } 38 } 39 40 static void dumpIVList(CompilationUnit *cUnit) 41 { 42 unsigned int i; 43 GrowableList *ivList = cUnit->loopAnalysis->ivList; 44 45 for (i = 0; i < ivList->numUsed; i++) { 46 InductionVariableInfo *ivInfo = 47 (InductionVariableInfo *) ivList->elemList[i]; 48 int iv = dvmConvertSSARegToDalvik(cUnit, ivInfo->ssaReg); 49 /* Basic IV */ 50 if (ivInfo->ssaReg == ivInfo->basicSSAReg) { 51 LOGE("BIV %d: s%d(v%d_%d) + %d", i, 52 ivInfo->ssaReg, 53 DECODE_REG(iv), DECODE_SUB(iv), 54 ivInfo->inc); 55 /* Dependent IV */ 56 } else { 57 int biv = dvmConvertSSARegToDalvik(cUnit, ivInfo->basicSSAReg); 58 59 LOGE("DIV %d: s%d(v%d_%d) = %d * s%d(v%d_%d) + %d", i, 60 ivInfo->ssaReg, 61 DECODE_REG(iv), DECODE_SUB(iv), 62 ivInfo->m, 63 ivInfo->basicSSAReg, 64 DECODE_REG(biv), DECODE_SUB(biv), 65 ivInfo->c); 66 } 67 } 68 } 69 70 static void dumpHoistedChecks(CompilationUnit *cUnit) 71 { 72 LoopAnalysis *loopAnalysis = cUnit->loopAnalysis; 73 unsigned int i; 74 75 for (i = 0; i < loopAnalysis->arrayAccessInfo->numUsed; i++) { 76 ArrayAccessInfo *arrayAccessInfo = 77 GET_ELEM_N(loopAnalysis->arrayAccessInfo, 78 ArrayAccessInfo*, i); 79 int arrayReg = DECODE_REG( 80 dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->arrayReg)); 81 int idxReg = DECODE_REG( 82 dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->ivReg)); 83 LOGE("Array access %d", i); 84 LOGE(" arrayReg %d", arrayReg); 85 LOGE(" idxReg %d", idxReg); 86 LOGE(" endReg %d", loopAnalysis->endConditionReg); 87 LOGE(" maxC %d", arrayAccessInfo->maxC); 88 LOGE(" minC %d", arrayAccessInfo->minC); 89 LOGE(" opcode %d", loopAnalysis->loopBranchOpcode); 90 } 91 } 92 93 #endif 94 95 static BasicBlock *findPredecessorBlock(const CompilationUnit *cUnit, 96 const BasicBlock *bb) 97 { 98 int numPred = dvmCountSetBits(bb->predecessors); 99 BitVectorIterator bvIterator; 100 dvmBitVectorIteratorInit(bb->predecessors, &bvIterator); 101 102 if (numPred == 1) { 103 int predIdx = dvmBitVectorIteratorNext(&bvIterator); 104 return (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 105 predIdx); 106 /* First loop block */ 107 } else if ((numPred == 2) && 108 dvmIsBitSet(bb->predecessors, cUnit->entryBlock->id)) { 109 while (true) { 110 int predIdx = dvmBitVectorIteratorNext(&bvIterator); 111 if (predIdx == cUnit->entryBlock->id) continue; 112 return (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 113 predIdx); 114 } 115 /* Doesn't support other shape of control flow yet */ 116 } else { 117 return NULL; 118 } 119 } 120 121 /* Used for normalized loop exit condition checks */ 122 static Opcode negateOpcode(Opcode opcode) 123 { 124 switch (opcode) { 125 /* reg/reg cmp */ 126 case OP_IF_EQ: 127 return OP_IF_NE; 128 case OP_IF_NE: 129 return OP_IF_EQ; 130 case OP_IF_LT: 131 return OP_IF_GE; 132 case OP_IF_GE: 133 return OP_IF_LT; 134 case OP_IF_GT: 135 return OP_IF_LE; 136 case OP_IF_LE: 137 return OP_IF_GT; 138 /* reg/zero cmp */ 139 case OP_IF_EQZ: 140 return OP_IF_NEZ; 141 case OP_IF_NEZ: 142 return OP_IF_EQZ; 143 case OP_IF_LTZ: 144 return OP_IF_GEZ; 145 case OP_IF_GEZ: 146 return OP_IF_LTZ; 147 case OP_IF_GTZ: 148 return OP_IF_LEZ; 149 case OP_IF_LEZ: 150 return OP_IF_GTZ; 151 default: 152 LOGE("opcode %d cannot be negated", opcode); 153 dvmAbort(); 154 break; 155 } 156 return (Opcode)-1; // unreached 157 } 158 159 /* 160 * A loop is considered optimizable if: 161 * 1) It has one basic induction variable. 162 * 2) The loop back branch compares the BIV with a constant. 163 * 3) We need to normalize the loop exit condition so that the loop is exited 164 * via the taken path. 165 * 4) If it is a count-up loop, the condition is GE/GT. Otherwise it is 166 * LE/LT/LEZ/LTZ for a count-down loop. 167 * 168 * Return false for loops that fail the above tests. 169 */ 170 static bool isSimpleCountedLoop(CompilationUnit *cUnit) 171 { 172 unsigned int i; 173 BasicBlock *loopBackBlock = cUnit->entryBlock->fallThrough; 174 LoopAnalysis *loopAnalysis = cUnit->loopAnalysis; 175 176 if (loopAnalysis->numBasicIV != 1) return false; 177 for (i = 0; i < loopAnalysis->ivList->numUsed; i++) { 178 InductionVariableInfo *ivInfo; 179 180 ivInfo = GET_ELEM_N(loopAnalysis->ivList, InductionVariableInfo*, i); 181 /* Count up or down loop? */ 182 if (ivInfo->ssaReg == ivInfo->basicSSAReg) { 183 /* Infinite loop */ 184 if (ivInfo->inc == 0) { 185 return false; 186 } 187 loopAnalysis->isCountUpLoop = ivInfo->inc > 0; 188 break; 189 } 190 } 191 192 /* Find the block that ends with a branch to exit the loop */ 193 while (true) { 194 loopBackBlock = findPredecessorBlock(cUnit, loopBackBlock); 195 /* Loop structure not recognized as counted blocks */ 196 if (loopBackBlock == NULL) { 197 return false; 198 } 199 /* Unconditional goto - continue to trace up the predecessor chain */ 200 if (loopBackBlock->taken == NULL) { 201 continue; 202 } 203 break; 204 } 205 206 MIR *branch = loopBackBlock->lastMIRInsn; 207 Opcode opcode = branch->dalvikInsn.opcode; 208 209 /* Last instruction is not a conditional branch - bail */ 210 if (dexGetFlagsFromOpcode(opcode) != (kInstrCanContinue|kInstrCanBranch)) { 211 return false; 212 } 213 214 int endSSAReg; 215 int endDalvikReg; 216 217 /* reg/reg comparison */ 218 if (branch->ssaRep->numUses == 2) { 219 if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) { 220 endSSAReg = branch->ssaRep->uses[1]; 221 } else if (branch->ssaRep->uses[1] == loopAnalysis->ssaBIV) { 222 endSSAReg = branch->ssaRep->uses[0]; 223 opcode = negateOpcode(opcode); 224 } else { 225 return false; 226 } 227 endDalvikReg = dvmConvertSSARegToDalvik(cUnit, endSSAReg); 228 /* 229 * If the comparison is not between the BIV and a loop invariant, 230 * return false. endDalvikReg is loop invariant if one of the 231 * following is true: 232 * - It is not defined in the loop (ie DECODE_SUB returns 0) 233 * - It is reloaded with a constant 234 */ 235 if ((DECODE_SUB(endDalvikReg) != 0) && 236 !dvmIsBitSet(cUnit->isConstantV, endSSAReg)) { 237 return false; 238 } 239 /* Compare against zero */ 240 } else if (branch->ssaRep->numUses == 1) { 241 if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) { 242 /* Keep the compiler happy */ 243 endDalvikReg = -1; 244 } else { 245 return false; 246 } 247 } else { 248 return false; 249 } 250 251 /* Normalize the loop exit check as "if (iv op end) exit;" */ 252 if (loopBackBlock->taken->blockType == kDalvikByteCode) { 253 opcode = negateOpcode(opcode); 254 } 255 256 if (loopAnalysis->isCountUpLoop) { 257 /* 258 * If the normalized condition op is not > or >=, this is not an 259 * optimization candidate. 260 */ 261 switch (opcode) { 262 case OP_IF_GT: 263 case OP_IF_GE: 264 break; 265 default: 266 return false; 267 } 268 loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg); 269 } else { 270 /* 271 * If the normalized condition op is not < or <=, this is not an 272 * optimization candidate. 273 */ 274 switch (opcode) { 275 case OP_IF_LT: 276 case OP_IF_LE: 277 loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg); 278 break; 279 case OP_IF_LTZ: 280 case OP_IF_LEZ: 281 break; 282 default: 283 return false; 284 } 285 } 286 /* 287 * Remember the normalized opcode, which will be used to determine the end 288 * value used for the yanked range checks. 289 */ 290 loopAnalysis->loopBranchOpcode = opcode; 291 return true; 292 } 293 294 /* 295 * Record the upper and lower bound information for range checks for each 296 * induction variable. If array A is accessed by index "i+5", the upper and 297 * lower bound will be len(A)-5 and -5, respectively. 298 */ 299 static void updateRangeCheckInfo(CompilationUnit *cUnit, int arrayReg, 300 int idxReg) 301 { 302 InductionVariableInfo *ivInfo; 303 LoopAnalysis *loopAnalysis = cUnit->loopAnalysis; 304 unsigned int i, j; 305 306 for (i = 0; i < loopAnalysis->ivList->numUsed; i++) { 307 ivInfo = GET_ELEM_N(loopAnalysis->ivList, InductionVariableInfo*, i); 308 if (ivInfo->ssaReg == idxReg) { 309 ArrayAccessInfo *arrayAccessInfo = NULL; 310 for (j = 0; j < loopAnalysis->arrayAccessInfo->numUsed; j++) { 311 ArrayAccessInfo *existingArrayAccessInfo = 312 GET_ELEM_N(loopAnalysis->arrayAccessInfo, 313 ArrayAccessInfo*, 314 j); 315 if (existingArrayAccessInfo->arrayReg == arrayReg) { 316 if (ivInfo->c > existingArrayAccessInfo->maxC) { 317 existingArrayAccessInfo->maxC = ivInfo->c; 318 } 319 if (ivInfo->c < existingArrayAccessInfo->minC) { 320 existingArrayAccessInfo->minC = ivInfo->c; 321 } 322 arrayAccessInfo = existingArrayAccessInfo; 323 break; 324 } 325 } 326 if (arrayAccessInfo == NULL) { 327 arrayAccessInfo = 328 (ArrayAccessInfo *)dvmCompilerNew(sizeof(ArrayAccessInfo), 329 false); 330 arrayAccessInfo->ivReg = ivInfo->basicSSAReg; 331 arrayAccessInfo->arrayReg = arrayReg; 332 arrayAccessInfo->maxC = (ivInfo->c > 0) ? ivInfo->c : 0; 333 arrayAccessInfo->minC = (ivInfo->c < 0) ? ivInfo->c : 0; 334 dvmInsertGrowableList(loopAnalysis->arrayAccessInfo, 335 (intptr_t) arrayAccessInfo); 336 } 337 break; 338 } 339 } 340 } 341 342 /* Returns true if the loop body cannot throw any exceptions */ 343 static bool doLoopBodyCodeMotion(CompilationUnit *cUnit) 344 { 345 BasicBlock *loopBody = cUnit->entryBlock->fallThrough; 346 MIR *mir; 347 bool loopBodyCanThrow = false; 348 349 for (mir = loopBody->firstMIRInsn; mir; mir = mir->next) { 350 DecodedInstruction *dInsn = &mir->dalvikInsn; 351 int dfAttributes = 352 dvmCompilerDataFlowAttributes[mir->dalvikInsn.opcode]; 353 354 /* Skip extended MIR instructions */ 355 if (dInsn->opcode >= kNumPackedOpcodes) continue; 356 357 int instrFlags = dexGetFlagsFromOpcode(dInsn->opcode); 358 359 /* Instruction is clean */ 360 if ((instrFlags & kInstrCanThrow) == 0) continue; 361 362 /* 363 * Currently we can only optimize away null and range checks. Punt on 364 * instructions that can throw due to other exceptions. 365 */ 366 if (!(dfAttributes & DF_HAS_NR_CHECKS)) { 367 loopBodyCanThrow = true; 368 continue; 369 } 370 371 /* 372 * This comparison is redundant now, but we will have more than one 373 * group of flags to check soon. 374 */ 375 if (dfAttributes & DF_HAS_NR_CHECKS) { 376 /* 377 * Check if the null check is applied on a loop invariant register? 378 * If the register's SSA id is less than the number of Dalvik 379 * registers, then it is loop invariant. 380 */ 381 int refIdx; 382 switch (dfAttributes & DF_HAS_NR_CHECKS) { 383 case DF_NULL_N_RANGE_CHECK_0: 384 refIdx = 0; 385 break; 386 case DF_NULL_N_RANGE_CHECK_1: 387 refIdx = 1; 388 break; 389 case DF_NULL_N_RANGE_CHECK_2: 390 refIdx = 2; 391 break; 392 default: 393 refIdx = 0; 394 LOGE("Jit: bad case in doLoopBodyCodeMotion"); 395 dvmCompilerAbort(cUnit); 396 } 397 398 int useIdx = refIdx + 1; 399 int subNRegArray = 400 dvmConvertSSARegToDalvik(cUnit, mir->ssaRep->uses[refIdx]); 401 int arraySub = DECODE_SUB(subNRegArray); 402 403 /* 404 * If the register is never updated in the loop (ie subscript == 0), 405 * it is an optimization candidate. 406 */ 407 if (arraySub != 0) { 408 loopBodyCanThrow = true; 409 continue; 410 } 411 412 /* 413 * Then check if the range check can be hoisted out of the loop if 414 * it is basic or dependent induction variable. 415 */ 416 if (dvmIsBitSet(cUnit->loopAnalysis->isIndVarV, 417 mir->ssaRep->uses[useIdx])) { 418 mir->OptimizationFlags |= 419 MIR_IGNORE_RANGE_CHECK | MIR_IGNORE_NULL_CHECK; 420 updateRangeCheckInfo(cUnit, mir->ssaRep->uses[refIdx], 421 mir->ssaRep->uses[useIdx]); 422 } 423 } 424 } 425 426 return !loopBodyCanThrow; 427 } 428 429 static void genHoistedChecks(CompilationUnit *cUnit) 430 { 431 unsigned int i; 432 BasicBlock *entry = cUnit->entryBlock; 433 LoopAnalysis *loopAnalysis = cUnit->loopAnalysis; 434 int globalMaxC = 0; 435 int globalMinC = 0; 436 /* Should be loop invariant */ 437 int idxReg = 0; 438 439 for (i = 0; i < loopAnalysis->arrayAccessInfo->numUsed; i++) { 440 ArrayAccessInfo *arrayAccessInfo = 441 GET_ELEM_N(loopAnalysis->arrayAccessInfo, 442 ArrayAccessInfo*, i); 443 int arrayReg = DECODE_REG( 444 dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->arrayReg)); 445 idxReg = DECODE_REG( 446 dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->ivReg)); 447 448 MIR *rangeCheckMIR = (MIR *)dvmCompilerNew(sizeof(MIR), true); 449 rangeCheckMIR->dalvikInsn.opcode = (loopAnalysis->isCountUpLoop) ? 450 (Opcode)kMirOpNullNRangeUpCheck : (Opcode)kMirOpNullNRangeDownCheck; 451 rangeCheckMIR->dalvikInsn.vA = arrayReg; 452 rangeCheckMIR->dalvikInsn.vB = idxReg; 453 rangeCheckMIR->dalvikInsn.vC = loopAnalysis->endConditionReg; 454 rangeCheckMIR->dalvikInsn.arg[0] = arrayAccessInfo->maxC; 455 rangeCheckMIR->dalvikInsn.arg[1] = arrayAccessInfo->minC; 456 rangeCheckMIR->dalvikInsn.arg[2] = loopAnalysis->loopBranchOpcode; 457 dvmCompilerAppendMIR(entry, rangeCheckMIR); 458 if (arrayAccessInfo->maxC > globalMaxC) { 459 globalMaxC = arrayAccessInfo->maxC; 460 } 461 if (arrayAccessInfo->minC < globalMinC) { 462 globalMinC = arrayAccessInfo->minC; 463 } 464 } 465 466 if (loopAnalysis->arrayAccessInfo->numUsed != 0) { 467 if (loopAnalysis->isCountUpLoop) { 468 MIR *boundCheckMIR = (MIR *)dvmCompilerNew(sizeof(MIR), true); 469 boundCheckMIR->dalvikInsn.opcode = (Opcode)kMirOpLowerBound; 470 boundCheckMIR->dalvikInsn.vA = idxReg; 471 boundCheckMIR->dalvikInsn.vB = globalMinC; 472 dvmCompilerAppendMIR(entry, boundCheckMIR); 473 } else { 474 if (loopAnalysis->loopBranchOpcode == OP_IF_LT || 475 loopAnalysis->loopBranchOpcode == OP_IF_LE) { 476 MIR *boundCheckMIR = (MIR *)dvmCompilerNew(sizeof(MIR), true); 477 boundCheckMIR->dalvikInsn.opcode = (Opcode)kMirOpLowerBound; 478 boundCheckMIR->dalvikInsn.vA = loopAnalysis->endConditionReg; 479 boundCheckMIR->dalvikInsn.vB = globalMinC; 480 /* 481 * If the end condition is ">" in the source, the check in the 482 * Dalvik bytecode is OP_IF_LE. In this case add 1 back to the 483 * constant field to reflect the fact that the smallest index 484 * value is "endValue + constant + 1". 485 */ 486 if (loopAnalysis->loopBranchOpcode == OP_IF_LE) { 487 boundCheckMIR->dalvikInsn.vB++; 488 } 489 dvmCompilerAppendMIR(entry, boundCheckMIR); 490 } else if (loopAnalysis->loopBranchOpcode == OP_IF_LTZ) { 491 /* Array index will fall below 0 */ 492 if (globalMinC < 0) { 493 MIR *boundCheckMIR = (MIR *)dvmCompilerNew(sizeof(MIR), 494 true); 495 boundCheckMIR->dalvikInsn.opcode = (Opcode)kMirOpPunt; 496 dvmCompilerAppendMIR(entry, boundCheckMIR); 497 } 498 } else if (loopAnalysis->loopBranchOpcode == OP_IF_LEZ) { 499 /* Array index will fall below 0 */ 500 if (globalMinC < -1) { 501 MIR *boundCheckMIR = (MIR *)dvmCompilerNew(sizeof(MIR), 502 true); 503 boundCheckMIR->dalvikInsn.opcode = (Opcode)kMirOpPunt; 504 dvmCompilerAppendMIR(entry, boundCheckMIR); 505 } 506 } else { 507 LOGE("Jit: bad case in genHoistedChecks"); 508 dvmCompilerAbort(cUnit); 509 } 510 } 511 } 512 } 513 514 void resetBlockEdges(BasicBlock *bb) 515 { 516 bb->taken = NULL; 517 bb->fallThrough = NULL; 518 bb->successorBlockList.blockListType = kNotUsed; 519 } 520 521 static bool clearPredecessorVector(struct CompilationUnit *cUnit, 522 struct BasicBlock *bb) 523 { 524 dvmClearAllBits(bb->predecessors); 525 return false; 526 } 527 528 bool dvmCompilerFilterLoopBlocks(CompilationUnit *cUnit) 529 { 530 BasicBlock *firstBB = cUnit->entryBlock->fallThrough; 531 532 int numPred = dvmCountSetBits(firstBB->predecessors); 533 /* 534 * A loop body should have at least two incoming edges. 535 */ 536 if (numPred < 2) return false; 537 538 GrowableList *blockList = &cUnit->blockList; 539 540 /* Record blocks included in the loop */ 541 dvmClearAllBits(cUnit->tempBlockV); 542 543 dvmCompilerSetBit(cUnit->tempBlockV, cUnit->entryBlock->id); 544 dvmCompilerSetBit(cUnit->tempBlockV, firstBB->id); 545 546 BasicBlock *bodyBB = firstBB; 547 548 /* 549 * First try to include the fall-through block in the loop, then the taken 550 * block. Stop loop formation on the first backward branch that enters the 551 * first block (ie only include the inner-most loop). 552 */ 553 while (true) { 554 /* Loop formed */ 555 if (bodyBB->taken == firstBB) { 556 /* Check if the fallThrough edge will cause a nested loop */ 557 if (bodyBB->fallThrough && 558 dvmIsBitSet(cUnit->tempBlockV, bodyBB->fallThrough->id)) { 559 return false; 560 } 561 /* Single loop formed */ 562 break; 563 } else if (bodyBB->fallThrough == firstBB) { 564 /* Check if the taken edge will cause a nested loop */ 565 if (bodyBB->taken && 566 dvmIsBitSet(cUnit->tempBlockV, bodyBB->taken->id)) { 567 return false; 568 } 569 /* Single loop formed */ 570 break; 571 } 572 573 /* Inner loops formed first - quit */ 574 if (bodyBB->fallThrough && 575 dvmIsBitSet(cUnit->tempBlockV, bodyBB->fallThrough->id)) { 576 return false; 577 } 578 if (bodyBB->taken && 579 dvmIsBitSet(cUnit->tempBlockV, bodyBB->taken->id)) { 580 return false; 581 } 582 583 if (bodyBB->fallThrough) { 584 if (bodyBB->fallThrough->iDom == bodyBB) { 585 bodyBB = bodyBB->fallThrough; 586 dvmCompilerSetBit(cUnit->tempBlockV, bodyBB->id); 587 /* 588 * Loop formation to be detected at the beginning of next 589 * iteration. 590 */ 591 continue; 592 } 593 } 594 if (bodyBB->taken) { 595 if (bodyBB->taken->iDom == bodyBB) { 596 bodyBB = bodyBB->taken; 597 dvmCompilerSetBit(cUnit->tempBlockV, bodyBB->id); 598 /* 599 * Loop formation to be detected at the beginning of next 600 * iteration. 601 */ 602 continue; 603 } 604 } 605 /* 606 * Current block is not the immediate dominator of either fallthrough 607 * nor taken block - bail out of loop formation. 608 */ 609 return false; 610 } 611 612 613 /* Now mark blocks not included in the loop as hidden */ 614 GrowableListIterator iterator; 615 dvmGrowableListIteratorInit(blockList, &iterator); 616 while (true) { 617 BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator); 618 if (bb == NULL) break; 619 if (!dvmIsBitSet(cUnit->tempBlockV, bb->id)) { 620 bb->hidden = true; 621 /* Clear the insn list */ 622 bb->firstMIRInsn = bb->lastMIRInsn = NULL; 623 resetBlockEdges(bb); 624 } 625 } 626 627 dvmCompilerDataFlowAnalysisDispatcher(cUnit, clearPredecessorVector, 628 kAllNodes, false /* isIterative */); 629 630 dvmGrowableListIteratorInit(blockList, &iterator); 631 while (true) { 632 BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator); 633 if (bb == NULL) break; 634 if (dvmIsBitSet(cUnit->tempBlockV, bb->id)) { 635 if (bb->taken) { 636 /* 637 * exit block means we run into control-flow that we don't want 638 * to handle. 639 */ 640 if (bb->taken == cUnit->exitBlock) { 641 return false; 642 } 643 if (bb->taken->hidden) { 644 bb->taken->blockType = kChainingCellNormal; 645 bb->taken->hidden = false; 646 } 647 dvmCompilerSetBit(bb->taken->predecessors, bb->id); 648 } 649 if (bb->fallThrough) { 650 /* 651 * exit block means we run into control-flow that we don't want 652 * to handle. 653 */ 654 if (bb->fallThrough == cUnit->exitBlock) { 655 return false; 656 } 657 if (bb->fallThrough->hidden) { 658 bb->fallThrough->blockType = kChainingCellNormal; 659 bb->fallThrough->hidden = false; 660 } 661 dvmCompilerSetBit(bb->fallThrough->predecessors, bb->id); 662 } 663 /* Loop blocks shouldn't contain any successor blocks (yet) */ 664 assert(bb->successorBlockList.blockListType == kNotUsed); 665 } 666 } 667 return true; 668 } 669 670 /* 671 * Main entry point to do loop optimization. 672 * Return false if sanity checks for loop formation/optimization failed. 673 */ 674 bool dvmCompilerLoopOpt(CompilationUnit *cUnit) 675 { 676 LoopAnalysis *loopAnalysis = 677 (LoopAnalysis *)dvmCompilerNew(sizeof(LoopAnalysis), true); 678 cUnit->loopAnalysis = loopAnalysis; 679 680 /* Constant propagation */ 681 cUnit->isConstantV = dvmAllocBitVector(cUnit->numSSARegs, false); 682 cUnit->constantValues = 683 (int *)dvmCompilerNew(sizeof(int) * cUnit->numSSARegs, 684 true); 685 dvmCompilerDataFlowAnalysisDispatcher(cUnit, 686 dvmCompilerDoConstantPropagation, 687 kAllNodes, 688 false /* isIterative */); 689 DEBUG_LOOP(dumpConstants(cUnit);) 690 691 /* Find induction variables - basic and dependent */ 692 loopAnalysis->ivList = 693 (GrowableList *)dvmCompilerNew(sizeof(GrowableList), true); 694 dvmInitGrowableList(loopAnalysis->ivList, 4); 695 loopAnalysis->isIndVarV = dvmAllocBitVector(cUnit->numSSARegs, false); 696 dvmCompilerDataFlowAnalysisDispatcher(cUnit, 697 dvmCompilerFindInductionVariables, 698 kAllNodes, 699 false /* isIterative */); 700 DEBUG_LOOP(dumpIVList(cUnit);) 701 702 /* Only optimize array accesses for simple counted loop for now */ 703 if (!isSimpleCountedLoop(cUnit)) 704 return false; 705 706 loopAnalysis->arrayAccessInfo = 707 (GrowableList *)dvmCompilerNew(sizeof(GrowableList), true); 708 dvmInitGrowableList(loopAnalysis->arrayAccessInfo, 4); 709 loopAnalysis->bodyIsClean = doLoopBodyCodeMotion(cUnit); 710 DEBUG_LOOP(dumpHoistedChecks(cUnit);) 711 712 /* 713 * Convert the array access information into extended MIR code in the loop 714 * header. 715 */ 716 genHoistedChecks(cUnit); 717 return true; 718 } 719 720 /* 721 * Select the target block of the backward branch. 722 */ 723 void dvmCompilerInsertBackwardChaining(CompilationUnit *cUnit) 724 { 725 /* 726 * If we are not in self-verification or profiling mode, the backward 727 * branch can go to the entryBlock->fallThrough directly. Suspend polling 728 * code will be generated along the backward branch to honor the suspend 729 * requests. 730 */ 731 #if !defined(WITH_SELF_VERIFICATION) 732 if (gDvmJit.profileMode != kTraceProfilingContinuous && 733 gDvmJit.profileMode != kTraceProfilingPeriodicOn) { 734 return; 735 } 736 #endif 737 /* 738 * In self-verification or profiling mode, the backward branch is altered 739 * to go to the backward chaining cell. Without using the backward chaining 740 * cell we won't be able to do check-pointing on the target PC, or count the 741 * number of iterations accurately. 742 */ 743 BasicBlock *firstBB = cUnit->entryBlock->fallThrough; 744 BasicBlock *backBranchBB = findPredecessorBlock(cUnit, firstBB); 745 if (backBranchBB->taken == firstBB) { 746 backBranchBB->taken = cUnit->backChainBlock; 747 } else { 748 assert(backBranchBB->fallThrough == firstBB); 749 backBranchBB->fallThrough = cUnit->backChainBlock; 750 } 751 cUnit->backChainBlock->startOffset = firstBB->startOffset; 752 } 753