blob: 2038e192bf0990e2b94f322bc3f33e172d69462a [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
buzbeefa57c472012-11-21 12:06:18 -080023static bool SetFp(CompilationUnit* cu, int index, bool is_fp) {
Bill Buzbeea114add2012-05-03 15:00:40 -070024 bool change = false;
buzbeefa57c472012-11-21 12:06:18 -080025 if (is_fp && !cu->reg_location[index].fp) {
26 cu->reg_location[index].fp = true;
27 cu->reg_location[index].defined = true;
Bill Buzbeea114add2012-05-03 15:00:40 -070028 change = true;
29 }
30 return change;
buzbee67bc2362011-10-11 18:08:40 -070031}
32
buzbeefa57c472012-11-21 12:06:18 -080033static bool SetCore(CompilationUnit* cu, int index, bool is_core) {
Bill Buzbeea114add2012-05-03 15:00:40 -070034 bool change = false;
buzbeefa57c472012-11-21 12:06:18 -080035 if (is_core && !cu->reg_location[index].defined) {
36 cu->reg_location[index].core = true;
37 cu->reg_location[index].defined = true;
Bill Buzbeea114add2012-05-03 15:00:40 -070038 change = true;
39 }
40 return change;
buzbee03fa2632011-09-20 17:10:57 -070041}
42
buzbeefa57c472012-11-21 12:06:18 -080043static bool SetRef(CompilationUnit* cu, int index, bool is_ref) {
buzbeebff24652012-05-06 16:22:05 -070044 bool change = false;
buzbeefa57c472012-11-21 12:06:18 -080045 if (is_ref && !cu->reg_location[index].defined) {
46 cu->reg_location[index].ref = true;
47 cu->reg_location[index].defined = true;
buzbeebff24652012-05-06 16:22:05 -070048 change = true;
49 }
50 return change;
51}
52
buzbeefa57c472012-11-21 12:06:18 -080053static bool SetWide(CompilationUnit* cu, int index, bool is_wide) {
buzbee2a83e8f2012-07-13 16:42:30 -070054 bool change = false;
buzbeefa57c472012-11-21 12:06:18 -080055 if (is_wide && !cu->reg_location[index].wide) {
56 cu->reg_location[index].wide = true;
buzbee2a83e8f2012-07-13 16:42:30 -070057 change = true;
58 }
59 return change;
60}
61
buzbeefa57c472012-11-21 12:06:18 -080062static bool SetHigh(CompilationUnit* cu, int index, bool is_high) {
buzbee2a83e8f2012-07-13 16:42:30 -070063 bool change = false;
buzbeefa57c472012-11-21 12:06:18 -080064 if (is_high && !cu->reg_location[index].high_word) {
65 cu->reg_location[index].high_word = true;
buzbee2a83e8f2012-07-13 16:42:30 -070066 change = true;
67 }
68 return change;
69}
70
buzbee67bf8852011-08-17 17:51:35 -070071/*
buzbee03fa2632011-09-20 17:10:57 -070072 * Infer types and sizes. We don't need to track change on sizes,
73 * as it doesn't propagate. We're guaranteed at least one pass through
74 * the cfg.
buzbee67bf8852011-08-17 17:51:35 -070075 */
buzbeefa57c472012-11-21 12:06:18 -080076static bool InferTypeAndSize(CompilationUnit* cu, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070077{
Bill Buzbeea114add2012-05-03 15:00:40 -070078 MIR *mir;
79 bool changed = false; // Did anything change?
buzbee03fa2632011-09-20 17:10:57 -070080
buzbeefa57c472012-11-21 12:06:18 -080081 if (bb->data_flow_info == NULL) return false;
82 if (bb->block_type != kDalvikByteCode && bb->block_type != kEntryBlock)
Bill Buzbeea114add2012-05-03 15:00:40 -070083 return false;
buzbee67bf8852011-08-17 17:51:35 -070084
buzbee28c9a832012-11-21 15:39:13 -080085 for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
buzbeefa57c472012-11-21 12:06:18 -080086 SSARepresentation *ssa_rep = mir->ssa_rep;
87 if (ssa_rep) {
88 int attrs = oat_data_flow_attributes[mir->dalvikInsn.opcode];
buzbee67bc2362011-10-11 18:08:40 -070089
Bill Buzbeea114add2012-05-03 15:00:40 -070090 // Handle defs
buzbeebff24652012-05-06 16:22:05 -070091 if (attrs & DF_DA) {
Bill Buzbeea114add2012-05-03 15:00:40 -070092 if (attrs & DF_CORE_A) {
buzbeefa57c472012-11-21 12:06:18 -080093 changed |= SetCore(cu, ssa_rep->defs[0], true);
buzbee67bf8852011-08-17 17:51:35 -070094 }
buzbeebff24652012-05-06 16:22:05 -070095 if (attrs & DF_REF_A) {
buzbeefa57c472012-11-21 12:06:18 -080096 changed |= SetRef(cu, ssa_rep->defs[0], true);
buzbeebff24652012-05-06 16:22:05 -070097 }
98 if (attrs & DF_A_WIDE) {
buzbeefa57c472012-11-21 12:06:18 -080099 cu->reg_location[ssa_rep->defs[0]].wide = true;
100 cu->reg_location[ssa_rep->defs[1]].wide = true;
101 cu->reg_location[ssa_rep->defs[1]].high_word = true;
102 DCHECK_EQ(SRegToVReg(cu, ssa_rep->defs[0])+1,
103 SRegToVReg(cu, ssa_rep->defs[1]));
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 }
105 }
106
107 // Handles uses
108 int next = 0;
buzbeebff24652012-05-06 16:22:05 -0700109 if (attrs & DF_UA) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700110 if (attrs & DF_CORE_A) {
buzbeefa57c472012-11-21 12:06:18 -0800111 changed |= SetCore(cu, ssa_rep->uses[next], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700112 }
buzbeebff24652012-05-06 16:22:05 -0700113 if (attrs & DF_REF_A) {
buzbeefa57c472012-11-21 12:06:18 -0800114 changed |= SetRef(cu, ssa_rep->uses[next], true);
buzbeebff24652012-05-06 16:22:05 -0700115 }
116 if (attrs & DF_A_WIDE) {
buzbeefa57c472012-11-21 12:06:18 -0800117 cu->reg_location[ssa_rep->uses[next]].wide = true;
118 cu->reg_location[ssa_rep->uses[next + 1]].wide = true;
119 cu->reg_location[ssa_rep->uses[next + 1]].high_word = true;
120 DCHECK_EQ(SRegToVReg(cu, ssa_rep->uses[next])+1,
121 SRegToVReg(cu, ssa_rep->uses[next + 1]));
Bill Buzbeea114add2012-05-03 15:00:40 -0700122 next += 2;
123 } else {
124 next++;
125 }
126 }
buzbeebff24652012-05-06 16:22:05 -0700127 if (attrs & DF_UB) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700128 if (attrs & DF_CORE_B) {
buzbeefa57c472012-11-21 12:06:18 -0800129 changed |= SetCore(cu, ssa_rep->uses[next], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700130 }
buzbeebff24652012-05-06 16:22:05 -0700131 if (attrs & DF_REF_B) {
buzbeefa57c472012-11-21 12:06:18 -0800132 changed |= SetRef(cu, ssa_rep->uses[next], true);
buzbeebff24652012-05-06 16:22:05 -0700133 }
134 if (attrs & DF_B_WIDE) {
buzbeefa57c472012-11-21 12:06:18 -0800135 cu->reg_location[ssa_rep->uses[next]].wide = true;
136 cu->reg_location[ssa_rep->uses[next + 1]].wide = true;
137 cu->reg_location[ssa_rep->uses[next + 1]].high_word = true;
138 DCHECK_EQ(SRegToVReg(cu, ssa_rep->uses[next])+1,
139 SRegToVReg(cu, ssa_rep->uses[next + 1]));
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 next += 2;
141 } else {
142 next++;
143 }
144 }
buzbeebff24652012-05-06 16:22:05 -0700145 if (attrs & DF_UC) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 if (attrs & DF_CORE_C) {
buzbeefa57c472012-11-21 12:06:18 -0800147 changed |= SetCore(cu, ssa_rep->uses[next], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 }
buzbeebff24652012-05-06 16:22:05 -0700149 if (attrs & DF_REF_C) {
buzbeefa57c472012-11-21 12:06:18 -0800150 changed |= SetRef(cu, ssa_rep->uses[next], true);
buzbeebff24652012-05-06 16:22:05 -0700151 }
152 if (attrs & DF_C_WIDE) {
buzbeefa57c472012-11-21 12:06:18 -0800153 cu->reg_location[ssa_rep->uses[next]].wide = true;
154 cu->reg_location[ssa_rep->uses[next + 1]].wide = true;
155 cu->reg_location[ssa_rep->uses[next + 1]].high_word = true;
156 DCHECK_EQ(SRegToVReg(cu, ssa_rep->uses[next])+1,
157 SRegToVReg(cu, ssa_rep->uses[next + 1]));
Bill Buzbeea114add2012-05-03 15:00:40 -0700158 }
159 }
160
buzbeed5018892012-07-11 14:23:40 -0700161 // Special-case return handling
162 if ((mir->dalvikInsn.opcode == Instruction::RETURN) ||
163 (mir->dalvikInsn.opcode == Instruction::RETURN_WIDE) ||
164 (mir->dalvikInsn.opcode == Instruction::RETURN_OBJECT)) {
buzbeefa57c472012-11-21 12:06:18 -0800165 switch(cu->shorty[0]) {
buzbeed5018892012-07-11 14:23:40 -0700166 case 'I':
buzbeefa57c472012-11-21 12:06:18 -0800167 changed |= SetCore(cu, ssa_rep->uses[0], true);
buzbeed5018892012-07-11 14:23:40 -0700168 break;
169 case 'J':
buzbeefa57c472012-11-21 12:06:18 -0800170 changed |= SetCore(cu, ssa_rep->uses[0], true);
171 changed |= SetCore(cu, ssa_rep->uses[1], true);
172 cu->reg_location[ssa_rep->uses[0]].wide = true;
173 cu->reg_location[ssa_rep->uses[1]].wide = true;
174 cu->reg_location[ssa_rep->uses[1]].high_word = true;
buzbeed5018892012-07-11 14:23:40 -0700175 break;
176 case 'F':
buzbeefa57c472012-11-21 12:06:18 -0800177 changed |= SetFp(cu, ssa_rep->uses[0], true);
buzbeed5018892012-07-11 14:23:40 -0700178 break;
179 case 'D':
buzbeefa57c472012-11-21 12:06:18 -0800180 changed |= SetFp(cu, ssa_rep->uses[0], true);
181 changed |= SetFp(cu, ssa_rep->uses[1], true);
182 cu->reg_location[ssa_rep->uses[0]].wide = true;
183 cu->reg_location[ssa_rep->uses[1]].wide = true;
184 cu->reg_location[ssa_rep->uses[1]].high_word = true;
buzbeed5018892012-07-11 14:23:40 -0700185 break;
186 case 'L':
buzbeefa57c472012-11-21 12:06:18 -0800187 changed |= SetRef(cu, ssa_rep->uses[0], true);
buzbeed5018892012-07-11 14:23:40 -0700188 break;
189 default: break;
190 }
191 }
192
Bill Buzbeea114add2012-05-03 15:00:40 -0700193 // Special-case handling for format 35c/3rc invokes
194 Instruction::Code opcode = mir->dalvikInsn.opcode;
195 int flags = (static_cast<int>(opcode) >= kNumPackedOpcodes)
Ian Rogersa75a0132012-09-28 11:41:42 -0700196 ? 0 : Instruction::FlagsOf(mir->dalvikInsn.opcode);
Bill Buzbeea114add2012-05-03 15:00:40 -0700197 if ((flags & Instruction::kInvoke) &&
198 (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) {
199 DCHECK_EQ(next, 0);
200 int target_idx = mir->dalvikInsn.vB;
buzbeefa57c472012-11-21 12:06:18 -0800201 const char* shorty = GetShortyFromTargetIdx(cu, target_idx);
Bill Buzbeea114add2012-05-03 15:00:40 -0700202 // Handle result type if floating point
203 if ((shorty[0] == 'F') || (shorty[0] == 'D')) {
buzbeefa57c472012-11-21 12:06:18 -0800204 MIR* move_result_mir = FindMoveResult(cu, bb, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 // Result might not be used at all, so no move-result
buzbeefa57c472012-11-21 12:06:18 -0800206 if (move_result_mir && (move_result_mir->dalvikInsn.opcode !=
Bill Buzbeec9f40dd2012-08-15 11:35:25 -0700207 Instruction::MOVE_RESULT_OBJECT)) {
buzbeefa57c472012-11-21 12:06:18 -0800208 SSARepresentation* tgt_rep = move_result_mir->ssa_rep;
209 DCHECK(tgt_rep != NULL);
210 tgt_rep->fp_def[0] = true;
211 changed |= SetFp(cu, tgt_rep->defs[0], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700212 if (shorty[0] == 'D') {
buzbeefa57c472012-11-21 12:06:18 -0800213 tgt_rep->fp_def[1] = true;
214 changed |= SetFp(cu, tgt_rep->defs[1], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700215 }
216 }
217 }
buzbeefa57c472012-11-21 12:06:18 -0800218 int num_uses = mir->dalvikInsn.vA;
buzbeebff24652012-05-06 16:22:05 -0700219 // If this is a non-static invoke, mark implicit "this"
Bill Buzbeea114add2012-05-03 15:00:40 -0700220 if (((mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC) &&
221 (mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC_RANGE))) {
buzbeefa57c472012-11-21 12:06:18 -0800222 cu->reg_location[ssa_rep->uses[next]].defined = true;
223 cu->reg_location[ssa_rep->uses[next]].ref = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700224 next++;
225 }
226 uint32_t cpos = 1;
227 if (strlen(shorty) > 1) {
buzbeefa57c472012-11-21 12:06:18 -0800228 for (int i = next; i < num_uses;) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700229 DCHECK_LT(cpos, strlen(shorty));
230 switch (shorty[cpos++]) {
231 case 'D':
buzbeefa57c472012-11-21 12:06:18 -0800232 ssa_rep->fp_use[i] = true;
233 ssa_rep->fp_use[i+1] = true;
234 cu->reg_location[ssa_rep->uses[i]].wide = true;
235 cu->reg_location[ssa_rep->uses[i+1]].wide = true;
236 cu->reg_location[ssa_rep->uses[i+1]].high_word = true;
237 DCHECK_EQ(SRegToVReg(cu, ssa_rep->uses[i])+1,
238 SRegToVReg(cu, ssa_rep->uses[i+1]));
Bill Buzbeea114add2012-05-03 15:00:40 -0700239 i++;
240 break;
241 case 'J':
buzbeefa57c472012-11-21 12:06:18 -0800242 cu->reg_location[ssa_rep->uses[i]].wide = true;
243 cu->reg_location[ssa_rep->uses[i+1]].wide = true;
244 cu->reg_location[ssa_rep->uses[i+1]].high_word = true;
245 DCHECK_EQ(SRegToVReg(cu, ssa_rep->uses[i])+1,
246 SRegToVReg(cu, ssa_rep->uses[i+1]));
247 changed |= SetCore(cu, ssa_rep->uses[i],true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700248 i++;
249 break;
250 case 'F':
buzbeefa57c472012-11-21 12:06:18 -0800251 ssa_rep->fp_use[i] = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700252 break;
buzbeebff24652012-05-06 16:22:05 -0700253 case 'L':
buzbeefa57c472012-11-21 12:06:18 -0800254 changed |= SetRef(cu,ssa_rep->uses[i], true);
buzbeebff24652012-05-06 16:22:05 -0700255 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700256 default:
buzbeefa57c472012-11-21 12:06:18 -0800257 changed |= SetCore(cu,ssa_rep->uses[i], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700258 break;
259 }
260 i++;
261 }
262 }
263 }
264
buzbeefa57c472012-11-21 12:06:18 -0800265 for (int i=0; ssa_rep->fp_use && i< ssa_rep->num_uses; i++) {
266 if (ssa_rep->fp_use[i])
267 changed |= SetFp(cu, ssa_rep->uses[i], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 }
buzbeefa57c472012-11-21 12:06:18 -0800269 for (int i=0; ssa_rep->fp_def && i< ssa_rep->num_defs; i++) {
270 if (ssa_rep->fp_def[i])
271 changed |= SetFp(cu, ssa_rep->defs[i], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700272 }
273 // Special-case handling for moves & Phi
274 if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
buzbee2a83e8f2012-07-13 16:42:30 -0700275 /*
276 * If any of our inputs or outputs is defined, set all.
277 * Some ugliness related to Phi nodes and wide values.
278 * The Phi set will include all low words or all high
279 * words, so we have to treat them specially.
280 */
buzbeefa57c472012-11-21 12:06:18 -0800281 bool is_phi = (static_cast<int>(mir->dalvikInsn.opcode) ==
buzbee2a83e8f2012-07-13 16:42:30 -0700282 kMirOpPhi);
buzbeefa57c472012-11-21 12:06:18 -0800283 RegLocation rl_temp = cu->reg_location[ssa_rep->defs[0]];
284 bool defined_fp = rl_temp.defined && rl_temp.fp;
285 bool defined_core = rl_temp.defined && rl_temp.core;
286 bool defined_ref = rl_temp.defined && rl_temp.ref;
287 bool is_wide = rl_temp.wide || ((attrs & DF_A_WIDE) != 0);
288 bool is_high = is_phi && rl_temp.wide && rl_temp.high_word;
289 for (int i = 0; i < ssa_rep->num_uses;i++) {
290 rl_temp = cu->reg_location[ssa_rep->uses[i]];
291 defined_fp |= rl_temp.defined && rl_temp.fp;
292 defined_core |= rl_temp.defined && rl_temp.core;
293 defined_ref |= rl_temp.defined && rl_temp.ref;
294 is_wide |= rl_temp.wide;
295 is_high |= is_phi && rl_temp.wide && rl_temp.high_word;
Bill Buzbeea114add2012-05-03 15:00:40 -0700296 }
297 /*
298 * TODO: cleaner fix
299 * We don't normally expect to see a Dalvik register
300 * definition used both as a floating point and core
301 * value. However, the instruction rewriting that occurs
302 * during verification can eliminate some type information,
303 * leaving us confused. The real fix here is either to
304 * add explicit type information to Dalvik byte codes,
305 * or to recognize THROW_VERIFICATION_ERROR as
306 * an unconditional branch and support dead code elimination.
307 * As a workaround we can detect this situation and
308 * disable register promotion (which is the only thing that
309 * relies on distinctions between core and fp usages.
310 */
buzbeefa57c472012-11-21 12:06:18 -0800311 if ((defined_fp && (defined_core | defined_ref)) &&
312 ((cu->disable_opt & (1 << kPromoteRegs)) == 0)) {
313 LOG(WARNING) << PrettyMethod(cu->method_idx, *cu->dex_file)
Bill Buzbeea114add2012-05-03 15:00:40 -0700314 << " op at block " << bb->id
buzbeebff24652012-05-06 16:22:05 -0700315 << " has both fp and core/ref uses for same def.";
buzbeefa57c472012-11-21 12:06:18 -0800316 cu->disable_opt |= (1 << kPromoteRegs);
Bill Buzbeea114add2012-05-03 15:00:40 -0700317 }
buzbeefa57c472012-11-21 12:06:18 -0800318 changed |= SetFp(cu, ssa_rep->defs[0], defined_fp);
319 changed |= SetCore(cu, ssa_rep->defs[0], defined_core);
320 changed |= SetRef(cu, ssa_rep->defs[0], defined_ref);
321 changed |= SetWide(cu, ssa_rep->defs[0], is_wide);
322 changed |= SetHigh(cu, ssa_rep->defs[0], is_high);
buzbee2a83e8f2012-07-13 16:42:30 -0700323 if (attrs & DF_A_WIDE) {
buzbeefa57c472012-11-21 12:06:18 -0800324 changed |= SetWide(cu, ssa_rep->defs[1], true);
325 changed |= SetHigh(cu, ssa_rep->defs[1], true);
buzbee2a83e8f2012-07-13 16:42:30 -0700326 }
buzbeefa57c472012-11-21 12:06:18 -0800327 for (int i = 0; i < ssa_rep->num_uses; i++) {
328 changed |= SetFp(cu, ssa_rep->uses[i], defined_fp);
329 changed |= SetCore(cu, ssa_rep->uses[i], defined_core);
330 changed |= SetRef(cu, ssa_rep->uses[i], defined_ref);
331 changed |= SetWide(cu, ssa_rep->uses[i], is_wide);
332 changed |= SetHigh(cu, ssa_rep->uses[i], is_high);
buzbee2a83e8f2012-07-13 16:42:30 -0700333 }
334 if (attrs & DF_A_WIDE) {
buzbeefa57c472012-11-21 12:06:18 -0800335 DCHECK_EQ(ssa_rep->num_uses, 2);
336 changed |= SetWide(cu, ssa_rep->uses[1], true);
337 changed |= SetHigh(cu, ssa_rep->uses[1], true);
Bill Buzbeea114add2012-05-03 15:00:40 -0700338 }
339 }
buzbee67bf8852011-08-17 17:51:35 -0700340 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700341 }
342 return changed;
buzbee67bf8852011-08-17 17:51:35 -0700343}
344
buzbeefa57c472012-11-21 12:06:18 -0800345static const char* storage_name[] = {" Frame ", "PhysReg", " Spill "};
buzbee67bf8852011-08-17 17:51:35 -0700346
buzbee02031b12012-11-23 09:41:35 -0800347static void DumpRegLocTable(CompilationUnit* cu, RegLocation* table, int count)
buzbee67bf8852011-08-17 17:51:35 -0700348{
buzbee02031b12012-11-23 09:41:35 -0800349 Codegen* cg = cu->cg.get();
Bill Buzbeea114add2012-05-03 15:00:40 -0700350 for (int i = 0; i < count; i++) {
buzbeea169e1d2012-12-05 14:26:44 -0800351 LOG(INFO) << StringPrintf("Loc[%02d] : %s, %c %c %c %c %c %c %c%d %c%d S%d",
buzbeefa57c472012-11-21 12:06:18 -0800352 table[i].orig_sreg, storage_name[table[i].location],
buzbeeca7a5e42012-08-20 11:12:18 -0700353 table[i].wide ? 'W' : 'N', table[i].defined ? 'D' : 'U',
buzbeed5018892012-07-11 14:23:40 -0700354 table[i].fp ? 'F' : table[i].ref ? 'R' :'C',
buzbeea169e1d2012-12-05 14:26:44 -0800355 table[i].is_const ? 'c' : 'n',
buzbeefa57c472012-11-21 12:06:18 -0800356 table[i].high_word ? 'H' : 'L', table[i].home ? 'h' : 't',
buzbee02031b12012-11-23 09:41:35 -0800357 cg->IsFpReg(table[i].low_reg) ? 's' : 'r',
358 table[i].low_reg & cg->FpRegMask(),
359 cg->IsFpReg(table[i].high_reg) ? 's' : 'r',
360 table[i].high_reg & cg->FpRegMask(), table[i].s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -0700361 }
buzbee67bf8852011-08-17 17:51:35 -0700362}
363
buzbeefa57c472012-11-21 12:06:18 -0800364static const RegLocation fresh_loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
buzbee2cfc6392012-05-07 14:51:40 -0700365 INVALID_REG, INVALID_REG, INVALID_SREG,
366 INVALID_SREG};
buzbee67bf8852011-08-17 17:51:35 -0700367
buzbeefa57c472012-11-21 12:06:18 -0800368int ComputeFrameSize(CompilationUnit* cu) {
buzbeead8f15e2012-06-18 14:49:45 -0700369 /* Figure out the frame size */
370 static const uint32_t kAlignMask = kStackAlignment - 1;
buzbeefa57c472012-11-21 12:06:18 -0800371 uint32_t size = (cu->num_core_spills + cu->num_fp_spills +
372 1 /* filler word */ + cu->num_regs + cu->num_outs +
373 cu->num_compiler_temps + 1 /* cur_method* */)
buzbeead8f15e2012-06-18 14:49:45 -0700374 * sizeof(uint32_t);
375 /* Align and set */
376 return (size + kAlignMask) & ~(kAlignMask);
377}
378
buzbee67bf8852011-08-17 17:51:35 -0700379/*
380 * Simple register allocation. Some Dalvik virtual registers may
381 * be promoted to physical registers. Most of the work for temp
Ian Rogersb5d09b22012-03-06 22:14:17 -0800382 * allocation is done on the fly. We also do some initialization and
buzbee67bf8852011-08-17 17:51:35 -0700383 * type inference here.
384 */
buzbeefa57c472012-11-21 12:06:18 -0800385void SimpleRegAlloc(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700386{
Bill Buzbeea114add2012-05-03 15:00:40 -0700387 int i;
388 RegLocation* loc;
buzbee67bf8852011-08-17 17:51:35 -0700389
Bill Buzbeea114add2012-05-03 15:00:40 -0700390 /* Allocate the location map */
buzbeefa57c472012-11-21 12:06:18 -0800391 loc = static_cast<RegLocation*>(NewMem(cu, cu->num_ssa_regs * sizeof(*loc),
buzbeecbd6d442012-11-17 14:11:25 -0800392 true, kAllocRegAlloc));
buzbeefa57c472012-11-21 12:06:18 -0800393 for (i=0; i< cu->num_ssa_regs; i++) {
394 loc[i] = fresh_loc;
395 loc[i].s_reg_low = i;
396 loc[i].is_const = IsBitSet(cu->is_constant_v, i);
Bill Buzbeea114add2012-05-03 15:00:40 -0700397 }
398
399 /* Patch up the locations for Method* and the compiler temps */
buzbeefa57c472012-11-21 12:06:18 -0800400 loc[cu->method_sreg].location = kLocCompilerTemp;
401 loc[cu->method_sreg].defined = true;
402 for (i = 0; i < cu->num_compiler_temps; i++) {
403 CompilerTemp* ct = reinterpret_cast<CompilerTemp*>(cu->compiler_temps.elem_list[i]);
404 loc[ct->s_reg].location = kLocCompilerTemp;
405 loc[ct->s_reg].defined = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700406 }
407
buzbeefa57c472012-11-21 12:06:18 -0800408 cu->reg_location = loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700409
410 /* Allocation the promotion map */
buzbeefa57c472012-11-21 12:06:18 -0800411 int num_regs = cu->num_dalvik_registers;
412 cu->promotion_map = static_cast<PromotionMap*>
413 (NewMem(cu, (num_regs + cu->num_compiler_temps + 1) * sizeof(cu->promotion_map[0]),
buzbeecbd6d442012-11-17 14:11:25 -0800414 true, kAllocRegAlloc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700415
416 /* Add types of incoming arguments based on signature */
buzbeefa57c472012-11-21 12:06:18 -0800417 int num_ins = cu->num_ins;
418 if (num_ins > 0) {
419 int s_reg = num_regs - num_ins;
420 if ((cu->access_flags & kAccStatic) == 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700421 // For non-static, skip past "this"
buzbeefa57c472012-11-21 12:06:18 -0800422 cu->reg_location[s_reg].defined = true;
423 cu->reg_location[s_reg].ref = true;
424 s_reg++;
buzbee67bf8852011-08-17 17:51:35 -0700425 }
buzbeefa57c472012-11-21 12:06:18 -0800426 const char* shorty = cu->shorty;
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 int shorty_len = strlen(shorty);
428 for (int i = 1; i < shorty_len; i++) {
429 switch (shorty[i]) {
430 case 'D':
buzbeefa57c472012-11-21 12:06:18 -0800431 cu->reg_location[s_reg].wide = true;
432 cu->reg_location[s_reg+1].high_word = true;
433 cu->reg_location[s_reg+1].fp = true;
434 DCHECK_EQ(SRegToVReg(cu, s_reg)+1, SRegToVReg(cu, s_reg+1));
435 cu->reg_location[s_reg].fp = true;
436 cu->reg_location[s_reg].defined = true;
437 s_reg++;
Bill Buzbeea114add2012-05-03 15:00:40 -0700438 break;
439 case 'J':
buzbeefa57c472012-11-21 12:06:18 -0800440 cu->reg_location[s_reg].wide = true;
441 cu->reg_location[s_reg+1].high_word = true;
442 DCHECK_EQ(SRegToVReg(cu, s_reg)+1, SRegToVReg(cu, s_reg+1));
443 cu->reg_location[s_reg].core = true;
444 cu->reg_location[s_reg].defined = true;
445 s_reg++;
buzbeed5018892012-07-11 14:23:40 -0700446 break;
447 case 'F':
buzbeefa57c472012-11-21 12:06:18 -0800448 cu->reg_location[s_reg].fp = true;
449 cu->reg_location[s_reg].defined = true;
buzbeed5018892012-07-11 14:23:40 -0700450 break;
451 case 'L':
buzbeefa57c472012-11-21 12:06:18 -0800452 cu->reg_location[s_reg].ref = true;
453 cu->reg_location[s_reg].defined = true;
buzbeed5018892012-07-11 14:23:40 -0700454 break;
455 default:
buzbeefa57c472012-11-21 12:06:18 -0800456 cu->reg_location[s_reg].core = true;
457 cu->reg_location[s_reg].defined = true;
buzbeed5018892012-07-11 14:23:40 -0700458 break;
buzbeee9a72f62011-09-04 17:59:07 -0700459 }
buzbeefa57c472012-11-21 12:06:18 -0800460 s_reg++;
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 }
462 }
463
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 /* Do type & size inference pass */
buzbeefa57c472012-11-21 12:06:18 -0800465 DataFlowAnalysisDispatcher(cu, InferTypeAndSize,
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 kPreOrderDFSTraversal,
buzbeefa57c472012-11-21 12:06:18 -0800467 true /* is_iterative */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700468
469 /*
buzbeefa57c472012-11-21 12:06:18 -0800470 * Set the s_reg_low field to refer to the pre-SSA name of the
Bill Buzbeea114add2012-05-03 15:00:40 -0700471 * base Dalvik virtual register. Once we add a better register
472 * allocator, remove this remapping.
473 */
buzbeefa57c472012-11-21 12:06:18 -0800474 for (i=0; i < cu->num_ssa_regs; i++) {
475 if (cu->reg_location[i].location != kLocCompilerTemp) {
476 int orig_sreg = cu->reg_location[i].s_reg_low;
477 cu->reg_location[i].orig_sreg = orig_sreg;
478 cu->reg_location[i].s_reg_low = SRegToVReg(cu, orig_sreg);
buzbeee9a72f62011-09-04 17:59:07 -0700479 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700480 }
buzbeee9a72f62011-09-04 17:59:07 -0700481
buzbeefa57c472012-11-21 12:06:18 -0800482 cu->core_spill_mask = 0;
483 cu->fp_spill_mask = 0;
484 cu->num_core_spills = 0;
buzbeec0ecd652011-09-25 18:11:54 -0700485
buzbeefa57c472012-11-21 12:06:18 -0800486 DoPromotion(cu);
buzbee67bf8852011-08-17 17:51:35 -0700487
buzbeead8f15e2012-06-18 14:49:45 -0700488 /* Get easily-accessable post-promotion copy of RegLocation for Method* */
buzbeefa57c472012-11-21 12:06:18 -0800489 cu->method_loc = cu->reg_location[cu->method_sreg];
buzbeead8f15e2012-06-18 14:49:45 -0700490
buzbeefa57c472012-11-21 12:06:18 -0800491 if (cu->verbose && !(cu->disable_opt & (1 << kPromoteRegs))) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700492 LOG(INFO) << "After Promotion";
buzbee02031b12012-11-23 09:41:35 -0800493 DumpRegLocTable(cu, cu->reg_location, cu->num_ssa_regs);
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 }
buzbee67bf8852011-08-17 17:51:35 -0700495
buzbeead8f15e2012-06-18 14:49:45 -0700496 /* Set the frame size */
buzbeefa57c472012-11-21 12:06:18 -0800497 cu->frame_size = ComputeFrameSize(cu);
buzbee67bf8852011-08-17 17:51:35 -0700498}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800499
500} // namespace art