blob: 6a98d60bca2e0d1b0cd12b6e01733fa2ccd089c7 [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#define SREG(c, s) ((c)->regLocation[(s)].sRegLow)
33/*
34 * Get the "real" sreg number associated with an sReg slot. In general,
35 * sReg values passed through codegen are the SSA names created by
36 * dataflow analysis and refer to slot numbers in the cUnit->regLocation
37 * array. However, renaming is accomplished by simply replacing RegLocation
38 * entries in the cUnit->reglocation[] array. Therefore, when location
39 * records for operands are first created, we need to ask the locRecord
40 * identified by the dataflow pass what it's new name is.
41 */
42
43/*
44 * Free all allocated temps in the temp pools. Note that this does
45 * not affect the "liveness" of a temp register, which will stay
46 * live until it is either explicitly killed or reallocated.
47 */
48extern void oatResetRegPool(CompilationUnit* cUnit)
49{
50 int i;
51 for (i=0; i < cUnit->regPool->numCoreRegs; i++) {
52 if (cUnit->regPool->coreRegs[i].isTemp)
53 cUnit->regPool->coreRegs[i].inUse = false;
54 }
55 for (i=0; i < cUnit->regPool->numFPRegs; i++) {
56 if (cUnit->regPool->FPRegs[i].isTemp)
57 cUnit->regPool->FPRegs[i].inUse = false;
58 }
59}
60
buzbeee3acd072012-02-25 17:03:10 -080061 /*
62 * Set up temp & preserved register pools specialized by target.
63 * Note: numRegs may be zero.
64 */
buzbee67bf8852011-08-17 17:51:35 -070065extern void oatInitPool(RegisterInfo* regs, int* regNums, int num)
66{
67 int i;
68 for (i=0; i < num; i++) {
69 regs[i].reg = regNums[i];
70 regs[i].inUse = false;
71 regs[i].isTemp = false;
72 regs[i].pair = false;
73 regs[i].live = false;
74 regs[i].dirty = false;
75 regs[i].sReg = INVALID_SREG;
76 }
77}
78
buzbee31a4a6f2012-02-28 15:36:15 -080079void dumpRegPool(RegisterInfo* p, int numRegs)
buzbee67bf8852011-08-17 17:51:35 -070080{
buzbee67bf8852011-08-17 17:51:35 -070081 LOG(INFO) << "================================================";
Elliott Hughesb25c3f62012-03-26 16:35:06 -070082 for (int i = 0; i < numRegs; i++) {
Elliott Hughesbdf6c3d2012-03-20 13:43:53 -070083 LOG(INFO) << StringPrintf(
buzbee67bf8852011-08-17 17:51:35 -070084 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
85 p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
86 p[i].live, p[i].dirty, p[i].sReg,(int)p[i].defStart,
87 (int)p[i].defEnd);
buzbee67bf8852011-08-17 17:51:35 -070088 }
89 LOG(INFO) << "================================================";
90}
91
buzbee6181f792011-09-29 11:14:04 -070092void oatDumpCoreRegPool(CompilationUnit* cUnit)
93{
94 dumpRegPool(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs);
95}
96
97void oatDumpFpRegPool(CompilationUnit* cUnit)
98{
99 dumpRegPool(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs);
100}
101
buzbee67bf8852011-08-17 17:51:35 -0700102/* Mark a temp register as dead. Does not affect allocation state. */
buzbee5abfa3e2012-01-31 17:01:43 -0800103static inline void clobberBody(CompilationUnit *cUnit, RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700104{
buzbee68253262011-10-07 14:02:25 -0700105 if (p->isTemp) {
106 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
107 p->live = false;
108 p->sReg = INVALID_SREG;
109 p->defStart = NULL;
110 p->defEnd = NULL;
111 if (p->pair) {
112 p->pair = false;
113 oatClobber(cUnit, p->partner);
114 }
buzbee67bf8852011-08-17 17:51:35 -0700115 }
116}
117
buzbee5abfa3e2012-01-31 17:01:43 -0800118/* Mark a temp register as dead. Does not affect allocation state. */
119void oatClobber(CompilationUnit* cUnit, int reg)
120{
121 clobberBody(cUnit, oatGetRegInfo(cUnit, reg));
122}
123
buzbee31a4a6f2012-02-28 15:36:15 -0800124void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700125{
126 int i;
127 for (i=0; i< numRegs; i++) {
128 if (p[i].sReg == sReg) {
129 if (p[i].isTemp) {
130 p[i].live = false;
131 }
132 p[i].defStart = NULL;
133 p[i].defEnd = NULL;
134 }
135 }
136}
137
138/* Clobber any temp associated with an sReg. Could be in either class */
139extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
140{
buzbee3d661942012-03-14 17:37:27 -0700141#ifndef NDEBUG
142 /* Reset live temp tracking sanity checker */
143 if (sReg == cUnit->liveSReg) {
144 cUnit->liveSReg = INVALID_SREG;
145 }
146#endif
buzbee67bf8852011-08-17 17:51:35 -0700147 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs,
148 sReg);
149 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs,
150 sReg);
151}
152
buzbee9c044ce2012-03-18 13:24:07 -0700153/*
154 * SSA names associated with the initial definitions of Dalvik
155 * registers are the same as the Dalvik register number (and
156 * thus take the same position in the promotionMap. However,
157 * the special Method* and compiler temp resisters use negative
Elliott Hughesbdf6c3d2012-03-20 13:43:53 -0700158 * vReg numbers to distinguish them and can have an arbitrary
buzbee9c044ce2012-03-18 13:24:07 -0700159 * ssa name (above the last original Dalvik register). This function
160 * maps SSA names to positions in the promotionMap array.
161 */
162int SRegToPMap(CompilationUnit* cUnit, int sReg)
buzbeee1965672012-03-11 18:39:19 -0700163{
buzbee9c044ce2012-03-18 13:24:07 -0700164 DCHECK_LT(sReg, cUnit->numSSARegs);
165 DCHECK_GE(sReg, 0);
166 int vReg = SRegToVReg(cUnit, sReg);
167 if (vReg >= 0) {
168 DCHECK_LT(vReg, cUnit->numDalvikRegisters);
169 return vReg;
170 } else {
171 int pos = std::abs(vReg) - std::abs(SSA_METHOD_BASEREG);
172 DCHECK_LE(pos, cUnit->numCompilerTemps);
173 return cUnit->numDalvikRegisters + pos;
buzbeee1965672012-03-11 18:39:19 -0700174 }
buzbeee1965672012-03-11 18:39:19 -0700175}
176
buzbee67bf8852011-08-17 17:51:35 -0700177/* Reserve a callee-save register. Return -1 if none available */
178extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
179{
180 int res = -1;
181 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
182 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
183 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
buzbee9c044ce2012-03-18 13:24:07 -0700184 int vReg = SRegToVReg(cUnit, sReg);
185 int pMapIdx = SRegToPMap(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700186 res = coreRegs[i].reg;
187 coreRegs[i].inUse = true;
188 cUnit->coreSpillMask |= (1 << res);
buzbee9c044ce2012-03-18 13:24:07 -0700189 cUnit->coreVmapTable.push_back(vReg);
buzbeebbaf8942011-10-02 13:08:29 -0700190 cUnit->numCoreSpills++;
buzbee9c044ce2012-03-18 13:24:07 -0700191 cUnit->promotionMap[pMapIdx].coreLocation = kLocPhysReg;
192 cUnit->promotionMap[pMapIdx].coreReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700193 break;
194 }
195 }
196 return res;
197}
198
199/*
200 * Reserve a callee-save fp single register. Try to fullfill request for
201 * even/odd allocation, but go ahead and allocate anything if not
202 * available. If nothing's available, return -1.
203 */
buzbee31a4a6f2012-02-28 15:36:15 -0800204int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700205{
206 int res = -1;
207 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
208 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
209 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
210 ((FPRegs[i].reg & 0x1) == 0) == even) {
buzbee9c044ce2012-03-18 13:24:07 -0700211 int vReg = SRegToVReg(cUnit, sReg);
212 int pMapIdx = SRegToPMap(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700213 res = FPRegs[i].reg;
214 FPRegs[i].inUse = true;
buzbee9c044ce2012-03-18 13:24:07 -0700215 oatMarkPreservedSingle(cUnit, vReg, res);
216 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
217 cUnit->promotionMap[pMapIdx].fpReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700218 break;
219 }
220 }
221 return res;
222}
223
224/*
225 * Somewhat messy code here. We want to allocate a pair of contiguous
226 * physical single-precision floating point registers starting with
227 * an even numbered reg. It is possible that the paired sReg (sReg+1)
228 * has already been allocated - try to fit if possible. Fail to
229 * allocate if we can't meet the requirements for the pair of
230 * sReg<=sX[even] & (sReg+1)<= sX+1.
231 */
buzbee31a4a6f2012-02-28 15:36:15 -0800232int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700233{
234 int res = -1; // Assume failure
buzbee9c044ce2012-03-18 13:24:07 -0700235 int vReg = SRegToVReg(cUnit, sReg);
236 int pMapIdx = SRegToPMap(cUnit, sReg);
237 if (cUnit->promotionMap[pMapIdx+1].fpLocation == kLocPhysReg) {
buzbee67bf8852011-08-17 17:51:35 -0700238 // Upper reg is already allocated. Can we fit?
buzbee9c044ce2012-03-18 13:24:07 -0700239 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
buzbee67bf8852011-08-17 17:51:35 -0700240 if ((highReg & 1) == 0) {
241 // High reg is even - fail.
242 return res;
243 }
244 // Is the low reg of the pair free?
buzbee68253262011-10-07 14:02:25 -0700245 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
buzbee67bf8852011-08-17 17:51:35 -0700246 if (p->inUse || p->isTemp) {
247 // Already allocated or not preserved - fail.
248 return res;
249 }
250 // OK - good to go.
251 res = p->reg;
252 p->inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700253 DCHECK_EQ((res & 1), 0);
buzbee9c044ce2012-03-18 13:24:07 -0700254 oatMarkPreservedSingle(cUnit, vReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700255 } else {
256 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
257 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
258 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
259 ((FPRegs[i].reg & 0x1) == 0x0) &&
260 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
261 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
262 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
263 res = FPRegs[i].reg;
264 FPRegs[i].inUse = true;
buzbee9c044ce2012-03-18 13:24:07 -0700265 oatMarkPreservedSingle(cUnit, vReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700266 FPRegs[i+1].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700267 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
buzbee9c044ce2012-03-18 13:24:07 -0700268 oatMarkPreservedSingle(cUnit, vReg+1, res+1);
buzbee67bf8852011-08-17 17:51:35 -0700269 break;
270 }
271 }
272 }
273 if (res != -1) {
buzbee9c044ce2012-03-18 13:24:07 -0700274 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
275 cUnit->promotionMap[pMapIdx].fpReg = res;
276 cUnit->promotionMap[pMapIdx+1].fpLocation = kLocPhysReg;
277 cUnit->promotionMap[pMapIdx+1].fpReg = res + 1;
buzbee67bf8852011-08-17 17:51:35 -0700278 }
279 return res;
280}
281
282
283/*
284 * Reserve a callee-save fp register. If this register can be used
285 * as the first of a double, attempt to allocate an even pair of fp
286 * single regs (but if can't still attempt to allocate a single, preferring
287 * first to allocate an odd register.
288 */
289extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
290 bool doubleStart)
291{
292 int res = -1;
293 if (doubleStart) {
294 res = allocPreservedDouble(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700295 }
296 if (res == -1) {
297 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
298 }
299 if (res == -1)
300 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
301 return res;
302}
303
buzbee31a4a6f2012-02-28 15:36:15 -0800304int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
305 int* nextTemp, bool required)
buzbee67bf8852011-08-17 17:51:35 -0700306{
307 int i;
308 int next = *nextTemp;
309 for (i=0; i< numRegs; i++) {
310 if (next >= numRegs)
311 next = 0;
312 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
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;
318 }
319 next++;
320 }
321 next = *nextTemp;
322 for (i=0; i< numRegs; i++) {
323 if (next >= numRegs)
324 next = 0;
325 if (p[next].isTemp && !p[next].inUse) {
326 oatClobber(cUnit, p[next].reg);
327 p[next].inUse = true;
328 p[next].pair = false;
329 *nextTemp = next + 1;
330 return p[next].reg;
331 }
332 next++;
333 }
334 if (required) {
buzbee6181f792011-09-29 11:14:04 -0700335 oatCodegenDump(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700336 dumpRegPool(cUnit->regPool->coreRegs,
337 cUnit->regPool->numCoreRegs);
338 LOG(FATAL) << "No free temp registers";
339 }
340 return -1; // No register available
341}
342
343//REDO: too many assumptions.
344extern int oatAllocTempDouble(CompilationUnit* cUnit)
345{
346 RegisterInfo* p = cUnit->regPool->FPRegs;
347 int numRegs = cUnit->regPool->numFPRegs;
buzbeea50638b2011-11-02 15:15:06 -0700348 /* Start looking at an even reg */
349 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700350
buzbeea50638b2011-11-02 15:15:06 -0700351 // First try to avoid allocating live registers
352 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700353 if (next >= numRegs)
354 next = 0;
355 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
356 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
357 oatClobber(cUnit, p[next].reg);
358 oatClobber(cUnit, p[next+1].reg);
359 p[next].inUse = true;
360 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700361 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
362 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700363 cUnit->regPool->nextFPReg = next + 2;
364 if (cUnit->regPool->nextFPReg >= numRegs) {
365 cUnit->regPool->nextFPReg = 0;
366 }
buzbee67bf8852011-08-17 17:51:35 -0700367 return p[next].reg;
368 }
369 next += 2;
370 }
buzbeea50638b2011-11-02 15:15:06 -0700371 next = cUnit->regPool->nextFPReg & ~0x1;
372
373 // No choice - find a pair and kill it.
374 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700375 if (next >= numRegs)
376 next = 0;
377 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
378 !p[next+1].inUse) {
379 oatClobber(cUnit, p[next].reg);
380 oatClobber(cUnit, p[next+1].reg);
381 p[next].inUse = true;
382 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700383 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
384 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700385 cUnit->regPool->nextFPReg = next + 2;
386 if (cUnit->regPool->nextFPReg >= numRegs) {
387 cUnit->regPool->nextFPReg = 0;
388 }
buzbee67bf8852011-08-17 17:51:35 -0700389 return p[next].reg;
390 }
391 next += 2;
392 }
buzbee6181f792011-09-29 11:14:04 -0700393 LOG(FATAL) << "No free temp registers (pair)";
buzbee67bf8852011-08-17 17:51:35 -0700394 return -1;
395}
396
397/* Return a temp if one is available, -1 otherwise */
398extern int oatAllocFreeTemp(CompilationUnit* cUnit)
399{
400 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
401 cUnit->regPool->numCoreRegs,
402 &cUnit->regPool->nextCoreReg, true);
403}
404
405extern int oatAllocTemp(CompilationUnit* cUnit)
406{
407 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
408 cUnit->regPool->numCoreRegs,
409 &cUnit->regPool->nextCoreReg, true);
410}
411
412extern int oatAllocTempFloat(CompilationUnit* cUnit)
413{
414 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
415 cUnit->regPool->numFPRegs,
416 &cUnit->regPool->nextFPReg, true);
417}
418
buzbee31a4a6f2012-02-28 15:36:15 -0800419RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700420{
421 int i;
422 if (sReg == -1)
423 return NULL;
424 for (i=0; i < numRegs; i++) {
425 if (p[i].live && (p[i].sReg == sReg)) {
426 if (p[i].isTemp)
427 p[i].inUse = true;
428 return &p[i];
429 }
430 }
431 return NULL;
432}
433
buzbee31a4a6f2012-02-28 15:36:15 -0800434RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg, int regClass)
buzbee67bf8852011-08-17 17:51:35 -0700435{
436 RegisterInfo* res = NULL;
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700437 switch (regClass) {
buzbee67bf8852011-08-17 17:51:35 -0700438 case kAnyReg:
439 res = allocLiveBody(cUnit->regPool->FPRegs,
440 cUnit->regPool->numFPRegs, sReg);
441 if (res)
442 break;
443 /* Intentional fallthrough */
444 case kCoreReg:
445 res = allocLiveBody(cUnit->regPool->coreRegs,
446 cUnit->regPool->numCoreRegs, sReg);
447 break;
448 case kFPReg:
449 res = allocLiveBody(cUnit->regPool->FPRegs,
450 cUnit->regPool->numFPRegs, sReg);
451 break;
452 default:
453 LOG(FATAL) << "Invalid register type";
454 }
455 return res;
456}
457
458extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
459{
460 RegisterInfo* p = cUnit->regPool->coreRegs;
461 int numRegs = cUnit->regPool->numCoreRegs;
462 int i;
463 for (i=0; i< numRegs; i++) {
464 if (p[i].reg == reg) {
465 if (p[i].isTemp) {
466 p[i].inUse = false;
467 }
468 p[i].pair = false;
469 return;
470 }
471 }
472 p = cUnit->regPool->FPRegs;
473 numRegs = cUnit->regPool->numFPRegs;
474 for (i=0; i< numRegs; i++) {
475 if (p[i].reg == reg) {
476 if (p[i].isTemp) {
477 p[i].inUse = false;
478 }
479 p[i].pair = false;
480 return;
481 }
482 }
483 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
484}
485
486extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
487{
488 RegisterInfo* p = cUnit->regPool->coreRegs;
489 int numRegs = cUnit->regPool->numCoreRegs;
490 int i;
491 for (i=0; i< numRegs; i++) {
492 if (p[i].reg == reg) {
493 return p[i].live ? &p[i] : NULL;
494 }
495 }
496 p = cUnit->regPool->FPRegs;
497 numRegs = cUnit->regPool->numFPRegs;
498 for (i=0; i< numRegs; i++) {
499 if (p[i].reg == reg) {
500 return p[i].live ? &p[i] : NULL;
501 }
502 }
503 return NULL;
504}
505
506extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
507{
buzbee68253262011-10-07 14:02:25 -0700508 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700509 return (p->isTemp) ? p : NULL;
510}
511
buzbeeb29e4d12011-09-26 15:05:48 -0700512extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
513{
buzbee68253262011-10-07 14:02:25 -0700514 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbeeb29e4d12011-09-26 15:05:48 -0700515 return (p->isTemp) ? NULL : p;
516}
517
buzbee67bf8852011-08-17 17:51:35 -0700518extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
519{
buzbee68253262011-10-07 14:02:25 -0700520 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700521 return p->dirty;
522}
523
524/*
525 * Similar to oatAllocTemp(), but forces the allocation of a specific
526 * register. No check is made to see if the register was previously
527 * allocated. Use with caution.
528 */
529extern void oatLockTemp(CompilationUnit* cUnit, int reg)
530{
531 RegisterInfo* p = cUnit->regPool->coreRegs;
532 int numRegs = cUnit->regPool->numCoreRegs;
533 int i;
534 for (i=0; i< numRegs; i++) {
535 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700536 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700537 p[i].inUse = true;
538 p[i].live = false;
539 return;
540 }
541 }
542 p = cUnit->regPool->FPRegs;
543 numRegs = cUnit->regPool->numFPRegs;
544 for (i=0; i< numRegs; i++) {
545 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700546 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700547 p[i].inUse = true;
548 p[i].live = false;
549 return;
550 }
551 }
552 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
553}
554
buzbee5abfa3e2012-01-31 17:01:43 -0800555static inline void resetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700556{
buzbee67bf8852011-08-17 17:51:35 -0700557 p->defStart = NULL;
558 p->defEnd = NULL;
559}
560
buzbee5abfa3e2012-01-31 17:01:43 -0800561extern void oatResetDef(CompilationUnit* cUnit, int reg)
562{
563 resetDefBody(oatGetRegInfo(cUnit, reg));
564}
565
buzbee31a4a6f2012-02-28 15:36:15 -0800566void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700567 int sReg1, int sReg2)
568{
569 if (start && finish) {
570 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700571 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700572 for (p = start; ;p = p->next) {
buzbeee3acd072012-02-25 17:03:10 -0800573 oatNopLIR(p);
buzbee67bf8852011-08-17 17:51:35 -0700574 if (p == finish)
575 break;
576 }
577 }
578}
579
580/*
581 * Mark the beginning and end LIR of a def sequence. Note that
582 * on entry start points to the LIR prior to the beginning of the
583 * sequence.
584 */
585extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
buzbee31a4a6f2012-02-28 15:36:15 -0800586 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700587{
buzbeeed3e9302011-09-23 17:34:19 -0700588 DCHECK(!rl.wide);
589 DCHECK(start && start->next);
590 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700591 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700592 p->defStart = start->next;
593 p->defEnd = finish;
594}
595
596/*
597 * Mark the beginning and end LIR of a def sequence. Note that
598 * on entry start points to the LIR prior to the beginning of the
599 * sequence.
600 */
601extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
buzbee31a4a6f2012-02-28 15:36:15 -0800602 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700603{
buzbeeed3e9302011-09-23 17:34:19 -0700604 DCHECK(rl.wide);
605 DCHECK(start && start->next);
606 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700607 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700608 oatResetDef(cUnit, rl.highReg); // Only track low of pair
609 p->defStart = start->next;
610 p->defEnd = finish;
611}
612
buzbee31a4a6f2012-02-28 15:36:15 -0800613extern RegLocation oatWideToNarrow(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700614{
buzbeeed3e9302011-09-23 17:34:19 -0700615 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700616 if (rl.location == kLocPhysReg) {
buzbee68253262011-10-07 14:02:25 -0700617 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
618 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700619 if (infoLo->isTemp) {
620 infoLo->pair = false;
621 infoLo->defStart = NULL;
622 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700623 }
buzbee0c7f26d2011-09-07 12:28:51 -0700624 if (infoHi->isTemp) {
625 infoHi->pair = false;
626 infoHi->defStart = NULL;
627 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700628 }
buzbee67bf8852011-08-17 17:51:35 -0700629 }
630 rl.wide = false;
631 return rl;
632}
633
634extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
635{
buzbeeed3e9302011-09-23 17:34:19 -0700636 DCHECK(!rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700637 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
638 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
buzbeeed3e9302011-09-23 17:34:19 -0700639 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700640 nullifyRange(cUnit, p->defStart, p->defEnd,
641 p->sReg, rl.sRegLow);
642 }
643 oatResetDef(cUnit, rl.lowReg);
644}
645
646extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
647{
buzbeeed3e9302011-09-23 17:34:19 -0700648 DCHECK(rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700649 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
650 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
651 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
652 DCHECK(pLow->pair);
653 nullifyRange(cUnit, pLow->defStart, pLow->defEnd,
654 pLow->sReg, rl.sRegLow);
655 }
656 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
657 DCHECK(pHigh->pair);
buzbee67bf8852011-08-17 17:51:35 -0700658 }
659 oatResetDef(cUnit, rl.lowReg);
660 oatResetDef(cUnit, rl.highReg);
661}
662
663extern void oatResetDefTracking(CompilationUnit* cUnit)
664{
665 int i;
666 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800667 resetDefBody(&cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700668 }
669 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800670 resetDefBody(&cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700671 }
672}
673
674extern void oatClobberAllRegs(CompilationUnit* cUnit)
675{
676 int i;
677 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800678 clobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700679 }
680 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800681 clobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700682 }
683}
684
buzbee67bf8852011-08-17 17:51:35 -0700685// Make sure nothing is live and dirty
buzbee31a4a6f2012-02-28 15:36:15 -0800686void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700687 int numRegs)
688{
689 int i;
690 for (i=0; i < numRegs; i++) {
691 if (info[i].live && info[i].dirty) {
692 if (info[i].pair) {
693 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
694 } else {
695 oatFlushReg(cUnit, info[i].reg);
696 }
697 }
698 }
699}
700
701extern void oatFlushAllRegs(CompilationUnit* cUnit)
702{
703 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
704 cUnit->regPool->numCoreRegs);
705 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
706 cUnit->regPool->numFPRegs);
707 oatClobberAllRegs(cUnit);
708}
709
710
711//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee31a4a6f2012-02-28 15:36:15 -0800712bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700713{
714 if (regClass == kAnyReg) {
715 return true;
716 } else if (regClass == kCoreReg) {
buzbeee3acd072012-02-25 17:03:10 -0800717 return !oatIsFpReg(reg);
buzbee67bf8852011-08-17 17:51:35 -0700718 } else {
buzbeee3acd072012-02-25 17:03:10 -0800719 return oatIsFpReg(reg);
buzbee67bf8852011-08-17 17:51:35 -0700720 }
721}
722
723extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
724{
buzbee68253262011-10-07 14:02:25 -0700725 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700726 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
727 return; /* already live */
728 } else if (sReg != INVALID_SREG) {
729 oatClobberSReg(cUnit, sReg);
730 if (info->isTemp) {
731 info->live = true;
732 }
733 } else {
734 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700735 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700736 info->live = false;
737 }
738 info->sReg = sReg;
739}
740
741extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
742{
buzbee68253262011-10-07 14:02:25 -0700743 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700744 info->isTemp = true;
745}
746
buzbee9e0f9b02011-08-24 15:32:46 -0700747extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
748{
buzbee68253262011-10-07 14:02:25 -0700749 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee9e0f9b02011-08-24 15:32:46 -0700750 info->isTemp = false;
751}
752
buzbee67bf8852011-08-17 17:51:35 -0700753extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
754{
buzbee68253262011-10-07 14:02:25 -0700755 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
756 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
buzbee67bf8852011-08-17 17:51:35 -0700757 infoLo->pair = infoHi->pair = true;
758 infoLo->partner = highReg;
759 infoHi->partner = lowReg;
760}
761
762extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
763{
buzbee68253262011-10-07 14:02:25 -0700764 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700765 info->dirty = false;
766 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700767 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700768 info->dirty = false;
769 }
770}
771
772extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
773{
774 if (loc.home) {
775 // If already home, can't be dirty
776 return;
777 }
buzbee68253262011-10-07 14:02:25 -0700778 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700779 info->dirty = true;
780 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700781 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700782 info->dirty = true;
783 }
784}
785
786extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
787{
buzbee68253262011-10-07 14:02:25 -0700788 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700789 info->inUse = true;
790}
791
buzbee31a4a6f2012-02-28 15:36:15 -0800792void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700793{
buzbee68253262011-10-07 14:02:25 -0700794 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
795 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700796 // Target temp status must not change
797 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700798 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700799 // Restore target's temp status
800 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700801 newInfo->reg = newReg;
802}
803
804/*
805 * Return an updated location record with current in-register status.
806 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700807 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700808 * clobber both low and high.
809 * TUNING: clobbering both is a bit heavy-handed, but the alternative
810 * is a bit complex when dealing with FP regs. Examine code to see
811 * if it's worthwhile trying to be more clever here.
812 */
813
814extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
815{
buzbeeed3e9302011-09-23 17:34:19 -0700816 DCHECK(!loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700817 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbeee1965672012-03-11 18:39:19 -0700818 if (loc.location != kLocPhysReg) {
819 DCHECK((loc.location == kLocDalvikFrame) ||
820 (loc.location == kLocCompilerTemp));
buzbee67bf8852011-08-17 17:51:35 -0700821 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
822 if (infoLo) {
823 if (infoLo->pair) {
824 oatClobber(cUnit, infoLo->reg);
825 oatClobber(cUnit, infoLo->partner);
buzbee58f92742011-10-01 11:22:17 -0700826 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700827 } else {
828 loc.lowReg = infoLo->reg;
829 loc.location = kLocPhysReg;
830 }
831 }
832 }
833
834 return loc;
835}
836
buzbee6181f792011-09-29 11:14:04 -0700837bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
838{
839 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
840 if (cUnit->regPool->coreRegs[i].pair) {
841 static int myReg = cUnit->regPool->coreRegs[i].reg;
842 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
843 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
buzbee68253262011-10-07 14:02:25 -0700844 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
buzbee6181f792011-09-29 11:14:04 -0700845 DCHECK(partner != NULL);
846 DCHECK(partner->pair);
847 DCHECK_EQ(myReg, partner->partner);
848 static int partnerSreg = partner->sReg;
849 if (mySreg == INVALID_SREG) {
850 DCHECK_EQ(partnerSreg, INVALID_SREG);
851 } else {
852 int diff = mySreg - partnerSreg;
853 DCHECK((diff == -1) || (diff == 1));
854 }
855 }
856 if (!cUnit->regPool->coreRegs[i].live) {
857 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
858 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
859 }
860 }
861 return true;
862}
863
buzbee67bf8852011-08-17 17:51:35 -0700864/* see comments for updateLoc */
buzbee31a4a6f2012-02-28 15:36:15 -0800865extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700866{
buzbeeed3e9302011-09-23 17:34:19 -0700867 DCHECK(loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700868 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbeee1965672012-03-11 18:39:19 -0700869 if (loc.location != kLocPhysReg) {
870 DCHECK((loc.location == kLocDalvikFrame) ||
871 (loc.location == kLocCompilerTemp));
buzbee67bf8852011-08-17 17:51:35 -0700872 // Are the dalvik regs already live in physical registers?
873 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
874 RegisterInfo* infoHi = allocLive(cUnit,
875 oatSRegHi(loc.sRegLow), kAnyReg);
876 bool match = true;
877 match = match && (infoLo != NULL);
878 match = match && (infoHi != NULL);
879 // Are they both core or both FP?
buzbeee3acd072012-02-25 17:03:10 -0800880 match = match && (oatIsFpReg(infoLo->reg) == oatIsFpReg(infoHi->reg));
buzbee67bf8852011-08-17 17:51:35 -0700881 // If a pair of floating point singles, are they properly aligned?
buzbeee3acd072012-02-25 17:03:10 -0800882 if (match && oatIsFpReg(infoLo->reg)) {
buzbee67bf8852011-08-17 17:51:35 -0700883 match &= ((infoLo->reg & 0x1) == 0);
884 match &= ((infoHi->reg - infoLo->reg) == 1);
885 }
886 // If previously used as a pair, it is the same pair?
887 if (match && (infoLo->pair || infoHi->pair)) {
888 match = (infoLo->pair == infoHi->pair);
889 match &= ((infoLo->reg == infoHi->partner) &&
890 (infoHi->reg == infoLo->partner));
891 }
892 if (match) {
893 // Can reuse - update the register usage info
894 loc.lowReg = infoLo->reg;
895 loc.highReg = infoHi->reg;
896 loc.location = kLocPhysReg;
897 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeee3acd072012-02-25 17:03:10 -0800898 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700899 return loc;
900 }
buzbee58f92742011-10-01 11:22:17 -0700901 // Can't easily reuse - clobber and free any overlaps
buzbee67bf8852011-08-17 17:51:35 -0700902 if (infoLo) {
903 oatClobber(cUnit, infoLo->reg);
buzbee58f92742011-10-01 11:22:17 -0700904 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700905 if (infoLo->pair)
906 oatClobber(cUnit, infoLo->partner);
907 }
908 if (infoHi) {
909 oatClobber(cUnit, infoHi->reg);
buzbee58f92742011-10-01 11:22:17 -0700910 oatFreeTemp(cUnit, infoHi->reg);
buzbee67bf8852011-08-17 17:51:35 -0700911 if (infoHi->pair)
912 oatClobber(cUnit, infoHi->partner);
913 }
914 }
915 return loc;
916}
917
buzbeeed3e9302011-09-23 17:34:19 -0700918
919/* For use in cases we don't know (or care) width */
buzbee31a4a6f2012-02-28 15:36:15 -0800920extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700921{
922 if (loc.wide)
923 return oatUpdateLocWide(cUnit, loc);
924 else
925 return oatUpdateLoc(cUnit, loc);
926}
927
buzbee31a4a6f2012-02-28 15:36:15 -0800928RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
929 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700930{
buzbeeed3e9302011-09-23 17:34:19 -0700931 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700932 int newRegs;
933 int lowReg;
934 int highReg;
935
936 loc = oatUpdateLocWide(cUnit, loc);
937
938 /* If already in registers, we can assume proper form. Right reg class? */
939 if (loc.location == kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -0800940 DCHECK_EQ(oatIsFpReg(loc.lowReg), oatIsFpReg(loc.highReg));
941 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700942 if (!regClassMatches(regClass, loc.lowReg)) {
943 /* Wrong register class. Reallocate and copy */
944 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
945 lowReg = newRegs & 0xff;
946 highReg = (newRegs >> 8) & 0xff;
947 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
948 loc.highReg);
949 copyRegInfo(cUnit, lowReg, loc.lowReg);
950 copyRegInfo(cUnit, highReg, loc.highReg);
951 oatClobber(cUnit, loc.lowReg);
952 oatClobber(cUnit, loc.highReg);
953 loc.lowReg = lowReg;
954 loc.highReg = highReg;
955 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeee3acd072012-02-25 17:03:10 -0800956 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700957 }
958 return loc;
959 }
960
buzbeeed3e9302011-09-23 17:34:19 -0700961 DCHECK_NE(loc.sRegLow, INVALID_SREG);
962 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700963
964 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
965 loc.lowReg = newRegs & 0xff;
966 loc.highReg = (newRegs >> 8) & 0xff;
967
968 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
969 if (update) {
970 loc.location = kLocPhysReg;
971 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
972 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
973 }
buzbeee3acd072012-02-25 17:03:10 -0800974 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700975 return loc;
976}
977
978extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
979 int regClass, bool update)
980{
981 int newReg;
982
983 if (loc.wide)
984 return evalLocWide(cUnit, loc, regClass, update);
985
986 loc = oatUpdateLoc(cUnit, loc);
987
988 if (loc.location == kLocPhysReg) {
989 if (!regClassMatches(regClass, loc.lowReg)) {
990 /* Wrong register class. Realloc, copy and transfer ownership */
991 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
992 oatRegCopy(cUnit, newReg, loc.lowReg);
993 copyRegInfo(cUnit, newReg, loc.lowReg);
994 oatClobber(cUnit, loc.lowReg);
995 loc.lowReg = newReg;
996 }
997 return loc;
998 }
999
buzbeeed3e9302011-09-23 17:34:19 -07001000 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001001
1002 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1003 loc.lowReg = newReg;
1004
1005 if (update) {
1006 loc.location = kLocPhysReg;
1007 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1008 }
1009 return loc;
1010}
1011
1012extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1013{
buzbeee9a72f62011-09-04 17:59:07 -07001014 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001015 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001016 return res;
buzbee67bf8852011-08-17 17:51:35 -07001017}
1018extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1019{
buzbeee9a72f62011-09-04 17:59:07 -07001020 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001021 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001022 return res;
1023}
1024extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1025{
1026 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1027 return res;
buzbee67bf8852011-08-17 17:51:35 -07001028}
1029extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1030 int low, int high)
1031{
buzbeee9a72f62011-09-04 17:59:07 -07001032 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001033 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001034 return res;
buzbee67bf8852011-08-17 17:51:35 -07001035}
1036
1037extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1038 int low, int high)
1039{
buzbeee9a72f62011-09-04 17:59:07 -07001040 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001041 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001042 return res;
buzbee67bf8852011-08-17 17:51:35 -07001043}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001044
buzbeee3acd072012-02-25 17:03:10 -08001045/* USE SSA names to count references of base Dalvik vRegs. */
1046void oatCountRefs(CompilationUnit *cUnit, BasicBlock* bb,
buzbee31a4a6f2012-02-28 15:36:15 -08001047 RefCounts* coreCounts, RefCounts* fpCounts)
buzbeee3acd072012-02-25 17:03:10 -08001048{
buzbee239c4e72012-03-16 08:42:29 -07001049 if ((cUnit->disableOpt & (1 << kPromoteRegs)) ||
1050 !((bb->blockType == kEntryBlock) || (bb->blockType == kExitBlock) ||
1051 (bb->blockType == kDalvikByteCode))) {
buzbeee3acd072012-02-25 17:03:10 -08001052 return;
buzbee239c4e72012-03-16 08:42:29 -07001053 }
1054 for (int i = 0; i < cUnit->numSSARegs;) {
1055 RegLocation loc = cUnit->regLocation[i];
1056 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
buzbee9c044ce2012-03-18 13:24:07 -07001057 int pMapIdx = SRegToPMap(cUnit, loc.sRegLow);
buzbee239c4e72012-03-16 08:42:29 -07001058 if (loc.defined) {
buzbee9c044ce2012-03-18 13:24:07 -07001059 counts[pMapIdx].count += cUnit->useCounts.elemList[i];
buzbee239c4e72012-03-16 08:42:29 -07001060 }
1061 if (loc.wide) {
1062 if (loc.defined) {
1063 if (loc.fp) {
buzbee9c044ce2012-03-18 13:24:07 -07001064 counts[pMapIdx].doubleStart = true;
1065 counts[pMapIdx+1].count += cUnit->useCounts.elemList[i+1];
buzbeee3acd072012-02-25 17:03:10 -08001066 }
1067 }
buzbee239c4e72012-03-16 08:42:29 -07001068 i += 2;
1069 } else {
1070 i++;
buzbeee3acd072012-02-25 17:03:10 -08001071 }
1072 }
1073}
1074
1075/* qsort callback function, sort descending */
1076int oatSortCounts(const void *val1, const void *val2)
1077{
1078 const RefCounts* op1 = (const RefCounts*)val1;
1079 const RefCounts* op2 = (const RefCounts*)val2;
1080 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
1081}
1082
1083void oatDumpCounts(const RefCounts* arr, int size, const char* msg)
1084{
1085 LOG(INFO) << msg;
1086 for (int i = 0; i < size; i++) {
1087 LOG(INFO) << "sReg[" << arr[i].sReg << "]: " << arr[i].count;
1088 }
1089}
1090
1091/*
1092 * Note: some portions of this code required even if the kPromoteRegs
1093 * optimization is disabled.
1094 */
1095extern void oatDoPromotion(CompilationUnit* cUnit)
1096{
buzbee239c4e72012-03-16 08:42:29 -07001097 int regBias = cUnit->numCompilerTemps + 1;
1098 int dalvikRegs = cUnit->numDalvikRegisters;
1099 int numRegs = dalvikRegs + regBias;
buzbeea7c12682012-03-19 13:13:53 -07001100 const int promotionThreshold = 2;
buzbeee3acd072012-02-25 17:03:10 -08001101
1102 // Allow target code to add any special registers
1103 oatAdjustSpillMask(cUnit);
1104
1105 /*
1106 * Simple register promotion. Just do a static count of the uses
1107 * of Dalvik registers. Note that we examine the SSA names, but
1108 * count based on original Dalvik register name. Count refs
1109 * separately based on type in order to give allocation
1110 * preference to fp doubles - which must be allocated sequential
1111 * physical single fp registers started with an even-numbered
1112 * reg.
1113 * TUNING: replace with linear scan once we have the ability
1114 * to describe register live ranges for GC.
1115 */
1116 RefCounts *coreRegs = (RefCounts *)
1117 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1118 RefCounts *fpRegs = (RefCounts *)
1119 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
buzbee239c4e72012-03-16 08:42:29 -07001120 // Set ssa names for original Dalvik registers
1121 for (int i = 0; i < dalvikRegs; i++) {
buzbeee3acd072012-02-25 17:03:10 -08001122 coreRegs[i].sReg = fpRegs[i].sReg = i;
1123 }
buzbee9c044ce2012-03-18 13:24:07 -07001124 // Set ssa name for Method*
1125 coreRegs[dalvikRegs].sReg = cUnit->methodSReg;
1126 fpRegs[dalvikRegs].sReg = cUnit->methodSReg; // For consistecy
1127 // Set ssa names for compilerTemps
1128 for (int i = 1; i <= cUnit->numCompilerTemps; i++) {
1129 CompilerTemp* ct = (CompilerTemp*)cUnit->compilerTemps.elemList[i];
1130 coreRegs[dalvikRegs + i].sReg = ct->sReg;
1131 fpRegs[dalvikRegs + i].sReg = ct->sReg;
buzbee239c4e72012-03-16 08:42:29 -07001132 }
buzbee9c044ce2012-03-18 13:24:07 -07001133
buzbeee3acd072012-02-25 17:03:10 -08001134 GrowableListIterator iterator;
1135 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
1136 while (true) {
1137 BasicBlock* bb;
1138 bb = (BasicBlock*)oatGrowableListIteratorNext(&iterator);
1139 if (bb == NULL) break;
1140 oatCountRefs(cUnit, bb, coreRegs, fpRegs);
1141 }
1142
1143 /*
1144 * Ideally, we'd allocate doubles starting with an even-numbered
1145 * register. Bias the counts to try to allocate any vreg that's
1146 * used as the start of a pair first.
1147 */
1148 for (int i = 0; i < numRegs; i++) {
1149 if (fpRegs[i].doubleStart) {
1150 fpRegs[i].count *= 2;
1151 }
1152 }
1153
1154 // Sort the count arrays
1155 qsort(coreRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1156 qsort(fpRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1157
1158 if (cUnit->printMe) {
1159 oatDumpCounts(coreRegs, numRegs, "Core regs after sort");
1160 oatDumpCounts(fpRegs, numRegs, "Fp regs after sort");
1161 }
1162
1163 if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
1164 // Promote fpRegs
buzbeea7c12682012-03-19 13:13:53 -07001165 for (int i = 0; (i < numRegs) &&
1166 (fpRegs[i].count >= promotionThreshold ); i++) {
buzbee9c044ce2012-03-18 13:24:07 -07001167 int pMapIdx = SRegToPMap(cUnit, fpRegs[i].sReg);
1168 if (cUnit->promotionMap[pMapIdx].fpLocation != kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001169 int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
1170 fpRegs[i].doubleStart);
1171 if (reg < 0) {
1172 break; // No more left
1173 }
1174 }
1175 }
1176
1177 // Promote core regs
buzbeea7c12682012-03-19 13:13:53 -07001178 for (int i = 0; (i < numRegs) &&
1179 (coreRegs[i].count > promotionThreshold); i++) {
buzbee9c044ce2012-03-18 13:24:07 -07001180 int pMapIdx = SRegToPMap(cUnit, coreRegs[i].sReg);
1181 if (cUnit->promotionMap[pMapIdx].coreLocation !=
buzbeee3acd072012-02-25 17:03:10 -08001182 kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001183 int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
1184 if (reg < 0) {
1185 break; // No more left
1186 }
1187 }
1188 }
buzbeea7c12682012-03-19 13:13:53 -07001189 } else if (cUnit->qdMode) {
1190 oatAllocPreservedCoreReg(cUnit, cUnit->methodSReg);
1191 for (int i = 0; i < numRegs; i++) {
1192 int reg = oatAllocPreservedCoreReg(cUnit, i);
1193 if (reg < 0) {
1194 break; // No more left
1195 }
1196 }
buzbeee3acd072012-02-25 17:03:10 -08001197 }
1198
buzbeea7c12682012-03-19 13:13:53 -07001199
buzbeee3acd072012-02-25 17:03:10 -08001200 // Now, update SSA names to new home locations
1201 for (int i = 0; i < cUnit->numSSARegs; i++) {
1202 RegLocation *curr = &cUnit->regLocation[i];
buzbee9c044ce2012-03-18 13:24:07 -07001203 int pMapIdx = SRegToPMap(cUnit, curr->sRegLow);
buzbeee3acd072012-02-25 17:03:10 -08001204 if (!curr->wide) {
1205 if (curr->fp) {
buzbee9c044ce2012-03-18 13:24:07 -07001206 if (cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001207 curr->location = kLocPhysReg;
buzbee9c044ce2012-03-18 13:24:07 -07001208 curr->lowReg = cUnit->promotionMap[pMapIdx].fpReg;
buzbeee3acd072012-02-25 17:03:10 -08001209 curr->home = true;
1210 }
1211 } else {
buzbee9c044ce2012-03-18 13:24:07 -07001212 if (cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001213 curr->location = kLocPhysReg;
buzbee9c044ce2012-03-18 13:24:07 -07001214 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
buzbeee3acd072012-02-25 17:03:10 -08001215 curr->home = true;
1216 }
1217 }
1218 curr->highReg = INVALID_REG;
1219 } else {
1220 if (curr->highWord) {
1221 continue;
1222 }
1223 if (curr->fp) {
buzbee9c044ce2012-03-18 13:24:07 -07001224 if ((cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) &&
1225 (cUnit->promotionMap[pMapIdx+1].fpLocation ==
buzbeee3acd072012-02-25 17:03:10 -08001226 kLocPhysReg)) {
buzbee9c044ce2012-03-18 13:24:07 -07001227 int lowReg = cUnit->promotionMap[pMapIdx].fpReg;
1228 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
buzbeee3acd072012-02-25 17:03:10 -08001229 // Doubles require pair of singles starting at even reg
1230 if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
1231 curr->location = kLocPhysReg;
1232 curr->lowReg = lowReg;
1233 curr->highReg = highReg;
1234 curr->home = true;
1235 }
1236 }
1237 } else {
buzbee9c044ce2012-03-18 13:24:07 -07001238 if ((cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg)
1239 && (cUnit->promotionMap[pMapIdx+1].coreLocation ==
buzbeee3acd072012-02-25 17:03:10 -08001240 kLocPhysReg)) {
1241 curr->location = kLocPhysReg;
buzbee9c044ce2012-03-18 13:24:07 -07001242 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1243 curr->highReg = cUnit->promotionMap[pMapIdx+1].coreReg;
buzbeee3acd072012-02-25 17:03:10 -08001244 curr->home = true;
1245 }
1246 }
1247 }
1248 }
1249}
1250
1251/* Returns sp-relative offset in bytes for a VReg */
1252extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
1253{
buzbeeefccc562012-03-11 11:19:28 -07001254 return Frame::GetVRegOffset(cUnit->code_item, cUnit->coreSpillMask,
1255 cUnit->fpSpillMask, cUnit->frameSize, vReg);
buzbeee3acd072012-02-25 17:03:10 -08001256}
1257
1258/* Returns sp-relative offset in bytes for a SReg */
1259extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
1260{
buzbeee1965672012-03-11 18:39:19 -07001261 return oatVRegOffset(cUnit, SRegToVReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -08001262}
1263
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001264} // namespace art