blob: 81c721dc883e2fbe9dc8c1fe1378c2e153b20ec7 [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/*
18 * This file contains Arm-specific register alloction support.
19 */
20
21#include "../../CompilerUtility.h"
22#include "../../CompilerIR.h"
23#include "../..//Dataflow.h"
24#include "ArmLIR.h"
25#include "Codegen.h"
26#include "../Ralloc.h"
27
28/*
29 * Placeholder routine until we do proper register allocation.
30 */
31
32typedef struct RefCounts {
33 int count;
34 int sReg;
35 bool doubleStart; // Starting vReg for a double
36} RefCounts;
37
buzbeee9a72f62011-09-04 17:59:07 -070038/* USE SSA names to count references of base Dalvik vRegs. */
buzbeeed3e9302011-09-23 17:34:19 -070039STATIC void countRefs(CompilationUnit *cUnit, BasicBlock* bb,
buzbee67bc2362011-10-11 18:08:40 -070040 RefCounts* coreCounts, RefCounts* fpCounts)
buzbee67bf8852011-08-17 17:51:35 -070041{
42 MIR* mir;
43 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
44 bb->blockType != kExitBlock)
45 return;
46
47 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
48 SSARepresentation *ssaRep = mir->ssaRep;
49 if (ssaRep) {
buzbee67bc2362011-10-11 18:08:40 -070050 for (int i = 0; i < ssaRep->numDefs;) {
51 RegLocation loc = cUnit->regLocation[ssaRep->defs[i]];
52 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
53 int vReg = oatS2VReg(cUnit, ssaRep->defs[i]);
54 if (loc.defined) {
55 counts[vReg].count++;
buzbee3ea4ec52011-08-22 17:37:19 -070056 }
buzbee67bc2362011-10-11 18:08:40 -070057 if (loc.wide) {
58 if (loc.defined) {
59 if (loc.fp) {
60 counts[vReg].doubleStart = true;
61 }
62 counts[vReg+1].count++;
63 }
64 i += 2;
65 } else {
66 i++;
buzbee3ea4ec52011-08-22 17:37:19 -070067 }
buzbee67bf8852011-08-17 17:51:35 -070068 }
buzbee67bc2362011-10-11 18:08:40 -070069 for (int i = 0; i < ssaRep->numUses;) {
70 RegLocation loc = cUnit->regLocation[ssaRep->uses[i]];
71 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
72 int vReg = oatS2VReg(cUnit, ssaRep->uses[i]);
73 if (loc.defined) {
74 counts[vReg].count++;
buzbee67bf8852011-08-17 17:51:35 -070075 }
buzbee67bc2362011-10-11 18:08:40 -070076 if (loc.wide) {
77 if (loc.defined) {
78 if (loc.fp) {
79 counts[vReg].doubleStart = true;
80 }
81 counts[vReg+1].count++;
82 }
83 i += 2;
84 } else {
85 i++;
buzbee67bf8852011-08-17 17:51:35 -070086 }
87 }
88 }
89 }
90}
91
92/* qsort callback function, sort descending */
buzbeeed3e9302011-09-23 17:34:19 -070093STATIC int sortCounts(const void *val1, const void *val2)
buzbee67bf8852011-08-17 17:51:35 -070094{
95 const RefCounts* op1 = (const RefCounts*)val1;
96 const RefCounts* op2 = (const RefCounts*)val2;
97 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
98}
99
buzbeeed3e9302011-09-23 17:34:19 -0700100STATIC void dumpCounts(const RefCounts* arr, int size, const char* msg)
buzbee67bf8852011-08-17 17:51:35 -0700101{
102 LOG(INFO) << msg;
103 for (int i = 0; i < size; i++) {
104 LOG(INFO) << "sReg[" << arr[i].sReg << "]: " << arr[i].count;
105 }
106}
107
108/*
109 * Note: some portions of this code required even if the kPromoteRegs
110 * optimization is disabled.
111 */
112extern void oatDoPromotion(CompilationUnit* cUnit)
113{
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700114 int numRegs = cUnit->method->NumRegisters();
buzbee67bf8852011-08-17 17:51:35 -0700115
116 /*
buzbee67bf8852011-08-17 17:51:35 -0700117 * TUNING: is leaf? Can't just use "hasInvoke" to determine as some
118 * instructions might call out to C/assembly helper functions. Until
119 * machinery is in place, always spill lr.
120 */
121 cUnit->coreSpillMask |= (1 << rLR);
buzbeebbaf8942011-10-02 13:08:29 -0700122 cUnit->numCoreSpills++;
buzbee67bf8852011-08-17 17:51:35 -0700123 /*
124 * Simple hack for testing register allocation. Just do a static
125 * count of the uses of Dalvik registers. Note that we examine
126 * the SSA names, but count based on original Dalvik register name.
127 * Count refs separately based on type in order to give allocation
128 * preference to fp doubles - which must be allocated sequential
129 * physical single fp registers started with an even-numbered
130 * reg.
131 */
132 RefCounts *coreRegs = (RefCounts *)
133 oatNew(sizeof(RefCounts) * numRegs, true);
134 RefCounts *fpRegs = (RefCounts *)
135 oatNew(sizeof(RefCounts) * numRegs, true);
136 for (int i = 0; i < numRegs; i++) {
137 coreRegs[i].sReg = fpRegs[i].sReg = i;
138 }
139 GrowableListIterator iterator;
140 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
141 while (true) {
142 BasicBlock* bb;
143 bb = (BasicBlock*)oatGrowableListIteratorNext(&iterator);
144 if (bb == NULL) break;
buzbee67bc2362011-10-11 18:08:40 -0700145 countRefs(cUnit, bb, coreRegs, fpRegs);
buzbee67bf8852011-08-17 17:51:35 -0700146 }
147
148 /*
149 * Ideally, we'd allocate doubles starting with an even-numbered
150 * register. Bias the counts to try to allocate any vreg that's
151 * used as the start of a pair first.
152 */
153 for (int i = 0; i < numRegs; i++) {
154 if (fpRegs[i].doubleStart) {
155 fpRegs[i].count *= 2;
156 }
157 }
158
159 // Sort the count arrays
160 qsort(coreRegs, numRegs, sizeof(RefCounts), sortCounts);
161 qsort(fpRegs, numRegs, sizeof(RefCounts), sortCounts);
162
buzbee67bc2362011-10-11 18:08:40 -0700163 if (cUnit->printMe) {
164 dumpCounts(coreRegs, numRegs, "Core regs after sort");
165 dumpCounts(fpRegs, numRegs, "Fp regs after sort");
166 }
167
buzbee67bf8852011-08-17 17:51:35 -0700168 if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
169 // Promote fpRegs
170 for (int i = 0; (fpRegs[i].count > 0) && (i < numRegs); i++) {
buzbee67bc2362011-10-11 18:08:40 -0700171 if (cUnit->promotionMap[fpRegs[i].sReg].fpLocation != kLocPhysReg) {
buzbeea50638b2011-11-02 15:15:06 -0700172 if (fpRegs[i].sReg >= cUnit->numRegs) {
173 // don't promote arg regs
174 continue;
175 }
buzbee67bf8852011-08-17 17:51:35 -0700176 int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
177 fpRegs[i].doubleStart);
178 if (reg < 0) {
buzbee67bc2362011-10-11 18:08:40 -0700179 break; // No more left
buzbee67bf8852011-08-17 17:51:35 -0700180 }
181 }
182 }
183
184 // Promote core regs
185 for (int i = 0; (coreRegs[i].count > 0) && i < numRegs; i++) {
buzbee67bc2362011-10-11 18:08:40 -0700186 if (cUnit->promotionMap[coreRegs[i].sReg].coreLocation !=
187 kLocPhysReg) {
buzbeea50638b2011-11-02 15:15:06 -0700188 if (coreRegs[i].sReg >= cUnit->numRegs) {
189 // don't promote arg regs
190 continue;
191 }
buzbee67bf8852011-08-17 17:51:35 -0700192 int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
193 if (reg < 0) {
194 break; // No more left
195 }
196 }
197 }
198 }
199
200 // Now, update SSA names to new home locations
201 for (int i = 0; i < cUnit->numSSARegs; i++) {
buzbee67bf8852011-08-17 17:51:35 -0700202 RegLocation *curr = &cUnit->regLocation[i];
buzbee67bc2362011-10-11 18:08:40 -0700203 int baseVReg = oatS2VReg(cUnit, curr->sRegLow);
204 if (!curr->wide) {
205 if (curr->fp) {
206 if (cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) {
207 curr->location = kLocPhysReg;
208 curr->lowReg = cUnit->promotionMap[baseVReg].fpReg;
209 curr->home = true;
buzbee67bf8852011-08-17 17:51:35 -0700210 }
buzbee67bc2362011-10-11 18:08:40 -0700211 } else {
212 if (cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg) {
213 curr->location = kLocPhysReg;
214 curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
215 curr->home = true;
216 }
buzbee67bf8852011-08-17 17:51:35 -0700217 }
buzbee67bc2362011-10-11 18:08:40 -0700218 curr->highReg = INVALID_REG;
buzbee67bf8852011-08-17 17:51:35 -0700219 } else {
buzbee67bc2362011-10-11 18:08:40 -0700220 if (curr->highWord) {
221 continue;
222 }
223 if (curr->fp) {
224 if ((cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) &&
225 (cUnit->promotionMap[baseVReg+1].fpLocation ==
226 kLocPhysReg)) {
227 int lowReg = cUnit->promotionMap[baseVReg].fpReg;
228 int highReg = cUnit->promotionMap[baseVReg+1].fpReg;
229 // Doubles require pair of singles starting at even reg
230 if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
231 curr->location = kLocPhysReg;
232 curr->lowReg = lowReg;
233 curr->highReg = highReg;
234 curr->home = true;
buzbee67bf8852011-08-17 17:51:35 -0700235 }
buzbee67bf8852011-08-17 17:51:35 -0700236 }
buzbee67bc2362011-10-11 18:08:40 -0700237 } else {
238 if ((cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg)
239 && (cUnit->promotionMap[baseVReg+1].coreLocation ==
240 kLocPhysReg)) {
241 curr->location = kLocPhysReg;
242 curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
243 curr->highReg = cUnit->promotionMap[baseVReg+1].coreReg;
244 curr->home = true;
245 }
buzbee67bf8852011-08-17 17:51:35 -0700246 }
247 }
248 }
249}
250
buzbee67bc2362011-10-11 18:08:40 -0700251/* Returns sp-relative offset in bytes for a VReg */
252extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
buzbee67bf8852011-08-17 17:51:35 -0700253{
buzbee67bc2362011-10-11 18:08:40 -0700254 return (vReg < cUnit->numRegs) ? cUnit->regsOffset + (vReg << 2) :
255 cUnit->insOffset + ((vReg - cUnit->numRegs) << 2);
buzbee67bf8852011-08-17 17:51:35 -0700256}
257
buzbee67bc2362011-10-11 18:08:40 -0700258/* Returns sp-relative offset in bytes for a SReg */
259extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
260{
261 return oatVRegOffset(cUnit, oatS2VReg(cUnit, sReg));
262}
263
264
buzbeec41e5b52011-09-23 12:46:19 -0700265/* Return sp-relative offset in bytes using Method* */
266extern int oatVRegOffsetFromMethod(Method* method, int reg)
267{
268 int numIns = method->NumIns();
269 int numRegs = method->NumRegisters() - numIns;
270 int numOuts = method->NumOuts();
271 int numSpills = __builtin_popcount(method->GetCoreSpillMask()) +
272 __builtin_popcount(method->GetFpSpillMask());
273 int numPadding = (STACK_ALIGN_WORDS -
274 (numSpills + numRegs + numOuts + 2)) & (STACK_ALIGN_WORDS-1);
275 int regsOffset = (numOuts + numPadding + 1) * 4;
276 int insOffset = method->GetFrameSizeInBytes() + 4;
277 return (reg < numRegs) ? regsOffset + (reg << 2) :
278 insOffset + ((reg - numRegs) << 2);
279}
buzbee67bf8852011-08-17 17:51:35 -0700280
281/* Clobber all regs that might be used by an external C call */
buzbee6181f792011-09-29 11:14:04 -0700282extern void oatClobberCalleeSave(CompilationUnit *cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700283{
284 oatClobber(cUnit, r0);
285 oatClobber(cUnit, r1);
286 oatClobber(cUnit, r2);
287 oatClobber(cUnit, r3);
288 oatClobber(cUnit, r12);
289 oatClobber(cUnit, r14lr);
290}
291
buzbee67bf8852011-08-17 17:51:35 -0700292extern RegLocation oatGetReturnWide(CompilationUnit* cUnit)
293{
294 RegLocation res = LOC_C_RETURN_WIDE;
295 oatClobber(cUnit, r0);
296 oatClobber(cUnit, r1);
297 oatMarkInUse(cUnit, r0);
298 oatMarkInUse(cUnit, r1);
299 oatMarkPair(cUnit, res.lowReg, res.highReg);
300 return res;
301}
302
303extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
304{
305 RegLocation res = LOC_C_RETURN_WIDE;
306 res.lowReg = r2;
307 res.highReg = r3;
308 oatClobber(cUnit, r2);
309 oatClobber(cUnit, r3);
310 oatMarkInUse(cUnit, r2);
311 oatMarkInUse(cUnit, r3);
312 oatMarkPair(cUnit, res.lowReg, res.highReg);
313 return res;
314}
315
316extern RegLocation oatGetReturn(CompilationUnit* cUnit)
317{
318 RegLocation res = LOC_C_RETURN;
319 oatClobber(cUnit, r0);
320 oatMarkInUse(cUnit, r0);
321 return res;
322}
323
324extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)
325{
326 RegLocation res = LOC_C_RETURN;
327 res.lowReg = r1;
328 oatClobber(cUnit, r1);
329 oatMarkInUse(cUnit, r1);
330 return res;
331}
buzbee68253262011-10-07 14:02:25 -0700332
333extern RegisterInfo* oatGetRegInfo(CompilationUnit* cUnit, int reg)
334{
335 return FPREG(reg) ? &cUnit->regPool->FPRegs[reg & FP_REG_MASK]
336 : &cUnit->regPool->coreRegs[reg];
337}