blob: e7844b6e49cae180c7e997346d150afd72662c9b [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Dalvik.h"
18#include "CompilerInternals.h"
19#include "Dataflow.h"
20#include "codegen/Ralloc.h"
21
buzbeeed3e9302011-09-23 17:34:19 -070022STATIC bool setFp(CompilationUnit* cUnit, int index, bool isFP) {
buzbee03fa2632011-09-20 17:10:57 -070023 bool change = false;
24 if (isFP && !cUnit->regLocation[index].fp) {
25 cUnit->regLocation[index].fp = true;
26 change = true;
27 }
28 return change;
29}
30
buzbeec0ecd652011-09-25 18:11:54 -070031STATIC bool remapNames(CompilationUnit* cUnit, BasicBlock* bb)
32{
33 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
34 bb->blockType != kExitBlock)
35 return false;
36
37 for (MIR* mir = bb->firstMIRInsn; mir; mir = mir->next) {
38 SSARepresentation *ssaRep = mir->ssaRep;
39 if (ssaRep) {
40 for (int i = 0; i < ssaRep->numUses; i++) {
41 ssaRep->uses[i] = cUnit->phiAliasMap[ssaRep->uses[i]];
42 }
43 for (int i = 0; i < ssaRep->numDefs; i++) {
44 ssaRep->defs[i] = cUnit->phiAliasMap[ssaRep->defs[i]];
45 }
46 }
47 }
48 return false;
49}
50
buzbee67bf8852011-08-17 17:51:35 -070051/*
buzbee03fa2632011-09-20 17:10:57 -070052 * Infer types and sizes. We don't need to track change on sizes,
53 * as it doesn't propagate. We're guaranteed at least one pass through
54 * the cfg.
buzbee67bf8852011-08-17 17:51:35 -070055 */
buzbeeed3e9302011-09-23 17:34:19 -070056STATIC bool inferTypeAndSize(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070057{
58 MIR *mir;
buzbee03fa2632011-09-20 17:10:57 -070059 bool changed = false; // Did anything change?
60
61 if (bb->dataFlowInfo == NULL) return false;
buzbee67bf8852011-08-17 17:51:35 -070062 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock)
buzbee03fa2632011-09-20 17:10:57 -070063 return false;
buzbee67bf8852011-08-17 17:51:35 -070064
65 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
66 SSARepresentation *ssaRep = mir->ssaRep;
67 if (ssaRep) {
buzbee03fa2632011-09-20 17:10:57 -070068 int attrs = oatDataFlowAttributes[mir->dalvikInsn.opcode];
69 int next = 0;
70 if (attrs & DF_DA_WIDE) {
71 cUnit->regLocation[ssaRep->defs[0]].wide = true;
buzbee67bf8852011-08-17 17:51:35 -070072 }
buzbee03fa2632011-09-20 17:10:57 -070073 if (attrs & DF_UA_WIDE) {
74 cUnit->regLocation[ssaRep->uses[next]].wide = true;
75 next += 2;
76 }
77 if (attrs & DF_UB_WIDE) {
78 cUnit->regLocation[ssaRep->uses[next]].wide = true;
79 next += 2;
80 }
81 if (attrs & DF_UC_WIDE) {
82 cUnit->regLocation[ssaRep->uses[next]].wide = true;
buzbeeed3e9302011-09-23 17:34:19 -070083 next += 2;
buzbee03fa2632011-09-20 17:10:57 -070084 }
buzbeeed3e9302011-09-23 17:34:19 -070085
86 // Special-case handling for format 35c/3rc invokes
87 Opcode opcode = mir->dalvikInsn.opcode;
88 int flags = (opcode >= kNumPackedOpcodes) ? 0 :
89 dexGetFlagsFromOpcode(opcode);
90 if ((flags & kInstrInvoke) &&
91 (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) {
92 DCHECK_EQ(next, 0);
93 int target_idx = mir->dalvikInsn.vB;
94 const char* shorty =
95 oatGetShortyFromTargetIdx(cUnit, target_idx);
96 int numUses = mir->dalvikInsn.vA;
97 // If this is a non-static invoke, skip implicit "this"
98 if (((mir->dalvikInsn.opcode != OP_INVOKE_STATIC) &&
99 (mir->dalvikInsn.opcode != OP_INVOKE_STATIC_RANGE))) {
100 next++;
101 }
102 uint32_t cpos = 1;
103 if (strlen(shorty) > 1) {
104 for (int i = next; i < numUses;) {
105 DCHECK_LT(cpos, strlen(shorty));
106 switch(shorty[cpos++]) {
107 case 'D':
108 ssaRep->fpUse[i] = true;
109 ssaRep->fpUse[i+1] = true;
110 cUnit->regLocation[ssaRep->uses[i]].wide = true;
111 i++;
112 break;
113 case 'J':
114 cUnit->regLocation[ssaRep->uses[i]].wide = true;
115 i++;
116 break;
117 case 'F':
118 ssaRep->fpUse[i] = true;
119 break;
120 default:
121 break;
122 }
123 i++;
124 }
125 }
126 }
127
buzbee03fa2632011-09-20 17:10:57 -0700128 for (int i=0; ssaRep->fpUse && i< ssaRep->numUses; i++) {
129 if (ssaRep->fpUse[i])
130 changed |= setFp(cUnit, ssaRep->uses[i], true);
131 }
132 for (int i=0; ssaRep->fpDef && i< ssaRep->numDefs; i++) {
buzbee67bf8852011-08-17 17:51:35 -0700133 if (ssaRep->fpDef[i])
buzbee03fa2632011-09-20 17:10:57 -0700134 changed |= setFp(cUnit, ssaRep->defs[i], true);
135 }
136 // Special-case handling for moves & Phi
137 if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
138 bool isFP = cUnit->regLocation[ssaRep->defs[0]].fp;
139 for (int i = 0; i < ssaRep->numUses; i++) {
140 isFP |= cUnit->regLocation[ssaRep->uses[i]].fp;
141 }
142 changed |= setFp(cUnit, ssaRep->defs[0], isFP);
143 for (int i = 0; i < ssaRep->numUses; i++) {
144 changed |= setFp(cUnit, ssaRep->uses[i], isFP);
145 }
buzbee67bf8852011-08-17 17:51:35 -0700146 }
147 }
148 }
buzbee03fa2632011-09-20 17:10:57 -0700149 return changed;
buzbee67bf8852011-08-17 17:51:35 -0700150}
151
152static const char* storageName[] = {" Frame ", "PhysReg", " Spill "};
153
buzbeedfd3d702011-08-28 12:56:51 -0700154void oatDumpRegLocTable(RegLocation* table, int count)
buzbee67bf8852011-08-17 17:51:35 -0700155{
156 for (int i = 0; i < count; i++) {
157 char buf[100];
158 snprintf(buf, 100, "Loc[%02d] : %s, %c %c r%d r%d S%d : %s s%d s%d",
159 i, storageName[table[i].location], table[i].wide ? 'W' : 'N',
160 table[i].fp ? 'F' : 'C', table[i].lowReg, table[i].highReg,
161 table[i].sRegLow, storageName[table[i].fpLocation],
162 table[i].fpLowReg & FP_REG_MASK, table[i].fpHighReg &
163 FP_REG_MASK);
164 LOG(INFO) << buf;
165 }
166}
167
168static const RegLocation freshLoc = {kLocDalvikFrame, 0, 0, INVALID_REG,
169 INVALID_REG, INVALID_SREG, 0,
170 kLocDalvikFrame, INVALID_REG, INVALID_REG,
171 INVALID_OFFSET};
172
173/*
174 * Simple register allocation. Some Dalvik virtual registers may
175 * be promoted to physical registers. Most of the work for temp
176 * allocation is done on the fly. We also do some initilization and
177 * type inference here.
178 */
179void oatSimpleRegAlloc(CompilationUnit* cUnit)
180{
181 int i;
182 RegLocation* loc;
183
184 /* Allocate the location map */
185 loc = (RegLocation*)oatNew(cUnit->numSSARegs * sizeof(*loc), true);
186 for (i=0; i< cUnit->numSSARegs; i++) {
187 loc[i] = freshLoc;
188 loc[i].sRegLow = i;
189 }
190 cUnit->regLocation = loc;
191
buzbeee9a72f62011-09-04 17:59:07 -0700192 /* Add types of incoming arguments based on signature */
193 int numRegs = cUnit->method->NumRegisters();
194 int numIns = cUnit->method->NumIns();
195 if (numIns > 0) {
196 int sReg = numRegs - numIns;
197 if (!cUnit->method->IsStatic()) {
198 // Skip past "this"
199 sReg++;
200 }
Brian Carlstromc74255f2011-09-11 22:47:39 -0700201 const String* shorty = cUnit->method->GetShorty();
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700202 for (int i = 1; i < shorty->GetLength(); i++) {
203 char arg = shorty->CharAt(i);
buzbeee9a72f62011-09-04 17:59:07 -0700204 // Is it wide?
205 if ((arg == 'D') || (arg == 'J')) {
206 cUnit->regLocation[sReg].wide = true;
207 cUnit->regLocation[sReg+1].fp = cUnit->regLocation[sReg].fp;
208 sReg++; // Skip to next
209 }
210 sReg++;
211 }
212 }
213
buzbeec0ecd652011-09-25 18:11:54 -0700214 /* Remap names */
215 oatDataFlowAnalysisDispatcher(cUnit, remapNames,
216 kPreOrderDFSTraversal,
217 false /* isIterative */);
218
buzbee03fa2632011-09-20 17:10:57 -0700219 /* Do type & size inference pass */
220 oatDataFlowAnalysisDispatcher(cUnit, inferTypeAndSize,
221 kPreOrderDFSTraversal,
222 true /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700223
224 /*
225 * Set the sRegLow field to refer to the pre-SSA name of the
226 * base Dalvik virtual register. Once we add a better register
227 * allocator, remove this remapping.
228 */
229 for (i=0; i < cUnit->numSSARegs; i++) {
230 cUnit->regLocation[i].sRegLow =
231 DECODE_REG(oatConvertSSARegToDalvik(cUnit, loc[i].sRegLow));
232 }
233
234 cUnit->coreSpillMask = 0;
235 cUnit->fpSpillMask = 0;
236 cUnit->numSpills = 0;
237
238 oatDoPromotion(cUnit);
239
240 if (cUnit->printMe && !(cUnit->disableOpt & (1 << kPromoteRegs))) {
241 LOG(INFO) << "After Promotion";
buzbeedfd3d702011-08-28 12:56:51 -0700242 oatDumpRegLocTable(cUnit->regLocation, cUnit->numSSARegs);
buzbee67bf8852011-08-17 17:51:35 -0700243 }
244
245 /* Figure out the frame size */
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700246 cUnit->numIns = cUnit->method->NumIns();
247 cUnit->numRegs = cUnit->method->NumRegisters() - cUnit->numIns;
248 cUnit->numOuts = cUnit->method->NumOuts();
buzbee67bf8852011-08-17 17:51:35 -0700249 cUnit->numPadding = (STACK_ALIGN_WORDS -
250 (cUnit->numSpills + cUnit->numRegs +
251 cUnit->numOuts + 2)) & (STACK_ALIGN_WORDS-1);
252 cUnit->frameSize = (cUnit->numSpills + cUnit->numRegs + cUnit->numOuts +
253 cUnit->numPadding + 2) * 4;
254 cUnit->insOffset = cUnit->frameSize + 4;
255 cUnit->regsOffset = (cUnit->numOuts + cUnit->numPadding + 1) * 4;
256
257 /* Compute sp-relative home location offsets */
258 for (i = 0; i < cUnit->numSSARegs; i++) {
259 int vReg = oatS2VReg(cUnit, cUnit->regLocation[i].sRegLow);
260 cUnit->regLocation[i].spOffset = oatVRegOffset(cUnit, vReg);
261 }
262}