1a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/*
2a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Copyright (C) 2009 The Android Open Source Project
3a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *
4a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Licensed under the Apache License, Version 2.0 (the "License");
5a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * you may not use this file except in compliance with the License.
6a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * You may obtain a copy of the License at
7a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *
8a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *      http://www.apache.org/licenses/LICENSE-2.0
9a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *
10a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Unless required by applicable law or agreed to in writing, software
11a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * distributed under the License is distributed on an "AS IS" BASIS,
12a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * See the License for the specific language governing permissions and
14a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * limitations under the License.
15a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */
16a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
17a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#include "Dalvik.h"
18a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#include "vm/compiler/CompilerInternals.h"
19a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#include "MipsLIR.h"
20a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#include "Codegen.h"
21a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
22a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define DEBUG_OPT(X)
23a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
24a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* Check RAW, WAR, and WAR dependency on the register operands */
25a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define CHECK_REG_DEP(use, def, check) ((def & check->useMask) || \
26a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                        ((use | def) & check->defMask))
27a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
28a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* Scheduler heuristics */
29a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define MAX_HOIST_DISTANCE 20
30a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define LDLD_DISTANCE 4
31a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define LD_LATENCY 2
32a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
33a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic inline bool isDalvikRegisterClobbered(MipsLIR *lir1, MipsLIR *lir2)
34a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{
35a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    int reg1Lo = DECODE_ALIAS_INFO_REG(lir1->aliasInfo);
36a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    int reg1Hi = reg1Lo + DECODE_ALIAS_INFO_WIDE(lir1->aliasInfo);
37a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    int reg2Lo = DECODE_ALIAS_INFO_REG(lir2->aliasInfo);
38a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    int reg2Hi = reg2Lo + DECODE_ALIAS_INFO_WIDE(lir2->aliasInfo);
39a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
40a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    return (reg1Lo == reg2Lo) || (reg1Lo == reg2Hi) || (reg1Hi == reg2Lo);
41a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham}
42a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
43a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if 0
44a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* Debugging utility routine */
45a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic void dumpDependentInsnPair(MipsLIR *thisLIR, MipsLIR *checkLIR,
46a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                  const char *optimization)
47a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{
48a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    LOGD("************ %s ************", optimization);
49a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    dvmDumpLIRInsn((LIR *) thisLIR, 0);
50a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    dvmDumpLIRInsn((LIR *) checkLIR, 0);
51a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham}
52a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif
53a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
54a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* Convert a more expensive instruction (ie load) into a move */
55a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic void convertMemOpIntoMove(CompilationUnit *cUnit, MipsLIR *origLIR,
56a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                 int dest, int src)
57a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{
58a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    /* Insert a move to replace the load */
59a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    MipsLIR *moveLIR;
60a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    moveLIR = dvmCompilerRegCopyNoInsert( cUnit, dest, src);
61a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    /*
62a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham     * Insert the converted instruction after the original since the
63a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham     * optimization is scannng in the top-down order and the new instruction
64a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham     * will need to be re-checked (eg the new dest clobbers the src used in
65a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham     * thisLIR).
66a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham     */
67a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    dvmCompilerInsertLIRAfter((LIR *) origLIR, (LIR *) moveLIR);
68a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham}
69a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
70a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/*
71a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Perform a pass of top-down walk, from the second-last instruction in the
72a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * superblock, to eliminate redundant loads and stores.
73a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *
74a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * An earlier load can eliminate a later load iff
75a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *   1) They are must-aliases
76a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *   2) The native register is not clobbered in between
77a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *   3) The memory location is not written to in between
78a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *
79a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * An earlier store can eliminate a later load iff
80a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *   1) They are must-aliases
81a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *   2) The native register is not clobbered in between
82a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *   3) The memory location is not written to in between
83a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *
84a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * A later store can be eliminated by an earlier store iff
85a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *   1) They are must-aliases
86a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *   2) The memory location is not written to in between
87a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */
88a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic void applyLoadStoreElimination(CompilationUnit *cUnit,
89a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                      MipsLIR *headLIR,
90a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                      MipsLIR *tailLIR)
91a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{
92a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    MipsLIR *thisLIR;
93a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
94a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    if (headLIR == tailLIR) return;
95a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
96a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    for (thisLIR = PREV_LIR(tailLIR);
97a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         thisLIR != headLIR;
98a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         thisLIR = PREV_LIR(thisLIR)) {
99a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        int sinkDistance = 0;
100a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
101a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        /* Skip non-interesting instructions */
102a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        if ((thisLIR->flags.isNop == true) ||
103a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            isPseudoOpCode(thisLIR->opcode) ||
104a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            !(EncodingMap[thisLIR->opcode].flags & (IS_LOAD | IS_STORE))) {
105a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            continue;
106a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        }
107a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
108a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        int nativeRegId = thisLIR->operands[0];
109a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        bool isThisLIRLoad = EncodingMap[thisLIR->opcode].flags & IS_LOAD;
110a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        MipsLIR *checkLIR;
111a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        /* Use the mem mask to determine the rough memory location */
112a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        u8 thisMemMask = (thisLIR->useMask | thisLIR->defMask) & ENCODE_MEM;
113a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
114a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        /*
115a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * Currently only eliminate redundant ld/st for constant and Dalvik
116a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * register accesses.
117a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         */
118a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        if (!(thisMemMask & (ENCODE_LITERAL | ENCODE_DALVIK_REG))) continue;
119a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
120a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        /*
121a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * Add r15 (pc) to the resource mask to prevent this instruction
122a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * from sinking past branch instructions. Also take out the memory
123a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * region bits since stopMask is used to check data/control
124a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * dependencies.
125a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         */
126a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        u8 stopUseRegMask = (ENCODE_REG_PC | thisLIR->useMask) &
127a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            ~ENCODE_MEM;
128a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        u8 stopDefRegMask = thisLIR->defMask & ~ENCODE_MEM;
129a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
130a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        for (checkLIR = NEXT_LIR(thisLIR);
131a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             checkLIR != tailLIR;
132a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             checkLIR = NEXT_LIR(checkLIR)) {
133a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
134a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            /*
135a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * Skip already dead instructions (whose dataflow information is
136a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * outdated and misleading).
137a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             */
138a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            if (checkLIR->flags.isNop) continue;
139a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
140a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            u8 checkMemMask = (checkLIR->useMask | checkLIR->defMask) &
141a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                              ENCODE_MEM;
142a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            u8 aliasCondition = thisMemMask & checkMemMask;
143a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            bool stopHere = false;
144a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
145a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            /*
146a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * Potential aliases seen - check the alias relations
147a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             */
148a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            if (checkMemMask != ENCODE_MEM && aliasCondition != 0) {
149a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                bool isCheckLIRLoad = EncodingMap[checkLIR->opcode].flags &
150a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                      IS_LOAD;
151a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                if  (aliasCondition == ENCODE_LITERAL) {
152a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    /*
153a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     * Should only see literal loads in the instruction
154a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     * stream.
155a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     */
156a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    assert(!(EncodingMap[checkLIR->opcode].flags &
157a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                             IS_STORE));
158a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    /* Same value && same register type */
159a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    if (checkLIR->aliasInfo == thisLIR->aliasInfo &&
160a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        REGTYPE(checkLIR->operands[0]) == REGTYPE(nativeRegId)){
161a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        /*
162a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                         * Different destination register - insert
163a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                         * a move
164a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                         */
165a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        if (checkLIR->operands[0] != nativeRegId) {
166a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            convertMemOpIntoMove(cUnit, checkLIR,
167a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                                 checkLIR->operands[0],
168a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                                 nativeRegId);
169a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        }
170a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        checkLIR->flags.isNop = true;
171a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    }
172a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                } else if (aliasCondition == ENCODE_DALVIK_REG) {
173a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    /* Must alias */
174a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    if (checkLIR->aliasInfo == thisLIR->aliasInfo) {
175a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        /* Only optimize compatible registers */
176a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        bool regCompatible =
177a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            REGTYPE(checkLIR->operands[0]) ==
178a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            REGTYPE(nativeRegId);
179a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        if ((isThisLIRLoad && isCheckLIRLoad) ||
180a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            (!isThisLIRLoad && isCheckLIRLoad)) {
181a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            /* RAR or RAW */
182a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            if (regCompatible) {
183a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                /*
184a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                 * Different destination register -
185a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                 * insert a move
186a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                 */
187a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                if (checkLIR->operands[0] !=
188a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                    nativeRegId) {
189a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                    convertMemOpIntoMove(cUnit,
190a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                                 checkLIR,
191a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                                 checkLIR->operands[0],
192a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                                 nativeRegId);
193a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                }
194a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                checkLIR->flags.isNop = true;
195a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            } else {
196a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                /*
197a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                 * Destinaions are of different types -
198a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                 * something complicated going on so
199a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                 * stop looking now.
200a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                 */
201a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                stopHere = true;
202a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            }
203a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        } else if (isThisLIRLoad && !isCheckLIRLoad) {
204a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            /* WAR - register value is killed */
205a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            stopHere = true;
206a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        } else if (!isThisLIRLoad && !isCheckLIRLoad) {
207a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            /* WAW - nuke the earlier store */
208a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            thisLIR->flags.isNop = true;
209a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                            stopHere = true;
210a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        }
211a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    /* Partial overlap */
212a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    } else if (isDalvikRegisterClobbered(thisLIR, checkLIR)) {
213a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        /*
214a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                         * It is actually ok to continue if checkLIR
215a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                         * is a read. But it is hard to make a test
216a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                         * case for this so we just stop here to be
217a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                         * conservative.
218a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                         */
219a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        stopHere = true;
220a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    }
221a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                }
222a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                /* Memory content may be updated. Stop looking now. */
223a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                if (stopHere) {
224a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    break;
225a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                /* The checkLIR has been transformed - check the next one */
226a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                } else if (checkLIR->flags.isNop) {
227a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    continue;
228a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                }
229a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            }
230a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
231a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
232a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            /*
233a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * this and check LIRs have no memory dependency. Now check if
234a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * their register operands have any RAW, WAR, and WAW
235a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * dependencies. If so, stop looking.
236a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             */
237a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            if (stopHere == false) {
238a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                stopHere = CHECK_REG_DEP(stopUseRegMask, stopDefRegMask,
239a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                         checkLIR);
240a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            }
241a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
242a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            if (stopHere == true) {
243a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR,
244a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                                "REG CLOBBERED"));
245a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                /* Only sink store instructions */
246a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                if (sinkDistance && !isThisLIRLoad) {
247a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    MipsLIR *newStoreLIR =
248a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        (MipsLIR *) dvmCompilerNew(sizeof(MipsLIR), true);
249a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    *newStoreLIR = *thisLIR;
250a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    /*
251a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     * Stop point found - insert *before* the checkLIR
252a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     * since the instruction list is scanned in the
253a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     * top-down order.
254a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     */
255a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    dvmCompilerInsertLIRBefore((LIR *) checkLIR,
256a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                               (LIR *) newStoreLIR);
257a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    thisLIR->flags.isNop = true;
258a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                }
259a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                break;
260a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            } else if (!checkLIR->flags.isNop) {
261a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                sinkDistance++;
262a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            }
263a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        }
264a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    }
265a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham}
266a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
267a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/*
268a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Perform a pass of bottom-up walk, from the second instruction in the
269a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * superblock, to try to hoist loads to earlier slots.
270a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */
271a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic void applyLoadHoisting(CompilationUnit *cUnit,
272a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                              MipsLIR *headLIR,
273a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                              MipsLIR *tailLIR)
274a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{
275a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    MipsLIR *thisLIR, *checkLIR;
276a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    /*
277a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham     * Store the list of independent instructions that can be hoisted past.
278a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham     * Will decide the best place to insert later.
279a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham     */
280a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    MipsLIR *prevInstList[MAX_HOIST_DISTANCE];
281a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
282a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    /* Empty block */
283a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    if (headLIR == tailLIR) return;
284a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
285a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    /* Start from the second instruction */
286a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    for (thisLIR = NEXT_LIR(headLIR);
287a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         thisLIR != tailLIR;
288a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         thisLIR = NEXT_LIR(thisLIR)) {
289a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
290a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        /* Skip non-interesting instructions */
291a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        if ((thisLIR->flags.isNop == true) ||
292a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            isPseudoOpCode(thisLIR->opcode) ||
293a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            !(EncodingMap[thisLIR->opcode].flags & IS_LOAD)) {
294a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            continue;
295a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        }
296a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
297a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        u8 stopUseAllMask = thisLIR->useMask;
298a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
299a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        /*
300a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * Branches for null/range checks are marked with the true resource
301a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * bits, and loads to Dalvik registers, constant pools, and non-alias
302a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * locations are safe to be hoisted. So only mark the heap references
303a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * conservatively here.
304a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         */
305a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        if (stopUseAllMask & ENCODE_HEAP_REF) {
306a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            stopUseAllMask |= ENCODE_REG_PC;
307a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        }
308a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
309a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        /* Similar as above, but just check for pure register dependency */
310a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        u8 stopUseRegMask = stopUseAllMask & ~ENCODE_MEM;
311a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        u8 stopDefRegMask = thisLIR->defMask & ~ENCODE_MEM;
312a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
313a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        int nextSlot = 0;
314a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        bool stopHere = false;
315a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
316a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        /* Try to hoist the load to a good spot */
317a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        for (checkLIR = PREV_LIR(thisLIR);
318a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             checkLIR != headLIR;
319a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             checkLIR = PREV_LIR(checkLIR)) {
320a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
321a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            /*
322a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * Skip already dead instructions (whose dataflow information is
323a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * outdated and misleading).
324a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             */
325a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            if (checkLIR->flags.isNop) continue;
326a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
327a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            u8 checkMemMask = checkLIR->defMask & ENCODE_MEM;
328a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            u8 aliasCondition = stopUseAllMask & checkMemMask;
329a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            stopHere = false;
330a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
331a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            /* Potential WAR alias seen - check the exact relation */
332a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            if (checkMemMask != ENCODE_MEM && aliasCondition != 0) {
333a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                /* We can fully disambiguate Dalvik references */
334a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                if (aliasCondition == ENCODE_DALVIK_REG) {
335a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    /* Must alias or partually overlap */
336a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    if ((checkLIR->aliasInfo == thisLIR->aliasInfo) ||
337a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        isDalvikRegisterClobbered(thisLIR, checkLIR)) {
338a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                        stopHere = true;
339a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    }
340a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                /* Conservatively treat all heap refs as may-alias */
341a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                } else {
342a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    assert(aliasCondition == ENCODE_HEAP_REF);
343a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    stopHere = true;
344a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                }
345a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                /* Memory content may be updated. Stop looking now. */
346a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                if (stopHere) {
347a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    prevInstList[nextSlot++] = checkLIR;
348a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    break;
349a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                }
350a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            }
351a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
352a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            if (stopHere == false) {
353a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                stopHere = CHECK_REG_DEP(stopUseRegMask, stopDefRegMask,
354a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                         checkLIR);
355a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            }
356a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
357a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            /*
358a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * Store the dependent or non-pseudo/indepedent instruction to the
359a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * list.
360a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             */
361a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            if (stopHere || !isPseudoOpCode(checkLIR->opcode)) {
362a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                prevInstList[nextSlot++] = checkLIR;
363a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                if (nextSlot == MAX_HOIST_DISTANCE) break;
364a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            }
365a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
366a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            /* Found a new place to put the load - move it here */
367a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            if (stopHere == true) {
368a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                DEBUG_OPT(dumpDependentInsnPair(checkLIR, thisLIR
369a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                                "HOIST STOP"));
370a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                break;
371a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            }
372a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        }
373a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
374a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        /*
375a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * Reached the top - use headLIR as the dependent marker as all labels
376a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * are barriers.
377a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         */
378a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        if (stopHere == false && nextSlot < MAX_HOIST_DISTANCE) {
379a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            prevInstList[nextSlot++] = headLIR;
380a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        }
381a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
382a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        /*
383a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * At least one independent instruction is found. Scan in the reversed
384a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         * direction to find a beneficial slot.
385a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham         */
386a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        if (nextSlot >= 2) {
387a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            int firstSlot = nextSlot - 2;
388a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            int slot;
389a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            MipsLIR *depLIR = prevInstList[nextSlot-1];
390a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            /* If there is ld-ld dependency, wait LDLD_DISTANCE cycles */
391a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            if (!isPseudoOpCode(depLIR->opcode) &&
392a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                (EncodingMap[depLIR->opcode].flags & IS_LOAD)) {
393a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                firstSlot -= LDLD_DISTANCE;
394a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            }
395a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            /*
396a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * Make sure we check slot >= 0 since firstSlot may be negative
397a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             * when the loop is first entered.
398a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham             */
399a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            for (slot = firstSlot; slot >= 0; slot--) {
400a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                MipsLIR *curLIR = prevInstList[slot];
401a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                MipsLIR *prevLIR = prevInstList[slot+1];
402a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
403bd1b0d74bbf40c69e47863fab7ea99eac418c515Douglas Leung                /*
404bd1b0d74bbf40c69e47863fab7ea99eac418c515Douglas Leung                 * Check the highest instruction.
405bd1b0d74bbf40c69e47863fab7ea99eac418c515Douglas Leung                 * ENCODE_ALL represents a scheduling barrier.
406bd1b0d74bbf40c69e47863fab7ea99eac418c515Douglas Leung                 */
407a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                if (prevLIR->defMask == ENCODE_ALL) {
408a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    /*
409a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     * If the first instruction is a load, don't hoist anything
410a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     * above it since it is unlikely to be beneficial.
411a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     */
412a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    if (EncodingMap[curLIR->opcode].flags & IS_LOAD) continue;
413a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    /*
414bd1b0d74bbf40c69e47863fab7ea99eac418c515Douglas Leung                     * Need to unconditionally break here even if the hoisted
415bd1b0d74bbf40c69e47863fab7ea99eac418c515Douglas Leung                     * distance is greater than LD_LATENCY (ie more than enough
416bd1b0d74bbf40c69e47863fab7ea99eac418c515Douglas Leung                     * cycles are inserted to hide the load latency) since theu
417bd1b0d74bbf40c69e47863fab7ea99eac418c515Douglas Leung                     * subsequent code doesn't expect to compare against a
418bd1b0d74bbf40c69e47863fab7ea99eac418c515Douglas Leung                     * pseudo opcode (whose opcode value is negative).
419a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     */
420bd1b0d74bbf40c69e47863fab7ea99eac418c515Douglas Leung                    break;
421a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                }
422a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
423a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                /*
424a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                 * NOTE: now prevLIR is guaranteed to be a non-pseudo
425a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                 * instruction (ie accessing EncodingMap[prevLIR->opcode] is
426a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                 * safe).
427a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                 *
428a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                 * Try to find two instructions with load/use dependency until
429a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                 * the remaining instructions are less than LD_LATENCY.
430a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                 */
431a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                if (((curLIR->useMask & prevLIR->defMask) &&
432a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                     (EncodingMap[prevLIR->opcode].flags & IS_LOAD)) ||
433a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    (slot < LD_LATENCY)) {
434a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                    break;
435a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                }
436a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            }
437a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
438a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            /* Found a slot to hoist to */
439a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            if (slot >= 0) {
440a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                MipsLIR *curLIR = prevInstList[slot];
441a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                MipsLIR *newLoadLIR = (MipsLIR *) dvmCompilerNew(sizeof(MipsLIR),
442a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                                               true);
443a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                *newLoadLIR = *thisLIR;
444a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                /*
445a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                 * Insertion is guaranteed to succeed since checkLIR
446a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                 * is never the first LIR on the list
447a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                 */
448a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                dvmCompilerInsertLIRBefore((LIR *) curLIR,
449a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                           (LIR *) newLoadLIR);
450a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                thisLIR->flags.isNop = true;
451a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham            }
452a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        }
453a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    }
454a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham}
455a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
456a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamvoid dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR,
457a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                        LIR *tailLIR)
458a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{
459a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    if (!(gDvmJit.disableOpt & (1 << kLoadStoreElimination))) {
460a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        applyLoadStoreElimination(cUnit, (MipsLIR *) headLIR,
461a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                                  (MipsLIR *) tailLIR);
462a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    }
463a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    if (!(gDvmJit.disableOpt & (1 << kLoadHoisting))) {
464a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham        applyLoadHoisting(cUnit, (MipsLIR *) headLIR, (MipsLIR *) tailLIR);
465a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    }
466a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham}
467