blob: 7111f6d537f9fa8f0500192086a53d8f5b5bb5f3 [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
buzbee67bf8852011-08-17 17:51:35 -070031/*
buzbee03fa2632011-09-20 17:10:57 -070032 * Infer types and sizes. We don't need to track change on sizes,
33 * as it doesn't propagate. We're guaranteed at least one pass through
34 * the cfg.
buzbee67bf8852011-08-17 17:51:35 -070035 */
buzbeeed3e9302011-09-23 17:34:19 -070036STATIC bool inferTypeAndSize(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070037{
38 MIR *mir;
buzbee03fa2632011-09-20 17:10:57 -070039 bool changed = false; // Did anything change?
40
41 if (bb->dataFlowInfo == NULL) return false;
buzbee67bf8852011-08-17 17:51:35 -070042 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock)
buzbee03fa2632011-09-20 17:10:57 -070043 return false;
buzbee67bf8852011-08-17 17:51:35 -070044
45 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
46 SSARepresentation *ssaRep = mir->ssaRep;
47 if (ssaRep) {
buzbee03fa2632011-09-20 17:10:57 -070048 int attrs = oatDataFlowAttributes[mir->dalvikInsn.opcode];
49 int next = 0;
50 if (attrs & DF_DA_WIDE) {
51 cUnit->regLocation[ssaRep->defs[0]].wide = true;
buzbee67bf8852011-08-17 17:51:35 -070052 }
buzbee03fa2632011-09-20 17:10:57 -070053 if (attrs & DF_UA_WIDE) {
54 cUnit->regLocation[ssaRep->uses[next]].wide = true;
55 next += 2;
56 }
57 if (attrs & DF_UB_WIDE) {
58 cUnit->regLocation[ssaRep->uses[next]].wide = true;
59 next += 2;
60 }
61 if (attrs & DF_UC_WIDE) {
62 cUnit->regLocation[ssaRep->uses[next]].wide = true;
buzbeeed3e9302011-09-23 17:34:19 -070063 next += 2;
buzbee03fa2632011-09-20 17:10:57 -070064 }
buzbeeed3e9302011-09-23 17:34:19 -070065
66 // Special-case handling for format 35c/3rc invokes
67 Opcode opcode = mir->dalvikInsn.opcode;
68 int flags = (opcode >= kNumPackedOpcodes) ? 0 :
69 dexGetFlagsFromOpcode(opcode);
70 if ((flags & kInstrInvoke) &&
71 (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) {
72 DCHECK_EQ(next, 0);
73 int target_idx = mir->dalvikInsn.vB;
74 const char* shorty =
75 oatGetShortyFromTargetIdx(cUnit, target_idx);
76 int numUses = mir->dalvikInsn.vA;
77 // If this is a non-static invoke, skip implicit "this"
78 if (((mir->dalvikInsn.opcode != OP_INVOKE_STATIC) &&
79 (mir->dalvikInsn.opcode != OP_INVOKE_STATIC_RANGE))) {
80 next++;
81 }
82 uint32_t cpos = 1;
83 if (strlen(shorty) > 1) {
84 for (int i = next; i < numUses;) {
85 DCHECK_LT(cpos, strlen(shorty));
86 switch(shorty[cpos++]) {
87 case 'D':
88 ssaRep->fpUse[i] = true;
89 ssaRep->fpUse[i+1] = true;
90 cUnit->regLocation[ssaRep->uses[i]].wide = true;
91 i++;
92 break;
93 case 'J':
94 cUnit->regLocation[ssaRep->uses[i]].wide = true;
95 i++;
96 break;
97 case 'F':
98 ssaRep->fpUse[i] = true;
99 break;
100 default:
101 break;
102 }
103 i++;
104 }
105 }
106 }
107
buzbee03fa2632011-09-20 17:10:57 -0700108 for (int i=0; ssaRep->fpUse && i< ssaRep->numUses; i++) {
109 if (ssaRep->fpUse[i])
110 changed |= setFp(cUnit, ssaRep->uses[i], true);
111 }
112 for (int i=0; ssaRep->fpDef && i< ssaRep->numDefs; i++) {
buzbee67bf8852011-08-17 17:51:35 -0700113 if (ssaRep->fpDef[i])
buzbee03fa2632011-09-20 17:10:57 -0700114 changed |= setFp(cUnit, ssaRep->defs[i], true);
115 }
116 // Special-case handling for moves & Phi
117 if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
118 bool isFP = cUnit->regLocation[ssaRep->defs[0]].fp;
119 for (int i = 0; i < ssaRep->numUses; i++) {
120 isFP |= cUnit->regLocation[ssaRep->uses[i]].fp;
121 }
122 changed |= setFp(cUnit, ssaRep->defs[0], isFP);
123 for (int i = 0; i < ssaRep->numUses; i++) {
124 changed |= setFp(cUnit, ssaRep->uses[i], isFP);
125 }
buzbee67bf8852011-08-17 17:51:35 -0700126 }
127 }
128 }
buzbee03fa2632011-09-20 17:10:57 -0700129 return changed;
buzbee67bf8852011-08-17 17:51:35 -0700130}
131
132static const char* storageName[] = {" Frame ", "PhysReg", " Spill "};
133
buzbeedfd3d702011-08-28 12:56:51 -0700134void oatDumpRegLocTable(RegLocation* table, int count)
buzbee67bf8852011-08-17 17:51:35 -0700135{
136 for (int i = 0; i < count; i++) {
137 char buf[100];
138 snprintf(buf, 100, "Loc[%02d] : %s, %c %c r%d r%d S%d : %s s%d s%d",
139 i, storageName[table[i].location], table[i].wide ? 'W' : 'N',
140 table[i].fp ? 'F' : 'C', table[i].lowReg, table[i].highReg,
141 table[i].sRegLow, storageName[table[i].fpLocation],
142 table[i].fpLowReg & FP_REG_MASK, table[i].fpHighReg &
143 FP_REG_MASK);
144 LOG(INFO) << buf;
145 }
146}
147
148static const RegLocation freshLoc = {kLocDalvikFrame, 0, 0, INVALID_REG,
149 INVALID_REG, INVALID_SREG, 0,
150 kLocDalvikFrame, INVALID_REG, INVALID_REG,
151 INVALID_OFFSET};
152
153/*
154 * Simple register allocation. Some Dalvik virtual registers may
155 * be promoted to physical registers. Most of the work for temp
156 * allocation is done on the fly. We also do some initilization and
157 * type inference here.
158 */
159void oatSimpleRegAlloc(CompilationUnit* cUnit)
160{
161 int i;
162 RegLocation* loc;
163
164 /* Allocate the location map */
165 loc = (RegLocation*)oatNew(cUnit->numSSARegs * sizeof(*loc), true);
166 for (i=0; i< cUnit->numSSARegs; i++) {
167 loc[i] = freshLoc;
168 loc[i].sRegLow = i;
169 }
170 cUnit->regLocation = loc;
171
buzbeee9a72f62011-09-04 17:59:07 -0700172 /* Add types of incoming arguments based on signature */
173 int numRegs = cUnit->method->NumRegisters();
174 int numIns = cUnit->method->NumIns();
175 if (numIns > 0) {
176 int sReg = numRegs - numIns;
177 if (!cUnit->method->IsStatic()) {
178 // Skip past "this"
179 sReg++;
180 }
Brian Carlstromc74255f2011-09-11 22:47:39 -0700181 const String* shorty = cUnit->method->GetShorty();
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700182 for (int i = 1; i < shorty->GetLength(); i++) {
183 char arg = shorty->CharAt(i);
buzbeee9a72f62011-09-04 17:59:07 -0700184 // Is it wide?
185 if ((arg == 'D') || (arg == 'J')) {
186 cUnit->regLocation[sReg].wide = true;
187 cUnit->regLocation[sReg+1].fp = cUnit->regLocation[sReg].fp;
188 sReg++; // Skip to next
189 }
190 sReg++;
191 }
192 }
193
buzbee03fa2632011-09-20 17:10:57 -0700194 /* Do type & size inference pass */
195 oatDataFlowAnalysisDispatcher(cUnit, inferTypeAndSize,
196 kPreOrderDFSTraversal,
197 true /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700198
199 /*
200 * Set the sRegLow field to refer to the pre-SSA name of the
201 * base Dalvik virtual register. Once we add a better register
202 * allocator, remove this remapping.
203 */
204 for (i=0; i < cUnit->numSSARegs; i++) {
205 cUnit->regLocation[i].sRegLow =
206 DECODE_REG(oatConvertSSARegToDalvik(cUnit, loc[i].sRegLow));
207 }
208
209 cUnit->coreSpillMask = 0;
210 cUnit->fpSpillMask = 0;
211 cUnit->numSpills = 0;
212
213 oatDoPromotion(cUnit);
214
215 if (cUnit->printMe && !(cUnit->disableOpt & (1 << kPromoteRegs))) {
216 LOG(INFO) << "After Promotion";
buzbeedfd3d702011-08-28 12:56:51 -0700217 oatDumpRegLocTable(cUnit->regLocation, cUnit->numSSARegs);
buzbee67bf8852011-08-17 17:51:35 -0700218 }
219
220 /* Figure out the frame size */
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700221 cUnit->numIns = cUnit->method->NumIns();
222 cUnit->numRegs = cUnit->method->NumRegisters() - cUnit->numIns;
223 cUnit->numOuts = cUnit->method->NumOuts();
buzbee67bf8852011-08-17 17:51:35 -0700224 cUnit->numPadding = (STACK_ALIGN_WORDS -
225 (cUnit->numSpills + cUnit->numRegs +
226 cUnit->numOuts + 2)) & (STACK_ALIGN_WORDS-1);
227 cUnit->frameSize = (cUnit->numSpills + cUnit->numRegs + cUnit->numOuts +
228 cUnit->numPadding + 2) * 4;
229 cUnit->insOffset = cUnit->frameSize + 4;
230 cUnit->regsOffset = (cUnit->numOuts + cUnit->numPadding + 1) * 4;
231
232 /* Compute sp-relative home location offsets */
233 for (i = 0; i < cUnit->numSSARegs; i++) {
234 int vReg = oatS2VReg(cUnit, cUnit->regLocation[i].sRegLow);
235 cUnit->regLocation[i].spOffset = oatVRegOffset(cUnit, vReg);
236 }
237}