blob: ffb7fecf688e8be4626ea58e0961ab9883c9847a [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
buzbeeefc63692012-11-14 16:31:52 -080017#include "compiler_internals.h"
18#include "dataflow.h"
buzbeeeaf09bc2012-11-15 14:51:41 -080019#include "codegen/ralloc_util.h"
buzbee67bf8852011-08-17 17:51:35 -070020
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080021namespace art {
22
buzbee31a4a6f2012-02-28 15:36:15 -080023bool setFp(CompilationUnit* cUnit, int index, bool isFP) {
Bill Buzbeea114add2012-05-03 15:00:40 -070024 bool change = false;
Bill Buzbeea114add2012-05-03 15:00:40 -070025 if (isFP && !cUnit->regLocation[index].fp) {
26 cUnit->regLocation[index].fp = true;
27 cUnit->regLocation[index].defined = true;
28 change = true;
29 }
30 return change;
buzbee67bc2362011-10-11 18:08:40 -070031}
32
buzbee31a4a6f2012-02-28 15:36:15 -080033bool setCore(CompilationUnit* cUnit, int index, bool isCore) {
Bill Buzbeea114add2012-05-03 15:00:40 -070034 bool change = false;
Bill Buzbeea114add2012-05-03 15:00:40 -070035 if (isCore && !cUnit->regLocation[index].defined) {
36 cUnit->regLocation[index].core = true;
37 cUnit->regLocation[index].defined = true;
38 change = true;
39 }
40 return change;
buzbee03fa2632011-09-20 17:10:57 -070041}
42
buzbeebff24652012-05-06 16:22:05 -070043bool setRef(CompilationUnit* cUnit, int index, bool isRef) {
44 bool change = false;
buzbeebff24652012-05-06 16:22:05 -070045 if (isRef && !cUnit->regLocation[index].defined) {
46 cUnit->regLocation[index].ref = true;
47 cUnit->regLocation[index].defined = true;
48 change = true;
49 }
50 return change;
51}
52
buzbee2a83e8f2012-07-13 16:42:30 -070053bool setWide(CompilationUnit* cUnit, int index, bool isWide) {
54 bool change = false;
55 if (isWide && !cUnit->regLocation[index].wide) {
56 cUnit->regLocation[index].wide = true;
57 change = true;
58 }
59 return change;
60}
61
62bool setHigh(CompilationUnit* cUnit, int index, bool isHigh) {
63 bool change = false;
64 if (isHigh && !cUnit->regLocation[index].highWord) {
65 cUnit->regLocation[index].highWord = true;
66 change = true;
67 }
68 return change;
69}
70
buzbee31a4a6f2012-02-28 15:36:15 -080071bool remapNames(CompilationUnit* cUnit, BasicBlock* bb)
buzbeec0ecd652011-09-25 18:11:54 -070072{
Bill Buzbeea114add2012-05-03 15:00:40 -070073 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
74 bb->blockType != kExitBlock)
buzbeec0ecd652011-09-25 18:11:54 -070075 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -070076
77 for (MIR* mir = bb->firstMIRInsn; mir; mir = mir->next) {
78 SSARepresentation *ssaRep = mir->ssaRep;
79 if (ssaRep) {
80 for (int i = 0; i < ssaRep->numUses; i++) {
81 ssaRep->uses[i] = cUnit->phiAliasMap[ssaRep->uses[i]];
82 }
83 for (int i = 0; i < ssaRep->numDefs; i++) {
84 ssaRep->defs[i] = cUnit->phiAliasMap[ssaRep->defs[i]];
85 }
86 }
87 }
88 return false;
buzbeec0ecd652011-09-25 18:11:54 -070089}
90
buzbee67bf8852011-08-17 17:51:35 -070091/*
buzbee03fa2632011-09-20 17:10:57 -070092 * Infer types and sizes. We don't need to track change on sizes,
93 * as it doesn't propagate. We're guaranteed at least one pass through
94 * the cfg.
buzbee67bf8852011-08-17 17:51:35 -070095 */
buzbee31a4a6f2012-02-28 15:36:15 -080096bool inferTypeAndSize(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070097{
Bill Buzbeea114add2012-05-03 15:00:40 -070098 MIR *mir;
99 bool changed = false; // Did anything change?
buzbee03fa2632011-09-20 17:10:57 -0700100
Bill Buzbeea114add2012-05-03 15:00:40 -0700101 if (bb->dataFlowInfo == NULL) return false;
102 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock)
103 return false;
buzbee67bf8852011-08-17 17:51:35 -0700104
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
106 SSARepresentation *ssaRep = mir->ssaRep;
107 if (ssaRep) {
108 int attrs = oatDataFlowAttributes[mir->dalvikInsn.opcode];
buzbee67bc2362011-10-11 18:08:40 -0700109
Bill Buzbeea114add2012-05-03 15:00:40 -0700110 // Handle defs
buzbeebff24652012-05-06 16:22:05 -0700111 if (attrs & DF_DA) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700112 if (attrs & DF_CORE_A) {
113 changed |= setCore(cUnit, ssaRep->defs[0], true);
buzbee67bf8852011-08-17 17:51:35 -0700114 }
buzbeebff24652012-05-06 16:22:05 -0700115 if (attrs & DF_REF_A) {
116 changed |= setRef(cUnit, ssaRep->defs[0], true);
117 }
118 if (attrs & DF_A_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700119 cUnit->regLocation[ssaRep->defs[0]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700120 cUnit->regLocation[ssaRep->defs[1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700121 cUnit->regLocation[ssaRep->defs[1]].highWord = true;
122 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->defs[0])+1,
123 SRegToVReg(cUnit, ssaRep->defs[1]));
124 }
125 }
126
127 // Handles uses
128 int next = 0;
buzbeebff24652012-05-06 16:22:05 -0700129 if (attrs & DF_UA) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700130 if (attrs & DF_CORE_A) {
131 changed |= setCore(cUnit, ssaRep->uses[next], true);
132 }
buzbeebff24652012-05-06 16:22:05 -0700133 if (attrs & DF_REF_A) {
134 changed |= setRef(cUnit, ssaRep->uses[next], true);
135 }
136 if (attrs & DF_A_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 cUnit->regLocation[ssaRep->uses[next]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700138 cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
140 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
141 SRegToVReg(cUnit, ssaRep->uses[next + 1]));
142 next += 2;
143 } else {
144 next++;
145 }
146 }
buzbeebff24652012-05-06 16:22:05 -0700147 if (attrs & DF_UB) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 if (attrs & DF_CORE_B) {
149 changed |= setCore(cUnit, ssaRep->uses[next], true);
150 }
buzbeebff24652012-05-06 16:22:05 -0700151 if (attrs & DF_REF_B) {
152 changed |= setRef(cUnit, ssaRep->uses[next], true);
153 }
154 if (attrs & DF_B_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700155 cUnit->regLocation[ssaRep->uses[next]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700156 cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700157 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
158 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
159 SRegToVReg(cUnit, ssaRep->uses[next + 1]));
160 next += 2;
161 } else {
162 next++;
163 }
164 }
buzbeebff24652012-05-06 16:22:05 -0700165 if (attrs & DF_UC) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700166 if (attrs & DF_CORE_C) {
167 changed |= setCore(cUnit, ssaRep->uses[next], true);
168 }
buzbeebff24652012-05-06 16:22:05 -0700169 if (attrs & DF_REF_C) {
170 changed |= setRef(cUnit, ssaRep->uses[next], true);
171 }
172 if (attrs & DF_C_WIDE) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700173 cUnit->regLocation[ssaRep->uses[next]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700174 cUnit->regLocation[ssaRep->uses[next + 1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700175 cUnit->regLocation[ssaRep->uses[next + 1]].highWord = true;
176 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[next])+1,
177 SRegToVReg(cUnit, ssaRep->uses[next + 1]));
178 }
179 }
180
buzbeed5018892012-07-11 14:23:40 -0700181 // Special-case return handling
182 if ((mir->dalvikInsn.opcode == Instruction::RETURN) ||
183 (mir->dalvikInsn.opcode == Instruction::RETURN_WIDE) ||
184 (mir->dalvikInsn.opcode == Instruction::RETURN_OBJECT)) {
185 switch(cUnit->shorty[0]) {
186 case 'I':
187 changed |= setCore(cUnit, ssaRep->uses[0], true);
188 break;
189 case 'J':
190 changed |= setCore(cUnit, ssaRep->uses[0], true);
191 changed |= setCore(cUnit, ssaRep->uses[1], true);
192 cUnit->regLocation[ssaRep->uses[0]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700193 cUnit->regLocation[ssaRep->uses[1]].wide = true;
buzbeed5018892012-07-11 14:23:40 -0700194 cUnit->regLocation[ssaRep->uses[1]].highWord = true;
195 break;
196 case 'F':
197 changed |= setFp(cUnit, ssaRep->uses[0], true);
198 break;
199 case 'D':
200 changed |= setFp(cUnit, ssaRep->uses[0], true);
201 changed |= setFp(cUnit, ssaRep->uses[1], true);
202 cUnit->regLocation[ssaRep->uses[0]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700203 cUnit->regLocation[ssaRep->uses[1]].wide = true;
buzbeed5018892012-07-11 14:23:40 -0700204 cUnit->regLocation[ssaRep->uses[1]].highWord = true;
205 break;
206 case 'L':
207 changed |= setRef(cUnit, ssaRep->uses[0], true);
208 break;
209 default: break;
210 }
211 }
212
Bill Buzbeea114add2012-05-03 15:00:40 -0700213 // Special-case handling for format 35c/3rc invokes
214 Instruction::Code opcode = mir->dalvikInsn.opcode;
215 int flags = (static_cast<int>(opcode) >= kNumPackedOpcodes)
Ian Rogersa75a0132012-09-28 11:41:42 -0700216 ? 0 : Instruction::FlagsOf(mir->dalvikInsn.opcode);
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 if ((flags & Instruction::kInvoke) &&
218 (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) {
219 DCHECK_EQ(next, 0);
220 int target_idx = mir->dalvikInsn.vB;
221 const char* shorty = oatGetShortyFromTargetIdx(cUnit, target_idx);
222 // Handle result type if floating point
223 if ((shorty[0] == 'F') || (shorty[0] == 'D')) {
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700224 MIR* moveResultMIR = oatFindMoveResult(cUnit, bb, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700225 // Result might not be used at all, so no move-result
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700226 if (moveResultMIR && (moveResultMIR->dalvikInsn.opcode !=
227 Instruction::MOVE_RESULT_OBJECT)) {
228 SSARepresentation* tgtRep = moveResultMIR->ssaRep;
229 DCHECK(tgtRep != NULL);
Bill Buzbeea114add2012-05-03 15:00:40 -0700230 tgtRep->fpDef[0] = true;
231 changed |= setFp(cUnit, tgtRep->defs[0], true);
232 if (shorty[0] == 'D') {
233 tgtRep->fpDef[1] = true;
234 changed |= setFp(cUnit, tgtRep->defs[1], true);
235 }
236 }
237 }
238 int numUses = mir->dalvikInsn.vA;
buzbeebff24652012-05-06 16:22:05 -0700239 // If this is a non-static invoke, mark implicit "this"
Bill Buzbeea114add2012-05-03 15:00:40 -0700240 if (((mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC) &&
241 (mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC_RANGE))) {
242 cUnit->regLocation[ssaRep->uses[next]].defined = true;
buzbeebff24652012-05-06 16:22:05 -0700243 cUnit->regLocation[ssaRep->uses[next]].ref = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700244 next++;
245 }
246 uint32_t cpos = 1;
247 if (strlen(shorty) > 1) {
248 for (int i = next; i < numUses;) {
249 DCHECK_LT(cpos, strlen(shorty));
250 switch (shorty[cpos++]) {
251 case 'D':
252 ssaRep->fpUse[i] = true;
253 ssaRep->fpUse[i+1] = true;
254 cUnit->regLocation[ssaRep->uses[i]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700255 cUnit->regLocation[ssaRep->uses[i+1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700256 cUnit->regLocation[ssaRep->uses[i+1]].highWord = true;
257 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[i])+1,
258 SRegToVReg(cUnit, ssaRep->uses[i+1]));
259 i++;
260 break;
261 case 'J':
262 cUnit->regLocation[ssaRep->uses[i]].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -0700263 cUnit->regLocation[ssaRep->uses[i+1]].wide = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 cUnit->regLocation[ssaRep->uses[i+1]].highWord = true;
265 DCHECK_EQ(SRegToVReg(cUnit, ssaRep->uses[i])+1,
266 SRegToVReg(cUnit, ssaRep->uses[i+1]));
267 changed |= setCore(cUnit, ssaRep->uses[i],true);
268 i++;
269 break;
270 case 'F':
271 ssaRep->fpUse[i] = true;
272 break;
buzbeebff24652012-05-06 16:22:05 -0700273 case 'L':
274 changed |= setRef(cUnit,ssaRep->uses[i], true);
275 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700276 default:
277 changed |= setCore(cUnit,ssaRep->uses[i], true);
278 break;
279 }
280 i++;
281 }
282 }
283 }
284
285 for (int i=0; ssaRep->fpUse && i< ssaRep->numUses; i++) {
286 if (ssaRep->fpUse[i])
287 changed |= setFp(cUnit, ssaRep->uses[i], true);
288 }
289 for (int i=0; ssaRep->fpDef && i< ssaRep->numDefs; i++) {
290 if (ssaRep->fpDef[i])
291 changed |= setFp(cUnit, ssaRep->defs[i], true);
292 }
293 // Special-case handling for moves & Phi
294 if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
buzbee2a83e8f2012-07-13 16:42:30 -0700295 /*
296 * If any of our inputs or outputs is defined, set all.
297 * Some ugliness related to Phi nodes and wide values.
298 * The Phi set will include all low words or all high
299 * words, so we have to treat them specially.
300 */
301 bool isPhi = (static_cast<int>(mir->dalvikInsn.opcode) ==
302 kMirOpPhi);
303 RegLocation rlTemp = cUnit->regLocation[ssaRep->defs[0]];
304 bool definedFP = rlTemp.defined && rlTemp.fp;
305 bool definedCore = rlTemp.defined && rlTemp.core;
306 bool definedRef = rlTemp.defined && rlTemp.ref;
307 bool isWide = rlTemp.wide || ((attrs & DF_A_WIDE) != 0);
308 bool isHigh = isPhi && rlTemp.wide && rlTemp.highWord;
309 for (int i = 0; i < ssaRep->numUses;i++) {
310 rlTemp = cUnit->regLocation[ssaRep->uses[i]];
311 definedFP |= rlTemp.defined && rlTemp.fp;
312 definedCore |= rlTemp.defined && rlTemp.core;
313 definedRef |= rlTemp.defined && rlTemp.ref;
314 isWide |= rlTemp.wide;
315 isHigh |= isPhi && rlTemp.wide && rlTemp.highWord;
Bill Buzbeea114add2012-05-03 15:00:40 -0700316 }
317 /*
318 * TODO: cleaner fix
319 * We don't normally expect to see a Dalvik register
320 * definition used both as a floating point and core
321 * value. However, the instruction rewriting that occurs
322 * during verification can eliminate some type information,
323 * leaving us confused. The real fix here is either to
324 * add explicit type information to Dalvik byte codes,
325 * or to recognize THROW_VERIFICATION_ERROR as
326 * an unconditional branch and support dead code elimination.
327 * As a workaround we can detect this situation and
328 * disable register promotion (which is the only thing that
329 * relies on distinctions between core and fp usages.
330 */
buzbeebff24652012-05-06 16:22:05 -0700331 if ((definedFP && (definedCore | definedRef)) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700332 ((cUnit->disableOpt & (1 << kPromoteRegs)) == 0)) {
333 LOG(WARNING) << PrettyMethod(cUnit->method_idx, *cUnit->dex_file)
334 << " op at block " << bb->id
buzbeebff24652012-05-06 16:22:05 -0700335 << " has both fp and core/ref uses for same def.";
Bill Buzbeea114add2012-05-03 15:00:40 -0700336 cUnit->disableOpt |= (1 << kPromoteRegs);
337 }
338 changed |= setFp(cUnit, ssaRep->defs[0], definedFP);
339 changed |= setCore(cUnit, ssaRep->defs[0], definedCore);
buzbeebff24652012-05-06 16:22:05 -0700340 changed |= setRef(cUnit, ssaRep->defs[0], definedRef);
buzbee2a83e8f2012-07-13 16:42:30 -0700341 changed |= setWide(cUnit, ssaRep->defs[0], isWide);
342 changed |= setHigh(cUnit, ssaRep->defs[0], isHigh);
343 if (attrs & DF_A_WIDE) {
344 changed |= setWide(cUnit, ssaRep->defs[1], true);
345 changed |= setHigh(cUnit, ssaRep->defs[1], true);
346 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700347 for (int i = 0; i < ssaRep->numUses; i++) {
buzbee2a83e8f2012-07-13 16:42:30 -0700348 changed |= setFp(cUnit, ssaRep->uses[i], definedFP);
349 changed |= setCore(cUnit, ssaRep->uses[i], definedCore);
350 changed |= setRef(cUnit, ssaRep->uses[i], definedRef);
351 changed |= setWide(cUnit, ssaRep->uses[i], isWide);
352 changed |= setHigh(cUnit, ssaRep->uses[i], isHigh);
353 }
354 if (attrs & DF_A_WIDE) {
355 DCHECK_EQ(ssaRep->numUses, 2);
356 changed |= setWide(cUnit, ssaRep->uses[1], true);
357 changed |= setHigh(cUnit, ssaRep->uses[1], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700358 }
359 }
buzbee67bf8852011-08-17 17:51:35 -0700360 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700361 }
362 return changed;
buzbee67bf8852011-08-17 17:51:35 -0700363}
364
365static const char* storageName[] = {" Frame ", "PhysReg", " Spill "};
366
buzbeedfd3d702011-08-28 12:56:51 -0700367void oatDumpRegLocTable(RegLocation* table, int count)
buzbee67bf8852011-08-17 17:51:35 -0700368{
Bill Buzbeea114add2012-05-03 15:00:40 -0700369 for (int i = 0; i < count; i++) {
370 LOG(INFO) << StringPrintf("Loc[%02d] : %s, %c %c %c %c %c %c%d %c%d S%d",
buzbeeca7a5e42012-08-20 11:12:18 -0700371 table[i].origSReg, storageName[table[i].location],
372 table[i].wide ? 'W' : 'N', table[i].defined ? 'D' : 'U',
buzbeed5018892012-07-11 14:23:40 -0700373 table[i].fp ? 'F' : table[i].ref ? 'R' :'C',
Bill Buzbeea114add2012-05-03 15:00:40 -0700374 table[i].highWord ? 'H' : 'L', table[i].home ? 'h' : 't',
375 oatIsFpReg(table[i].lowReg) ? 's' : 'r',
376 table[i].lowReg & oatFpRegMask(),
377 oatIsFpReg(table[i].highReg) ? 's' : 'r',
378 table[i].highReg & oatFpRegMask(), table[i].sRegLow);
379 }
buzbee67bf8852011-08-17 17:51:35 -0700380}
381
buzbee6969d502012-06-15 16:40:31 -0700382void oatDumpRegLoc(RegLocation loc) {
383 oatDumpRegLocTable(&loc, 1);
384}
385
buzbee2cfc6392012-05-07 14:51:40 -0700386static const RegLocation freshLoc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
387 INVALID_REG, INVALID_REG, INVALID_SREG,
388 INVALID_SREG};
buzbee67bf8852011-08-17 17:51:35 -0700389
buzbeead8f15e2012-06-18 14:49:45 -0700390int oatComputeFrameSize(CompilationUnit* cUnit) {
391 /* Figure out the frame size */
392 static const uint32_t kAlignMask = kStackAlignment - 1;
393 uint32_t size = (cUnit->numCoreSpills + cUnit->numFPSpills +
394 1 /* filler word */ + cUnit->numRegs + cUnit->numOuts +
395 cUnit->numCompilerTemps + 1 /* curMethod* */)
396 * sizeof(uint32_t);
397 /* Align and set */
398 return (size + kAlignMask) & ~(kAlignMask);
399}
400
buzbee67bf8852011-08-17 17:51:35 -0700401/*
402 * Simple register allocation. Some Dalvik virtual registers may
403 * be promoted to physical registers. Most of the work for temp
Ian Rogersb5d09b22012-03-06 22:14:17 -0800404 * allocation is done on the fly. We also do some initialization and
buzbee67bf8852011-08-17 17:51:35 -0700405 * type inference here.
406 */
407void oatSimpleRegAlloc(CompilationUnit* cUnit)
408{
Bill Buzbeea114add2012-05-03 15:00:40 -0700409 int i;
410 RegLocation* loc;
buzbee67bf8852011-08-17 17:51:35 -0700411
Bill Buzbeea114add2012-05-03 15:00:40 -0700412 /* Allocate the location map */
413 loc = (RegLocation*)oatNew(cUnit, cUnit->numSSARegs * sizeof(*loc), true,
414 kAllocRegAlloc);
415 for (i=0; i< cUnit->numSSARegs; i++) {
416 loc[i] = freshLoc;
417 loc[i].sRegLow = i;
buzbee2cfc6392012-05-07 14:51:40 -0700418 loc[i].isConst = oatIsBitSet(cUnit->isConstantV, i);
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 }
420
421 /* Patch up the locations for Method* and the compiler temps */
422 loc[cUnit->methodSReg].location = kLocCompilerTemp;
423 loc[cUnit->methodSReg].defined = true;
424 for (i = 0; i < cUnit->numCompilerTemps; i++) {
425 CompilerTemp* ct = (CompilerTemp*)cUnit->compilerTemps.elemList[i];
426 loc[ct->sReg].location = kLocCompilerTemp;
427 loc[ct->sReg].defined = true;
428 }
429
430 cUnit->regLocation = loc;
431
432 /* Allocation the promotion map */
433 int numRegs = cUnit->numDalvikRegisters;
434 cUnit->promotionMap =
435 (PromotionMap*)oatNew(cUnit, (numRegs + cUnit->numCompilerTemps + 1) *
436 sizeof(cUnit->promotionMap[0]), true,
437 kAllocRegAlloc);
438
439 /* Add types of incoming arguments based on signature */
440 int numIns = cUnit->numIns;
441 if (numIns > 0) {
442 int sReg = numRegs - numIns;
443 if ((cUnit->access_flags & kAccStatic) == 0) {
444 // For non-static, skip past "this"
445 cUnit->regLocation[sReg].defined = true;
buzbeebff24652012-05-06 16:22:05 -0700446 cUnit->regLocation[sReg].ref = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700447 sReg++;
buzbee67bf8852011-08-17 17:51:35 -0700448 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700449 const char* shorty = cUnit->shorty;
450 int shorty_len = strlen(shorty);
451 for (int i = 1; i < shorty_len; i++) {
452 switch (shorty[i]) {
453 case 'D':
454 cUnit->regLocation[sReg].wide = true;
455 cUnit->regLocation[sReg+1].highWord = true;
456 cUnit->regLocation[sReg+1].fp = true;
457 DCHECK_EQ(SRegToVReg(cUnit, sReg)+1, SRegToVReg(cUnit, sReg+1));
458 cUnit->regLocation[sReg].fp = true;
459 cUnit->regLocation[sReg].defined = true;
460 sReg++;
461 break;
462 case 'J':
463 cUnit->regLocation[sReg].wide = true;
464 cUnit->regLocation[sReg+1].highWord = true;
465 DCHECK_EQ(SRegToVReg(cUnit, sReg)+1, SRegToVReg(cUnit, sReg+1));
466 cUnit->regLocation[sReg].core = true;
467 cUnit->regLocation[sReg].defined = true;
468 sReg++;
buzbeed5018892012-07-11 14:23:40 -0700469 break;
470 case 'F':
471 cUnit->regLocation[sReg].fp = true;
472 cUnit->regLocation[sReg].defined = true;
473 break;
474 case 'L':
475 cUnit->regLocation[sReg].ref = true;
476 cUnit->regLocation[sReg].defined = true;
477 break;
478 default:
479 cUnit->regLocation[sReg].core = true;
480 cUnit->regLocation[sReg].defined = true;
481 break;
buzbeee9a72f62011-09-04 17:59:07 -0700482 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 sReg++;
484 }
485 }
486
buzbee2cfc6392012-05-07 14:51:40 -0700487 if (!cUnit->genBitcode) {
488 /* Remap names */
489 oatDataFlowAnalysisDispatcher(cUnit, remapNames,
490 kPreOrderDFSTraversal,
491 false /* isIterative */);
492 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700493
494 /* Do type & size inference pass */
495 oatDataFlowAnalysisDispatcher(cUnit, inferTypeAndSize,
496 kPreOrderDFSTraversal,
497 true /* isIterative */);
498
499 /*
500 * Set the sRegLow field to refer to the pre-SSA name of the
501 * base Dalvik virtual register. Once we add a better register
502 * allocator, remove this remapping.
503 */
504 for (i=0; i < cUnit->numSSARegs; i++) {
505 if (cUnit->regLocation[i].location != kLocCompilerTemp) {
buzbee2cfc6392012-05-07 14:51:40 -0700506 int origSReg = cUnit->regLocation[i].sRegLow;
507 cUnit->regLocation[i].origSReg = origSReg;
508 cUnit->regLocation[i].sRegLow = SRegToVReg(cUnit, origSReg);
buzbeee9a72f62011-09-04 17:59:07 -0700509 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 }
buzbeee9a72f62011-09-04 17:59:07 -0700511
Bill Buzbeea114add2012-05-03 15:00:40 -0700512 cUnit->coreSpillMask = 0;
513 cUnit->fpSpillMask = 0;
514 cUnit->numCoreSpills = 0;
buzbeec0ecd652011-09-25 18:11:54 -0700515
Bill Buzbeea114add2012-05-03 15:00:40 -0700516 oatDoPromotion(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700517
buzbeead8f15e2012-06-18 14:49:45 -0700518 /* Get easily-accessable post-promotion copy of RegLocation for Method* */
519 cUnit->methodLoc = cUnit->regLocation[cUnit->methodSReg];
520
Bill Buzbeea114add2012-05-03 15:00:40 -0700521 if (cUnit->printMe && !(cUnit->disableOpt & (1 << kPromoteRegs))) {
522 LOG(INFO) << "After Promotion";
523 oatDumpRegLocTable(cUnit->regLocation, cUnit->numSSARegs);
524 }
buzbee67bf8852011-08-17 17:51:35 -0700525
buzbeead8f15e2012-06-18 14:49:45 -0700526 /* Set the frame size */
527 cUnit->frameSize = oatComputeFrameSize(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700528}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800529
530} // namespace art