blob: 500b1b2d1b06957a3df6968c6c12c9fa680f5c05 [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
Brian Carlstrom937b73e2012-08-01 16:09:16 -070092// Try to find the next move result which might have an FP target
93SSARepresentation* findFPMoveResult(MIR* mir)
94{
95 SSARepresentation* res = NULL;
96 for (; mir; mir = mir->next) {
97 if ((mir->dalvikInsn.opcode == Instruction::MOVE_RESULT) ||
98 (mir->dalvikInsn.opcode == Instruction::MOVE_RESULT_WIDE)) {
99 res = mir->ssaRep;
100 break;
101 }
102 }
103 return res;
104}
105
buzbee67bf8852011-08-17 17:51:35 -0700106/*
buzbee03fa2632011-09-20 17:10:57 -0700107 * Infer types and sizes. We don't need to track change on sizes,
108 * as it doesn't propagate. We're guaranteed at least one pass through
109 * the cfg.
buzbee67bf8852011-08-17 17:51:35 -0700110 */
buzbee31a4a6f2012-02-28 15:36:15 -0800111bool inferTypeAndSize(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700112{
Bill Buzbeea114add2012-05-03 15:00:40 -0700113 MIR *mir;
114 bool changed = false; // Did anything change?
buzbee03fa2632011-09-20 17:10:57 -0700115
Bill Buzbeea114add2012-05-03 15:00:40 -0700116 if (bb->dataFlowInfo == NULL) return false;
117 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock)
118 return false;
buzbee67bf8852011-08-17 17:51:35 -0700119
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
121 SSARepresentation *ssaRep = mir->ssaRep;
122 if (ssaRep) {
123 int attrs = oatDataFlowAttributes[mir->dalvikInsn.opcode];
buzbee67bc2362011-10-11 18:08:40 -0700124
Bill Buzbeea114add2012-05-03 15:00:40 -0700125 // Handle defs
buzbeebff24652012-05-06 16:22:05 -0700126 if (attrs & DF_DA) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700127 if (attrs & DF_CORE_A) {
128 changed |= setCore(cUnit, ssaRep->defs[0], true);
buzbee67bf8852011-08-17 17:51:35 -0700129 }
buzbeebff24652012-05-06 16:22:05 -0700130 if (attrs & DF_REF_A) {
131 changed |= setRef(cUnit, ssaRep->defs[0], true);
132 }
133 if (attrs & DF_A_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700134 cUnit->regLocation[ssaRep->defs[0]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700135 cUnit->regLocation[ssaRep->defs[1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 cUnit->regLocation[ssaRep->defs[1]].highWord = true;
137 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->defs[0])+1,
138 SRegToVReg(cUnit, ssaRep->defs[1]));
139 }
140 }
141
142 // Handles uses
143 int next = 0;
buzbeebff24652012-05-06 16:22:05 -0700144 if (attrs & DF_UA) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700145 if (attrs & DF_CORE_A) {
146 changed |= setCore(cUnit, ssaRep->uses[next], true);
147 }
buzbeebff24652012-05-06 16:22:05 -0700148 if (attrs & DF_REF_A) {
149 changed |= setRef(cUnit, ssaRep->uses[next], true);
150 }
151 if (attrs & DF_A_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700152 cUnit->regLocation[ssaRep->uses[next]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700153 cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700154 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
155 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
156 SRegToVReg(cUnit, ssaRep->uses[next + 1]));
157 next += 2;
158 } else {
159 next++;
160 }
161 }
buzbeebff24652012-05-06 16:22:05 -0700162 if (attrs & DF_UB) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700163 if (attrs & DF_CORE_B) {
164 changed |= setCore(cUnit, ssaRep->uses[next], true);
165 }
buzbeebff24652012-05-06 16:22:05 -0700166 if (attrs & DF_REF_B) {
167 changed |= setRef(cUnit, ssaRep->uses[next], true);
168 }
169 if (attrs & DF_B_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700170 cUnit->regLocation[ssaRep->uses[next]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700171 cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700172 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
173 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
174 SRegToVReg(cUnit, ssaRep->uses[next + 1]));
175 next += 2;
176 } else {
177 next++;
178 }
179 }
buzbeebff24652012-05-06 16:22:05 -0700180 if (attrs & DF_UC) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700181 if (attrs & DF_CORE_C) {
182 changed |= setCore(cUnit, ssaRep->uses[next], true);
183 }
buzbeebff24652012-05-06 16:22:05 -0700184 if (attrs & DF_REF_C) {
185 changed |= setRef(cUnit, ssaRep->uses[next], true);
186 }
187 if (attrs & DF_C_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700188 cUnit->regLocation[ssaRep->uses[next]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700189 cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700190 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
191 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
192 SRegToVReg(cUnit, ssaRep->uses[next + 1]));
193 }
194 }
195
buzbeed5018892012-07-11 14:23:40 -0700196 // Special-case return handling
197 if ((mir->dalvikInsn.opcode == Instruction::RETURN) ||
198 (mir->dalvikInsn.opcode == Instruction::RETURN_WIDE) ||
199 (mir->dalvikInsn.opcode == Instruction::RETURN_OBJECT)) {
200 switch(cUnit->shorty[0]) {
201 case 'I':
202 changed |= setCore(cUnit, ssaRep->uses[0], true);
203 break;
204 case 'J':
205 changed |= setCore(cUnit, ssaRep->uses[0], true);
206 changed |= setCore(cUnit, ssaRep->uses[1], true);
207 cUnit->regLocation[ssaRep->uses[0]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700208 cUnit->regLocation[ssaRep->uses[1]].wide = true;
buzbeed5018892012-07-11 14:23:40 -0700209 cUnit->regLocation[ssaRep->uses[1]].highWord = true;
210 break;
211 case 'F':
212 changed |= setFp(cUnit, ssaRep->uses[0], true);
213 break;
214 case 'D':
215 changed |= setFp(cUnit, ssaRep->uses[0], true);
216 changed |= setFp(cUnit, ssaRep->uses[1], true);
217 cUnit->regLocation[ssaRep->uses[0]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700218 cUnit->regLocation[ssaRep->uses[1]].wide = true;
buzbeed5018892012-07-11 14:23:40 -0700219 cUnit->regLocation[ssaRep->uses[1]].highWord = true;
220 break;
221 case 'L':
222 changed |= setRef(cUnit, ssaRep->uses[0], true);
223 break;
224 default: break;
225 }
226 }
227
Bill Buzbeea114add2012-05-03 15:00:40 -0700228 // Special-case handling for format 35c/3rc invokes
229 Instruction::Code opcode = mir->dalvikInsn.opcode;
230 int flags = (static_cast<int>(opcode) >= kNumPackedOpcodes)
231 ? 0 : Instruction::Flags(mir->dalvikInsn.opcode);
232 if ((flags & Instruction::kInvoke) &&
233 (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) {
234 DCHECK_EQ(next, 0);
235 int target_idx = mir->dalvikInsn.vB;
236 const char* shorty = oatGetShortyFromTargetIdx(cUnit, target_idx);
237 // Handle result type if floating point
238 if ((shorty[0] == 'F') || (shorty[0] == 'D')) {
Brian Carlstrom937b73e2012-08-01 16:09:16 -0700239 // Find move-result that consumes this result
240 SSARepresentation* tgtRep = findFPMoveResult(mir->next);
241 // Might be in next basic block
242 if (!tgtRep) {
243 tgtRep = findFPMoveResult(bb->fallThrough->firstMIRInsn);
244 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700245 // Result might not be used at all, so no move-result
Brian Carlstrom937b73e2012-08-01 16:09:16 -0700246 if (tgtRep) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700247 tgtRep->fpDef[0] = true;
248 changed |= setFp(cUnit, tgtRep->defs[0], true);
249 if (shorty[0] == 'D') {
250 tgtRep->fpDef[1] = true;
251 changed |= setFp(cUnit, tgtRep->defs[1], true);
252 }
253 }
254 }
255 int numUses = mir->dalvikInsn.vA;
buzbeebff24652012-05-06 16:22:05 -0700256 // If this is a non-static invoke, mark implicit "this"
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 if (((mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC) &&
258 (mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC_RANGE))) {
259 cUnit->regLocation[ssaRep->uses[next]].defined = true;
buzbeebff24652012-05-06 16:22:05 -0700260 cUnit->regLocation[ssaRep->uses[next]].ref = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700261 next++;
262 }
263 uint32_t cpos = 1;
264 if (strlen(shorty) > 1) {
265 for (int i = next; i < numUses;) {
266 DCHECK_LT(cpos, strlen(shorty));
267 switch (shorty[cpos++]) {
268 case 'D':
269 ssaRep->fpUse[i] = true;
270 ssaRep->fpUse[i+1] = true;
271 cUnit->regLocation[ssaRep->uses[i]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700272 cUnit->regLocation[ssaRep->uses[i+1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700273 cUnit->regLocation[ssaRep->uses[i+1]].highWord = true;
274 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[i])+1,
275 SRegToVReg(cUnit, ssaRep->uses[i+1]));
276 i++;
277 break;
278 case 'J':
279 cUnit->regLocation[ssaRep->uses[i]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700280 cUnit->regLocation[ssaRep->uses[i+1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700281 cUnit->regLocation[ssaRep->uses[i+1]].highWord = true;
282 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[i])+1,
283 SRegToVReg(cUnit, ssaRep->uses[i+1]));
284 changed |= setCore(cUnit, ssaRep->uses[i],true);
285 i++;
286 break;
287 case 'F':
288 ssaRep->fpUse[i] = true;
289 break;
buzbeebff24652012-05-06 16:22:05 -0700290 case 'L':
291 changed |= setRef(cUnit,ssaRep->uses[i], true);
292 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700293 default:
294 changed |= setCore(cUnit,ssaRep->uses[i], true);
295 break;
296 }
297 i++;
298 }
299 }
300 }
301
302 for (int i=0; ssaRep->fpUse && i< ssaRep->numUses; i++) {
303 if (ssaRep->fpUse[i])
304 changed |= setFp(cUnit, ssaRep->uses[i], true);
305 }
306 for (int i=0; ssaRep->fpDef && i< ssaRep->numDefs; i++) {
307 if (ssaRep->fpDef[i])
308 changed |= setFp(cUnit, ssaRep->defs[i], true);
309 }
310 // Special-case handling for moves & Phi
311 if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
buzbee2a83e8f2012-07-13 16:42:30 -0700312 /*
313 * If any of our inputs or outputs is defined, set all.
314 * Some ugliness related to Phi nodes and wide values.
315 * The Phi set will include all low words or all high
316 * words, so we have to treat them specially.
317 */
318 bool isPhi = (static_cast<int>(mir->dalvikInsn.opcode) ==
319 kMirOpPhi);
320 RegLocation rlTemp = cUnit->regLocation[ssaRep->defs[0]];
321 bool definedFP = rlTemp.defined && rlTemp.fp;
322 bool definedCore = rlTemp.defined && rlTemp.core;
323 bool definedRef = rlTemp.defined && rlTemp.ref;
324 bool isWide = rlTemp.wide || ((attrs & DF_A_WIDE) != 0);
325 bool isHigh = isPhi && rlTemp.wide && rlTemp.highWord;
326 for (int i = 0; i < ssaRep->numUses;i++) {
327 rlTemp = cUnit->regLocation[ssaRep->uses[i]];
328 definedFP |= rlTemp.defined && rlTemp.fp;
329 definedCore |= rlTemp.defined && rlTemp.core;
330 definedRef |= rlTemp.defined && rlTemp.ref;
331 isWide |= rlTemp.wide;
332 isHigh |= isPhi && rlTemp.wide && rlTemp.highWord;
Bill Buzbeea114add2012-05-03 15:00:40 -0700333 }
334 /*
335 * TODO: cleaner fix
336 * We don't normally expect to see a Dalvik register
337 * definition used both as a floating point and core
338 * value. However, the instruction rewriting that occurs
339 * during verification can eliminate some type information,
340 * leaving us confused. The real fix here is either to
341 * add explicit type information to Dalvik byte codes,
342 * or to recognize THROW_VERIFICATION_ERROR as
343 * an unconditional branch and support dead code elimination.
344 * As a workaround we can detect this situation and
345 * disable register promotion (which is the only thing that
346 * relies on distinctions between core and fp usages.
347 */
buzbeebff24652012-05-06 16:22:05 -0700348 if ((definedFP && (definedCore | definedRef)) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700349 ((cUnit->disableOpt & (1 << kPromoteRegs)) == 0)) {
350 LOG(WARNING) << PrettyMethod(cUnit->method_idx, *cUnit->dex_file)
351 << " op at block " << bb->id
buzbeebff24652012-05-06 16:22:05 -0700352 << " has both fp and core/ref uses for same def.";
Bill Buzbeea114add2012-05-03 15:00:40 -0700353 cUnit->disableOpt |= (1 << kPromoteRegs);
354 }
355 changed |= setFp(cUnit, ssaRep->defs[0], definedFP);
356 changed |= setCore(cUnit, ssaRep->defs[0], definedCore);
buzbeebff24652012-05-06 16:22:05 -0700357 changed |= setRef(cUnit, ssaRep->defs[0], definedRef);
buzbee2a83e8f2012-07-13 16:42:30 -0700358 changed |= setWide(cUnit, ssaRep->defs[0], isWide);
359 changed |= setHigh(cUnit, ssaRep->defs[0], isHigh);
360 if (attrs & DF_A_WIDE) {
361 changed |= setWide(cUnit, ssaRep->defs[1], true);
362 changed |= setHigh(cUnit, ssaRep->defs[1], true);
363 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700364 for (int i = 0; i < ssaRep->numUses; i++) {
buzbee2a83e8f2012-07-13 16:42:30 -0700365 changed |= setFp(cUnit, ssaRep->uses[i], definedFP);
366 changed |= setCore(cUnit, ssaRep->uses[i], definedCore);
367 changed |= setRef(cUnit, ssaRep->uses[i], definedRef);
368 changed |= setWide(cUnit, ssaRep->uses[i], isWide);
369 changed |= setHigh(cUnit, ssaRep->uses[i], isHigh);
370 }
371 if (attrs & DF_A_WIDE) {
372 DCHECK_EQ(ssaRep->numUses, 2);
373 changed |= setWide(cUnit, ssaRep->uses[1], true);
374 changed |= setHigh(cUnit, ssaRep->uses[1], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 }
376 }
buzbee67bf8852011-08-17 17:51:35 -0700377 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700378 }
379 return changed;
buzbee67bf8852011-08-17 17:51:35 -0700380}
381
382static const char* storageName[] = {" Frame ", "PhysReg", " Spill "};
383
buzbeedfd3d702011-08-28 12:56:51 -0700384void oatDumpRegLocTable(RegLocation* table, int count)
buzbee67bf8852011-08-17 17:51:35 -0700385{
Bill Buzbeea114add2012-05-03 15:00:40 -0700386 for (int i = 0; i < count; i++) {
387 LOG(INFO) << StringPrintf("Loc[%02d] : %s, %c %c %c %c %c %c%d %c%d S%d",
388 i, storageName[table[i].location], table[i].wide ? 'W' : 'N',
buzbeed5018892012-07-11 14:23:40 -0700389 table[i].defined ? 'D' : 'U',
390 table[i].fp ? 'F' : table[i].ref ? 'R' :'C',
Bill Buzbeea114add2012-05-03 15:00:40 -0700391 table[i].highWord ? 'H' : 'L', table[i].home ? 'h' : 't',
392 oatIsFpReg(table[i].lowReg) ? 's' : 'r',
393 table[i].lowReg & oatFpRegMask(),
394 oatIsFpReg(table[i].highReg) ? 's' : 'r',
395 table[i].highReg & oatFpRegMask(), table[i].sRegLow);
396 }
buzbee67bf8852011-08-17 17:51:35 -0700397}
398
buzbee6969d502012-06-15 16:40:31 -0700399void oatDumpRegLoc(RegLocation loc) {
400 oatDumpRegLocTable(&loc, 1);
401}
402
buzbee2cfc6392012-05-07 14:51:40 -0700403static const RegLocation freshLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
404 INVALID_REG, INVALID_REG, INVALID_SREG,
405 INVALID_SREG};
buzbee67bf8852011-08-17 17:51:35 -0700406
buzbeead8f15e2012-06-18 14:49:45 -0700407int oatComputeFrameSize(CompilationUnit* cUnit) {
408 /* Figure out the frame size */
409 static const uint32_t kAlignMask = kStackAlignment - 1;
410 uint32_t size = (cUnit->numCoreSpills + cUnit->numFPSpills +
411 1 /* filler word */ + cUnit->numRegs + cUnit->numOuts +
412 cUnit->numCompilerTemps + 1 /* curMethod* */)
413 * sizeof(uint32_t);
414 /* Align and set */
415 return (size + kAlignMask) & ~(kAlignMask);
416}
417
buzbee67bf8852011-08-17 17:51:35 -0700418/*
419 * Simple register allocation. Some Dalvik virtual registers may
420 * be promoted to physical registers. Most of the work for temp
Ian Rogersb5d09b22012-03-06 22:14:17 -0800421 * allocation is done on the fly. We also do some initialization and
buzbee67bf8852011-08-17 17:51:35 -0700422 * type inference here.
423 */
424void oatSimpleRegAlloc(CompilationUnit* cUnit)
425{
Bill Buzbeea114add2012-05-03 15:00:40 -0700426 int i;
427 RegLocation* loc;
buzbee67bf8852011-08-17 17:51:35 -0700428
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 /* Allocate the location map */
430 loc = (RegLocation*)oatNew(cUnit, cUnit->numSSARegs * sizeof(*loc), true,
431 kAllocRegAlloc);
432 for (i=0; i< cUnit->numSSARegs; i++) {
433 loc[i] = freshLoc;
434 loc[i].sRegLow = i;
buzbee2cfc6392012-05-07 14:51:40 -0700435 loc[i].isConst = oatIsBitSet(cUnit->isConstantV, i);
Bill Buzbeea114add2012-05-03 15:00:40 -0700436 }
437
438 /* Patch up the locations for Method* and the compiler temps */
439 loc[cUnit->methodSReg].location = kLocCompilerTemp;
440 loc[cUnit->methodSReg].defined = true;
441 for (i = 0; i < cUnit->numCompilerTemps; i++) {
442 CompilerTemp* ct = (CompilerTemp*)cUnit->compilerTemps.elemList[i];
443 loc[ct->sReg].location = kLocCompilerTemp;
444 loc[ct->sReg].defined = true;
445 }
446
447 cUnit->regLocation = loc;
448
449 /* Allocation the promotion map */
450 int numRegs = cUnit->numDalvikRegisters;
451 cUnit->promotionMap =
452 (PromotionMap*)oatNew(cUnit, (numRegs + cUnit->numCompilerTemps + 1) *
453 sizeof(cUnit->promotionMap[0]), true,
454 kAllocRegAlloc);
455
456 /* Add types of incoming arguments based on signature */
457 int numIns = cUnit->numIns;
458 if (numIns > 0) {
459 int sReg = numRegs - numIns;
460 if ((cUnit->access_flags & kAccStatic) == 0) {
461 // For non-static, skip past "this"
462 cUnit->regLocation[sReg].defined = true;
buzbeebff24652012-05-06 16:22:05 -0700463 cUnit->regLocation[sReg].ref = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 sReg++;
buzbee67bf8852011-08-17 17:51:35 -0700465 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 const char* shorty = cUnit->shorty;
467 int shorty_len = strlen(shorty);
468 for (int i = 1; i < shorty_len; i++) {
469 switch (shorty[i]) {
470 case 'D':
471 cUnit->regLocation[sReg].wide = true;
472 cUnit->regLocation[sReg+1].highWord = true;
473 cUnit->regLocation[sReg+1].fp = true;
474 DCHECK_EQ(SRegToVReg(cUnit, sReg)+1, SRegToVReg(cUnit, sReg+1));
475 cUnit->regLocation[sReg].fp = true;
476 cUnit->regLocation[sReg].defined = true;
477 sReg++;
478 break;
479 case 'J':
480 cUnit->regLocation[sReg].wide = true;
481 cUnit->regLocation[sReg+1].highWord = true;
482 DCHECK_EQ(SRegToVReg(cUnit, sReg)+1, SRegToVReg(cUnit, sReg+1));
483 cUnit->regLocation[sReg].core = true;
484 cUnit->regLocation[sReg].defined = true;
485 sReg++;
buzbeed5018892012-07-11 14:23:40 -0700486 break;
487 case 'F':
488 cUnit->regLocation[sReg].fp = true;
489 cUnit->regLocation[sReg].defined = true;
490 break;
491 case 'L':
492 cUnit->regLocation[sReg].ref = true;
493 cUnit->regLocation[sReg].defined = true;
494 break;
495 default:
496 cUnit->regLocation[sReg].core = true;
497 cUnit->regLocation[sReg].defined = true;
498 break;
buzbeee9a72f62011-09-04 17:59:07 -0700499 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 sReg++;
501 }
502 }
503
buzbee2cfc6392012-05-07 14:51:40 -0700504#if defined(ART_USE_QUICK_COMPILER)
505 if (!cUnit->genBitcode) {
506 /* Remap names */
507 oatDataFlowAnalysisDispatcher(cUnit, remapNames,
508 kPreOrderDFSTraversal,
509 false /* isIterative */);
510 }
511#else
Bill Buzbeea114add2012-05-03 15:00:40 -0700512 /* Remap names */
513 oatDataFlowAnalysisDispatcher(cUnit, remapNames,
514 kPreOrderDFSTraversal,
515 false /* isIterative */);
buzbee2cfc6392012-05-07 14:51:40 -0700516#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700517
518 /* Do type & size inference pass */
519 oatDataFlowAnalysisDispatcher(cUnit, inferTypeAndSize,
520 kPreOrderDFSTraversal,
521 true /* isIterative */);
522
523 /*
524 * Set the sRegLow field to refer to the pre-SSA name of the
525 * base Dalvik virtual register. Once we add a better register
526 * allocator, remove this remapping.
527 */
528 for (i=0; i < cUnit->numSSARegs; i++) {
529 if (cUnit->regLocation[i].location != kLocCompilerTemp) {
buzbee2cfc6392012-05-07 14:51:40 -0700530 int origSReg = cUnit->regLocation[i].sRegLow;
531 cUnit->regLocation[i].origSReg = origSReg;
532 cUnit->regLocation[i].sRegLow = SRegToVReg(cUnit, origSReg);
buzbeee9a72f62011-09-04 17:59:07 -0700533 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 }
buzbeee9a72f62011-09-04 17:59:07 -0700535
Bill Buzbeea114add2012-05-03 15:00:40 -0700536 cUnit->coreSpillMask = 0;
537 cUnit->fpSpillMask = 0;
538 cUnit->numCoreSpills = 0;
buzbeec0ecd652011-09-25 18:11:54 -0700539
Bill Buzbeea114add2012-05-03 15:00:40 -0700540 oatDoPromotion(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700541
buzbeead8f15e2012-06-18 14:49:45 -0700542 /* Get easily-accessable post-promotion copy of RegLocation for Method* */
543 cUnit->methodLoc = cUnit->regLocation[cUnit->methodSReg];
544
Bill Buzbeea114add2012-05-03 15:00:40 -0700545 if (cUnit->printMe && !(cUnit->disableOpt & (1 << kPromoteRegs))) {
546 LOG(INFO) << "After Promotion";
547 oatDumpRegLocTable(cUnit->regLocation, cUnit->numSSARegs);
548 }
buzbee67bf8852011-08-17 17:51:35 -0700549
buzbeead8f15e2012-06-18 14:49:45 -0700550 /* Set the frame size */
551 cUnit->frameSize = oatComputeFrameSize(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700552}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800553
554} // namespace art