blob: ca25b38fdcbf413937a85dec9a4afb8157018e70 [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
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080022namespace art {
23
buzbee31a4a6f2012-02-28 15:36:15 -080024bool setFp(CompilationUnit* cUnit, int index, bool isFP) {
Bill Buzbeea114add2012-05-03 15:00:40 -070025 bool change = false;
Bill Buzbeea114add2012-05-03 15:00:40 -070026 if (isFP && !cUnit->regLocation[index].fp) {
27 cUnit->regLocation[index].fp = true;
28 cUnit->regLocation[index].defined = true;
29 change = true;
30 }
31 return change;
buzbee67bc2362011-10-11 18:08:40 -070032}
33
buzbee31a4a6f2012-02-28 15:36:15 -080034bool setCore(CompilationUnit* cUnit, int index, bool isCore) {
Bill Buzbeea114add2012-05-03 15:00:40 -070035 bool change = false;
Bill Buzbeea114add2012-05-03 15:00:40 -070036 if (isCore && !cUnit->regLocation[index].defined) {
37 cUnit->regLocation[index].core = true;
38 cUnit->regLocation[index].defined = true;
39 change = true;
40 }
41 return change;
buzbee03fa2632011-09-20 17:10:57 -070042}
43
buzbeebff24652012-05-06 16:22:05 -070044bool setRef(CompilationUnit* cUnit, int index, bool isRef) {
45 bool change = false;
buzbeebff24652012-05-06 16:22:05 -070046 if (isRef && !cUnit->regLocation[index].defined) {
47 cUnit->regLocation[index].ref = true;
48 cUnit->regLocation[index].defined = true;
49 change = true;
50 }
51 return change;
52}
53
buzbee2a83e8f2012-07-13 16:42:30 -070054bool setWide(CompilationUnit* cUnit, int index, bool isWide) {
55 bool change = false;
56 if (isWide && !cUnit->regLocation[index].wide) {
57 cUnit->regLocation[index].wide = true;
58 change = true;
59 }
60 return change;
61}
62
63bool setHigh(CompilationUnit* cUnit, int index, bool isHigh) {
64 bool change = false;
65 if (isHigh && !cUnit->regLocation[index].highWord) {
66 cUnit->regLocation[index].highWord = true;
67 change = true;
68 }
69 return change;
70}
71
buzbee31a4a6f2012-02-28 15:36:15 -080072bool remapNames(CompilationUnit* cUnit, BasicBlock* bb)
buzbeec0ecd652011-09-25 18:11:54 -070073{
Bill Buzbeea114add2012-05-03 15:00:40 -070074 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
75 bb->blockType != kExitBlock)
buzbeec0ecd652011-09-25 18:11:54 -070076 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -070077
78 for (MIR* mir = bb->firstMIRInsn; mir; mir = mir->next) {
79 SSARepresentation *ssaRep = mir->ssaRep;
80 if (ssaRep) {
81 for (int i = 0; i < ssaRep->numUses; i++) {
82 ssaRep->uses[i] = cUnit->phiAliasMap[ssaRep->uses[i]];
83 }
84 for (int i = 0; i < ssaRep->numDefs; i++) {
85 ssaRep->defs[i] = cUnit->phiAliasMap[ssaRep->defs[i]];
86 }
87 }
88 }
89 return false;
buzbeec0ecd652011-09-25 18:11:54 -070090}
91
buzbee67bf8852011-08-17 17:51:35 -070092/*
buzbee03fa2632011-09-20 17:10:57 -070093 * Infer types and sizes. We don't need to track change on sizes,
94 * as it doesn't propagate. We're guaranteed at least one pass through
95 * the cfg.
buzbee67bf8852011-08-17 17:51:35 -070096 */
buzbee31a4a6f2012-02-28 15:36:15 -080097bool inferTypeAndSize(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070098{
Bill Buzbeea114add2012-05-03 15:00:40 -070099 MIR *mir;
100 bool changed = false; // Did anything change?
buzbee03fa2632011-09-20 17:10:57 -0700101
Bill Buzbeea114add2012-05-03 15:00:40 -0700102 if (bb->dataFlowInfo == NULL) return false;
103 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock)
104 return false;
buzbee67bf8852011-08-17 17:51:35 -0700105
Bill Buzbeea114add2012-05-03 15:00:40 -0700106 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
107 SSARepresentation *ssaRep = mir->ssaRep;
108 if (ssaRep) {
109 int attrs = oatDataFlowAttributes[mir->dalvikInsn.opcode];
buzbee67bc2362011-10-11 18:08:40 -0700110
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 // Handle defs
buzbeebff24652012-05-06 16:22:05 -0700112 if (attrs & DF_DA) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700113 if (attrs & DF_CORE_A) {
114 changed |= setCore(cUnit, ssaRep->defs[0], true);
buzbee67bf8852011-08-17 17:51:35 -0700115 }
buzbeebff24652012-05-06 16:22:05 -0700116 if (attrs & DF_REF_A) {
117 changed |= setRef(cUnit, ssaRep->defs[0], true);
118 }
119 if (attrs & DF_A_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 cUnit->regLocation[ssaRep->defs[0]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700121 cUnit->regLocation[ssaRep->defs[1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700122 cUnit->regLocation[ssaRep->defs[1]].highWord = true;
123 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->defs[0])+1,
124 SRegToVReg(cUnit, ssaRep->defs[1]));
125 }
126 }
127
128 // Handles uses
129 int next = 0;
buzbeebff24652012-05-06 16:22:05 -0700130 if (attrs & DF_UA) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 if (attrs & DF_CORE_A) {
132 changed |= setCore(cUnit, ssaRep->uses[next], true);
133 }
buzbeebff24652012-05-06 16:22:05 -0700134 if (attrs & DF_REF_A) {
135 changed |= setRef(cUnit, ssaRep->uses[next], true);
136 }
137 if (attrs & DF_A_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700138 cUnit->regLocation[ssaRep->uses[next]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700139 cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
141 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
142 SRegToVReg(cUnit, ssaRep->uses[next + 1]));
143 next += 2;
144 } else {
145 next++;
146 }
147 }
buzbeebff24652012-05-06 16:22:05 -0700148 if (attrs & DF_UB) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700149 if (attrs & DF_CORE_B) {
150 changed |= setCore(cUnit, ssaRep->uses[next], true);
151 }
buzbeebff24652012-05-06 16:22:05 -0700152 if (attrs & DF_REF_B) {
153 changed |= setRef(cUnit, ssaRep->uses[next], true);
154 }
155 if (attrs & DF_B_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700156 cUnit->regLocation[ssaRep->uses[next]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700157 cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700158 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
159 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
160 SRegToVReg(cUnit, ssaRep->uses[next + 1]));
161 next += 2;
162 } else {
163 next++;
164 }
165 }
buzbeebff24652012-05-06 16:22:05 -0700166 if (attrs & DF_UC) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700167 if (attrs & DF_CORE_C) {
168 changed |= setCore(cUnit, ssaRep->uses[next], true);
169 }
buzbeebff24652012-05-06 16:22:05 -0700170 if (attrs & DF_REF_C) {
171 changed |= setRef(cUnit, ssaRep->uses[next], true);
172 }
173 if (attrs & DF_C_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700174 cUnit->regLocation[ssaRep->uses[next]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700175 cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
177 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
178 SRegToVReg(cUnit, ssaRep->uses[next + 1]));
179 }
180 }
181
buzbeed5018892012-07-11 14:23:40 -0700182 // Special-case return handling
183 if ((mir->dalvikInsn.opcode == Instruction::RETURN) ||
184 (mir->dalvikInsn.opcode == Instruction::RETURN_WIDE) ||
185 (mir->dalvikInsn.opcode == Instruction::RETURN_OBJECT)) {
186 switch(cUnit->shorty[0]) {
187 case 'I':
188 changed |= setCore(cUnit, ssaRep->uses[0], true);
189 break;
190 case 'J':
191 changed |= setCore(cUnit, ssaRep->uses[0], true);
192 changed |= setCore(cUnit, ssaRep->uses[1], true);
193 cUnit->regLocation[ssaRep->uses[0]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700194 cUnit->regLocation[ssaRep->uses[1]].wide = true;
buzbeed5018892012-07-11 14:23:40 -0700195 cUnit->regLocation[ssaRep->uses[1]].highWord = true;
196 break;
197 case 'F':
198 changed |= setFp(cUnit, ssaRep->uses[0], true);
199 break;
200 case 'D':
201 changed |= setFp(cUnit, ssaRep->uses[0], true);
202 changed |= setFp(cUnit, ssaRep->uses[1], true);
203 cUnit->regLocation[ssaRep->uses[0]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700204 cUnit->regLocation[ssaRep->uses[1]].wide = true;
buzbeed5018892012-07-11 14:23:40 -0700205 cUnit->regLocation[ssaRep->uses[1]].highWord = true;
206 break;
207 case 'L':
208 changed |= setRef(cUnit, ssaRep->uses[0], true);
209 break;
210 default: break;
211 }
212 }
213
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 // Special-case handling for format 35c/3rc invokes
215 Instruction::Code opcode = mir->dalvikInsn.opcode;
216 int flags = (static_cast<int>(opcode) >= kNumPackedOpcodes)
Ian Rogersa75a0132012-09-28 11:41:42 -0700217 ? 0 : Instruction::FlagsOf(mir->dalvikInsn.opcode);
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 if ((flags & Instruction::kInvoke) &&
219 (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) {
220 DCHECK_EQ(next, 0);
221 int target_idx = mir->dalvikInsn.vB;
222 const char* shorty = oatGetShortyFromTargetIdx(cUnit, target_idx);
223 // Handle result type if floating point
224 if ((shorty[0] == 'F') || (shorty[0] == 'D')) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700225 MIR* moveResultMIR = oatFindMoveResult(cUnit, bb, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700226 // Result might not be used at all, so no move-result
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700227 if (moveResultMIR && (moveResultMIR->dalvikInsn.opcode !=
228 Instruction::MOVE_RESULT_OBJECT)) {
229 SSARepresentation* tgtRep = moveResultMIR->ssaRep;
230 DCHECK(tgtRep != NULL);
Bill Buzbeea114add2012-05-03 15:00:40 -0700231 tgtRep->fpDef[0] = true;
232 changed |= setFp(cUnit, tgtRep->defs[0], true);
233 if (shorty[0] == 'D') {
234 tgtRep->fpDef[1] = true;
235 changed |= setFp(cUnit, tgtRep->defs[1], true);
236 }
237 }
238 }
239 int numUses = mir->dalvikInsn.vA;
buzbeebff24652012-05-06 16:22:05 -0700240 // If this is a non-static invoke, mark implicit "this"
Bill Buzbeea114add2012-05-03 15:00:40 -0700241 if (((mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC) &&
242 (mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC_RANGE))) {
243 cUnit->regLocation[ssaRep->uses[next]].defined = true;
buzbeebff24652012-05-06 16:22:05 -0700244 cUnit->regLocation[ssaRep->uses[next]].ref = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700245 next++;
246 }
247 uint32_t cpos = 1;
248 if (strlen(shorty) > 1) {
249 for (int i = next; i < numUses;) {
250 DCHECK_LT(cpos, strlen(shorty));
251 switch (shorty[cpos++]) {
252 case 'D':
253 ssaRep->fpUse[i] = true;
254 ssaRep->fpUse[i+1] = true;
255 cUnit->regLocation[ssaRep->uses[i]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700256 cUnit->regLocation[ssaRep->uses[i+1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 cUnit->regLocation[ssaRep->uses[i+1]].highWord = true;
258 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[i])+1,
259 SRegToVReg(cUnit, ssaRep->uses[i+1]));
260 i++;
261 break;
262 case 'J':
263 cUnit->regLocation[ssaRep->uses[i]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700264 cUnit->regLocation[ssaRep->uses[i+1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700265 cUnit->regLocation[ssaRep->uses[i+1]].highWord = true;
266 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[i])+1,
267 SRegToVReg(cUnit, ssaRep->uses[i+1]));
268 changed |= setCore(cUnit, ssaRep->uses[i],true);
269 i++;
270 break;
271 case 'F':
272 ssaRep->fpUse[i] = true;
273 break;
buzbeebff24652012-05-06 16:22:05 -0700274 case 'L':
275 changed |= setRef(cUnit,ssaRep->uses[i], true);
276 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700277 default:
278 changed |= setCore(cUnit,ssaRep->uses[i], true);
279 break;
280 }
281 i++;
282 }
283 }
284 }
285
286 for (int i=0; ssaRep->fpUse && i< ssaRep->numUses; i++) {
287 if (ssaRep->fpUse[i])
288 changed |= setFp(cUnit, ssaRep->uses[i], true);
289 }
290 for (int i=0; ssaRep->fpDef && i< ssaRep->numDefs; i++) {
291 if (ssaRep->fpDef[i])
292 changed |= setFp(cUnit, ssaRep->defs[i], true);
293 }
294 // Special-case handling for moves & Phi
295 if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
buzbee2a83e8f2012-07-13 16:42:30 -0700296 /*
297 * If any of our inputs or outputs is defined, set all.
298 * Some ugliness related to Phi nodes and wide values.
299 * The Phi set will include all low words or all high
300 * words, so we have to treat them specially.
301 */
302 bool isPhi = (static_cast<int>(mir->dalvikInsn.opcode) ==
303 kMirOpPhi);
304 RegLocation rlTemp = cUnit->regLocation[ssaRep->defs[0]];
305 bool definedFP = rlTemp.defined && rlTemp.fp;
306 bool definedCore = rlTemp.defined && rlTemp.core;
307 bool definedRef = rlTemp.defined && rlTemp.ref;
308 bool isWide = rlTemp.wide || ((attrs & DF_A_WIDE) != 0);
309 bool isHigh = isPhi && rlTemp.wide && rlTemp.highWord;
310 for (int i = 0; i < ssaRep->numUses;i++) {
311 rlTemp = cUnit->regLocation[ssaRep->uses[i]];
312 definedFP |= rlTemp.defined && rlTemp.fp;
313 definedCore |= rlTemp.defined && rlTemp.core;
314 definedRef |= rlTemp.defined && rlTemp.ref;
315 isWide |= rlTemp.wide;
316 isHigh |= isPhi && rlTemp.wide && rlTemp.highWord;
Bill Buzbeea114add2012-05-03 15:00:40 -0700317 }
318 /*
319 * TODO: cleaner fix
320 * We don't normally expect to see a Dalvik register
321 * definition used both as a floating point and core
322 * value. However, the instruction rewriting that occurs
323 * during verification can eliminate some type information,
324 * leaving us confused. The real fix here is either to
325 * add explicit type information to Dalvik byte codes,
326 * or to recognize THROW_VERIFICATION_ERROR as
327 * an unconditional branch and support dead code elimination.
328 * As a workaround we can detect this situation and
329 * disable register promotion (which is the only thing that
330 * relies on distinctions between core and fp usages.
331 */
buzbeebff24652012-05-06 16:22:05 -0700332 if ((definedFP && (definedCore | definedRef)) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700333 ((cUnit->disableOpt & (1 << kPromoteRegs)) == 0)) {
334 LOG(WARNING) << PrettyMethod(cUnit->method_idx, *cUnit->dex_file)
335 << " op at block " << bb->id
buzbeebff24652012-05-06 16:22:05 -0700336 << " has both fp and core/ref uses for same def.";
Bill Buzbeea114add2012-05-03 15:00:40 -0700337 cUnit->disableOpt |= (1 << kPromoteRegs);
338 }
339 changed |= setFp(cUnit, ssaRep->defs[0], definedFP);
340 changed |= setCore(cUnit, ssaRep->defs[0], definedCore);
buzbeebff24652012-05-06 16:22:05 -0700341 changed |= setRef(cUnit, ssaRep->defs[0], definedRef);
buzbee2a83e8f2012-07-13 16:42:30 -0700342 changed |= setWide(cUnit, ssaRep->defs[0], isWide);
343 changed |= setHigh(cUnit, ssaRep->defs[0], isHigh);
344 if (attrs & DF_A_WIDE) {
345 changed |= setWide(cUnit, ssaRep->defs[1], true);
346 changed |= setHigh(cUnit, ssaRep->defs[1], true);
347 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700348 for (int i = 0; i < ssaRep->numUses; i++) {
buzbee2a83e8f2012-07-13 16:42:30 -0700349 changed |= setFp(cUnit, ssaRep->uses[i], definedFP);
350 changed |= setCore(cUnit, ssaRep->uses[i], definedCore);
351 changed |= setRef(cUnit, ssaRep->uses[i], definedRef);
352 changed |= setWide(cUnit, ssaRep->uses[i], isWide);
353 changed |= setHigh(cUnit, ssaRep->uses[i], isHigh);
354 }
355 if (attrs & DF_A_WIDE) {
356 DCHECK_EQ(ssaRep->numUses, 2);
357 changed |= setWide(cUnit, ssaRep->uses[1], true);
358 changed |= setHigh(cUnit, ssaRep->uses[1], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700359 }
360 }
buzbee67bf8852011-08-17 17:51:35 -0700361 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700362 }
363 return changed;
buzbee67bf8852011-08-17 17:51:35 -0700364}
365
366static const char* storageName[] = {" Frame ", "PhysReg", " Spill "};
367
buzbeedfd3d702011-08-28 12:56:51 -0700368void oatDumpRegLocTable(RegLocation* table, int count)
buzbee67bf8852011-08-17 17:51:35 -0700369{
Bill Buzbeea114add2012-05-03 15:00:40 -0700370 for (int i = 0; i < count; i++) {
371 LOG(INFO) << StringPrintf("Loc[%02d] : %s, %c %c %c %c %c %c%d %c%d S%d",
buzbeeca7a5e42012-08-20 11:12:18 -0700372 table[i].origSReg, storageName[table[i].location],
373 table[i].wide ? 'W' : 'N', table[i].defined ? 'D' : 'U',
buzbeed5018892012-07-11 14:23:40 -0700374 table[i].fp ? 'F' : table[i].ref ? 'R' :'C',
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 table[i].highWord ? 'H' : 'L', table[i].home ? 'h' : 't',
376 oatIsFpReg(table[i].lowReg) ? 's' : 'r',
377 table[i].lowReg & oatFpRegMask(),
378 oatIsFpReg(table[i].highReg) ? 's' : 'r',
379 table[i].highReg & oatFpRegMask(), table[i].sRegLow);
380 }
buzbee67bf8852011-08-17 17:51:35 -0700381}
382
buzbee6969d502012-06-15 16:40:31 -0700383void oatDumpRegLoc(RegLocation loc) {
384 oatDumpRegLocTable(&loc, 1);
385}
386
buzbee2cfc6392012-05-07 14:51:40 -0700387static const RegLocation freshLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
388 INVALID_REG, INVALID_REG, INVALID_SREG,
389 INVALID_SREG};
buzbee67bf8852011-08-17 17:51:35 -0700390
buzbeead8f15e2012-06-18 14:49:45 -0700391int oatComputeFrameSize(CompilationUnit* cUnit) {
392 /* Figure out the frame size */
393 static const uint32_t kAlignMask = kStackAlignment - 1;
394 uint32_t size = (cUnit->numCoreSpills + cUnit->numFPSpills +
395 1 /* filler word */ + cUnit->numRegs + cUnit->numOuts +
396 cUnit->numCompilerTemps + 1 /* curMethod* */)
397 * sizeof(uint32_t);
398 /* Align and set */
399 return (size + kAlignMask) & ~(kAlignMask);
400}
401
buzbee67bf8852011-08-17 17:51:35 -0700402/*
403 * Simple register allocation. Some Dalvik virtual registers may
404 * be promoted to physical registers. Most of the work for temp
Ian Rogersb5d09b22012-03-06 22:14:17 -0800405 * allocation is done on the fly. We also do some initialization and
buzbee67bf8852011-08-17 17:51:35 -0700406 * type inference here.
407 */
408void oatSimpleRegAlloc(CompilationUnit* cUnit)
409{
Bill Buzbeea114add2012-05-03 15:00:40 -0700410 int i;
411 RegLocation* loc;
buzbee67bf8852011-08-17 17:51:35 -0700412
Bill Buzbeea114add2012-05-03 15:00:40 -0700413 /* Allocate the location map */
414 loc = (RegLocation*)oatNew(cUnit, cUnit->numSSARegs * sizeof(*loc), true,
415 kAllocRegAlloc);
416 for (i=0; i< cUnit->numSSARegs; i++) {
417 loc[i] = freshLoc;
418 loc[i].sRegLow = i;
buzbee2cfc6392012-05-07 14:51:40 -0700419 loc[i].isConst = oatIsBitSet(cUnit->isConstantV, i);
Bill Buzbeea114add2012-05-03 15:00:40 -0700420 }
421
422 /* Patch up the locations for Method* and the compiler temps */
423 loc[cUnit->methodSReg].location = kLocCompilerTemp;
424 loc[cUnit->methodSReg].defined = true;
425 for (i = 0; i < cUnit->numCompilerTemps; i++) {
426 CompilerTemp* ct = (CompilerTemp*)cUnit->compilerTemps.elemList[i];
427 loc[ct->sReg].location = kLocCompilerTemp;
428 loc[ct->sReg].defined = true;
429 }
430
431 cUnit->regLocation = loc;
432
433 /* Allocation the promotion map */
434 int numRegs = cUnit->numDalvikRegisters;
435 cUnit->promotionMap =
436 (PromotionMap*)oatNew(cUnit, (numRegs + cUnit->numCompilerTemps + 1) *
437 sizeof(cUnit->promotionMap[0]), true,
438 kAllocRegAlloc);
439
440 /* Add types of incoming arguments based on signature */
441 int numIns = cUnit->numIns;
442 if (numIns > 0) {
443 int sReg = numRegs - numIns;
444 if ((cUnit->access_flags & kAccStatic) == 0) {
445 // For non-static, skip past "this"
446 cUnit->regLocation[sReg].defined = true;
buzbeebff24652012-05-06 16:22:05 -0700447 cUnit->regLocation[sReg].ref = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700448 sReg++;
buzbee67bf8852011-08-17 17:51:35 -0700449 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700450 const char* shorty = cUnit->shorty;
451 int shorty_len = strlen(shorty);
452 for (int i = 1; i < shorty_len; i++) {
453 switch (shorty[i]) {
454 case 'D':
455 cUnit->regLocation[sReg].wide = true;
456 cUnit->regLocation[sReg+1].highWord = true;
457 cUnit->regLocation[sReg+1].fp = true;
458 DCHECK_EQ(SRegToVReg(cUnit, sReg)+1, SRegToVReg(cUnit, sReg+1));
459 cUnit->regLocation[sReg].fp = true;
460 cUnit->regLocation[sReg].defined = true;
461 sReg++;
462 break;
463 case 'J':
464 cUnit->regLocation[sReg].wide = true;
465 cUnit->regLocation[sReg+1].highWord = true;
466 DCHECK_EQ(SRegToVReg(cUnit, sReg)+1, SRegToVReg(cUnit, sReg+1));
467 cUnit->regLocation[sReg].core = true;
468 cUnit->regLocation[sReg].defined = true;
469 sReg++;
buzbeed5018892012-07-11 14:23:40 -0700470 break;
471 case 'F':
472 cUnit->regLocation[sReg].fp = true;
473 cUnit->regLocation[sReg].defined = true;
474 break;
475 case 'L':
476 cUnit->regLocation[sReg].ref = true;
477 cUnit->regLocation[sReg].defined = true;
478 break;
479 default:
480 cUnit->regLocation[sReg].core = true;
481 cUnit->regLocation[sReg].defined = true;
482 break;
buzbeee9a72f62011-09-04 17:59:07 -0700483 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700484 sReg++;
485 }
486 }
487
buzbee2cfc6392012-05-07 14:51:40 -0700488 if (!cUnit->genBitcode) {
489 /* Remap names */
490 oatDataFlowAnalysisDispatcher(cUnit, remapNames,
491 kPreOrderDFSTraversal,
492 false /* isIterative */);
493 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700494
495 /* Do type & size inference pass */
496 oatDataFlowAnalysisDispatcher(cUnit, inferTypeAndSize,
497 kPreOrderDFSTraversal,
498 true /* isIterative */);
499
500 /*
501 * Set the sRegLow field to refer to the pre-SSA name of the
502 * base Dalvik virtual register. Once we add a better register
503 * allocator, remove this remapping.
504 */
505 for (i=0; i < cUnit->numSSARegs; i++) {
506 if (cUnit->regLocation[i].location != kLocCompilerTemp) {
buzbee2cfc6392012-05-07 14:51:40 -0700507 int origSReg = cUnit->regLocation[i].sRegLow;
508 cUnit->regLocation[i].origSReg = origSReg;
509 cUnit->regLocation[i].sRegLow = SRegToVReg(cUnit, origSReg);
buzbeee9a72f62011-09-04 17:59:07 -0700510 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700511 }
buzbeee9a72f62011-09-04 17:59:07 -0700512
Bill Buzbeea114add2012-05-03 15:00:40 -0700513 cUnit->coreSpillMask = 0;
514 cUnit->fpSpillMask = 0;
515 cUnit->numCoreSpills = 0;
buzbeec0ecd652011-09-25 18:11:54 -0700516
Bill Buzbeea114add2012-05-03 15:00:40 -0700517 oatDoPromotion(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700518
buzbeead8f15e2012-06-18 14:49:45 -0700519 /* Get easily-accessable post-promotion copy of RegLocation for Method* */
520 cUnit->methodLoc = cUnit->regLocation[cUnit->methodSReg];
521
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 if (cUnit->printMe && !(cUnit->disableOpt & (1 << kPromoteRegs))) {
523 LOG(INFO) << "After Promotion";
524 oatDumpRegLocTable(cUnit->regLocation, cUnit->numSSARegs);
525 }
buzbee67bf8852011-08-17 17:51:35 -0700526
buzbeead8f15e2012-06-18 14:49:45 -0700527 /* Set the frame size */
528 cUnit->frameSize = oatComputeFrameSize(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700529}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800530
531} // namespace art