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"
205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng#include "Codegen.h"
21e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
22d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng#define DEBUG_OPT(X)
23d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
247ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng/* Check RAW, WAR, and WAR dependency on the register operands */
257ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng#define CHECK_REG_DEP(use, def, check) ((def & check->useMask) || \
267ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                        ((use | def) & check->defMask))
277ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee
287ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng/* Scheduler heuristics */
297ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng#define MAX_HOIST_DISTANCE 20
307ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng#define LDLD_DISTANCE 4
317ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng#define LD_LATENCY 2
327ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee
33a4aaf68a8bafa44433ceff2bb957a481381aa9a8Ben Chengstatic inline bool isDalvikRegisterClobbered(ArmLIR *lir1, ArmLIR *lir2)
34270c1d64a192341be842f46734054c692bac061eBill Buzbee{
357ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    int reg1Lo = DECODE_ALIAS_INFO_REG(lir1->aliasInfo);
367ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    int reg1Hi = reg1Lo + DECODE_ALIAS_INFO_WIDE(lir1->aliasInfo);
377ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    int reg2Lo = DECODE_ALIAS_INFO_REG(lir2->aliasInfo);
387ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    int reg2Hi = reg2Lo + DECODE_ALIAS_INFO_WIDE(lir2->aliasInfo);
39d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
407ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    return (reg1Lo == reg2Lo) || (reg1Lo == reg2Hi) || (reg1Hi == reg2Lo);
41d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng}
42d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
43fc075c2d1ae63c26f96e0c6eeb72efc898dbebbfBen Cheng#if 0
44fc075c2d1ae63c26f96e0c6eeb72efc898dbebbfBen Cheng/* Debugging utility routine */
45d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Chengstatic void dumpDependentInsnPair(ArmLIR *thisLIR, ArmLIR *checkLIR,
46d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                                  const char *optimization)
47d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng{
48062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block    ALOGD("************ %s ************", optimization);
49d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    dvmDumpLIRInsn((LIR *) thisLIR, 0);
50d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    dvmDumpLIRInsn((LIR *) checkLIR, 0);
51270c1d64a192341be842f46734054c692bac061eBill Buzbee}
52fc075c2d1ae63c26f96e0c6eeb72efc898dbebbfBen Cheng#endif
53d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
547ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng/* Convert a more expensive instruction (ie load) into a move */
557ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Chengstatic void convertMemOpIntoMove(CompilationUnit *cUnit, ArmLIR *origLIR,
567ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                 int dest, int src)
577ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng{
587ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    /* Insert a move to replace the load */
597ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    ArmLIR *moveLIR;
607ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    moveLIR = dvmCompilerRegCopyNoInsert( cUnit, dest, src);
617ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    /*
627ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng     * Insert the converted instruction after the original since the
637ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng     * optimization is scannng in the top-down order and the new instruction
647ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng     * will need to be re-checked (eg the new dest clobbers the src used in
657ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng     * thisLIR).
667ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng     */
677ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    dvmCompilerInsertLIRAfter((LIR *) origLIR, (LIR *) moveLIR);
687ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng}
697ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
70e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng/*
717ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng * Perform a pass of top-down walk, from the second-last instruction in the
727ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng * superblock, to eliminate redundant loads and stores.
737ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng *
747ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng * An earlier load can eliminate a later load iff
757ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng *   1) They are must-aliases
767ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng *   2) The native register is not clobbered in between
777ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng *   3) The memory location is not written to in between
787ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng *
797ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng * An earlier store can eliminate a later load iff
807ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng *   1) They are must-aliases
817ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng *   2) The native register is not clobbered in between
827ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng *   3) The memory location is not written to in between
837ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng *
847ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng * A later store can be eliminated by an earlier store iff
857ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng *   1) They are must-aliases
867ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng *   2) The memory location is not written to in between
87e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng */
88e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Chengstatic void applyLoadStoreElimination(CompilationUnit *cUnit,
8989efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                                      ArmLIR *headLIR,
9089efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee                                      ArmLIR *tailLIR)
91e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng{
9289efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee    ArmLIR *thisLIR;
93e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
947ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    if (headLIR == tailLIR) return;
957ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
967ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    for (thisLIR = PREV_LIR(tailLIR);
977ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         thisLIR != headLIR;
987ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         thisLIR = PREV_LIR(thisLIR)) {
997ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        int sinkDistance = 0;
1007ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
1017ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        /* Skip non-interesting instructions */
1027ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        if ((thisLIR->flags.isNop == true) ||
1037ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            isPseudoOpcode(thisLIR->opcode) ||
1047ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            !(EncodingMap[thisLIR->opcode].flags & (IS_LOAD | IS_STORE))) {
105e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            continue;
106e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        }
1077ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
1087ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        int nativeRegId = thisLIR->operands[0];
1097ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        bool isThisLIRLoad = EncodingMap[thisLIR->opcode].flags & IS_LOAD;
1107ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        ArmLIR *checkLIR;
1117ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        /* Use the mem mask to determine the rough memory location */
1127ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        u8 thisMemMask = (thisLIR->useMask | thisLIR->defMask) & ENCODE_MEM;
1137ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
1147ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        /*
1157ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * Currently only eliminate redundant ld/st for constant and Dalvik
1167ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * register accesses.
1177ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         */
1187ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        if (!(thisMemMask & (ENCODE_LITERAL | ENCODE_DALVIK_REG))) continue;
1197ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
1207ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        /*
1217ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * Add r15 (pc) to the resource mask to prevent this instruction
1227ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * from sinking past branch instructions. Also take out the memory
1237ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * region bits since stopMask is used to check data/control
1247ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * dependencies.
1257ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         */
1267ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        u8 stopUseRegMask = (ENCODE_REG_PC | thisLIR->useMask) &
1277ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            ~ENCODE_MEM;
1287ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        u8 stopDefRegMask = thisLIR->defMask & ~ENCODE_MEM;
1297ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
1307ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        for (checkLIR = NEXT_LIR(thisLIR);
1317ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             checkLIR != tailLIR;
1327ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             checkLIR = NEXT_LIR(checkLIR)) {
1337ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
134243db252574a78ff7326e7446d9042e321314c4fBen Cheng            /*
135243db252574a78ff7326e7446d9042e321314c4fBen Cheng             * Skip already dead instructions (whose dataflow information is
136243db252574a78ff7326e7446d9042e321314c4fBen Cheng             * outdated and misleading).
137243db252574a78ff7326e7446d9042e321314c4fBen Cheng             */
138243db252574a78ff7326e7446d9042e321314c4fBen Cheng            if (checkLIR->flags.isNop) continue;
139243db252574a78ff7326e7446d9042e321314c4fBen Cheng
1407ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            u8 checkMemMask = (checkLIR->useMask | checkLIR->defMask) &
1417ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                              ENCODE_MEM;
1427ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            u8 aliasCondition = thisMemMask & checkMemMask;
1437ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            bool stopHere = false;
1447ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
145dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng            /*
1467ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             * Potential aliases seen - check the alias relations
147dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng             */
1487ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            if (checkMemMask != ENCODE_MEM && aliasCondition != 0) {
1497ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                bool isCheckLIRLoad = EncodingMap[checkLIR->opcode].flags &
1507ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                      IS_LOAD;
1517ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                if  (aliasCondition == ENCODE_LITERAL) {
1527ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    /*
1537ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                     * Should only see literal loads in the instruction
1547ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                     * stream.
1557ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                     */
1567ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    assert(!(EncodingMap[checkLIR->opcode].flags &
1577ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                             IS_STORE));
1587ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    /* Same value && same register type */
1597ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    if (checkLIR->aliasInfo == thisLIR->aliasInfo &&
1607ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        REGTYPE(checkLIR->operands[0]) == REGTYPE(nativeRegId)){
161e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng                        /*
1627ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                         * Different destination register - insert
1637ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                         * a move
164e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng                         */
1657ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        if (checkLIR->operands[0] != nativeRegId) {
1667ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            convertMemOpIntoMove(cUnit, checkLIR,
1677ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                                 checkLIR->operands[0],
1687ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                                 nativeRegId);
1697ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        }
1707ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        checkLIR->flags.isNop = true;
171d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                    }
1727ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                } else if (aliasCondition == ENCODE_DALVIK_REG) {
1737ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    /* Must alias */
1747ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    if (checkLIR->aliasInfo == thisLIR->aliasInfo) {
1757ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        /* Only optimize compatible registers */
1767ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        bool regCompatible =
1777ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            REGTYPE(checkLIR->operands[0]) ==
1787ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            REGTYPE(nativeRegId);
1797ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        if ((isThisLIRLoad && isCheckLIRLoad) ||
1807ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            (!isThisLIRLoad && isCheckLIRLoad)) {
1817ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            /* RAR or RAW */
1827ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            if (regCompatible) {
1837ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                /*
1847ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                 * Different destination register -
1857ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                 * insert a move
1867ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                 */
1877ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                if (checkLIR->operands[0] !=
1887ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                    nativeRegId) {
1897ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                    convertMemOpIntoMove(cUnit,
1907ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                                 checkLIR,
1917ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                                 checkLIR->operands[0],
1927ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                                 nativeRegId);
1937ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                }
1947ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                checkLIR->flags.isNop = true;
1957ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            } else {
1967ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                /*
1977ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                 * Destinaions are of different types -
1987ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                 * something complicated going on so
1997ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                 * stop looking now.
2007ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                 */
2017ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                stopHere = true;
2027ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            }
2037ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        } else if (isThisLIRLoad && !isCheckLIRLoad) {
2047ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            /* WAR - register value is killed */
2057ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            stopHere = true;
2067ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        } else if (!isThisLIRLoad && !isCheckLIRLoad) {
2077ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            /* WAW - nuke the earlier store */
208d72564ca7aa66c6d95b6ca34299258b65ecfd1cbBen Cheng                            thisLIR->flags.isNop = true;
2097ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                            stopHere = true;
210e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng                        }
2117ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    /* Partial overlap */
2127ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    } else if (isDalvikRegisterClobbered(thisLIR, checkLIR)) {
2137ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        /*
2147ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                         * It is actually ok to continue if checkLIR
2157ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                         * is a read. But it is hard to make a test
2167ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                         * case for this so we just stop here to be
2177ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                         * conservative.
2187ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                         */
2197ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        stopHere = true;
220e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng                    }
2217ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                }
2227ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                /* Memory content may be updated. Stop looking now. */
2237ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                if (stopHere) {
2247ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    break;
2257ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                /* The checkLIR has been transformed - check the next one */
2267ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                } else if (checkLIR->flags.isNop) {
2277ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    continue;
2287ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                }
2297ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            }
2307ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
231e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
2327ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            /*
2337ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             * this and check LIRs have no memory dependency. Now check if
2347ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             * their register operands have any RAW, WAR, and WAW
2357ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             * dependencies. If so, stop looking.
2367ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             */
2377ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            if (stopHere == false) {
2387ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                stopHere = CHECK_REG_DEP(stopUseRegMask, stopDefRegMask,
2397ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                         checkLIR);
2407ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            }
2417ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
2427ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            if (stopHere == true) {
2437ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR,
2447ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                                "REG CLOBBERED"));
2457ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                /* Only sink store instructions */
2467ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                if (sinkDistance && !isThisLIRLoad) {
2477ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    ArmLIR *newStoreLIR =
2487ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
2497ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    *newStoreLIR = *thisLIR;
250e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng                    /*
2517ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                     * Stop point found - insert *before* the checkLIR
2527ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                     * since the instruction list is scanned in the
2537ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                     * top-down order.
254e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng                     */
2557ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    dvmCompilerInsertLIRBefore((LIR *) checkLIR,
2567ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                               (LIR *) newStoreLIR);
2577ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    thisLIR->flags.isNop = true;
258e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng                }
2597ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                break;
2607ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            } else if (!checkLIR->flags.isNop) {
2617ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                sinkDistance++;
262e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            }
263e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng        }
264e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng    }
265e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng}
266e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng
2677ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng/*
2687ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng * Perform a pass of bottom-up walk, from the second instruction in the
2697ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng * superblock, to try to hoist loads to earlier slots.
2707ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng */
271dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Chengstatic void applyLoadHoisting(CompilationUnit *cUnit,
272dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng                              ArmLIR *headLIR,
273dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng                              ArmLIR *tailLIR)
274dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng{
2757ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    ArmLIR *thisLIR, *checkLIR;
2761f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee    /*
2777ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng     * Store the list of independent instructions that can be hoisted past.
2787ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng     * Will decide the best place to insert later.
2791f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee     */
2807ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    ArmLIR *prevInstList[MAX_HOIST_DISTANCE];
2817ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
2827ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    /* Empty block */
2837ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    if (headLIR == tailLIR) return;
284dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng
2857ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    /* Start from the second instruction */
2867ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng    for (thisLIR = NEXT_LIR(headLIR);
287dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng         thisLIR != tailLIR;
288dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng         thisLIR = NEXT_LIR(thisLIR)) {
2897ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
2907ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        /* Skip non-interesting instructions */
2917ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        if ((thisLIR->flags.isNop == true) ||
2927ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            isPseudoOpcode(thisLIR->opcode) ||
2937ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            !(EncodingMap[thisLIR->opcode].flags & IS_LOAD)) {
294dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng            continue;
295dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng        }
2961f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee
2977ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        u8 stopUseAllMask = thisLIR->useMask;
2987ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng
2997ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        /*
3007ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * Branches for null/range checks are marked with the true resource
3017ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * bits, and loads to Dalvik registers, constant pools, and non-alias
3027ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * locations are safe to be hoisted. So only mark the heap references
3037ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * conservatively here.
3047ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         */
3057ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        if (stopUseAllMask & ENCODE_HEAP_REF) {
3067ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            stopUseAllMask |= ENCODE_REG_PC;
3071f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee        }
3081f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee
3097ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        /* Similar as above, but just check for pure register dependency */
3107ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        u8 stopUseRegMask = stopUseAllMask & ~ENCODE_MEM;
3117ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        u8 stopDefRegMask = thisLIR->defMask & ~ENCODE_MEM;
3121f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee
3137ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        int nextSlot = 0;
3148402bdf3308aac0743e2c3af248c48202b8b2dc1Doug Kwan        bool stopHere = false;
315dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng
3167ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        /* Try to hoist the load to a good spot */
3177ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        for (checkLIR = PREV_LIR(thisLIR);
3187ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             checkLIR != headLIR;
3197ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             checkLIR = PREV_LIR(checkLIR)) {
320dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng
321243db252574a78ff7326e7446d9042e321314c4fBen Cheng            /*
322243db252574a78ff7326e7446d9042e321314c4fBen Cheng             * Skip already dead instructions (whose dataflow information is
323243db252574a78ff7326e7446d9042e321314c4fBen Cheng             * outdated and misleading).
324243db252574a78ff7326e7446d9042e321314c4fBen Cheng             */
3257ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            if (checkLIR->flags.isNop) continue;
326dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng
3277ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            u8 checkMemMask = checkLIR->defMask & ENCODE_MEM;
3287ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            u8 aliasCondition = stopUseAllMask & checkMemMask;
3297ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            stopHere = false;
330d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
3317ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            /* Potential WAR alias seen - check the exact relation */
3327ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            if (checkMemMask != ENCODE_MEM && aliasCondition != 0) {
3337ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                /* We can fully disambiguate Dalvik references */
3347ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                if (aliasCondition == ENCODE_DALVIK_REG) {
3357ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    /* Must alias or partually overlap */
3367ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    if ((checkLIR->aliasInfo == thisLIR->aliasInfo) ||
3377ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        isDalvikRegisterClobbered(thisLIR, checkLIR)) {
3387ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                        stopHere = true;
3397ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    }
3407ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                /* Conservatively treat all heap refs as may-alias */
3417ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                } else {
3427ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    assert(aliasCondition == ENCODE_HEAP_REF);
3437ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    stopHere = true;
344d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                }
3457ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                /* Memory content may be updated. Stop looking now. */
3467ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                if (stopHere) {
3477ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    prevInstList[nextSlot++] = checkLIR;
348d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                    break;
349d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                }
350d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            }
351d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
3527ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            if (stopHere == false) {
3537ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                stopHere = CHECK_REG_DEP(stopUseRegMask, stopDefRegMask,
3547ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                         checkLIR);
3557ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            }
356d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
357d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            /*
3587ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             * Store the dependent or non-pseudo/indepedent instruction to the
3597ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             * list.
360d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng             */
3617ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            if (stopHere || !isPseudoOpcode(checkLIR->opcode)) {
3627ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                prevInstList[nextSlot++] = checkLIR;
3637ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                if (nextSlot == MAX_HOIST_DISTANCE) break;
3647ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            }
365dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng
3667ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            /* Found a new place to put the load - move it here */
3677ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            if (stopHere == true) {
3687ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                DEBUG_OPT(dumpDependentInsnPair(checkLIR, thisLIR
3697ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                                "HOIST STOP"));
3707ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                break;
3717ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            }
3727ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        }
373dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng
3747ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        /*
3757ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * Reached the top - use headLIR as the dependent marker as all labels
3767ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * are barriers.
3777ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         */
3787ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        if (stopHere == false && nextSlot < MAX_HOIST_DISTANCE) {
3797ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            prevInstList[nextSlot++] = headLIR;
3807ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        }
381d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
3827ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        /*
3837ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * At least one independent instruction is found. Scan in the reversed
3847ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         * direction to find a beneficial slot.
3857ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng         */
3867ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng        if (nextSlot >= 2) {
3877ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            int firstSlot = nextSlot - 2;
3887ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            int slot;
3897ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            ArmLIR *depLIR = prevInstList[nextSlot-1];
3907ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            /* If there is ld-ld dependency, wait LDLD_DISTANCE cycles */
3917ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            if (!isPseudoOpcode(depLIR->opcode) &&
3927ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                (EncodingMap[depLIR->opcode].flags & IS_LOAD)) {
3937ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                firstSlot -= LDLD_DISTANCE;
3947ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            }
3957ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            /*
3967ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             * Make sure we check slot >= 0 since firstSlot may be negative
3977ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             * when the loop is first entered.
3987ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng             */
3997ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            for (slot = firstSlot; slot >= 0; slot--) {
4007ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                ArmLIR *curLIR = prevInstList[slot];
4017ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                ArmLIR *prevLIR = prevInstList[slot+1];
402d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
403513691130f0c1ab94f52127c40d0018bb7dfc529Ben Cheng                /*
404513691130f0c1ab94f52127c40d0018bb7dfc529Ben Cheng                 * Check the highest instruction.
405513691130f0c1ab94f52127c40d0018bb7dfc529Ben Cheng                 * ENCODE_ALL represents a scheduling barrier.
406513691130f0c1ab94f52127c40d0018bb7dfc529Ben Cheng                 */
4077ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                if (prevLIR->defMask == ENCODE_ALL) {
408d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                    /*
4097ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                     * If the first instruction is a load, don't hoist anything
4107ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                     * above it since it is unlikely to be beneficial.
411d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                     */
4127ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    if (EncodingMap[curLIR->opcode].flags & IS_LOAD) continue;
413dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng                    /*
414513691130f0c1ab94f52127c40d0018bb7dfc529Ben Cheng                     * Need to unconditionally break here even if the hoisted
415513691130f0c1ab94f52127c40d0018bb7dfc529Ben Cheng                     * distance is greater than LD_LATENCY (ie more than enough
416513691130f0c1ab94f52127c40d0018bb7dfc529Ben Cheng                     * cycles are inserted to hide the load latency) since theu
417513691130f0c1ab94f52127c40d0018bb7dfc529Ben Cheng                     * subsequent code doesn't expect to compare against a
418513691130f0c1ab94f52127c40d0018bb7dfc529Ben Cheng                     * pseudo opcode (whose opcode value is negative).
419dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng                     */
420513691130f0c1ab94f52127c40d0018bb7dfc529Ben Cheng                    break;
4211f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee                }
4221f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee
4231f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee                /*
4247ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                 * NOTE: now prevLIR is guaranteed to be a non-pseudo
4257ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                 * instruction (ie accessing EncodingMap[prevLIR->opcode] is
4267ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                 * safe).
4277ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                 *
4287ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                 * Try to find two instructions with load/use dependency until
4297ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                 * the remaining instructions are less than LD_LATENCY.
4301f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee                 */
4317ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                if (((curLIR->useMask & prevLIR->defMask) &&
4327ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                     (EncodingMap[prevLIR->opcode].flags & IS_LOAD)) ||
4337ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                    (slot < LD_LATENCY)) {
4341f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee                    break;
4351f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee                }
4361f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee            }
4371f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee
4387ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            /* Found a slot to hoist to */
4397ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng            if (slot >= 0) {
4407ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                ArmLIR *curLIR = prevInstList[slot];
4417ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                ArmLIR *newLoadLIR = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR),
4427ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                                               true);
4437ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                *newLoadLIR = *thisLIR;
4441f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee                /*
4457ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                 * Insertion is guaranteed to succeed since checkLIR
4467ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                 * is never the first LIR on the list
4471f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee                 */
4487ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                dvmCompilerInsertLIRBefore((LIR *) curLIR,
4497ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                                           (LIR *) newLoadLIR);
4507ab74e14ed8dac0e51ce72fc6283ee2f1ffdf087Ben Cheng                thisLIR->flags.isNop = true;
4511f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee            }
452dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng        }
453dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng    }
454dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng}
455dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng
456e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Chengvoid dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR,
457e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng                                        LIR *tailLIR)
458e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng{
459dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng    if (!(gDvmJit.disableOpt & (1 << kLoadStoreElimination))) {
460dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng        applyLoadStoreElimination(cUnit, (ArmLIR *) headLIR,
461dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng                                  (ArmLIR *) tailLIR);
462dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng    }
463dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng    if (!(gDvmJit.disableOpt & (1 << kLoadHoisting))) {
464dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng        applyLoadHoisting(cUnit, (ArmLIR *) headLIR, (ArmLIR *) tailLIR);
465dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng    }
466e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng}
467