blob: d91734fcf420a20fb0efc06ed0e5ef6ecac8da68 [file] [log] [blame]
Ben Chenge9695e52009-06-16 16:11:47 -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 "vm/compiler/CompilerInternals.h"
Bill Buzbee89efc3d2009-07-28 11:22:22 -070019#include "ArmLIR.h"
Ben Cheng5d90c202009-11-22 23:31:11 -080020#include "Codegen.h"
Ben Chenge9695e52009-06-16 16:11:47 -070021
Ben Chengd7d426a2009-09-22 11:23:36 -070022#define DEBUG_OPT(X)
23
Bill Buzbee7ea0f642009-08-10 17:06:51 -070024ArmLIR* dvmCompilerGenCopy(CompilationUnit *cUnit, int rDest, int rSrc);
25
26/* Is this a Dalvik register access? */
27static inline bool isDalvikLoad(ArmLIR *lir)
28{
Bill Buzbee1f748632010-03-02 16:14:41 -080029 return (lir->useMask != ENCODE_ALL) && (lir->useMask & ENCODE_DALVIK_REG);
30}
31
32/* Is this a load from the literal pool? */
33static inline bool isLiteralLoad(ArmLIR *lir)
34{
35 return (lir->useMask != ENCODE_ALL) && (lir->useMask & ENCODE_LITERAL);
Bill Buzbee7ea0f642009-08-10 17:06:51 -070036}
37
38static inline bool isDalvikStore(ArmLIR *lir)
39{
Bill Buzbee1f748632010-03-02 16:14:41 -080040 return (lir->defMask != ENCODE_ALL) && (lir->defMask & ENCODE_DALVIK_REG);
Bill Buzbee7ea0f642009-08-10 17:06:51 -070041}
42
Ben Chenga4aaf682009-09-30 22:53:44 -070043static inline bool isDalvikRegisterClobbered(ArmLIR *lir1, ArmLIR *lir2)
Bill Buzbee270c1d62009-08-13 16:58:07 -070044{
Ben Chengd7d426a2009-09-22 11:23:36 -070045 int reg1Lo = DECODE_ALIAS_INFO_REG(lir1->aliasInfo);
46 int reg1Hi = reg1Lo + DECODE_ALIAS_INFO_WIDE(lir1->aliasInfo);
47 int reg2Lo = DECODE_ALIAS_INFO_REG(lir2->aliasInfo);
48 int reg2Hi = reg2Lo + DECODE_ALIAS_INFO_WIDE(lir2->aliasInfo);
49
Ben Chenga4aaf682009-09-30 22:53:44 -070050 return (reg1Lo == reg2Lo) || (reg1Lo == reg2Hi) || (reg1Hi == reg2Lo);
Bill Buzbee270c1d62009-08-13 16:58:07 -070051}
Ben Chengd7d426a2009-09-22 11:23:36 -070052
Ben Chengfc075c22010-05-28 15:20:08 -070053#if 0
54/* Debugging utility routine */
Ben Chengd7d426a2009-09-22 11:23:36 -070055static void dumpDependentInsnPair(ArmLIR *thisLIR, ArmLIR *checkLIR,
56 const char *optimization)
57{
58 LOGD("************ %s ************", optimization);
59 dvmDumpLIRInsn((LIR *) thisLIR, 0);
60 dvmDumpLIRInsn((LIR *) checkLIR, 0);
61}
Ben Chengfc075c22010-05-28 15:20:08 -070062#endif
Ben Chengd7d426a2009-09-22 11:23:36 -070063
Ben Chenge9695e52009-06-16 16:11:47 -070064/*
65 * Perform a pass of top-down walk to
66 * 1) Eliminate redundant loads and stores
67 * 2) Sink stores to latest possible slot
68 */
69static void applyLoadStoreElimination(CompilationUnit *cUnit,
Bill Buzbee89efc3d2009-07-28 11:22:22 -070070 ArmLIR *headLIR,
71 ArmLIR *tailLIR)
Ben Chenge9695e52009-06-16 16:11:47 -070072{
Bill Buzbee89efc3d2009-07-28 11:22:22 -070073 ArmLIR *thisLIR;
Ben Chenge9695e52009-06-16 16:11:47 -070074
75 cUnit->optRound++;
76 for (thisLIR = headLIR;
77 thisLIR != tailLIR;
78 thisLIR = NEXT_LIR(thisLIR)) {
79 /* Skip newly added instructions */
80 if (thisLIR->age >= cUnit->optRound) {
81 continue;
82 }
Bill Buzbee7ea0f642009-08-10 17:06:51 -070083 if (isDalvikStore(thisLIR)) {
Ben Chenge9695e52009-06-16 16:11:47 -070084 int nativeRegId = thisLIR->operands[0];
Bill Buzbee89efc3d2009-07-28 11:22:22 -070085 ArmLIR *checkLIR;
Ben Chenge9695e52009-06-16 16:11:47 -070086 int sinkDistance = 0;
Ben Chengdcf3e5d2009-09-11 13:42:05 -070087 /*
88 * Add r15 (pc) to the mask to prevent this instruction
Ben Chengd7d426a2009-09-22 11:23:36 -070089 * from sinking past branch instructions. Unset the Dalvik register
90 * bit when checking with native resource constraints.
Ben Chengdcf3e5d2009-09-11 13:42:05 -070091 */
Ben Chengd7d426a2009-09-22 11:23:36 -070092 u8 stopMask = (ENCODE_REG_PC | thisLIR->useMask) &
93 ~ENCODE_DALVIK_REG;
Ben Chenge9695e52009-06-16 16:11:47 -070094
95 for (checkLIR = NEXT_LIR(thisLIR);
96 checkLIR != tailLIR;
97 checkLIR = NEXT_LIR(checkLIR)) {
98
99 /* Check if a Dalvik register load is redundant */
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700100 if (isDalvikLoad(checkLIR) &&
Ben Chengd7d426a2009-09-22 11:23:36 -0700101 (checkLIR->aliasInfo == thisLIR->aliasInfo) &&
102 (REGTYPE(checkLIR->operands[0]) == REGTYPE(nativeRegId))) {
Ben Chenge9695e52009-06-16 16:11:47 -0700103 /* Insert a move to replace the load */
104 if (checkLIR->operands[0] != nativeRegId) {
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700105 ArmLIR *moveLIR;
Ben Cheng5d90c202009-11-22 23:31:11 -0800106 moveLIR = dvmCompilerRegCopyNoInsert(
107 cUnit, checkLIR->operands[0], nativeRegId);
Ben Chenge9695e52009-06-16 16:11:47 -0700108 /*
Ben Cheng58ece732010-03-17 23:32:26 -0700109 * Insert the converted checkLIR instruction after the
110 * the original checkLIR since the optimization is
111 * scannng in the top-down order and the new instruction
112 * will need to be checked.
Ben Chenge9695e52009-06-16 16:11:47 -0700113 */
Ben Cheng58ece732010-03-17 23:32:26 -0700114 dvmCompilerInsertLIRAfter((LIR *) checkLIR,
115 (LIR *) moveLIR);
Ben Chenge9695e52009-06-16 16:11:47 -0700116 }
117 checkLIR->isNop = true;
118 continue;
119
Ben Chengd7d426a2009-09-22 11:23:36 -0700120 /*
121 * Found a true output dependency - nuke the previous store.
122 * The register type doesn't matter here.
123 */
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700124 } else if (isDalvikStore(checkLIR) &&
Ben Chengd7d426a2009-09-22 11:23:36 -0700125 (checkLIR->aliasInfo == thisLIR->aliasInfo)) {
Ben Chenge9695e52009-06-16 16:11:47 -0700126 thisLIR->isNop = true;
127 break;
128 /* Find out the latest slot that the store can be sunk into */
129 } else {
Ben Chenge9695e52009-06-16 16:11:47 -0700130 /* Last instruction reached */
Ben Chengd7d426a2009-09-22 11:23:36 -0700131 bool stopHere = (NEXT_LIR(checkLIR) == tailLIR);
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700132
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700133 /* Store data is clobbered */
Ben Chengd7d426a2009-09-22 11:23:36 -0700134 stopHere |= ((stopMask & checkLIR->defMask) != 0);
135
136 /* Store data partially clobbers the Dalvik register */
137 if (stopHere == false &&
138 ((checkLIR->useMask | checkLIR->defMask) &
139 ENCODE_DALVIK_REG)) {
Ben Chenga4aaf682009-09-30 22:53:44 -0700140 stopHere = isDalvikRegisterClobbered(thisLIR, checkLIR);
Ben Chengd7d426a2009-09-22 11:23:36 -0700141 }
Ben Chenge9695e52009-06-16 16:11:47 -0700142
143 /* Found a new place to put the store - move it here */
144 if (stopHere == true) {
Ben Chengd7d426a2009-09-22 11:23:36 -0700145 DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR,
146 "SINK STORE"));
Ben Chenge9695e52009-06-16 16:11:47 -0700147 /* The store can be sunk for at least one cycle */
148 if (sinkDistance != 0) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700149 ArmLIR *newStoreLIR =
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800150 (ArmLIR *)dvmCompilerNew(sizeof(ArmLIR), true);
Ben Chenge9695e52009-06-16 16:11:47 -0700151 *newStoreLIR = *thisLIR;
152 newStoreLIR->age = cUnit->optRound;
153 /*
Ben Cheng63868fe2010-03-25 16:16:02 -0700154 * Stop point found - insert *before* the checkLIR
155 * since the instruction list is scanned in the
156 * top-down order.
Ben Chenge9695e52009-06-16 16:11:47 -0700157 */
158 dvmCompilerInsertLIRBefore((LIR *) checkLIR,
159 (LIR *) newStoreLIR);
160 thisLIR->isNop = true;
161 }
162 break;
163 }
164
165 /*
166 * Saw a real instruction that the store can be sunk after
167 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800168 if (!isPseudoOpcode(checkLIR->opcode)) {
Ben Chenge9695e52009-06-16 16:11:47 -0700169 sinkDistance++;
170 }
171 }
172 }
173 }
174 }
175}
176
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700177static void applyLoadHoisting(CompilationUnit *cUnit,
178 ArmLIR *headLIR,
179 ArmLIR *tailLIR)
180{
181 ArmLIR *thisLIR;
Bill Buzbee1f748632010-03-02 16:14:41 -0800182 /*
183 * Don't want to hoist in front of first load following a barrier (or
184 * first instruction of the block.
185 */
186 bool firstLoad = true;
187 int maxHoist = dvmCompilerTargetOptHint(kMaxHoistDistance);
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700188
189 cUnit->optRound++;
190 for (thisLIR = headLIR;
191 thisLIR != tailLIR;
192 thisLIR = NEXT_LIR(thisLIR)) {
193 /* Skip newly added instructions */
194 if (thisLIR->age >= cUnit->optRound ||
195 thisLIR->isNop == true) {
196 continue;
197 }
Bill Buzbee1f748632010-03-02 16:14:41 -0800198
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800199 if (firstLoad && (EncodingMap[thisLIR->opcode].flags & IS_LOAD)) {
Bill Buzbee1f748632010-03-02 16:14:41 -0800200 /*
201 * Ensure nothing will be hoisted in front of this load because
202 * it's result will likely be needed soon.
203 */
204 thisLIR->defMask |= ENCODE_MEM_USE;
205 firstLoad = false;
206 }
207
208 firstLoad |= (thisLIR->defMask == ENCODE_ALL);
209
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700210 if (isDalvikLoad(thisLIR)) {
Ben Chengd7d426a2009-09-22 11:23:36 -0700211 int dRegId = DECODE_ALIAS_INFO_REG(thisLIR->aliasInfo);
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700212 int nativeRegId = thisLIR->operands[0];
213 ArmLIR *checkLIR;
214 int hoistDistance = 0;
Ben Cheng63868fe2010-03-25 16:16:02 -0700215 u8 stopUseMask = (ENCODE_REG_PC | thisLIR->useMask);
216 u8 stopDefMask = thisLIR->defMask;
217 u8 checkResult;
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700218
Ben Chengd7d426a2009-09-22 11:23:36 -0700219 /* First check if the load can be completely elinimated */
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700220 for (checkLIR = PREV_LIR(thisLIR);
221 checkLIR != headLIR;
222 checkLIR = PREV_LIR(checkLIR)) {
223
224 if (checkLIR->isNop) continue;
225
Ben Chengd7d426a2009-09-22 11:23:36 -0700226 /*
227 * Check if the Dalvik register is previously accessed
228 * with exactly the same type.
229 */
230 if ((isDalvikLoad(checkLIR) || isDalvikStore(checkLIR)) &&
231 (checkLIR->aliasInfo == thisLIR->aliasInfo) &&
232 (checkLIR->operands[0] == nativeRegId)) {
233 /*
234 * If it is previously accessed but with a different type,
235 * the search will terminate later at the point checking
236 * for partially overlapping stores.
237 */
238 thisLIR->isNop = true;
239 break;
240 }
241
242 /*
243 * No earlier use/def can reach this load if:
244 * 1) Head instruction is reached
Ben Cheng63868fe2010-03-25 16:16:02 -0700245 */
246 if (checkLIR == headLIR) {
247 break;
248 }
249
250 checkResult = (stopUseMask | stopDefMask) & checkLIR->defMask;
251
252 /*
253 * If both instructions are verified Dalvik accesses, clear the
254 * may- and must-alias bits to detect true resource
255 * dependencies.
256 */
257 if (checkResult & ENCODE_DALVIK_REG) {
258 checkResult &= ~(ENCODE_DALVIK_REG | ENCODE_FRAME_REF);
259 }
260
261 /*
Ben Chengd7d426a2009-09-22 11:23:36 -0700262 * 2) load target register is clobbered
263 * 3) A branch is seen (stopUseMask has the PC bit set).
264 */
Ben Cheng63868fe2010-03-25 16:16:02 -0700265 if (checkResult) {
Ben Chengd7d426a2009-09-22 11:23:36 -0700266 break;
267 }
268
269 /* Store data partially clobbers the Dalvik register */
270 if (isDalvikStore(checkLIR) &&
Ben Chenga4aaf682009-09-30 22:53:44 -0700271 isDalvikRegisterClobbered(thisLIR, checkLIR)) {
Ben Chengd7d426a2009-09-22 11:23:36 -0700272 break;
273 }
274 }
275
276 /* The load has been eliminated */
277 if (thisLIR->isNop) continue;
278
279 /*
280 * The load cannot be eliminated. See if it can be hoisted to an
281 * earlier spot.
282 */
283 for (checkLIR = PREV_LIR(thisLIR);
284 /* empty by intention */;
285 checkLIR = PREV_LIR(checkLIR)) {
286
287 if (checkLIR->isNop) continue;
288
Bill Buzbee1f748632010-03-02 16:14:41 -0800289 /*
290 * Check if the "thisLIR" load is redundant
291 * NOTE: At one point, we also triggered if the checkLIR
292 * instruction was a load. However, that tended to insert
293 * a load/use dependency because the full scheduler is
294 * not yet complete. When it is, we chould also trigger
295 * on loads.
296 */
297 if (isDalvikStore(checkLIR) &&
Ben Chengd7d426a2009-09-22 11:23:36 -0700298 (checkLIR->aliasInfo == thisLIR->aliasInfo) &&
299 (REGTYPE(checkLIR->operands[0]) == REGTYPE(nativeRegId))) {
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700300 /* Insert a move to replace the load */
301 if (checkLIR->operands[0] != nativeRegId) {
302 ArmLIR *moveLIR;
Ben Cheng5d90c202009-11-22 23:31:11 -0800303 moveLIR = dvmCompilerRegCopyNoInsert(
304 cUnit, nativeRegId, checkLIR->operands[0]);
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700305 /*
306 * Convert *thisLIR* load into a move
307 */
308 dvmCompilerInsertLIRAfter((LIR *) checkLIR,
309 (LIR *) moveLIR);
310 }
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700311 thisLIR->isNop = true;
312 break;
313
314 /* Find out if the load can be yanked past the checkLIR */
315 } else {
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700316 /* Last instruction reached */
Ben Chengd7d426a2009-09-22 11:23:36 -0700317 bool stopHere = (checkLIR == headLIR);
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700318
319 /* Base address is clobbered by checkLIR */
Ben Cheng63868fe2010-03-25 16:16:02 -0700320 checkResult = stopUseMask & checkLIR->defMask;
321 if (checkResult & ENCODE_DALVIK_REG) {
322 checkResult &= ~(ENCODE_DALVIK_REG | ENCODE_FRAME_REF);
323 }
324 stopHere |= (checkResult != 0);
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700325
326 /* Load target clobbers use/def in checkLIR */
Ben Cheng63868fe2010-03-25 16:16:02 -0700327 checkResult = stopDefMask &
328 (checkLIR->useMask | checkLIR->defMask);
329 if (checkResult & ENCODE_DALVIK_REG) {
330 checkResult &= ~(ENCODE_DALVIK_REG | ENCODE_FRAME_REF);
331 }
332 stopHere |= (checkResult != 0);
Ben Chengd7d426a2009-09-22 11:23:36 -0700333
334 /* Store data partially clobbers the Dalvik register */
335 if (stopHere == false &&
336 (checkLIR->defMask & ENCODE_DALVIK_REG)) {
Ben Chenga4aaf682009-09-30 22:53:44 -0700337 stopHere = isDalvikRegisterClobbered(thisLIR, checkLIR);
Ben Chengd7d426a2009-09-22 11:23:36 -0700338 }
339
340 /*
341 * Stop at an earlier Dalvik load if the offset of checkLIR
342 * is not less than thisLIR
343 *
344 * Experiments show that doing
345 *
346 * ldr r1, [r5, #16]
347 * ldr r0, [r5, #20]
348 *
349 * is much faster than
350 *
351 * ldr r0, [r5, #20]
352 * ldr r1, [r5, #16]
353 */
354 if (isDalvikLoad(checkLIR)) {
355 int dRegId2 =
356 DECODE_ALIAS_INFO_REG(checkLIR->aliasInfo);
357 if (dRegId2 <= dRegId) {
358 stopHere = true;
359 }
360 }
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700361
Bill Buzbee1f748632010-03-02 16:14:41 -0800362 /* Don't go too far */
363 stopHere |= (hoistDistance >= maxHoist);
364
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700365 /* Found a new place to put the load - move it here */
366 if (stopHere == true) {
Ben Chengd7d426a2009-09-22 11:23:36 -0700367 DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR,
368 "HOIST LOAD"));
Ben Cheng63868fe2010-03-25 16:16:02 -0700369 /* The load can be hoisted for at least one cycle */
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700370 if (hoistDistance != 0) {
371 ArmLIR *newLoadLIR =
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800372 (ArmLIR *)dvmCompilerNew(sizeof(ArmLIR), true);
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700373 *newLoadLIR = *thisLIR;
374 newLoadLIR->age = cUnit->optRound;
375 /*
Ben Cheng63868fe2010-03-25 16:16:02 -0700376 * Stop point found - insert *after* the checkLIR
377 * since the instruction list is scanned in the
378 * bottom-up order.
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700379 */
380 dvmCompilerInsertLIRAfter((LIR *) checkLIR,
381 (LIR *) newLoadLIR);
382 thisLIR->isNop = true;
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700383 }
384 break;
385 }
386
387 /*
Ben Chengd7d426a2009-09-22 11:23:36 -0700388 * Saw a real instruction that hosting the load is
389 * beneficial
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700390 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800391 if (!isPseudoOpcode(checkLIR->opcode)) {
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700392 hoistDistance++;
393 }
394 }
395 }
Bill Buzbee1f748632010-03-02 16:14:41 -0800396 } else if (isLiteralLoad(thisLIR)) {
397 int litVal = thisLIR->aliasInfo;
398 int nativeRegId = thisLIR->operands[0];
399 ArmLIR *checkLIR;
400 int hoistDistance = 0;
401 u8 stopUseMask = (ENCODE_REG_PC | thisLIR->useMask) &
402 ~ENCODE_LITPOOL_REF;
403 u8 stopDefMask = thisLIR->defMask & ~ENCODE_LITPOOL_REF;
404
405 /* First check if the load can be completely elinimated */
406 for (checkLIR = PREV_LIR(thisLIR);
407 checkLIR != headLIR;
408 checkLIR = PREV_LIR(checkLIR)) {
409
410 if (checkLIR->isNop) continue;
411
412 /* Reloading same literal into same tgt reg? Eliminate if so */
413 if (isLiteralLoad(checkLIR) &&
414 (checkLIR->aliasInfo == litVal) &&
415 (checkLIR->operands[0] == nativeRegId)) {
416 thisLIR->isNop = true;
417 break;
418 }
419
420 /*
421 * No earlier use/def can reach this load if:
422 * 1) Head instruction is reached
423 * 2) load target register is clobbered
424 * 3) A branch is seen (stopUseMask has the PC bit set).
425 */
426 if ((checkLIR == headLIR) ||
427 (stopUseMask | stopDefMask) & checkLIR->defMask) {
428 break;
429 }
430 }
431
432 /* The load has been eliminated */
433 if (thisLIR->isNop) continue;
434
435 /*
436 * The load cannot be eliminated. See if it can be hoisted to an
437 * earlier spot.
438 */
439 for (checkLIR = PREV_LIR(thisLIR);
440 /* empty by intention */;
441 checkLIR = PREV_LIR(checkLIR)) {
442
443 if (checkLIR->isNop) continue;
444
445 /*
446 * TUNING: once a full scheduler exists, check here
447 * for conversion of a redundant load into a copy similar
448 * to the way redundant loads are handled above.
449 */
450
451 /* Find out if the load can be yanked past the checkLIR */
452
453 /* Last instruction reached */
454 bool stopHere = (checkLIR == headLIR);
455
456 /* Base address is clobbered by checkLIR */
457 stopHere |= ((stopUseMask & checkLIR->defMask) != 0);
458
459 /* Load target clobbers use/def in checkLIR */
460 stopHere |= ((stopDefMask &
461 (checkLIR->useMask | checkLIR->defMask)) != 0);
462
463 /* Avoid re-ordering literal pool loads */
464 stopHere |= isLiteralLoad(checkLIR);
465
466 /* Don't go too far */
467 stopHere |= (hoistDistance >= maxHoist);
468
469 /* Found a new place to put the load - move it here */
470 if (stopHere == true) {
471 DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR,
472 "HOIST LOAD"));
473 /* The store can be hoisted for at least one cycle */
474 if (hoistDistance != 0) {
475 ArmLIR *newLoadLIR =
Carl Shapirofc75f3e2010-12-07 11:43:38 -0800476 (ArmLIR *)dvmCompilerNew(sizeof(ArmLIR), true);
Bill Buzbee1f748632010-03-02 16:14:41 -0800477 *newLoadLIR = *thisLIR;
478 newLoadLIR->age = cUnit->optRound;
479 /*
480 * Insertion is guaranteed to succeed since checkLIR
481 * is never the first LIR on the list
482 */
483 dvmCompilerInsertLIRAfter((LIR *) checkLIR,
484 (LIR *) newLoadLIR);
485 thisLIR->isNop = true;
486 }
487 break;
488 }
489
490 /*
491 * Saw a real instruction that hosting the load is
492 * beneficial
493 */
Dan Bornstein9a1f8162010-12-01 17:02:26 -0800494 if (!isPseudoOpcode(checkLIR->opcode)) {
Bill Buzbee1f748632010-03-02 16:14:41 -0800495 hoistDistance++;
496 }
497 }
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700498 }
499 }
500}
501
Ben Chenge9695e52009-06-16 16:11:47 -0700502void dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR,
503 LIR *tailLIR)
504{
Ben Chengdcf3e5d2009-09-11 13:42:05 -0700505 if (!(gDvmJit.disableOpt & (1 << kLoadStoreElimination))) {
506 applyLoadStoreElimination(cUnit, (ArmLIR *) headLIR,
507 (ArmLIR *) tailLIR);
508 }
509 if (!(gDvmJit.disableOpt & (1 << kLoadHoisting))) {
510 applyLoadHoisting(cUnit, (ArmLIR *) headLIR, (ArmLIR *) tailLIR);
511 }
Ben Chenge9695e52009-06-16 16:11:47 -0700512}