blob: 6492187260ebbe88eec4f9d727231038c1b62167 [file] [log] [blame]
Ben Cheng4238ec22009-08-24 16:32:22 -07001/*
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/*
25 * Given the current simple natural loops, the phi node placement can be
26 * determined in the following fashion:
27 * entry (B0)
28 * +---v v
29 * | loop body (B1)
30 * | v
31 * | loop back (B2)
32 * +---+ v
33 * exit (B3)
34 *
35 * 1) Add live-ins of B1 to B0 as defs
36 * 2) The intersect of defs(B0)/defs(B1) and defs(B2)/def(B0) are the variables
37 * that need PHI nodes in B1.
38 */
39static void handlePhiPlacement(CompilationUnit *cUnit)
40{
41 BasicBlock *entry = cUnit->blockList[0];
42 BasicBlock *loopBody = cUnit->blockList[1];
43 BasicBlock *loopBranch = cUnit->blockList[2];
44 dvmCopyBitVector(entry->dataFlowInfo->defV,
45 loopBody->dataFlowInfo->liveInV);
46
47 BitVector *phiV = dvmCompilerAllocBitVector(cUnit->method->registersSize,
48 false);
49 dvmIntersectBitVectors(phiV, entry->dataFlowInfo->defV,
50 loopBody->dataFlowInfo->defV);
51 dvmIntersectBitVectors(phiV, entry->dataFlowInfo->defV,
52 loopBranch->dataFlowInfo->defV);
53
54 /* Insert the PHI MIRs */
55 int i;
56 for (i = 0; i < cUnit->method->registersSize; i++) {
57 if (!dvmIsBitSet(phiV, i)) {
58 continue;
59 }
60 MIR *phi = dvmCompilerNew(sizeof(MIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -070061 phi->dalvikInsn.opCode = kMirOpPhi;
Ben Cheng4238ec22009-08-24 16:32:22 -070062 phi->dalvikInsn.vA = i;
63 dvmCompilerPrependMIR(loopBody, phi);
64 }
65}
66
67static void fillPhiNodeContents(CompilationUnit *cUnit)
68{
69 BasicBlock *entry = cUnit->blockList[0];
70 BasicBlock *loopBody = cUnit->blockList[1];
71 BasicBlock *loopBranch = cUnit->blockList[2];
72 MIR *mir;
73
74 for (mir = loopBody->firstMIRInsn; mir; mir = mir->next) {
Bill Buzbee1465db52009-09-23 17:17:35 -070075 if (mir->dalvikInsn.opCode != kMirOpPhi) break;
Ben Cheng4238ec22009-08-24 16:32:22 -070076 int dalvikReg = mir->dalvikInsn.vA;
77
78 mir->ssaRep->numUses = 2;
79 mir->ssaRep->uses = dvmCompilerNew(sizeof(int) * 2, false);
80 mir->ssaRep->uses[0] =
81 DECODE_REG(entry->dataFlowInfo->dalvikToSSAMap[dalvikReg]);
82 mir->ssaRep->uses[1] =
83 DECODE_REG(loopBranch->dataFlowInfo->dalvikToSSAMap[dalvikReg]);
84 }
85
86
87}
88
Ben Chengfc075c22010-05-28 15:20:08 -070089#if 0
90/* Debugging routines */
Ben Cheng4238ec22009-08-24 16:32:22 -070091static void dumpConstants(CompilationUnit *cUnit)
92{
93 int i;
94 for (i = 0; i < cUnit->numSSARegs; i++) {
95 if (dvmIsBitSet(cUnit->isConstantV, i)) {
96 int subNReg = dvmConvertSSARegToDalvik(cUnit, i);
97 LOGE("s%d(v%d_%d) has %d", i,
98 DECODE_REG(subNReg), DECODE_SUB(subNReg),
99 cUnit->constantValues[i]);
100 }
101 }
102}
103
104static void dumpIVList(CompilationUnit *cUnit)
105{
106 unsigned int i;
107 GrowableList *ivList = cUnit->loopAnalysis->ivList;
108 int *ssaToDalvikMap = (int *) cUnit->ssaToDalvikMap->elemList;
109
110 for (i = 0; i < ivList->numUsed; i++) {
111 InductionVariableInfo *ivInfo = ivList->elemList[i];
112 /* Basic IV */
113 if (ivInfo->ssaReg == ivInfo->basicSSAReg) {
114 LOGE("BIV %d: s%d(v%d) + %d", i,
115 ivInfo->ssaReg,
116 ssaToDalvikMap[ivInfo->ssaReg] & 0xffff,
117 ivInfo->inc);
118 /* Dependent IV */
119 } else {
120 LOGE("DIV %d: s%d(v%d) = %d * s%d(v%d) + %d", i,
121 ivInfo->ssaReg,
122 ssaToDalvikMap[ivInfo->ssaReg] & 0xffff,
123 ivInfo->m,
124 ivInfo->basicSSAReg,
125 ssaToDalvikMap[ivInfo->basicSSAReg] & 0xffff,
126 ivInfo->c);
127 }
128 }
129}
130
Ben Chengfc075c22010-05-28 15:20:08 -0700131static void dumpHoistedChecks(CompilationUnit *cUnit)
132{
133 LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
134 unsigned int i;
135
136 for (i = 0; i < loopAnalysis->arrayAccessInfo->numUsed; i++) {
137 ArrayAccessInfo *arrayAccessInfo =
138 GET_ELEM_N(loopAnalysis->arrayAccessInfo,
139 ArrayAccessInfo*, i);
140 int arrayReg = DECODE_REG(
141 dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->arrayReg));
142 int idxReg = DECODE_REG(
143 dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->ivReg));
144 LOGE("Array access %d", i);
145 LOGE(" arrayReg %d", arrayReg);
146 LOGE(" idxReg %d", idxReg);
147 LOGE(" endReg %d", loopAnalysis->endConditionReg);
148 LOGE(" maxC %d", arrayAccessInfo->maxC);
149 LOGE(" minC %d", arrayAccessInfo->minC);
150 LOGE(" opcode %d", loopAnalysis->loopBranchOpcode);
151 }
152}
153
154#endif
155
Ben Cheng4238ec22009-08-24 16:32:22 -0700156/*
157 * A loop is considered optimizable if:
158 * 1) It has one basic induction variable
159 * 2) The loop back branch compares the BIV with a constant
160 * 3) If it is a count-up loop, the condition is GE/GT, or LE/LT/LEZ/LTZ for
161 * a count-down loop.
Ben Cheng4a419582010-08-04 13:23:09 -0700162 *
163 * Return false if the loop is not optimizable.
Ben Cheng4238ec22009-08-24 16:32:22 -0700164 */
165static bool isLoopOptimizable(CompilationUnit *cUnit)
166{
167 unsigned int i;
168 BasicBlock *loopBranch = cUnit->blockList[2];
169 LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
170
171 if (loopAnalysis->numBasicIV != 1) return false;
172 for (i = 0; i < loopAnalysis->ivList->numUsed; i++) {
173 InductionVariableInfo *ivInfo;
174
175 ivInfo = GET_ELEM_N(loopAnalysis->ivList, InductionVariableInfo*, i);
176 /* Count up or down loop? */
177 if (ivInfo->ssaReg == ivInfo->basicSSAReg) {
Ben Cheng4a419582010-08-04 13:23:09 -0700178 /* Infinite loop */
179 if (ivInfo->inc == 0) {
180 return false;
181 }
Ben Cheng4238ec22009-08-24 16:32:22 -0700182 loopAnalysis->isCountUpLoop = ivInfo->inc > 0;
183 break;
184 }
185 }
186
187 MIR *branch = loopBranch->lastMIRInsn;
188 OpCode opCode = branch->dalvikInsn.opCode;
189
190 /*
191 * If the instruction is not accessing the IV as the first operand, return
192 * false.
193 */
194 if (branch->ssaRep->numUses == 0 || branch->ssaRep->numDefs != 0) {
195 return false;
196 }
197
198 /*
199 * If the first operand of the comparison is not the basic induction
200 * variable, return false.
201 */
202 if (branch->ssaRep->uses[0] != loopAnalysis->ssaBIV) {
203 return false;
204 }
205
206 if (loopAnalysis->isCountUpLoop) {
207 /*
208 * If the condition op is not > or >=, this is not an optimization
209 * candidate.
210 */
211 if (opCode != OP_IF_GT && opCode != OP_IF_GE) {
212 return false;
213 }
214 /*
215 * If the comparison is not between the BIV and a loop invariant,
Ben Cheng4a419582010-08-04 13:23:09 -0700216 * return false. endReg is loop invariant if one of the following is
217 * true:
218 * - It is not defined in the loop (ie DECODE_SUB returns 0)
219 * - It is reloaded with a constant
Ben Cheng4238ec22009-08-24 16:32:22 -0700220 */
221 int endReg = dvmConvertSSARegToDalvik(cUnit, branch->ssaRep->uses[1]);
Ben Cheng4a419582010-08-04 13:23:09 -0700222 if (DECODE_SUB(endReg) != 0 &&
223 !dvmIsBitSet(cUnit->isConstantV, branch->ssaRep->uses[1])) {
Ben Cheng4238ec22009-08-24 16:32:22 -0700224 return false;
225 }
226 loopAnalysis->endConditionReg = DECODE_REG(endReg);
227 } else {
228 /*
229 * If the condition op is not < or <=, this is not an optimization
230 * candidate.
231 */
232 if (opCode == OP_IF_LT || opCode == OP_IF_LE) {
233 /*
234 * If the comparison is not between the BIV and a loop invariant,
235 * return false.
236 */
237 int endReg = dvmConvertSSARegToDalvik(cUnit,
238 branch->ssaRep->uses[1]);
239
240 if (DECODE_SUB(endReg) != 0) {
241 return false;
242 }
243 loopAnalysis->endConditionReg = DECODE_REG(endReg);
244 } else if (opCode != OP_IF_LTZ && opCode != OP_IF_LEZ) {
245 return false;
246 }
247 }
248 loopAnalysis->loopBranchOpcode = opCode;
249 return true;
250}
251
252/*
253 * Record the upper and lower bound information for range checks for each
254 * induction variable. If array A is accessed by index "i+5", the upper and
255 * lower bound will be len(A)-5 and -5, respectively.
256 */
257static void updateRangeCheckInfo(CompilationUnit *cUnit, int arrayReg,
258 int idxReg)
259{
260 InductionVariableInfo *ivInfo;
261 LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
262 unsigned int i, j;
263
264 for (i = 0; i < loopAnalysis->ivList->numUsed; i++) {
265 ivInfo = GET_ELEM_N(loopAnalysis->ivList, InductionVariableInfo*, i);
266 if (ivInfo->ssaReg == idxReg) {
267 ArrayAccessInfo *arrayAccessInfo = NULL;
268 for (j = 0; j < loopAnalysis->arrayAccessInfo->numUsed; j++) {
269 ArrayAccessInfo *existingArrayAccessInfo =
270 GET_ELEM_N(loopAnalysis->arrayAccessInfo,
271 ArrayAccessInfo*,
272 j);
273 if (existingArrayAccessInfo->arrayReg == arrayReg) {
274 if (ivInfo->c > existingArrayAccessInfo->maxC) {
275 existingArrayAccessInfo->maxC = ivInfo->c;
276 }
277 if (ivInfo->c < existingArrayAccessInfo->minC) {
278 existingArrayAccessInfo->minC = ivInfo->c;
279 }
280 arrayAccessInfo = existingArrayAccessInfo;
281 break;
282 }
283 }
284 if (arrayAccessInfo == NULL) {
285 arrayAccessInfo =
286 dvmCompilerNew(sizeof(ArrayAccessInfo), false);
287 arrayAccessInfo->ivReg = ivInfo->basicSSAReg;
288 arrayAccessInfo->arrayReg = arrayReg;
289 arrayAccessInfo->maxC = (ivInfo->c > 0) ? ivInfo->c : 0;
290 arrayAccessInfo->minC = (ivInfo->c < 0) ? ivInfo->c : 0;
291 dvmInsertGrowableList(loopAnalysis->arrayAccessInfo,
292 arrayAccessInfo);
293 }
294 break;
295 }
296 }
297}
298
299/* Returns true if the loop body cannot throw any exceptions */
300static bool doLoopBodyCodeMotion(CompilationUnit *cUnit)
301{
Ben Cheng4238ec22009-08-24 16:32:22 -0700302 BasicBlock *loopBody = cUnit->blockList[1];
303 MIR *mir;
304 bool loopBodyCanThrow = false;
Ben Cheng4238ec22009-08-24 16:32:22 -0700305
306 for (mir = loopBody->firstMIRInsn; mir; mir = mir->next) {
307 DecodedInstruction *dInsn = &mir->dalvikInsn;
308 int dfAttributes =
309 dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
310
311 /* Skip extended MIR instructions */
312 if (dInsn->opCode > 255) continue;
313
Dan Bornstein41e286c2010-11-19 12:36:19 -0800314 int instrFlags = dexGetInstrFlags(dInsn->opCode);
Ben Cheng4238ec22009-08-24 16:32:22 -0700315
316 /* Instruction is clean */
317 if ((instrFlags & kInstrCanThrow) == 0) continue;
318
319 /*
320 * Currently we can only optimize away null and range checks. Punt on
321 * instructions that can throw due to other exceptions.
322 */
323 if (!(dfAttributes & DF_HAS_NR_CHECKS)) {
324 loopBodyCanThrow = true;
325 continue;
326 }
327
328 /*
329 * This comparison is redundant now, but we will have more than one
330 * group of flags to check soon.
331 */
332 if (dfAttributes & DF_HAS_NR_CHECKS) {
333 /*
334 * Check if the null check is applied on a loop invariant register?
335 * If the register's SSA id is less than the number of Dalvik
336 * registers, then it is loop invariant.
337 */
338 int refIdx;
339 switch (dfAttributes & DF_HAS_NR_CHECKS) {
340 case DF_NULL_N_RANGE_CHECK_0:
341 refIdx = 0;
342 break;
343 case DF_NULL_N_RANGE_CHECK_1:
344 refIdx = 1;
345 break;
346 case DF_NULL_N_RANGE_CHECK_2:
347 refIdx = 2;
348 break;
349 default:
350 refIdx = 0;
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800351 LOGE("Jit: bad case in doLoopBodyCodeMotion");
352 dvmCompilerAbort(cUnit);
Ben Cheng4238ec22009-08-24 16:32:22 -0700353 }
354
355 int useIdx = refIdx + 1;
356 int subNRegArray =
357 dvmConvertSSARegToDalvik(cUnit, mir->ssaRep->uses[refIdx]);
Ben Cheng4238ec22009-08-24 16:32:22 -0700358 int arraySub = DECODE_SUB(subNRegArray);
359
360 /*
361 * If the register is never updated in the loop (ie subscript == 0),
362 * it is an optimization candidate.
363 */
364 if (arraySub != 0) {
365 loopBodyCanThrow = true;
366 continue;
367 }
368
369 /*
370 * Then check if the range check can be hoisted out of the loop if
371 * it is basic or dependent induction variable.
372 */
373 if (dvmIsBitSet(cUnit->loopAnalysis->isIndVarV,
374 mir->ssaRep->uses[useIdx])) {
375 mir->OptimizationFlags |=
376 MIR_IGNORE_RANGE_CHECK | MIR_IGNORE_NULL_CHECK;
377 updateRangeCheckInfo(cUnit, mir->ssaRep->uses[refIdx],
378 mir->ssaRep->uses[useIdx]);
379 }
380 }
381 }
382
383 return !loopBodyCanThrow;
384}
385
Ben Cheng4238ec22009-08-24 16:32:22 -0700386static void genHoistedChecks(CompilationUnit *cUnit)
387{
388 unsigned int i;
389 BasicBlock *entry = cUnit->blockList[0];
390 LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
Ben Cheng4238ec22009-08-24 16:32:22 -0700391 int globalMaxC = 0;
392 int globalMinC = 0;
393 /* Should be loop invariant */
394 int idxReg = 0;
395
396 for (i = 0; i < loopAnalysis->arrayAccessInfo->numUsed; i++) {
397 ArrayAccessInfo *arrayAccessInfo =
398 GET_ELEM_N(loopAnalysis->arrayAccessInfo,
399 ArrayAccessInfo*, i);
400 int arrayReg = DECODE_REG(
401 dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->arrayReg));
402 idxReg = DECODE_REG(
403 dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->ivReg));
404
405 MIR *rangeCheckMIR = dvmCompilerNew(sizeof(MIR), true);
406 rangeCheckMIR->dalvikInsn.opCode = (loopAnalysis->isCountUpLoop) ?
Bill Buzbee1465db52009-09-23 17:17:35 -0700407 kMirOpNullNRangeUpCheck : kMirOpNullNRangeDownCheck;
Ben Cheng4238ec22009-08-24 16:32:22 -0700408 rangeCheckMIR->dalvikInsn.vA = arrayReg;
409 rangeCheckMIR->dalvikInsn.vB = idxReg;
410 rangeCheckMIR->dalvikInsn.vC = loopAnalysis->endConditionReg;
411 rangeCheckMIR->dalvikInsn.arg[0] = arrayAccessInfo->maxC;
412 rangeCheckMIR->dalvikInsn.arg[1] = arrayAccessInfo->minC;
413 rangeCheckMIR->dalvikInsn.arg[2] = loopAnalysis->loopBranchOpcode;
414 dvmCompilerAppendMIR(entry, rangeCheckMIR);
415 if (arrayAccessInfo->maxC > globalMaxC) {
416 globalMaxC = arrayAccessInfo->maxC;
417 }
418 if (arrayAccessInfo->minC < globalMinC) {
419 globalMinC = arrayAccessInfo->minC;
420 }
421 }
422
423 if (loopAnalysis->arrayAccessInfo->numUsed != 0) {
424 if (loopAnalysis->isCountUpLoop) {
425 MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700426 boundCheckMIR->dalvikInsn.opCode = kMirOpLowerBound;
Ben Cheng4238ec22009-08-24 16:32:22 -0700427 boundCheckMIR->dalvikInsn.vA = idxReg;
428 boundCheckMIR->dalvikInsn.vB = globalMinC;
429 dvmCompilerAppendMIR(entry, boundCheckMIR);
430 } else {
431 if (loopAnalysis->loopBranchOpcode == OP_IF_LT ||
432 loopAnalysis->loopBranchOpcode == OP_IF_LE) {
433 MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700434 boundCheckMIR->dalvikInsn.opCode = kMirOpLowerBound;
Ben Cheng4238ec22009-08-24 16:32:22 -0700435 boundCheckMIR->dalvikInsn.vA = loopAnalysis->endConditionReg;
436 boundCheckMIR->dalvikInsn.vB = globalMinC;
437 /*
Ben Cheng36bd1342010-10-25 20:54:31 -0700438 * If the end condition is ">" in the source, the check in the
439 * Dalvik bytecode is OP_IF_LE. In this case add 1 back to the
440 * constant field to reflect the fact that the smallest index
441 * value is "endValue + constant + 1".
Ben Cheng4238ec22009-08-24 16:32:22 -0700442 */
Ben Cheng36bd1342010-10-25 20:54:31 -0700443 if (loopAnalysis->loopBranchOpcode == OP_IF_LE) {
Ben Cheng4238ec22009-08-24 16:32:22 -0700444 boundCheckMIR->dalvikInsn.vB++;
445 }
446 dvmCompilerAppendMIR(entry, boundCheckMIR);
447 } else if (loopAnalysis->loopBranchOpcode == OP_IF_LTZ) {
448 /* Array index will fall below 0 */
449 if (globalMinC < 0) {
450 MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700451 boundCheckMIR->dalvikInsn.opCode = kMirOpPunt;
Ben Cheng4238ec22009-08-24 16:32:22 -0700452 dvmCompilerAppendMIR(entry, boundCheckMIR);
453 }
454 } else if (loopAnalysis->loopBranchOpcode == OP_IF_LEZ) {
455 /* Array index will fall below 0 */
456 if (globalMinC < -1) {
457 MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
Bill Buzbee1465db52009-09-23 17:17:35 -0700458 boundCheckMIR->dalvikInsn.opCode = kMirOpPunt;
Ben Cheng4238ec22009-08-24 16:32:22 -0700459 dvmCompilerAppendMIR(entry, boundCheckMIR);
460 }
461 } else {
Bill Buzbeefc519dc2010-03-06 23:30:57 -0800462 LOGE("Jit: bad case in genHoistedChecks");
463 dvmCompilerAbort(cUnit);
Ben Cheng4238ec22009-08-24 16:32:22 -0700464 }
465 }
466
467 }
468}
469
Ben Cheng4a419582010-08-04 13:23:09 -0700470/*
471 * Main entry point to do loop optimization.
472 * Return false if sanity checks for loop formation/optimization failed.
473 */
474bool dvmCompilerLoopOpt(CompilationUnit *cUnit)
Ben Cheng4238ec22009-08-24 16:32:22 -0700475{
Ben Cheng4238ec22009-08-24 16:32:22 -0700476 LoopAnalysis *loopAnalysis = dvmCompilerNew(sizeof(LoopAnalysis), true);
477
Ben Cheng7a2697d2010-06-07 13:44:23 -0700478 assert(cUnit->blockList[0]->blockType == kTraceEntryBlock);
Bill Buzbee1465db52009-09-23 17:17:35 -0700479 assert(cUnit->blockList[2]->blockType == kDalvikByteCode);
Ben Cheng7a2697d2010-06-07 13:44:23 -0700480 assert(cUnit->blockList[3]->blockType == kTraceExitBlock);
Ben Cheng4238ec22009-08-24 16:32:22 -0700481
482 cUnit->loopAnalysis = loopAnalysis;
483 /*
484 * Find live-in variables to the loop body so that we can fake their
485 * definitions in the entry block.
486 */
487 dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerFindLiveIn);
488
489 /* Insert phi nodes to the loop body */
490 handlePhiPlacement(cUnit);
491
492 dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion);
493 fillPhiNodeContents(cUnit);
494
495 /* Constant propagation */
496 cUnit->isConstantV = dvmAllocBitVector(cUnit->numSSARegs, false);
497 cUnit->constantValues = dvmCompilerNew(sizeof(int) * cUnit->numSSARegs,
498 true);
499 dvmCompilerDataFlowAnalysisDispatcher(cUnit,
500 dvmCompilerDoConstantPropagation);
501 DEBUG_LOOP(dumpConstants(cUnit);)
502
503 /* Find induction variables - basic and dependent */
504 loopAnalysis->ivList = dvmCompilerNew(sizeof(GrowableList), true);
505 dvmInitGrowableList(loopAnalysis->ivList, 4);
506 loopAnalysis->isIndVarV = dvmAllocBitVector(cUnit->numSSARegs, false);
507 dvmCompilerDataFlowAnalysisDispatcher(cUnit,
508 dvmCompilerFindInductionVariables);
509 DEBUG_LOOP(dumpIVList(cUnit);)
510
511 /* If the loop turns out to be non-optimizable, return early */
512 if (!isLoopOptimizable(cUnit))
Ben Cheng4a419582010-08-04 13:23:09 -0700513 return false;
Ben Cheng4238ec22009-08-24 16:32:22 -0700514
515 loopAnalysis->arrayAccessInfo = dvmCompilerNew(sizeof(GrowableList), true);
516 dvmInitGrowableList(loopAnalysis->arrayAccessInfo, 4);
517 loopAnalysis->bodyIsClean = doLoopBodyCodeMotion(cUnit);
518 DEBUG_LOOP(dumpHoistedChecks(cUnit);)
519
520 /*
521 * Convert the array access information into extended MIR code in the loop
522 * header.
523 */
524 genHoistedChecks(cUnit);
Ben Cheng4a419582010-08-04 13:23:09 -0700525 return true;
Ben Cheng4238ec22009-08-24 16:32:22 -0700526}