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