blob: b4cc0b5689ab7c968d73d08f9046c771ddc944d9 [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 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 "CompilerInternals.h"
19#include "Dataflow.h"
20#include "codegen/Ralloc.h"
21
buzbeeed3e9302011-09-23 17:34:19 -070022STATIC bool setFp(CompilationUnit* cUnit, int index, bool isFP) {
buzbee03fa2632011-09-20 17:10:57 -070023 bool change = false;
buzbee67bc2362011-10-11 18:08:40 -070024 if (cUnit->regLocation[index].highWord) {
25 return change;
26 }
buzbee03fa2632011-09-20 17:10:57 -070027 if (isFP && !cUnit->regLocation[index].fp) {
28 cUnit->regLocation[index].fp = true;
buzbee67bc2362011-10-11 18:08:40 -070029 cUnit->regLocation[index].defined = true;
30 change = true;
31 }
32 return change;
33}
34
35STATIC bool setCore(CompilationUnit* cUnit, int index, bool isCore) {
36 bool change = false;
37 if (cUnit->regLocation[index].highWord) {
38 return change;
39 }
40 if (isCore && !cUnit->regLocation[index].defined) {
41 cUnit->regLocation[index].core = true;
42 cUnit->regLocation[index].defined = true;
buzbee03fa2632011-09-20 17:10:57 -070043 change = true;
44 }
45 return change;
46}
47
buzbeec0ecd652011-09-25 18:11:54 -070048STATIC bool remapNames(CompilationUnit* cUnit, BasicBlock* bb)
49{
50 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
51 bb->blockType != kExitBlock)
52 return false;
53
54 for (MIR* mir = bb->firstMIRInsn; mir; mir = mir->next) {
55 SSARepresentation *ssaRep = mir->ssaRep;
56 if (ssaRep) {
57 for (int i = 0; i < ssaRep->numUses; i++) {
58 ssaRep->uses[i] = cUnit->phiAliasMap[ssaRep->uses[i]];
59 }
60 for (int i = 0; i < ssaRep->numDefs; i++) {
61 ssaRep->defs[i] = cUnit->phiAliasMap[ssaRep->defs[i]];
62 }
63 }
64 }
65 return false;
66}
67
buzbee67bf8852011-08-17 17:51:35 -070068/*
buzbee03fa2632011-09-20 17:10:57 -070069 * Infer types and sizes. We don't need to track change on sizes,
70 * as it doesn't propagate. We're guaranteed at least one pass through
71 * the cfg.
buzbee67bf8852011-08-17 17:51:35 -070072 */
buzbeeed3e9302011-09-23 17:34:19 -070073STATIC bool inferTypeAndSize(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070074{
75 MIR *mir;
buzbee03fa2632011-09-20 17:10:57 -070076 bool changed = false; // Did anything change?
77
78 if (bb->dataFlowInfo == NULL) return false;
buzbee67bf8852011-08-17 17:51:35 -070079 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock)
buzbee03fa2632011-09-20 17:10:57 -070080 return false;
buzbee67bf8852011-08-17 17:51:35 -070081
82 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
83 SSARepresentation *ssaRep = mir->ssaRep;
84 if (ssaRep) {
buzbee03fa2632011-09-20 17:10:57 -070085 int attrs = oatDataFlowAttributes[mir->dalvikInsn.opcode];
buzbee67bc2362011-10-11 18:08:40 -070086
87 // Handle defs
88 if (attrs & (DF_DA | DF_DA_WIDE)) {
89 if (attrs & DF_CORE_A) {
90 changed |= setCore(cUnit, ssaRep->defs[0], true);
91 }
92 if (attrs & DF_DA_WIDE) {
93 cUnit->regLocation[ssaRep->defs[0]].wide = true;
94 cUnit->regLocation[ssaRep->defs[1]].highWord = true;
95 DCHECK_EQ(oatS2VReg(cUnit, ssaRep->defs[0])+1,
96 oatS2VReg(cUnit, ssaRep->defs[1]));
97 }
98 }
99
100 // Handles uses
buzbee03fa2632011-09-20 17:10:57 -0700101 int next = 0;
buzbee67bc2362011-10-11 18:08:40 -0700102 if (attrs & (DF_UA | DF_UA_WIDE)) {
103 if (attrs & DF_CORE_A) {
104 changed |= setCore(cUnit, ssaRep->uses[next], true);
105 }
106 if (attrs & DF_UA_WIDE) {
107 cUnit->regLocation[ssaRep->uses[next]].wide = true;
108 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
109 DCHECK_EQ(oatS2VReg(cUnit, ssaRep->uses[next])+1,
110 oatS2VReg(cUnit, ssaRep->uses[next + 1]));
111 next += 2;
112 } else {
113 next++;
114 }
buzbee67bf8852011-08-17 17:51:35 -0700115 }
buzbee67bc2362011-10-11 18:08:40 -0700116 if (attrs & (DF_UB | DF_UB_WIDE)) {
117 if (attrs & DF_CORE_B) {
118 changed |= setCore(cUnit, ssaRep->uses[next], true);
119 }
120 if (attrs & DF_UB_WIDE) {
121 cUnit->regLocation[ssaRep->uses[next]].wide = true;
122 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
123 DCHECK_EQ(oatS2VReg(cUnit, ssaRep->uses[next])+1,
124 oatS2VReg(cUnit, ssaRep->uses[next + 1]));
125 next += 2;
126 } else {
127 next++;
128 }
buzbee03fa2632011-09-20 17:10:57 -0700129 }
buzbee67bc2362011-10-11 18:08:40 -0700130 if (attrs & (DF_UC | DF_UC_WIDE)) {
131 if (attrs & DF_CORE_C) {
132 changed |= setCore(cUnit, ssaRep->uses[next], true);
133 }
134 if (attrs & DF_UC_WIDE) {
135 cUnit->regLocation[ssaRep->uses[next]].wide = true;
136 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
137 DCHECK_EQ(oatS2VReg(cUnit, ssaRep->uses[next])+1,
138 oatS2VReg(cUnit, ssaRep->uses[next + 1]));
139 }
buzbee03fa2632011-09-20 17:10:57 -0700140 }
buzbeeed3e9302011-09-23 17:34:19 -0700141
142 // Special-case handling for format 35c/3rc invokes
143 Opcode opcode = mir->dalvikInsn.opcode;
144 int flags = (opcode >= kNumPackedOpcodes) ? 0 :
145 dexGetFlagsFromOpcode(opcode);
146 if ((flags & kInstrInvoke) &&
147 (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) {
148 DCHECK_EQ(next, 0);
149 int target_idx = mir->dalvikInsn.vB;
150 const char* shorty =
151 oatGetShortyFromTargetIdx(cUnit, target_idx);
152 int numUses = mir->dalvikInsn.vA;
153 // If this is a non-static invoke, skip implicit "this"
154 if (((mir->dalvikInsn.opcode != OP_INVOKE_STATIC) &&
155 (mir->dalvikInsn.opcode != OP_INVOKE_STATIC_RANGE))) {
buzbee67bc2362011-10-11 18:08:40 -0700156 cUnit->regLocation[ssaRep->uses[next]].defined = true;
157 cUnit->regLocation[ssaRep->uses[next]].core = true;
buzbeeed3e9302011-09-23 17:34:19 -0700158 next++;
159 }
160 uint32_t cpos = 1;
161 if (strlen(shorty) > 1) {
162 for (int i = next; i < numUses;) {
163 DCHECK_LT(cpos, strlen(shorty));
164 switch(shorty[cpos++]) {
165 case 'D':
166 ssaRep->fpUse[i] = true;
167 ssaRep->fpUse[i+1] = true;
168 cUnit->regLocation[ssaRep->uses[i]].wide = true;
buzbee67bc2362011-10-11 18:08:40 -0700169 cUnit->regLocation[ssaRep->uses[i+1]].highWord
170 = true;
171 DCHECK_EQ(oatS2VReg(cUnit, ssaRep->uses[i])+1,
172 oatS2VReg(cUnit, ssaRep->uses[i+1]));
buzbeeed3e9302011-09-23 17:34:19 -0700173 i++;
174 break;
175 case 'J':
176 cUnit->regLocation[ssaRep->uses[i]].wide = true;
buzbee67bc2362011-10-11 18:08:40 -0700177 cUnit->regLocation[ssaRep->uses[i+1]].highWord
178 = true;
179 DCHECK_EQ(oatS2VReg(cUnit, ssaRep->uses[i])+1,
180 oatS2VReg(cUnit, ssaRep->uses[i+1]));
181 changed |= setCore(cUnit, ssaRep->uses[i],true);
buzbeeed3e9302011-09-23 17:34:19 -0700182 i++;
183 break;
184 case 'F':
185 ssaRep->fpUse[i] = true;
186 break;
187 default:
buzbee67bc2362011-10-11 18:08:40 -0700188 changed |= setCore(cUnit,ssaRep->uses[i], true);
buzbeeed3e9302011-09-23 17:34:19 -0700189 break;
190 }
191 i++;
192 }
193 }
194 }
195
buzbee03fa2632011-09-20 17:10:57 -0700196 for (int i=0; ssaRep->fpUse && i< ssaRep->numUses; i++) {
197 if (ssaRep->fpUse[i])
198 changed |= setFp(cUnit, ssaRep->uses[i], true);
199 }
200 for (int i=0; ssaRep->fpDef && i< ssaRep->numDefs; i++) {
buzbee67bf8852011-08-17 17:51:35 -0700201 if (ssaRep->fpDef[i])
buzbee03fa2632011-09-20 17:10:57 -0700202 changed |= setFp(cUnit, ssaRep->defs[i], true);
203 }
204 // Special-case handling for moves & Phi
205 if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
buzbee67bc2362011-10-11 18:08:40 -0700206 // If any of our inputs or outputs is defined, set all
207 bool definedFP = false;
208 bool definedCore = false;
209 definedFP |= (cUnit->regLocation[ssaRep->defs[0]].defined &&
210 cUnit->regLocation[ssaRep->defs[0]].fp);
211 definedCore |= (cUnit->regLocation[ssaRep->defs[0]].defined &&
212 cUnit->regLocation[ssaRep->defs[0]].core);
buzbee03fa2632011-09-20 17:10:57 -0700213 for (int i = 0; i < ssaRep->numUses; i++) {
buzbee67bc2362011-10-11 18:08:40 -0700214 definedFP |= (cUnit->regLocation[ssaRep->uses[i]].defined &&
215 cUnit->regLocation[ssaRep->uses[i]].fp);
216 definedCore |= (cUnit->regLocation[ssaRep->uses[i]].defined
217 && cUnit->regLocation[ssaRep->uses[i]].core);
buzbee03fa2632011-09-20 17:10:57 -0700218 }
buzbee67bc2362011-10-11 18:08:40 -0700219 DCHECK(!(definedFP && definedCore));
220 changed |= setFp(cUnit, ssaRep->defs[0], definedFP);
221 changed |= setCore(cUnit, ssaRep->defs[0], definedCore);
buzbee03fa2632011-09-20 17:10:57 -0700222 for (int i = 0; i < ssaRep->numUses; i++) {
buzbee67bc2362011-10-11 18:08:40 -0700223 changed |= setFp(cUnit, ssaRep->uses[i], definedFP);
224 changed |= setCore(cUnit, ssaRep->uses[i], definedCore);
buzbee03fa2632011-09-20 17:10:57 -0700225 }
buzbee67bf8852011-08-17 17:51:35 -0700226 }
227 }
228 }
buzbee03fa2632011-09-20 17:10:57 -0700229 return changed;
buzbee67bf8852011-08-17 17:51:35 -0700230}
231
232static const char* storageName[] = {" Frame ", "PhysReg", " Spill "};
233
buzbeedfd3d702011-08-28 12:56:51 -0700234void oatDumpRegLocTable(RegLocation* table, int count)
buzbee67bf8852011-08-17 17:51:35 -0700235{
236 for (int i = 0; i < count; i++) {
237 char buf[100];
buzbee67bc2362011-10-11 18:08:40 -0700238 snprintf(buf, 100, "Loc[%02d] : %s, %c %c %c %c %c %c%d %c%d S%d",
buzbee67bf8852011-08-17 17:51:35 -0700239 i, storageName[table[i].location], table[i].wide ? 'W' : 'N',
buzbee67bc2362011-10-11 18:08:40 -0700240 table[i].defined ? 'D' : 'U', table[i].fp ? 'F' : 'C',
241 table[i].highWord ? 'H' : 'L', table[i].home ? 'h' : 't',
242 FPREG(table[i].lowReg) ? 's' : 'r', table[i].lowReg & FP_REG_MASK,
243 FPREG(table[i].highReg) ? 's' : 'r', table[i].highReg & FP_REG_MASK,
244 table[i].sRegLow);
buzbee67bf8852011-08-17 17:51:35 -0700245 LOG(INFO) << buf;
246 }
247}
248
buzbee67bc2362011-10-11 18:08:40 -0700249static const RegLocation freshLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0,
250 INVALID_REG, INVALID_REG, INVALID_SREG};
buzbee67bf8852011-08-17 17:51:35 -0700251
252/*
253 * Simple register allocation. Some Dalvik virtual registers may
254 * be promoted to physical registers. Most of the work for temp
255 * allocation is done on the fly. We also do some initilization and
256 * type inference here.
257 */
258void oatSimpleRegAlloc(CompilationUnit* cUnit)
259{
260 int i;
261 RegLocation* loc;
262
263 /* Allocate the location map */
264 loc = (RegLocation*)oatNew(cUnit->numSSARegs * sizeof(*loc), true);
265 for (i=0; i< cUnit->numSSARegs; i++) {
266 loc[i] = freshLoc;
267 loc[i].sRegLow = i;
268 }
269 cUnit->regLocation = loc;
270
buzbee67bc2362011-10-11 18:08:40 -0700271 /* Allocation the promotion map */
272 cUnit->promotionMap = (PromotionMap*)oatNew( cUnit->method->NumRegisters()
273 * sizeof(cUnit->promotionMap[0]), true);
274
buzbeee9a72f62011-09-04 17:59:07 -0700275 /* Add types of incoming arguments based on signature */
276 int numRegs = cUnit->method->NumRegisters();
277 int numIns = cUnit->method->NumIns();
278 if (numIns > 0) {
279 int sReg = numRegs - numIns;
280 if (!cUnit->method->IsStatic()) {
281 // Skip past "this"
buzbee67bc2362011-10-11 18:08:40 -0700282 cUnit->regLocation[sReg].defined = true;
283 cUnit->regLocation[sReg].core = true;
buzbeee9a72f62011-09-04 17:59:07 -0700284 sReg++;
285 }
Brian Carlstromc74255f2011-09-11 22:47:39 -0700286 const String* shorty = cUnit->method->GetShorty();
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700287 for (int i = 1; i < shorty->GetLength(); i++) {
buzbee67bc2362011-10-11 18:08:40 -0700288 switch(shorty->CharAt(i)) {
289 case 'D':
290 cUnit->regLocation[sReg].wide = true;
291 cUnit->regLocation[sReg+1].highWord = true;
292 DCHECK_EQ(oatS2VReg(cUnit, sReg)+1,
293 oatS2VReg(cUnit, sReg+1));
294 cUnit->regLocation[sReg].fp = true;
295 cUnit->regLocation[sReg].defined = true;
296 sReg++;
297 break;
298 case 'J':
299 cUnit->regLocation[sReg].wide = true;
300 cUnit->regLocation[sReg+1].highWord = true;
301 DCHECK_EQ(oatS2VReg(cUnit, sReg)+1,
302 oatS2VReg(cUnit, sReg+1));
303 cUnit->regLocation[sReg].core = true;
304 cUnit->regLocation[sReg].defined = true;
305 sReg++;
306 break;
307 case 'F':
308 cUnit->regLocation[sReg].fp = true;
309 cUnit->regLocation[sReg].defined = true;
310 break;
311 default:
312 cUnit->regLocation[sReg].core = true;
313 cUnit->regLocation[sReg].defined = true;
314 break;
buzbeee9a72f62011-09-04 17:59:07 -0700315 }
316 sReg++;
317 }
318 }
319
buzbeec0ecd652011-09-25 18:11:54 -0700320 /* Remap names */
321 oatDataFlowAnalysisDispatcher(cUnit, remapNames,
322 kPreOrderDFSTraversal,
323 false /* isIterative */);
324
buzbee03fa2632011-09-20 17:10:57 -0700325 /* Do type & size inference pass */
326 oatDataFlowAnalysisDispatcher(cUnit, inferTypeAndSize,
327 kPreOrderDFSTraversal,
328 true /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700329
330 /*
331 * Set the sRegLow field to refer to the pre-SSA name of the
332 * base Dalvik virtual register. Once we add a better register
333 * allocator, remove this remapping.
334 */
335 for (i=0; i < cUnit->numSSARegs; i++) {
336 cUnit->regLocation[i].sRegLow =
337 DECODE_REG(oatConvertSSARegToDalvik(cUnit, loc[i].sRegLow));
338 }
339
340 cUnit->coreSpillMask = 0;
341 cUnit->fpSpillMask = 0;
buzbeebbaf8942011-10-02 13:08:29 -0700342 cUnit->numCoreSpills = 0;
buzbee67bf8852011-08-17 17:51:35 -0700343
344 oatDoPromotion(cUnit);
345
346 if (cUnit->printMe && !(cUnit->disableOpt & (1 << kPromoteRegs))) {
347 LOG(INFO) << "After Promotion";
buzbeedfd3d702011-08-28 12:56:51 -0700348 oatDumpRegLocTable(cUnit->regLocation, cUnit->numSSARegs);
buzbee67bf8852011-08-17 17:51:35 -0700349 }
350
351 /* Figure out the frame size */
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700352 cUnit->numIns = cUnit->method->NumIns();
353 cUnit->numRegs = cUnit->method->NumRegisters() - cUnit->numIns;
354 cUnit->numOuts = cUnit->method->NumOuts();
buzbee67bf8852011-08-17 17:51:35 -0700355 cUnit->numPadding = (STACK_ALIGN_WORDS -
buzbeebbaf8942011-10-02 13:08:29 -0700356 (cUnit->numCoreSpills + cUnit->numFPSpills + cUnit->numRegs +
buzbee67bf8852011-08-17 17:51:35 -0700357 cUnit->numOuts + 2)) & (STACK_ALIGN_WORDS-1);
buzbeebbaf8942011-10-02 13:08:29 -0700358 cUnit->frameSize = (cUnit->numCoreSpills + cUnit->numFPSpills +
359 cUnit->numRegs + cUnit->numOuts +
buzbee67bf8852011-08-17 17:51:35 -0700360 cUnit->numPadding + 2) * 4;
361 cUnit->insOffset = cUnit->frameSize + 4;
362 cUnit->regsOffset = (cUnit->numOuts + cUnit->numPadding + 1) * 4;
buzbee67bf8852011-08-17 17:51:35 -0700363}