blob: 6f00b9e4c771b166ee8d6d2c37d82b151f426438 [file] [log] [blame]
Ben Chenge9695e52009-06-16 16:11:47 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Dalvik.h"
18#include "vm/compiler/CompilerInternals.h"
Bill Buzbee89efc3d2009-07-28 11:22:22 -070019#include "ArmLIR.h"
Ben Chenge9695e52009-06-16 16:11:47 -070020
Bill Buzbee7ea0f642009-08-10 17:06:51 -070021ArmLIR* dvmCompilerGenCopy(CompilationUnit *cUnit, int rDest, int rSrc);
22
23/* Is this a Dalvik register access? */
24static inline bool isDalvikLoad(ArmLIR *lir)
25{
26 return ((lir->operands[1] == rFP) &&
27 ((lir->opCode == THUMB_LDR_RRI5) ||
28 (lir->opCode == THUMB2_LDR_RRI12) ||
29 (lir->opCode == THUMB2_VLDRS) ||
30 (lir->opCode == THUMB2_VLDRD)));
31}
32
33static inline bool isDalvikStore(ArmLIR *lir)
34{
35 return ((lir->operands[1] == rFP) &&
36 ((lir->opCode == THUMB_STR_RRI5) ||
37 (lir->opCode == THUMB2_STR_RRI12) ||
38 (lir->opCode == THUMB2_VSTRS) ||
39 (lir->opCode == THUMB2_VSTRD)));
40}
41
Bill Buzbee270c1d62009-08-13 16:58:07 -070042/* Double regs overlap float regs. Return true if collision */
43static bool regClobber(int reg1, int reg2)
44{
45 int reg1a, reg1b;
46 int reg2a, reg2b;
47 if (!FPREG(reg1) || !FPREG(reg2))
48 return (reg1 == reg2);
49 if (DOUBLEREG(reg1)) {
50 reg1a = reg1 & FP_REG_MASK;
51 reg1b = reg1a + 1;
52 } else {
53 reg1a = reg1b = reg1 & FP_REG_MASK;
54 }
55 if (DOUBLEREG(reg2)) {
56 reg2a = reg2 & FP_REG_MASK;
57 reg2b = reg2a + 1;
58 } else {
59 reg2a = reg2b = reg2 & FP_REG_MASK;
60 }
61 return (reg1a == reg2a) || (reg1a == reg2b) ||
62 (reg1b == reg2a) || (reg1b == reg2b);
63}
Ben Chenge9695e52009-06-16 16:11:47 -070064/*
65 * Perform a pass of top-down walk to
66 * 1) Eliminate redundant loads and stores
67 * 2) Sink stores to latest possible slot
68 */
69static void applyLoadStoreElimination(CompilationUnit *cUnit,
Bill Buzbee89efc3d2009-07-28 11:22:22 -070070 ArmLIR *headLIR,
71 ArmLIR *tailLIR)
Ben Chenge9695e52009-06-16 16:11:47 -070072{
Bill Buzbee89efc3d2009-07-28 11:22:22 -070073 ArmLIR *thisLIR;
Ben Chenge9695e52009-06-16 16:11:47 -070074
75 cUnit->optRound++;
76 for (thisLIR = headLIR;
77 thisLIR != tailLIR;
78 thisLIR = NEXT_LIR(thisLIR)) {
79 /* Skip newly added instructions */
80 if (thisLIR->age >= cUnit->optRound) {
81 continue;
82 }
Bill Buzbee7ea0f642009-08-10 17:06:51 -070083 if (isDalvikStore(thisLIR)) {
Ben Chenge9695e52009-06-16 16:11:47 -070084 int dRegId = thisLIR->operands[2];
85 int nativeRegId = thisLIR->operands[0];
Bill Buzbee89efc3d2009-07-28 11:22:22 -070086 ArmLIR *checkLIR;
Ben Chenge9695e52009-06-16 16:11:47 -070087 int sinkDistance = 0;
88
89 for (checkLIR = NEXT_LIR(thisLIR);
90 checkLIR != tailLIR;
91 checkLIR = NEXT_LIR(checkLIR)) {
92
93 /* Check if a Dalvik register load is redundant */
Bill Buzbee7ea0f642009-08-10 17:06:51 -070094 if (isDalvikLoad(checkLIR) &&
95 checkLIR->operands[2] == dRegId ) {
96 if (FPREG(nativeRegId) != FPREG(checkLIR->operands[0])) {
97 break; // TODO: handle gen<=>float copies
98 }
Ben Chenge9695e52009-06-16 16:11:47 -070099 /* Insert a move to replace the load */
100 if (checkLIR->operands[0] != nativeRegId) {
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700101 ArmLIR *moveLIR;
102 moveLIR = dvmCompilerRegCopy(cUnit,
103 checkLIR->operands[0],
104 nativeRegId);
Ben Chenge9695e52009-06-16 16:11:47 -0700105 /*
106 * Insertion is guaranteed to succeed since checkLIR
107 * is never the first LIR on the list
108 */
109 dvmCompilerInsertLIRBefore((LIR *) checkLIR,
110 (LIR *) moveLIR);
111 }
112 checkLIR->isNop = true;
113 continue;
114
115 /* Found a true output dependency - nuke the previous store */
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700116 } else if (isDalvikStore(checkLIR) &&
Ben Chenge9695e52009-06-16 16:11:47 -0700117 checkLIR->operands[2] == dRegId) {
118 thisLIR->isNop = true;
119 break;
120 /* Find out the latest slot that the store can be sunk into */
121 } else {
122 bool stopHere = false;
123
124 /* Last instruction reached */
125 stopHere |= checkLIR->generic.next == NULL;
126
Ben Chenge9695e52009-06-16 16:11:47 -0700127 /*
128 * Conservatively assume there is a memory dependency
129 * for st/ld multiples and reg+reg address mode
130 */
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700131 stopHere |= checkLIR->opCode == THUMB_STMIA ||
132 checkLIR->opCode == THUMB_LDMIA ||
133 checkLIR->opCode == THUMB_STR_RRR ||
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700134 checkLIR->opCode == THUMB_LDR_RRR ||
Bill Buzbee270c1d62009-08-13 16:58:07 -0700135 checkLIR->opCode == THUMB2_STR_RRR ||
136 checkLIR->opCode == THUMB2_LDR_RRR ||
137 checkLIR->opCode == THUMB2_STMIA ||
138 checkLIR->opCode == THUMB2_LDMIA ||
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700139 checkLIR->opCode == THUMB2_VLDRD ||
140 checkLIR->opCode == THUMB2_VSTRD;
Ben Chenge9695e52009-06-16 16:11:47 -0700141
Bill Buzbeea4a7f072009-08-27 13:58:09 -0700142 /* Don't migrate into an IF region */
143 stopHere |= checkLIR->opCode == THUMB2_IT;
144
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700145 if (!isPseudoOpCode(checkLIR->opCode)) {
Bill Buzbee9bc3df32009-07-30 10:52:29 -0700146
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700147 /* Store data is clobbered */
148 stopHere |= (EncodingMap[checkLIR->opCode].flags &
149 CLOBBER_DEST) != 0 &&
Bill Buzbee270c1d62009-08-13 16:58:07 -0700150 regClobber(checkLIR->operands[0],
151 nativeRegId);
Bill Buzbee7ea0f642009-08-10 17:06:51 -0700152
153 stopHere |= (EncodingMap[checkLIR->opCode].flags &
154 IS_BRANCH) != 0;
155 }
Ben Chenge9695e52009-06-16 16:11:47 -0700156
157 /* Found a new place to put the store - move it here */
158 if (stopHere == true) {
159
160 /* The store can be sunk for at least one cycle */
161 if (sinkDistance != 0) {
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700162 ArmLIR *newStoreLIR =
163 dvmCompilerNew(sizeof(ArmLIR), true);
Ben Chenge9695e52009-06-16 16:11:47 -0700164 *newStoreLIR = *thisLIR;
165 newStoreLIR->age = cUnit->optRound;
166 /*
167 * Insertion is guaranteed to succeed since checkLIR
168 * is never the first LIR on the list
169 */
170 dvmCompilerInsertLIRBefore((LIR *) checkLIR,
171 (LIR *) newStoreLIR);
172 thisLIR->isNop = true;
173 }
174 break;
175 }
176
177 /*
178 * Saw a real instruction that the store can be sunk after
179 */
180 if (!isPseudoOpCode(checkLIR->opCode)) {
181 sinkDistance++;
182 }
183 }
184 }
185 }
186 }
187}
188
189void dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR,
190 LIR *tailLIR)
191{
192 applyLoadStoreElimination(cUnit,
Bill Buzbee89efc3d2009-07-28 11:22:22 -0700193 (ArmLIR *) headLIR,
194 (ArmLIR *) tailLIR);
Ben Chenge9695e52009-06-16 16:11:47 -0700195}