blob: 2088cdc3602bc83277cab29619de06d35d3c75d4 [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 register alloction support and is intended to be
19 * included by:
20 *
21 * Codegen-$(TARGET_ARCH_VARIANT).c
22 *
23 */
24
25#include "../CompilerUtility.h"
26#include "../CompilerIR.h"
27#include "../Dataflow.h"
28#include "Ralloc.h"
29
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080030namespace art {
31
buzbee67bf8852011-08-17 17:51:35 -070032/*
33 * Free all allocated temps in the temp pools. Note that this does
34 * not affect the "liveness" of a temp register, which will stay
35 * live until it is either explicitly killed or reallocated.
36 */
37extern void oatResetRegPool(CompilationUnit* cUnit)
38{
Bill Buzbeea114add2012-05-03 15:00:40 -070039 int i;
40 for (i=0; i < cUnit->regPool->numCoreRegs; i++) {
41 if (cUnit->regPool->coreRegs[i].isTemp)
42 cUnit->regPool->coreRegs[i].inUse = false;
43 }
44 for (i=0; i < cUnit->regPool->numFPRegs; i++) {
45 if (cUnit->regPool->FPRegs[i].isTemp)
46 cUnit->regPool->FPRegs[i].inUse = false;
47 }
buzbee67bf8852011-08-17 17:51:35 -070048}
49
buzbeee3acd072012-02-25 17:03:10 -080050 /*
51 * Set up temp & preserved register pools specialized by target.
52 * Note: numRegs may be zero.
53 */
buzbee67bf8852011-08-17 17:51:35 -070054extern void oatInitPool(RegisterInfo* regs, int* regNums, int num)
55{
Bill Buzbeea114add2012-05-03 15:00:40 -070056 int i;
57 for (i=0; i < num; i++) {
58 regs[i].reg = regNums[i];
59 regs[i].inUse = false;
60 regs[i].isTemp = false;
61 regs[i].pair = false;
62 regs[i].live = false;
63 regs[i].dirty = false;
64 regs[i].sReg = INVALID_SREG;
65 }
buzbee67bf8852011-08-17 17:51:35 -070066}
67
buzbee31a4a6f2012-02-28 15:36:15 -080068void dumpRegPool(RegisterInfo* p, int numRegs)
buzbee67bf8852011-08-17 17:51:35 -070069{
Bill Buzbeea114add2012-05-03 15:00:40 -070070 LOG(INFO) << "================================================";
71 for (int i = 0; i < numRegs; i++) {
72 LOG(INFO) << StringPrintf(
73 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
74 p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
75 p[i].live, p[i].dirty, p[i].sReg,(int)p[i].defStart,
76 (int)p[i].defEnd);
77 }
78 LOG(INFO) << "================================================";
buzbee67bf8852011-08-17 17:51:35 -070079}
80
buzbee6181f792011-09-29 11:14:04 -070081void oatDumpCoreRegPool(CompilationUnit* cUnit)
82{
Bill Buzbeea114add2012-05-03 15:00:40 -070083 dumpRegPool(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs);
buzbee6181f792011-09-29 11:14:04 -070084}
85
86void oatDumpFpRegPool(CompilationUnit* cUnit)
87{
Bill Buzbeea114add2012-05-03 15:00:40 -070088 dumpRegPool(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs);
buzbee6181f792011-09-29 11:14:04 -070089}
90
buzbee67bf8852011-08-17 17:51:35 -070091/* Mark a temp register as dead. Does not affect allocation state. */
buzbee5abfa3e2012-01-31 17:01:43 -080092static inline void clobberBody(CompilationUnit *cUnit, RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -070093{
Bill Buzbeea114add2012-05-03 15:00:40 -070094 if (p->isTemp) {
95 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
96 p->live = false;
97 p->sReg = INVALID_SREG;
98 p->defStart = NULL;
99 p->defEnd = NULL;
100 if (p->pair) {
101 p->pair = false;
102 oatClobber(cUnit, p->partner);
buzbee67bf8852011-08-17 17:51:35 -0700103 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 }
buzbee67bf8852011-08-17 17:51:35 -0700105}
106
buzbee5abfa3e2012-01-31 17:01:43 -0800107/* Mark a temp register as dead. Does not affect allocation state. */
108void oatClobber(CompilationUnit* cUnit, int reg)
109{
Bill Buzbeea114add2012-05-03 15:00:40 -0700110 clobberBody(cUnit, oatGetRegInfo(cUnit, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800111}
112
buzbee31a4a6f2012-02-28 15:36:15 -0800113void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700114{
Bill Buzbeea114add2012-05-03 15:00:40 -0700115 int i;
116 for (i=0; i< numRegs; i++) {
117 if (p[i].sReg == sReg) {
118 if (p[i].isTemp) {
119 p[i].live = false;
120 }
121 p[i].defStart = NULL;
122 p[i].defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700123 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700124 }
buzbee67bf8852011-08-17 17:51:35 -0700125}
126
127/* Clobber any temp associated with an sReg. Could be in either class */
128extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
129{
buzbee3d661942012-03-14 17:37:27 -0700130#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 /* Reset live temp tracking sanity checker */
132 if (sReg == cUnit->liveSReg) {
133 cUnit->liveSReg = INVALID_SREG;
134 }
buzbee3d661942012-03-14 17:37:27 -0700135#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs, sReg);
137 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700138}
139
buzbee9c044ce2012-03-18 13:24:07 -0700140/*
141 * SSA names associated with the initial definitions of Dalvik
142 * registers are the same as the Dalvik register number (and
143 * thus take the same position in the promotionMap. However,
144 * the special Method* and compiler temp resisters use negative
Elliott Hughesbdf6c3d2012-03-20 13:43:53 -0700145 * vReg numbers to distinguish them and can have an arbitrary
buzbee9c044ce2012-03-18 13:24:07 -0700146 * ssa name (above the last original Dalvik register). This function
147 * maps SSA names to positions in the promotionMap array.
148 */
149int SRegToPMap(CompilationUnit* cUnit, int sReg)
buzbeee1965672012-03-11 18:39:19 -0700150{
Bill Buzbeea114add2012-05-03 15:00:40 -0700151 DCHECK_LT(sReg, cUnit->numSSARegs);
152 DCHECK_GE(sReg, 0);
153 int vReg = SRegToVReg(cUnit, sReg);
154 if (vReg >= 0) {
155 DCHECK_LT(vReg, cUnit->numDalvikRegisters);
156 return vReg;
157 } else {
158 int pos = std::abs(vReg) - std::abs(SSA_METHOD_BASEREG);
159 DCHECK_LE(pos, cUnit->numCompilerTemps);
160 return cUnit->numDalvikRegisters + pos;
161 }
buzbeee1965672012-03-11 18:39:19 -0700162}
163
buzbee67bf8852011-08-17 17:51:35 -0700164/* Reserve a callee-save register. Return -1 if none available */
165extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
166{
Bill Buzbeea114add2012-05-03 15:00:40 -0700167 int res = -1;
168 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
169 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
170 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
171 int vReg = SRegToVReg(cUnit, sReg);
172 int pMapIdx = SRegToPMap(cUnit, sReg);
173 res = coreRegs[i].reg;
174 coreRegs[i].inUse = true;
175 cUnit->coreSpillMask |= (1 << res);
176 cUnit->coreVmapTable.push_back(vReg);
177 cUnit->numCoreSpills++;
178 cUnit->promotionMap[pMapIdx].coreLocation = kLocPhysReg;
179 cUnit->promotionMap[pMapIdx].coreReg = res;
180 break;
buzbee67bf8852011-08-17 17:51:35 -0700181 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700182 }
183 return res;
buzbee67bf8852011-08-17 17:51:35 -0700184}
185
186/*
187 * Reserve a callee-save fp single register. Try to fullfill request for
188 * even/odd allocation, but go ahead and allocate anything if not
189 * available. If nothing's available, return -1.
190 */
buzbee31a4a6f2012-02-28 15:36:15 -0800191int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700192{
Bill Buzbeea114add2012-05-03 15:00:40 -0700193 int res = -1;
194 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
195 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
196 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
197 ((FPRegs[i].reg & 0x1) == 0) == even) {
198 int vReg = SRegToVReg(cUnit, sReg);
199 int pMapIdx = SRegToPMap(cUnit, sReg);
200 res = FPRegs[i].reg;
201 FPRegs[i].inUse = true;
202 oatMarkPreservedSingle(cUnit, vReg, res);
203 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
204 cUnit->promotionMap[pMapIdx].fpReg = res;
205 break;
buzbee67bf8852011-08-17 17:51:35 -0700206 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700207 }
208 return res;
buzbee67bf8852011-08-17 17:51:35 -0700209}
210
211/*
212 * Somewhat messy code here. We want to allocate a pair of contiguous
213 * physical single-precision floating point registers starting with
214 * an even numbered reg. It is possible that the paired sReg (sReg+1)
215 * has already been allocated - try to fit if possible. Fail to
216 * allocate if we can't meet the requirements for the pair of
217 * sReg<=sX[even] & (sReg+1)<= sX+1.
218 */
buzbee31a4a6f2012-02-28 15:36:15 -0800219int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700220{
Bill Buzbeea114add2012-05-03 15:00:40 -0700221 int res = -1; // Assume failure
222 int vReg = SRegToVReg(cUnit, sReg);
223 int pMapIdx = SRegToPMap(cUnit, sReg);
224 if (cUnit->promotionMap[pMapIdx+1].fpLocation == kLocPhysReg) {
225 // Upper reg is already allocated. Can we fit?
226 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
227 if ((highReg & 1) == 0) {
228 // High reg is even - fail.
229 return res;
230 }
231 // Is the low reg of the pair free?
232 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
233 if (p->inUse || p->isTemp) {
234 // Already allocated or not preserved - fail.
235 return res;
236 }
237 // OK - good to go.
238 res = p->reg;
239 p->inUse = true;
240 DCHECK_EQ((res & 1), 0);
241 oatMarkPreservedSingle(cUnit, vReg, res);
242 } else {
243 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
244 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
245 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
246 ((FPRegs[i].reg & 0x1) == 0x0) &&
247 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
248 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
249 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
250 res = FPRegs[i].reg;
251 FPRegs[i].inUse = true;
buzbee9c044ce2012-03-18 13:24:07 -0700252 oatMarkPreservedSingle(cUnit, vReg, res);
Bill Buzbeea114add2012-05-03 15:00:40 -0700253 FPRegs[i+1].inUse = true;
254 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
255 oatMarkPreservedSingle(cUnit, vReg+1, res+1);
256 break;
257 }
buzbee67bf8852011-08-17 17:51:35 -0700258 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700259 }
260 if (res != -1) {
261 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
262 cUnit->promotionMap[pMapIdx].fpReg = res;
263 cUnit->promotionMap[pMapIdx+1].fpLocation = kLocPhysReg;
264 cUnit->promotionMap[pMapIdx+1].fpReg = res + 1;
265 }
266 return res;
buzbee67bf8852011-08-17 17:51:35 -0700267}
268
269
270/*
271 * Reserve a callee-save fp register. If this register can be used
272 * as the first of a double, attempt to allocate an even pair of fp
273 * single regs (but if can't still attempt to allocate a single, preferring
274 * first to allocate an odd register.
275 */
276extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
Bill Buzbeea114add2012-05-03 15:00:40 -0700277 bool doubleStart)
buzbee67bf8852011-08-17 17:51:35 -0700278{
Bill Buzbeea114add2012-05-03 15:00:40 -0700279 int res = -1;
280 if (doubleStart) {
281 res = allocPreservedDouble(cUnit, sReg);
282 }
283 if (res == -1) {
284 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
285 }
286 if (res == -1)
287 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
288 return res;
buzbee67bf8852011-08-17 17:51:35 -0700289}
290
buzbee31a4a6f2012-02-28 15:36:15 -0800291int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700292 int* nextTemp, bool required)
buzbee67bf8852011-08-17 17:51:35 -0700293{
Bill Buzbeea114add2012-05-03 15:00:40 -0700294 int i;
295 int next = *nextTemp;
296 for (i=0; i< numRegs; i++) {
297 if (next >= numRegs)
298 next = 0;
299 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
300 oatClobber(cUnit, p[next].reg);
301 p[next].inUse = true;
302 p[next].pair = false;
303 *nextTemp = next + 1;
304 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700305 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700306 next++;
307 }
308 next = *nextTemp;
309 for (i=0; i< numRegs; i++) {
310 if (next >= numRegs)
311 next = 0;
312 if (p[next].isTemp && !p[next].inUse) {
313 oatClobber(cUnit, p[next].reg);
314 p[next].inUse = true;
315 p[next].pair = false;
316 *nextTemp = next + 1;
317 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700318 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700319 next++;
320 }
321 if (required) {
322 oatCodegenDump(cUnit);
323 dumpRegPool(cUnit->regPool->coreRegs,
324 cUnit->regPool->numCoreRegs);
325 LOG(FATAL) << "No free temp registers";
326 }
327 return -1; // No register available
buzbee67bf8852011-08-17 17:51:35 -0700328}
329
330//REDO: too many assumptions.
331extern int oatAllocTempDouble(CompilationUnit* cUnit)
332{
Bill Buzbeea114add2012-05-03 15:00:40 -0700333 RegisterInfo* p = cUnit->regPool->FPRegs;
334 int numRegs = cUnit->regPool->numFPRegs;
335 /* Start looking at an even reg */
336 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700337
Bill Buzbeea114add2012-05-03 15:00:40 -0700338 // First try to avoid allocating live registers
339 for (int i=0; i < numRegs; i+=2) {
340 if (next >= numRegs)
341 next = 0;
342 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
343 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
344 oatClobber(cUnit, p[next].reg);
345 oatClobber(cUnit, p[next+1].reg);
346 p[next].inUse = true;
347 p[next+1].inUse = true;
348 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
349 DCHECK_EQ((p[next].reg & 0x1), 0);
350 cUnit->regPool->nextFPReg = next + 2;
351 if (cUnit->regPool->nextFPReg >= numRegs) {
352 cUnit->regPool->nextFPReg = 0;
353 }
354 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700355 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700356 next += 2;
357 }
358 next = cUnit->regPool->nextFPReg & ~0x1;
buzbeea50638b2011-11-02 15:15:06 -0700359
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 // No choice - find a pair and kill it.
361 for (int i=0; i < numRegs; i+=2) {
362 if (next >= numRegs)
363 next = 0;
364 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
365 !p[next+1].inUse) {
366 oatClobber(cUnit, p[next].reg);
367 oatClobber(cUnit, p[next+1].reg);
368 p[next].inUse = true;
369 p[next+1].inUse = true;
370 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
371 DCHECK_EQ((p[next].reg & 0x1), 0);
372 cUnit->regPool->nextFPReg = next + 2;
373 if (cUnit->regPool->nextFPReg >= numRegs) {
374 cUnit->regPool->nextFPReg = 0;
375 }
376 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700377 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700378 next += 2;
379 }
380 LOG(FATAL) << "No free temp registers (pair)";
381 return -1;
buzbee67bf8852011-08-17 17:51:35 -0700382}
383
384/* Return a temp if one is available, -1 otherwise */
385extern int oatAllocFreeTemp(CompilationUnit* cUnit)
386{
Bill Buzbeea114add2012-05-03 15:00:40 -0700387 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
388 cUnit->regPool->numCoreRegs,
389 &cUnit->regPool->nextCoreReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700390}
391
392extern int oatAllocTemp(CompilationUnit* cUnit)
393{
Bill Buzbeea114add2012-05-03 15:00:40 -0700394 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
395 cUnit->regPool->numCoreRegs,
396 &cUnit->regPool->nextCoreReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700397}
398
399extern int oatAllocTempFloat(CompilationUnit* cUnit)
400{
Bill Buzbeea114add2012-05-03 15:00:40 -0700401 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
402 cUnit->regPool->numFPRegs,
403 &cUnit->regPool->nextFPReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700404}
405
buzbee31a4a6f2012-02-28 15:36:15 -0800406RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700407{
Bill Buzbeea114add2012-05-03 15:00:40 -0700408 int i;
409 if (sReg == -1)
buzbee67bf8852011-08-17 17:51:35 -0700410 return NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 for (i=0; i < numRegs; i++) {
412 if (p[i].live && (p[i].sReg == sReg)) {
413 if (p[i].isTemp)
414 p[i].inUse = true;
415 return &p[i];
416 }
417 }
418 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700419}
420
buzbee31a4a6f2012-02-28 15:36:15 -0800421RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg, int regClass)
buzbee67bf8852011-08-17 17:51:35 -0700422{
Bill Buzbeea114add2012-05-03 15:00:40 -0700423 RegisterInfo* res = NULL;
424 switch (regClass) {
425 case kAnyReg:
426 res = allocLiveBody(cUnit->regPool->FPRegs,
427 cUnit->regPool->numFPRegs, sReg);
428 if (res)
429 break;
430 /* Intentional fallthrough */
431 case kCoreReg:
432 res = allocLiveBody(cUnit->regPool->coreRegs,
433 cUnit->regPool->numCoreRegs, sReg);
434 break;
435 case kFPReg:
436 res = allocLiveBody(cUnit->regPool->FPRegs,
437 cUnit->regPool->numFPRegs, sReg);
438 break;
439 default:
440 LOG(FATAL) << "Invalid register type";
441 }
442 return res;
buzbee67bf8852011-08-17 17:51:35 -0700443}
444
445extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
446{
Bill Buzbeea114add2012-05-03 15:00:40 -0700447 RegisterInfo* p = cUnit->regPool->coreRegs;
448 int numRegs = cUnit->regPool->numCoreRegs;
449 int i;
450 for (i=0; i< numRegs; i++) {
451 if (p[i].reg == reg) {
452 if (p[i].isTemp) {
453 p[i].inUse = false;
454 }
455 p[i].pair = false;
456 return;
buzbee67bf8852011-08-17 17:51:35 -0700457 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700458 }
459 p = cUnit->regPool->FPRegs;
460 numRegs = cUnit->regPool->numFPRegs;
461 for (i=0; i< numRegs; i++) {
462 if (p[i].reg == reg) {
463 if (p[i].isTemp) {
464 p[i].inUse = false;
465 }
466 p[i].pair = false;
467 return;
buzbee67bf8852011-08-17 17:51:35 -0700468 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700469 }
470 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700471}
472
473extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
474{
Bill Buzbeea114add2012-05-03 15:00:40 -0700475 RegisterInfo* p = cUnit->regPool->coreRegs;
476 int numRegs = cUnit->regPool->numCoreRegs;
477 int i;
478 for (i=0; i< numRegs; i++) {
479 if (p[i].reg == reg) {
480 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700481 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 }
483 p = cUnit->regPool->FPRegs;
484 numRegs = cUnit->regPool->numFPRegs;
485 for (i=0; i< numRegs; i++) {
486 if (p[i].reg == reg) {
487 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700488 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 }
490 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700491}
492
493extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
494{
Bill Buzbeea114add2012-05-03 15:00:40 -0700495 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
496 return (p->isTemp) ? p : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700497}
498
buzbeeb29e4d12011-09-26 15:05:48 -0700499extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
500{
Bill Buzbeea114add2012-05-03 15:00:40 -0700501 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
502 return (p->isTemp) ? NULL : p;
buzbeeb29e4d12011-09-26 15:05:48 -0700503}
504
buzbee67bf8852011-08-17 17:51:35 -0700505extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
506{
Bill Buzbeea114add2012-05-03 15:00:40 -0700507 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
508 return p->dirty;
buzbee67bf8852011-08-17 17:51:35 -0700509}
510
511/*
512 * Similar to oatAllocTemp(), but forces the allocation of a specific
513 * register. No check is made to see if the register was previously
514 * allocated. Use with caution.
515 */
516extern void oatLockTemp(CompilationUnit* cUnit, int reg)
517{
Bill Buzbeea114add2012-05-03 15:00:40 -0700518 RegisterInfo* p = cUnit->regPool->coreRegs;
519 int numRegs = cUnit->regPool->numCoreRegs;
520 int i;
521 for (i=0; i< numRegs; i++) {
522 if (p[i].reg == reg) {
523 DCHECK(p[i].isTemp);
524 p[i].inUse = true;
525 p[i].live = false;
526 return;
buzbee67bf8852011-08-17 17:51:35 -0700527 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700528 }
529 p = cUnit->regPool->FPRegs;
530 numRegs = cUnit->regPool->numFPRegs;
531 for (i=0; i< numRegs; i++) {
532 if (p[i].reg == reg) {
533 DCHECK(p[i].isTemp);
534 p[i].inUse = true;
535 p[i].live = false;
536 return;
buzbee67bf8852011-08-17 17:51:35 -0700537 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700538 }
539 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700540}
541
buzbee5abfa3e2012-01-31 17:01:43 -0800542static inline void resetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700543{
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 p->defStart = NULL;
545 p->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700546}
547
buzbee5abfa3e2012-01-31 17:01:43 -0800548extern void oatResetDef(CompilationUnit* cUnit, int reg)
549{
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 resetDefBody(oatGetRegInfo(cUnit, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800551}
552
buzbee31a4a6f2012-02-28 15:36:15 -0800553void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
Bill Buzbeea114add2012-05-03 15:00:40 -0700554 int sReg1, int sReg2)
buzbee67bf8852011-08-17 17:51:35 -0700555{
Bill Buzbeea114add2012-05-03 15:00:40 -0700556 if (start && finish) {
557 LIR *p;
558 DCHECK_EQ(sReg1, sReg2);
559 for (p = start; ;p = p->next) {
560 oatNopLIR(p);
561 if (p == finish)
562 break;
buzbee67bf8852011-08-17 17:51:35 -0700563 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700564 }
buzbee67bf8852011-08-17 17:51:35 -0700565}
566
567/*
568 * Mark the beginning and end LIR of a def sequence. Note that
569 * on entry start points to the LIR prior to the beginning of the
570 * sequence.
571 */
572extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
Bill Buzbeea114add2012-05-03 15:00:40 -0700573 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700574{
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 DCHECK(!rl.wide);
576 DCHECK(start && start->next);
577 DCHECK(finish);
578 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
579 p->defStart = start->next;
580 p->defEnd = finish;
buzbee67bf8852011-08-17 17:51:35 -0700581}
582
583/*
584 * Mark the beginning and end LIR of a def sequence. Note that
585 * on entry start points to the LIR prior to the beginning of the
586 * sequence.
587 */
588extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
Bill Buzbeea114add2012-05-03 15:00:40 -0700589 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700590{
Bill Buzbeea114add2012-05-03 15:00:40 -0700591 DCHECK(rl.wide);
592 DCHECK(start && start->next);
593 DCHECK(finish);
594 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
595 oatResetDef(cUnit, rl.highReg); // Only track low of pair
596 p->defStart = start->next;
597 p->defEnd = finish;
buzbee67bf8852011-08-17 17:51:35 -0700598}
599
buzbee31a4a6f2012-02-28 15:36:15 -0800600extern RegLocation oatWideToNarrow(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700601{
Bill Buzbeea114add2012-05-03 15:00:40 -0700602 DCHECK(rl.wide);
603 if (rl.location == kLocPhysReg) {
604 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
605 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
606 if (infoLo->isTemp) {
607 infoLo->pair = false;
608 infoLo->defStart = NULL;
609 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700610 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700611 if (infoHi->isTemp) {
612 infoHi->pair = false;
613 infoHi->defStart = NULL;
614 infoHi->defEnd = NULL;
615 }
616 }
617 rl.wide = false;
618 return rl;
buzbee67bf8852011-08-17 17:51:35 -0700619}
620
621extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
622{
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 DCHECK(!rl.wide);
624 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
625 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
626 DCHECK(!p->pair);
627 nullifyRange(cUnit, p->defStart, p->defEnd, p->sReg, rl.sRegLow);
628 }
629 oatResetDef(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700630}
631
632extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
633{
Bill Buzbeea114add2012-05-03 15:00:40 -0700634 DCHECK(rl.wide);
635 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
636 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
637 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
638 DCHECK(pLow->pair);
639 nullifyRange(cUnit, pLow->defStart, pLow->defEnd, pLow->sReg, rl.sRegLow);
640 }
641 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
642 DCHECK(pHigh->pair);
643 }
644 oatResetDef(cUnit, rl.lowReg);
645 oatResetDef(cUnit, rl.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700646}
647
648extern void oatResetDefTracking(CompilationUnit* cUnit)
649{
Bill Buzbeea114add2012-05-03 15:00:40 -0700650 int i;
651 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
652 resetDefBody(&cUnit->regPool->coreRegs[i]);
653 }
654 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
655 resetDefBody(&cUnit->regPool->FPRegs[i]);
656 }
buzbee67bf8852011-08-17 17:51:35 -0700657}
658
659extern void oatClobberAllRegs(CompilationUnit* cUnit)
660{
Bill Buzbeea114add2012-05-03 15:00:40 -0700661 int i;
662 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
663 clobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
664 }
665 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
666 clobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
667 }
buzbee67bf8852011-08-17 17:51:35 -0700668}
669
buzbee67bf8852011-08-17 17:51:35 -0700670// Make sure nothing is live and dirty
buzbee31a4a6f2012-02-28 15:36:15 -0800671void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
Bill Buzbeea114add2012-05-03 15:00:40 -0700672 int numRegs)
buzbee67bf8852011-08-17 17:51:35 -0700673{
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 int i;
675 for (i=0; i < numRegs; i++) {
676 if (info[i].live && info[i].dirty) {
677 if (info[i].pair) {
678 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
679 } else {
680 oatFlushReg(cUnit, info[i].reg);
681 }
buzbee67bf8852011-08-17 17:51:35 -0700682 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700683 }
buzbee67bf8852011-08-17 17:51:35 -0700684}
685
686extern void oatFlushAllRegs(CompilationUnit* cUnit)
687{
Bill Buzbeea114add2012-05-03 15:00:40 -0700688 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
689 cUnit->regPool->numCoreRegs);
690 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
691 cUnit->regPool->numFPRegs);
692 oatClobberAllRegs(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700693}
694
695
696//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee31a4a6f2012-02-28 15:36:15 -0800697bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700698{
Bill Buzbeea114add2012-05-03 15:00:40 -0700699 if (regClass == kAnyReg) {
700 return true;
701 } else if (regClass == kCoreReg) {
702 return !oatIsFpReg(reg);
703 } else {
704 return oatIsFpReg(reg);
705 }
buzbee67bf8852011-08-17 17:51:35 -0700706}
707
708extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
709{
Bill Buzbeea114add2012-05-03 15:00:40 -0700710 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
711 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
712 return; /* already live */
713 } else if (sReg != INVALID_SREG) {
714 oatClobberSReg(cUnit, sReg);
715 if (info->isTemp) {
716 info->live = true;
buzbee67bf8852011-08-17 17:51:35 -0700717 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700718 } else {
719 /* Can't be live if no associated sReg */
720 DCHECK(info->isTemp);
721 info->live = false;
722 }
723 info->sReg = sReg;
buzbee67bf8852011-08-17 17:51:35 -0700724}
725
726extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
727{
Bill Buzbeea114add2012-05-03 15:00:40 -0700728 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
729 info->isTemp = true;
buzbee67bf8852011-08-17 17:51:35 -0700730}
731
buzbee9e0f9b02011-08-24 15:32:46 -0700732extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
733{
Bill Buzbeea114add2012-05-03 15:00:40 -0700734 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
735 info->isTemp = false;
buzbee9e0f9b02011-08-24 15:32:46 -0700736}
737
buzbee67bf8852011-08-17 17:51:35 -0700738extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
739{
Bill Buzbeea114add2012-05-03 15:00:40 -0700740 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
741 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
742 infoLo->pair = infoHi->pair = true;
743 infoLo->partner = highReg;
744 infoHi->partner = lowReg;
buzbee67bf8852011-08-17 17:51:35 -0700745}
746
747extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
748{
Bill Buzbeea114add2012-05-03 15:00:40 -0700749 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
750 info->dirty = false;
751 if (loc.wide) {
752 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700753 info->dirty = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700754 }
buzbee67bf8852011-08-17 17:51:35 -0700755}
756
757extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
758{
Bill Buzbeea114add2012-05-03 15:00:40 -0700759 if (loc.home) {
760 // If already home, can't be dirty
761 return;
762 }
763 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
764 info->dirty = true;
765 if (loc.wide) {
766 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700767 info->dirty = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700768 }
buzbee67bf8852011-08-17 17:51:35 -0700769}
770
771extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
772{
Bill Buzbeea114add2012-05-03 15:00:40 -0700773 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
774 info->inUse = true;
buzbee67bf8852011-08-17 17:51:35 -0700775}
776
buzbee31a4a6f2012-02-28 15:36:15 -0800777void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700778{
Bill Buzbeea114add2012-05-03 15:00:40 -0700779 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
780 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
781 // Target temp status must not change
782 bool isTemp = newInfo->isTemp;
783 *newInfo = *oldInfo;
784 // Restore target's temp status
785 newInfo->isTemp = isTemp;
786 newInfo->reg = newReg;
buzbee67bf8852011-08-17 17:51:35 -0700787}
788
789/*
790 * Return an updated location record with current in-register status.
791 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700792 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700793 * clobber both low and high.
794 * TUNING: clobbering both is a bit heavy-handed, but the alternative
795 * is a bit complex when dealing with FP regs. Examine code to see
796 * if it's worthwhile trying to be more clever here.
797 */
798
799extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
800{
Bill Buzbeea114add2012-05-03 15:00:40 -0700801 DCHECK(!loc.wide);
802 DCHECK(oatCheckCorePoolSanity(cUnit));
803 if (loc.location != kLocPhysReg) {
804 DCHECK((loc.location == kLocDalvikFrame) ||
805 (loc.location == kLocCompilerTemp));
806 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
807 if (infoLo) {
808 if (infoLo->pair) {
809 oatClobber(cUnit, infoLo->reg);
810 oatClobber(cUnit, infoLo->partner);
811 oatFreeTemp(cUnit, infoLo->reg);
812 } else {
813 loc.lowReg = infoLo->reg;
814 loc.location = kLocPhysReg;
815 }
buzbee67bf8852011-08-17 17:51:35 -0700816 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700817 }
buzbee67bf8852011-08-17 17:51:35 -0700818
Bill Buzbeea114add2012-05-03 15:00:40 -0700819 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700820}
821
buzbee6181f792011-09-29 11:14:04 -0700822bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
823{
824 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700825 if (cUnit->regPool->coreRegs[i].pair) {
826 static int myReg = cUnit->regPool->coreRegs[i].reg;
827 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
828 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
829 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
830 DCHECK(partner != NULL);
831 DCHECK(partner->pair);
832 DCHECK_EQ(myReg, partner->partner);
833 static int partnerSreg = partner->sReg;
834 if (mySreg == INVALID_SREG) {
835 DCHECK_EQ(partnerSreg, INVALID_SREG);
836 } else {
837 int diff = mySreg - partnerSreg;
838 DCHECK((diff == -1) || (diff == 1));
buzbee6181f792011-09-29 11:14:04 -0700839 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700840 }
841 if (!cUnit->regPool->coreRegs[i].live) {
842 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
843 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
844 }
buzbee6181f792011-09-29 11:14:04 -0700845 }
846 return true;
847}
848
buzbee67bf8852011-08-17 17:51:35 -0700849/* see comments for updateLoc */
buzbee31a4a6f2012-02-28 15:36:15 -0800850extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700851{
Bill Buzbeea114add2012-05-03 15:00:40 -0700852 DCHECK(loc.wide);
853 DCHECK(oatCheckCorePoolSanity(cUnit));
854 if (loc.location != kLocPhysReg) {
855 DCHECK((loc.location == kLocDalvikFrame) ||
856 (loc.location == kLocCompilerTemp));
857 // Are the dalvik regs already live in physical registers?
858 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
859 RegisterInfo* infoHi = allocLive(cUnit,
860 oatSRegHi(loc.sRegLow), kAnyReg);
861 bool match = true;
862 match = match && (infoLo != NULL);
863 match = match && (infoHi != NULL);
864 // Are they both core or both FP?
865 match = match && (oatIsFpReg(infoLo->reg) == oatIsFpReg(infoHi->reg));
866 // If a pair of floating point singles, are they properly aligned?
867 if (match && oatIsFpReg(infoLo->reg)) {
868 match &= ((infoLo->reg & 0x1) == 0);
869 match &= ((infoHi->reg - infoLo->reg) == 1);
buzbee67bf8852011-08-17 17:51:35 -0700870 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 // If previously used as a pair, it is the same pair?
872 if (match && (infoLo->pair || infoHi->pair)) {
873 match = (infoLo->pair == infoHi->pair);
874 match &= ((infoLo->reg == infoHi->partner) &&
875 (infoHi->reg == infoLo->partner));
876 }
877 if (match) {
878 // Can reuse - update the register usage info
879 loc.lowReg = infoLo->reg;
880 loc.highReg = infoHi->reg;
881 loc.location = kLocPhysReg;
882 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
883 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
884 return loc;
885 }
886 // Can't easily reuse - clobber and free any overlaps
887 if (infoLo) {
888 oatClobber(cUnit, infoLo->reg);
889 oatFreeTemp(cUnit, infoLo->reg);
890 if (infoLo->pair)
891 oatClobber(cUnit, infoLo->partner);
892 }
893 if (infoHi) {
894 oatClobber(cUnit, infoHi->reg);
895 oatFreeTemp(cUnit, infoHi->reg);
896 if (infoHi->pair)
897 oatClobber(cUnit, infoHi->partner);
898 }
899 }
900 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700901}
902
buzbeeed3e9302011-09-23 17:34:19 -0700903
904/* For use in cases we don't know (or care) width */
buzbee31a4a6f2012-02-28 15:36:15 -0800905extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700906{
Bill Buzbeea114add2012-05-03 15:00:40 -0700907 if (loc.wide)
908 return oatUpdateLocWide(cUnit, loc);
909 else
910 return oatUpdateLoc(cUnit, loc);
buzbeeed3e9302011-09-23 17:34:19 -0700911}
912
buzbee31a4a6f2012-02-28 15:36:15 -0800913RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700914 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700915{
Bill Buzbeea114add2012-05-03 15:00:40 -0700916 DCHECK(loc.wide);
917 int newRegs;
918 int lowReg;
919 int highReg;
buzbee67bf8852011-08-17 17:51:35 -0700920
Bill Buzbeea114add2012-05-03 15:00:40 -0700921 loc = oatUpdateLocWide(cUnit, loc);
buzbee67bf8852011-08-17 17:51:35 -0700922
Bill Buzbeea114add2012-05-03 15:00:40 -0700923 /* If already in registers, we can assume proper form. Right reg class? */
924 if (loc.location == kLocPhysReg) {
925 DCHECK_EQ(oatIsFpReg(loc.lowReg), oatIsFpReg(loc.highReg));
buzbeee3acd072012-02-25 17:03:10 -0800926 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700927 if (!regClassMatches(regClass, loc.lowReg)) {
928 /* Wrong register class. Reallocate and copy */
929 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
930 lowReg = newRegs & 0xff;
931 highReg = (newRegs >> 8) & 0xff;
932 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
933 loc.highReg);
934 copyRegInfo(cUnit, lowReg, loc.lowReg);
935 copyRegInfo(cUnit, highReg, loc.highReg);
936 oatClobber(cUnit, loc.lowReg);
937 oatClobber(cUnit, loc.highReg);
938 loc.lowReg = lowReg;
939 loc.highReg = highReg;
940 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
941 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
942 }
buzbee67bf8852011-08-17 17:51:35 -0700943 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700944 }
945
946 DCHECK_NE(loc.sRegLow, INVALID_SREG);
947 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
948
949 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
950 loc.lowReg = newRegs & 0xff;
951 loc.highReg = (newRegs >> 8) & 0xff;
952
953 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
954 if (update) {
955 loc.location = kLocPhysReg;
956 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
957 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
958 }
959 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
960 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700961}
962
963extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700964 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700965{
Bill Buzbeea114add2012-05-03 15:00:40 -0700966 int newReg;
buzbee67bf8852011-08-17 17:51:35 -0700967
Bill Buzbeea114add2012-05-03 15:00:40 -0700968 if (loc.wide)
969 return evalLocWide(cUnit, loc, regClass, update);
buzbee67bf8852011-08-17 17:51:35 -0700970
Bill Buzbeea114add2012-05-03 15:00:40 -0700971 loc = oatUpdateLoc(cUnit, loc);
buzbee67bf8852011-08-17 17:51:35 -0700972
Bill Buzbeea114add2012-05-03 15:00:40 -0700973 if (loc.location == kLocPhysReg) {
974 if (!regClassMatches(regClass, loc.lowReg)) {
975 /* Wrong register class. Realloc, copy and transfer ownership */
976 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
977 oatRegCopy(cUnit, newReg, loc.lowReg);
978 copyRegInfo(cUnit, newReg, loc.lowReg);
979 oatClobber(cUnit, loc.lowReg);
980 loc.lowReg = newReg;
buzbee67bf8852011-08-17 17:51:35 -0700981 }
982 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700983 }
984
985 DCHECK_NE(loc.sRegLow, INVALID_SREG);
986
987 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
988 loc.lowReg = newReg;
989
990 if (update) {
991 loc.location = kLocPhysReg;
992 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
993 }
994 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700995}
996
buzbee15bf9802012-06-12 17:49:27 -0700997extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
buzbee67bf8852011-08-17 17:51:35 -0700998{
buzbee15bf9802012-06-12 17:49:27 -0700999 DCHECK(num < mir->ssaRep->numUses);
1000 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1001 DCHECK(!res.wide || num < (mir->ssaRep->numUses - 1));
1002 return res;
1003}
1004extern RegLocation oatGetRawDest(CompilationUnit* cUnit, MIR* mir)
1005{
Elliott Hughes74847412012-06-20 18:10:21 -07001006 DCHECK_GT(mir->ssaRep->numDefs, 0);
buzbee15bf9802012-06-12 17:49:27 -07001007 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[0]];
1008 DCHECK(!res.wide || mir->ssaRep->numDefs == 2);
1009 return res;
1010}
1011extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir)
1012{
1013 RegLocation res = oatGetRawDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001014 DCHECK(!res.wide);
1015 return res;
buzbee67bf8852011-08-17 17:51:35 -07001016}
1017extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1018{
buzbee15bf9802012-06-12 17:49:27 -07001019 RegLocation res = oatGetRawSrc(cUnit, mir, num);
Bill Buzbeea114add2012-05-03 15:00:40 -07001020 DCHECK(!res.wide);
1021 return res;
buzbeee9a72f62011-09-04 17:59:07 -07001022}
buzbee15bf9802012-06-12 17:49:27 -07001023extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir)
buzbeee9a72f62011-09-04 17:59:07 -07001024{
buzbee15bf9802012-06-12 17:49:27 -07001025 RegLocation res = oatGetRawDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001026 DCHECK(res.wide);
1027 return res;
buzbee67bf8852011-08-17 17:51:35 -07001028}
1029
1030extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
buzbee15bf9802012-06-12 17:49:27 -07001031 int low)
buzbee67bf8852011-08-17 17:51:35 -07001032{
buzbee15bf9802012-06-12 17:49:27 -07001033 RegLocation res = oatGetRawSrc(cUnit, mir, low);
Bill Buzbeea114add2012-05-03 15:00:40 -07001034 DCHECK(res.wide);
1035 return res;
buzbee67bf8852011-08-17 17:51:35 -07001036}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001037
buzbeee3acd072012-02-25 17:03:10 -08001038/* USE SSA names to count references of base Dalvik vRegs. */
1039void oatCountRefs(CompilationUnit *cUnit, BasicBlock* bb,
Bill Buzbeea114add2012-05-03 15:00:40 -07001040 RefCounts* coreCounts, RefCounts* fpCounts)
buzbeee3acd072012-02-25 17:03:10 -08001041{
Bill Buzbeea114add2012-05-03 15:00:40 -07001042 if ((cUnit->disableOpt & (1 << kPromoteRegs)) ||
1043 !((bb->blockType == kEntryBlock) || (bb->blockType == kExitBlock) ||
1044 (bb->blockType == kDalvikByteCode))) {
1045 return;
1046 }
1047 for (int i = 0; i < cUnit->numSSARegs;) {
1048 RegLocation loc = cUnit->regLocation[i];
1049 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
1050 int pMapIdx = SRegToPMap(cUnit, loc.sRegLow);
1051 if (loc.defined) {
1052 counts[pMapIdx].count += cUnit->useCounts.elemList[i];
buzbee239c4e72012-03-16 08:42:29 -07001053 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001054 if (loc.wide) {
1055 if (loc.defined) {
1056 if (loc.fp) {
1057 counts[pMapIdx].doubleStart = true;
1058 counts[pMapIdx+1].count += cUnit->useCounts.elemList[i+1];
buzbee239c4e72012-03-16 08:42:29 -07001059 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001060 }
1061 i += 2;
1062 } else {
1063 i++;
buzbeee3acd072012-02-25 17:03:10 -08001064 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001065 }
buzbeee3acd072012-02-25 17:03:10 -08001066}
1067
1068/* qsort callback function, sort descending */
1069int oatSortCounts(const void *val1, const void *val2)
1070{
Bill Buzbeea114add2012-05-03 15:00:40 -07001071 const RefCounts* op1 = (const RefCounts*)val1;
1072 const RefCounts* op2 = (const RefCounts*)val2;
1073 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
buzbeee3acd072012-02-25 17:03:10 -08001074}
1075
1076void oatDumpCounts(const RefCounts* arr, int size, const char* msg)
1077{
Bill Buzbeea114add2012-05-03 15:00:40 -07001078 LOG(INFO) << msg;
1079 for (int i = 0; i < size; i++) {
1080 LOG(INFO) << "sReg[" << arr[i].sReg << "]: " << arr[i].count;
1081 }
buzbeee3acd072012-02-25 17:03:10 -08001082}
1083
1084/*
1085 * Note: some portions of this code required even if the kPromoteRegs
1086 * optimization is disabled.
1087 */
1088extern void oatDoPromotion(CompilationUnit* cUnit)
1089{
Bill Buzbeea114add2012-05-03 15:00:40 -07001090 int regBias = cUnit->numCompilerTemps + 1;
1091 int dalvikRegs = cUnit->numDalvikRegisters;
1092 int numRegs = dalvikRegs + regBias;
1093 const int promotionThreshold = 2;
buzbeee3acd072012-02-25 17:03:10 -08001094
Bill Buzbeea114add2012-05-03 15:00:40 -07001095 // Allow target code to add any special registers
1096 oatAdjustSpillMask(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001097
Bill Buzbeea114add2012-05-03 15:00:40 -07001098 /*
1099 * Simple register promotion. Just do a static count of the uses
1100 * of Dalvik registers. Note that we examine the SSA names, but
1101 * count based on original Dalvik register name. Count refs
1102 * separately based on type in order to give allocation
1103 * preference to fp doubles - which must be allocated sequential
1104 * physical single fp registers started with an even-numbered
1105 * reg.
1106 * TUNING: replace with linear scan once we have the ability
1107 * to describe register live ranges for GC.
1108 */
1109 RefCounts *coreRegs = (RefCounts *)
1110 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1111 RefCounts *fpRegs = (RefCounts *)
1112 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1113 // Set ssa names for original Dalvik registers
1114 for (int i = 0; i < dalvikRegs; i++) {
1115 coreRegs[i].sReg = fpRegs[i].sReg = i;
1116 }
1117 // Set ssa name for Method*
1118 coreRegs[dalvikRegs].sReg = cUnit->methodSReg;
1119 fpRegs[dalvikRegs].sReg = cUnit->methodSReg; // For consistecy
1120 // Set ssa names for compilerTemps
1121 for (int i = 1; i <= cUnit->numCompilerTemps; i++) {
1122 CompilerTemp* ct = (CompilerTemp*)cUnit->compilerTemps.elemList[i];
1123 coreRegs[dalvikRegs + i].sReg = ct->sReg;
1124 fpRegs[dalvikRegs + i].sReg = ct->sReg;
1125 }
1126
1127 GrowableListIterator iterator;
1128 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
1129 while (true) {
1130 BasicBlock* bb;
1131 bb = (BasicBlock*)oatGrowableListIteratorNext(&iterator);
1132 if (bb == NULL) break;
1133 oatCountRefs(cUnit, bb, coreRegs, fpRegs);
1134 }
1135
1136 /*
1137 * Ideally, we'd allocate doubles starting with an even-numbered
1138 * register. Bias the counts to try to allocate any vreg that's
1139 * used as the start of a pair first.
1140 */
1141 for (int i = 0; i < numRegs; i++) {
1142 if (fpRegs[i].doubleStart) {
1143 fpRegs[i].count *= 2;
buzbeee3acd072012-02-25 17:03:10 -08001144 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001145 }
1146
1147 // Sort the count arrays
1148 qsort(coreRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1149 qsort(fpRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1150
1151 if (cUnit->printMe) {
1152 oatDumpCounts(coreRegs, numRegs, "Core regs after sort");
1153 oatDumpCounts(fpRegs, numRegs, "Fp regs after sort");
1154 }
1155
1156 if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
1157 // Promote fpRegs
1158 for (int i = 0; (i < numRegs) &&
1159 (fpRegs[i].count >= promotionThreshold ); i++) {
1160 int pMapIdx = SRegToPMap(cUnit, fpRegs[i].sReg);
1161 if (cUnit->promotionMap[pMapIdx].fpLocation != kLocPhysReg) {
1162 int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
1163 fpRegs[i].doubleStart);
1164 if (reg < 0) {
1165 break; // No more left
1166 }
1167 }
buzbee239c4e72012-03-16 08:42:29 -07001168 }
buzbee9c044ce2012-03-18 13:24:07 -07001169
Bill Buzbeea114add2012-05-03 15:00:40 -07001170 // Promote core regs
1171 for (int i = 0; (i < numRegs) &&
1172 (coreRegs[i].count > promotionThreshold); i++) {
1173 int pMapIdx = SRegToPMap(cUnit, coreRegs[i].sReg);
1174 if (cUnit->promotionMap[pMapIdx].coreLocation !=
1175 kLocPhysReg) {
1176 int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
1177 if (reg < 0) {
1178 break; // No more left
1179 }
1180 }
buzbeee3acd072012-02-25 17:03:10 -08001181 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001182 } else if (cUnit->qdMode) {
1183 oatAllocPreservedCoreReg(cUnit, cUnit->methodSReg);
buzbeee3acd072012-02-25 17:03:10 -08001184 for (int i = 0; i < numRegs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001185 int reg = oatAllocPreservedCoreReg(cUnit, i);
1186 if (reg < 0) {
1187 break; // No more left
1188 }
buzbeee3acd072012-02-25 17:03:10 -08001189 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001190 }
buzbeee3acd072012-02-25 17:03:10 -08001191
buzbeee3acd072012-02-25 17:03:10 -08001192
Bill Buzbeea114add2012-05-03 15:00:40 -07001193 // Now, update SSA names to new home locations
1194 for (int i = 0; i < cUnit->numSSARegs; i++) {
1195 RegLocation *curr = &cUnit->regLocation[i];
1196 int pMapIdx = SRegToPMap(cUnit, curr->sRegLow);
1197 if (!curr->wide) {
1198 if (curr->fp) {
1199 if (cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) {
1200 curr->location = kLocPhysReg;
1201 curr->lowReg = cUnit->promotionMap[pMapIdx].fpReg;
1202 curr->home = true;
1203 }
1204 } else {
1205 if (cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg) {
1206 curr->location = kLocPhysReg;
1207 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1208 curr->home = true;
1209 }
1210 }
1211 curr->highReg = INVALID_REG;
1212 } else {
1213 if (curr->highWord) {
1214 continue;
1215 }
1216 if (curr->fp) {
1217 if ((cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) &&
1218 (cUnit->promotionMap[pMapIdx+1].fpLocation ==
1219 kLocPhysReg)) {
1220 int lowReg = cUnit->promotionMap[pMapIdx].fpReg;
1221 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
1222 // Doubles require pair of singles starting at even reg
1223 if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
1224 curr->location = kLocPhysReg;
1225 curr->lowReg = lowReg;
1226 curr->highReg = highReg;
1227 curr->home = true;
1228 }
1229 }
1230 } else {
1231 if ((cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg)
1232 && (cUnit->promotionMap[pMapIdx+1].coreLocation ==
1233 kLocPhysReg)) {
1234 curr->location = kLocPhysReg;
1235 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1236 curr->highReg = cUnit->promotionMap[pMapIdx+1].coreReg;
1237 curr->home = true;
1238 }
1239 }
buzbeee3acd072012-02-25 17:03:10 -08001240 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001241 }
buzbeee3acd072012-02-25 17:03:10 -08001242}
1243
1244/* Returns sp-relative offset in bytes for a VReg */
1245extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
1246{
Ian Rogers0399dde2012-06-06 17:09:28 -07001247 return StackVisitor::GetVRegOffset(cUnit->code_item, cUnit->coreSpillMask,
1248 cUnit->fpSpillMask, cUnit->frameSize, vReg);
buzbeee3acd072012-02-25 17:03:10 -08001249}
1250
1251/* Returns sp-relative offset in bytes for a SReg */
1252extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
1253{
Bill Buzbeea114add2012-05-03 15:00:40 -07001254 return oatVRegOffset(cUnit, SRegToVReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -08001255}
1256
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001257} // namespace art