LocalOptimizations.cpp revision a4aaf68a8bafa44433ceff2bb957a481381aa9a8
1e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng/* 2e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * Copyright (C) 2009 The Android Open Source Project 3e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * 4e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 5e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * you may not use this file except in compliance with the License. 6e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * You may obtain a copy of the License at 7e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * 8e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * http://www.apache.org/licenses/LICENSE-2.0 9e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * 10e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * Unless required by applicable law or agreed to in writing, software 11e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * distributed under the License is distributed on an "AS IS" BASIS, 12e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * See the License for the specific language governing permissions and 14e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * limitations under the License. 15e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng */ 16e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng 17e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng#include "Dalvik.h" 18e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng#include "vm/compiler/CompilerInternals.h" 1989efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee#include "ArmLIR.h" 20e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng 21d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng#define DEBUG_OPT(X) 22d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 237ea0f64d067cd8a2213c2c04a3291335c34d9602Bill BuzbeeArmLIR* dvmCompilerGenCopy(CompilationUnit *cUnit, int rDest, int rSrc); 247ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee 257ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee/* Is this a Dalvik register access? */ 267ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbeestatic inline bool isDalvikLoad(ArmLIR *lir) 277ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee{ 28d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng return (lir->useMask != ~0ULL) && (lir->useMask & ENCODE_DALVIK_REG); 297ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee} 307ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee 317ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbeestatic inline bool isDalvikStore(ArmLIR *lir) 327ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee{ 33d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng return (lir->defMask != ~0ULL) && (lir->defMask & ENCODE_DALVIK_REG); 347ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee} 357ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee 36a4aaf68a8bafa44433ceff2bb957a481381aa9a8Ben Chengstatic inline bool isDalvikRegisterClobbered(ArmLIR *lir1, ArmLIR *lir2) 37270c1d64a192341be842f46734054c692bac061eBill Buzbee{ 38d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng int reg1Lo = DECODE_ALIAS_INFO_REG(lir1->aliasInfo); 39d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng int reg1Hi = reg1Lo + DECODE_ALIAS_INFO_WIDE(lir1->aliasInfo); 40d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng int reg2Lo = DECODE_ALIAS_INFO_REG(lir2->aliasInfo); 41d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng int reg2Hi = reg2Lo + DECODE_ALIAS_INFO_WIDE(lir2->aliasInfo); 42d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 43a4aaf68a8bafa44433ceff2bb957a481381aa9a8Ben Cheng return (reg1Lo == reg2Lo) || (reg1Lo == reg2Hi) || (reg1Hi == reg2Lo); 44d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng} 45d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 46d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Chengstatic void dumpDependentInsnPair(ArmLIR *thisLIR, ArmLIR *checkLIR, 47d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng const char *optimization) 48d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng{ 49d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng LOGD("************ %s ************", optimization); 50d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng dvmDumpLIRInsn((LIR *) thisLIR, 0); 51d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng dvmDumpLIRInsn((LIR *) checkLIR, 0); 52270c1d64a192341be842f46734054c692bac061eBill Buzbee} 53d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 54e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng/* 55e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * Perform a pass of top-down walk to 56e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * 1) Eliminate redundant loads and stores 57e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * 2) Sink stores to latest possible slot 58e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng */ 59e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Chengstatic void applyLoadStoreElimination(CompilationUnit *cUnit, 6089efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee ArmLIR *headLIR, 6189efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee ArmLIR *tailLIR) 62e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng{ 6389efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee ArmLIR *thisLIR; 64e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng 65e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng cUnit->optRound++; 66e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng for (thisLIR = headLIR; 67e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng thisLIR != tailLIR; 68e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng thisLIR = NEXT_LIR(thisLIR)) { 69e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng /* Skip newly added instructions */ 70e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng if (thisLIR->age >= cUnit->optRound) { 71e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng continue; 72e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng } 737ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee if (isDalvikStore(thisLIR)) { 74d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng int dRegId = DECODE_ALIAS_INFO_REG(thisLIR->aliasInfo); 75d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng int dRegIdHi = dRegId + DECODE_ALIAS_INFO_WIDE(thisLIR->aliasInfo); 76e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng int nativeRegId = thisLIR->operands[0]; 7789efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee ArmLIR *checkLIR; 78e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng int sinkDistance = 0; 79dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* 80dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng * Add r15 (pc) to the mask to prevent this instruction 81d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * from sinking past branch instructions. Unset the Dalvik register 82d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * bit when checking with native resource constraints. 83dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng */ 84d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng u8 stopMask = (ENCODE_REG_PC | thisLIR->useMask) & 85d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng ~ENCODE_DALVIK_REG; 86e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng 87e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng for (checkLIR = NEXT_LIR(thisLIR); 88e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng checkLIR != tailLIR; 89e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng checkLIR = NEXT_LIR(checkLIR)) { 90e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng 91e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng /* Check if a Dalvik register load is redundant */ 927ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee if (isDalvikLoad(checkLIR) && 93d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng (checkLIR->aliasInfo == thisLIR->aliasInfo) && 94d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng (REGTYPE(checkLIR->operands[0]) == REGTYPE(nativeRegId))) { 95e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng /* Insert a move to replace the load */ 96e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng if (checkLIR->operands[0] != nativeRegId) { 977ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee ArmLIR *moveLIR; 987ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee moveLIR = dvmCompilerRegCopy(cUnit, 997ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee checkLIR->operands[0], 1007ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee nativeRegId); 101e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng /* 102e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * Insertion is guaranteed to succeed since checkLIR 103e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * is never the first LIR on the list 104e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng */ 105e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng dvmCompilerInsertLIRBefore((LIR *) checkLIR, 106e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng (LIR *) moveLIR); 107e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng } 108e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng checkLIR->isNop = true; 109e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng continue; 110e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng 111d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* 112d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * Found a true output dependency - nuke the previous store. 113d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * The register type doesn't matter here. 114d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng */ 1157ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee } else if (isDalvikStore(checkLIR) && 116d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng (checkLIR->aliasInfo == thisLIR->aliasInfo)) { 117e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng thisLIR->isNop = true; 118e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng break; 119e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng /* Find out the latest slot that the store can be sunk into */ 120e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng } else { 121e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng /* Last instruction reached */ 122d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng bool stopHere = (NEXT_LIR(checkLIR) == tailLIR); 123a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee 124dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* Store data is clobbered */ 125d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng stopHere |= ((stopMask & checkLIR->defMask) != 0); 126d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 127d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* Store data partially clobbers the Dalvik register */ 128d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng if (stopHere == false && 129d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng ((checkLIR->useMask | checkLIR->defMask) & 130d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng ENCODE_DALVIK_REG)) { 131a4aaf68a8bafa44433ceff2bb957a481381aa9a8Ben Cheng stopHere = isDalvikRegisterClobbered(thisLIR, checkLIR); 132d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng } 133e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng 134e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng /* Found a new place to put the store - move it here */ 135e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng if (stopHere == true) { 136d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR, 137d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng "SINK STORE")); 138e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng /* The store can be sunk for at least one cycle */ 139e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng if (sinkDistance != 0) { 14089efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee ArmLIR *newStoreLIR = 14189efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee dvmCompilerNew(sizeof(ArmLIR), true); 142e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng *newStoreLIR = *thisLIR; 143e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng newStoreLIR->age = cUnit->optRound; 144e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng /* 145e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * Insertion is guaranteed to succeed since checkLIR 146e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * is never the first LIR on the list 147e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng */ 148e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng dvmCompilerInsertLIRBefore((LIR *) checkLIR, 149e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng (LIR *) newStoreLIR); 150e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng thisLIR->isNop = true; 151e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng } 152e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng break; 153e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng } 154e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng 155e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng /* 156e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng * Saw a real instruction that the store can be sunk after 157e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng */ 158e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng if (!isPseudoOpCode(checkLIR->opCode)) { 159e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng sinkDistance++; 160e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng } 161e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng } 162e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng } 163e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng } 164e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng } 165e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng} 166e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng 167dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Chengstatic void applyLoadHoisting(CompilationUnit *cUnit, 168dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng ArmLIR *headLIR, 169dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng ArmLIR *tailLIR) 170dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng{ 171dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng ArmLIR *thisLIR; 172dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng 173dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng cUnit->optRound++; 174dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng for (thisLIR = headLIR; 175dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng thisLIR != tailLIR; 176dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng thisLIR = NEXT_LIR(thisLIR)) { 177dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* Skip newly added instructions */ 178dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng if (thisLIR->age >= cUnit->optRound || 179dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng thisLIR->isNop == true) { 180dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng continue; 181dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } 182dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng if (isDalvikLoad(thisLIR)) { 183d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng int dRegId = DECODE_ALIAS_INFO_REG(thisLIR->aliasInfo); 184d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng int dRegIdHi = dRegId + DECODE_ALIAS_INFO_WIDE(thisLIR->aliasInfo); 185dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng int nativeRegId = thisLIR->operands[0]; 186dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng ArmLIR *checkLIR; 187dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng int hoistDistance = 0; 188d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng u8 stopUseMask = (ENCODE_REG_PC | thisLIR->useMask) & 189d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng ~ENCODE_DALVIK_REG; 190d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng u8 stopDefMask = thisLIR->defMask & ~ENCODE_DALVIK_REG; 191dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng 192d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* First check if the load can be completely elinimated */ 193dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng for (checkLIR = PREV_LIR(thisLIR); 194dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng checkLIR != headLIR; 195dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng checkLIR = PREV_LIR(checkLIR)) { 196dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng 197dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng if (checkLIR->isNop) continue; 198dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng 199d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* 200d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * Check if the Dalvik register is previously accessed 201d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * with exactly the same type. 202d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng */ 203d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng if ((isDalvikLoad(checkLIR) || isDalvikStore(checkLIR)) && 204d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng (checkLIR->aliasInfo == thisLIR->aliasInfo) && 205d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng (checkLIR->operands[0] == nativeRegId)) { 206d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* 207d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * If it is previously accessed but with a different type, 208d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * the search will terminate later at the point checking 209d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * for partially overlapping stores. 210d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng */ 211d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng thisLIR->isNop = true; 212d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng break; 213d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng } 214d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 215d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* 216d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * No earlier use/def can reach this load if: 217d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * 1) Head instruction is reached 218d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * 2) load target register is clobbered 219d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * 3) A branch is seen (stopUseMask has the PC bit set). 220d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng */ 221d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng if ((checkLIR == headLIR) || 222d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng (stopUseMask | stopDefMask) & checkLIR->defMask) { 223d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng break; 224d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng } 225d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 226d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* Store data partially clobbers the Dalvik register */ 227d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng if (isDalvikStore(checkLIR) && 228a4aaf68a8bafa44433ceff2bb957a481381aa9a8Ben Cheng isDalvikRegisterClobbered(thisLIR, checkLIR)) { 229d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng break; 230d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng } 231d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng } 232d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 233d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* The load has been eliminated */ 234d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng if (thisLIR->isNop) continue; 235d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 236d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* 237d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * The load cannot be eliminated. See if it can be hoisted to an 238d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * earlier spot. 239d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng */ 240d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng for (checkLIR = PREV_LIR(thisLIR); 241d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* empty by intention */; 242d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng checkLIR = PREV_LIR(checkLIR)) { 243d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 244d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng if (checkLIR->isNop) continue; 245d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 246dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* Check if the current load is redundant */ 247dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng if ((isDalvikLoad(checkLIR) || isDalvikStore(checkLIR)) && 248d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng (checkLIR->aliasInfo == thisLIR->aliasInfo) && 249d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng (REGTYPE(checkLIR->operands[0]) == REGTYPE(nativeRegId))) { 250dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* Insert a move to replace the load */ 251dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng if (checkLIR->operands[0] != nativeRegId) { 252dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng ArmLIR *moveLIR; 253dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng moveLIR = dvmCompilerRegCopy(cUnit, 254dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng nativeRegId, 255dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng checkLIR->operands[0]); 256dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* 257dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng * Convert *thisLIR* load into a move 258dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng */ 259dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng dvmCompilerInsertLIRAfter((LIR *) checkLIR, 260dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng (LIR *) moveLIR); 261dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } 262dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng thisLIR->isNop = true; 263dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng break; 264dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng 265dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* Find out if the load can be yanked past the checkLIR */ 266dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } else { 267dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* Last instruction reached */ 268d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng bool stopHere = (checkLIR == headLIR); 269dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng 270dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* Base address is clobbered by checkLIR */ 271d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng stopHere |= ((stopUseMask & checkLIR->defMask) != 0); 272dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng 273dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* Load target clobbers use/def in checkLIR */ 274d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng stopHere |= ((stopDefMask & 275d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng (checkLIR->useMask | checkLIR->defMask)) != 0); 276d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 277d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* Store data partially clobbers the Dalvik register */ 278d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng if (stopHere == false && 279d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng (checkLIR->defMask & ENCODE_DALVIK_REG)) { 280a4aaf68a8bafa44433ceff2bb957a481381aa9a8Ben Cheng stopHere = isDalvikRegisterClobbered(thisLIR, checkLIR); 281d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng } 282d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng 283d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng /* 284d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * Stop at an earlier Dalvik load if the offset of checkLIR 285d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * is not less than thisLIR 286d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * 287d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * Experiments show that doing 288d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * 289d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * ldr r1, [r5, #16] 290d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * ldr r0, [r5, #20] 291d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * 292d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * is much faster than 293d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * 294d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * ldr r0, [r5, #20] 295d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * ldr r1, [r5, #16] 296d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng */ 297d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng if (isDalvikLoad(checkLIR)) { 298d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng int dRegId2 = 299d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng DECODE_ALIAS_INFO_REG(checkLIR->aliasInfo); 300d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng if (dRegId2 <= dRegId) { 301d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng stopHere = true; 302d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng } 303d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng } 304dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng 305dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* Found a new place to put the load - move it here */ 306dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng if (stopHere == true) { 307d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR, 308d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng "HOIST LOAD")); 309dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* The store can be hoisted for at least one cycle */ 310dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng if (hoistDistance != 0) { 311dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng ArmLIR *newLoadLIR = 312dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng dvmCompilerNew(sizeof(ArmLIR), true); 313dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng *newLoadLIR = *thisLIR; 314dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng newLoadLIR->age = cUnit->optRound; 315dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* 316dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng * Insertion is guaranteed to succeed since checkLIR 317dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng * is never the first LIR on the list 318dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng */ 319dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng dvmCompilerInsertLIRAfter((LIR *) checkLIR, 320dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng (LIR *) newLoadLIR); 321dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng thisLIR->isNop = true; 322dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } 323dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng break; 324dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } 325dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng 326dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng /* 327d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * Saw a real instruction that hosting the load is 328d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * beneficial 329dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng */ 330dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng if (!isPseudoOpCode(checkLIR->opCode)) { 331dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng hoistDistance++; 332dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } 333dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } 334dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } 335dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } 336dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } 337dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng} 338dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng 339e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Chengvoid dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR, 340e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng LIR *tailLIR) 341e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng{ 342dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng if (!(gDvmJit.disableOpt & (1 << kLoadStoreElimination))) { 343dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng applyLoadStoreElimination(cUnit, (ArmLIR *) headLIR, 344dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng (ArmLIR *) tailLIR); 345dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } 346dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng if (!(gDvmJit.disableOpt & (1 << kLoadHoisting))) { 347dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng applyLoadHoisting(cUnit, (ArmLIR *) headLIR, (ArmLIR *) tailLIR); 348dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng } 349e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng} 350