blob: b3fa739d0ecb8327ce1ecd89bc6a16ca0a43dcb4 [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{
81 int i;
82 LOG(INFO) << "================================================";
83 for (i=0; i < numRegs; i++ ){
84 char buf[100];
85 snprintf(buf, 100,
86 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
87 p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
88 p[i].live, p[i].dirty, p[i].sReg,(int)p[i].defStart,
89 (int)p[i].defEnd);
90 LOG(INFO) << buf;
91 }
92 LOG(INFO) << "================================================";
93}
94
buzbee6181f792011-09-29 11:14:04 -070095void oatDumpCoreRegPool(CompilationUnit* cUnit)
96{
97 dumpRegPool(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs);
98}
99
100void oatDumpFpRegPool(CompilationUnit* cUnit)
101{
102 dumpRegPool(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs);
103}
104
buzbee67bf8852011-08-17 17:51:35 -0700105/* Mark a temp register as dead. Does not affect allocation state. */
buzbee5abfa3e2012-01-31 17:01:43 -0800106static inline void clobberBody(CompilationUnit *cUnit, RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700107{
buzbee68253262011-10-07 14:02:25 -0700108 if (p->isTemp) {
109 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
110 p->live = false;
111 p->sReg = INVALID_SREG;
112 p->defStart = NULL;
113 p->defEnd = NULL;
114 if (p->pair) {
115 p->pair = false;
116 oatClobber(cUnit, p->partner);
117 }
buzbee67bf8852011-08-17 17:51:35 -0700118 }
119}
120
buzbee5abfa3e2012-01-31 17:01:43 -0800121/* Mark a temp register as dead. Does not affect allocation state. */
122void oatClobber(CompilationUnit* cUnit, int reg)
123{
124 clobberBody(cUnit, oatGetRegInfo(cUnit, reg));
125}
126
buzbee31a4a6f2012-02-28 15:36:15 -0800127void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700128{
129 int i;
130 for (i=0; i< numRegs; i++) {
131 if (p[i].sReg == sReg) {
132 if (p[i].isTemp) {
133 p[i].live = false;
134 }
135 p[i].defStart = NULL;
136 p[i].defEnd = NULL;
137 }
138 }
139}
140
141/* Clobber any temp associated with an sReg. Could be in either class */
142extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
143{
buzbee3d661942012-03-14 17:37:27 -0700144#ifndef NDEBUG
145 /* Reset live temp tracking sanity checker */
146 if (sReg == cUnit->liveSReg) {
147 cUnit->liveSReg = INVALID_SREG;
148 }
149#endif
buzbee67bf8852011-08-17 17:51:35 -0700150 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs,
151 sReg);
152 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs,
153 sReg);
154}
155
buzbee9c044ce2012-03-18 13:24:07 -0700156/*
157 * SSA names associated with the initial definitions of Dalvik
158 * registers are the same as the Dalvik register number (and
159 * thus take the same position in the promotionMap. However,
160 * the special Method* and compiler temp resisters use negative
161 * vReg numbers to distinquish them and can have an arbitrary
162 * ssa name (above the last original Dalvik register). This function
163 * maps SSA names to positions in the promotionMap array.
164 */
165int SRegToPMap(CompilationUnit* cUnit, int sReg)
buzbeee1965672012-03-11 18:39:19 -0700166{
buzbee9c044ce2012-03-18 13:24:07 -0700167 DCHECK_LT(sReg, cUnit->numSSARegs);
168 DCHECK_GE(sReg, 0);
169 int vReg = SRegToVReg(cUnit, sReg);
170 if (vReg >= 0) {
171 DCHECK_LT(vReg, cUnit->numDalvikRegisters);
172 return vReg;
173 } else {
174 int pos = std::abs(vReg) - std::abs(SSA_METHOD_BASEREG);
175 DCHECK_LE(pos, cUnit->numCompilerTemps);
176 return cUnit->numDalvikRegisters + pos;
buzbeee1965672012-03-11 18:39:19 -0700177 }
buzbeee1965672012-03-11 18:39:19 -0700178}
179
buzbee67bf8852011-08-17 17:51:35 -0700180/* Reserve a callee-save register. Return -1 if none available */
181extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
182{
183 int res = -1;
184 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
185 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
186 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
buzbee9c044ce2012-03-18 13:24:07 -0700187 int vReg = SRegToVReg(cUnit, sReg);
188 int pMapIdx = SRegToPMap(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700189 res = coreRegs[i].reg;
190 coreRegs[i].inUse = true;
191 cUnit->coreSpillMask |= (1 << res);
buzbee9c044ce2012-03-18 13:24:07 -0700192 cUnit->coreVmapTable.push_back(vReg);
buzbeebbaf8942011-10-02 13:08:29 -0700193 cUnit->numCoreSpills++;
buzbee9c044ce2012-03-18 13:24:07 -0700194 cUnit->promotionMap[pMapIdx].coreLocation = kLocPhysReg;
195 cUnit->promotionMap[pMapIdx].coreReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700196 break;
197 }
198 }
199 return res;
200}
201
202/*
203 * Reserve a callee-save fp single register. Try to fullfill request for
204 * even/odd allocation, but go ahead and allocate anything if not
205 * available. If nothing's available, return -1.
206 */
buzbee31a4a6f2012-02-28 15:36:15 -0800207int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700208{
209 int res = -1;
210 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
211 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
212 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
213 ((FPRegs[i].reg & 0x1) == 0) == even) {
buzbee9c044ce2012-03-18 13:24:07 -0700214 int vReg = SRegToVReg(cUnit, sReg);
215 int pMapIdx = SRegToPMap(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700216 res = FPRegs[i].reg;
217 FPRegs[i].inUse = true;
buzbee9c044ce2012-03-18 13:24:07 -0700218 oatMarkPreservedSingle(cUnit, vReg, res);
219 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
220 cUnit->promotionMap[pMapIdx].fpReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700221 break;
222 }
223 }
224 return res;
225}
226
227/*
228 * Somewhat messy code here. We want to allocate a pair of contiguous
229 * physical single-precision floating point registers starting with
230 * an even numbered reg. It is possible that the paired sReg (sReg+1)
231 * has already been allocated - try to fit if possible. Fail to
232 * allocate if we can't meet the requirements for the pair of
233 * sReg<=sX[even] & (sReg+1)<= sX+1.
234 */
buzbee31a4a6f2012-02-28 15:36:15 -0800235int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700236{
237 int res = -1; // Assume failure
buzbee9c044ce2012-03-18 13:24:07 -0700238 int vReg = SRegToVReg(cUnit, sReg);
239 int pMapIdx = SRegToPMap(cUnit, sReg);
240 if (cUnit->promotionMap[pMapIdx+1].fpLocation == kLocPhysReg) {
buzbee67bf8852011-08-17 17:51:35 -0700241 // Upper reg is already allocated. Can we fit?
buzbee9c044ce2012-03-18 13:24:07 -0700242 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
buzbee67bf8852011-08-17 17:51:35 -0700243 if ((highReg & 1) == 0) {
244 // High reg is even - fail.
245 return res;
246 }
247 // Is the low reg of the pair free?
buzbee68253262011-10-07 14:02:25 -0700248 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
buzbee67bf8852011-08-17 17:51:35 -0700249 if (p->inUse || p->isTemp) {
250 // Already allocated or not preserved - fail.
251 return res;
252 }
253 // OK - good to go.
254 res = p->reg;
255 p->inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700256 DCHECK_EQ((res & 1), 0);
buzbee9c044ce2012-03-18 13:24:07 -0700257 oatMarkPreservedSingle(cUnit, vReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700258 } else {
259 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
260 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
261 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
262 ((FPRegs[i].reg & 0x1) == 0x0) &&
263 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
264 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
265 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
266 res = FPRegs[i].reg;
267 FPRegs[i].inUse = true;
buzbee9c044ce2012-03-18 13:24:07 -0700268 oatMarkPreservedSingle(cUnit, vReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700269 FPRegs[i+1].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700270 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
buzbee9c044ce2012-03-18 13:24:07 -0700271 oatMarkPreservedSingle(cUnit, vReg+1, res+1);
buzbee67bf8852011-08-17 17:51:35 -0700272 break;
273 }
274 }
275 }
276 if (res != -1) {
buzbee9c044ce2012-03-18 13:24:07 -0700277 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
278 cUnit->promotionMap[pMapIdx].fpReg = res;
279 cUnit->promotionMap[pMapIdx+1].fpLocation = kLocPhysReg;
280 cUnit->promotionMap[pMapIdx+1].fpReg = res + 1;
buzbee67bf8852011-08-17 17:51:35 -0700281 }
282 return res;
283}
284
285
286/*
287 * Reserve a callee-save fp register. If this register can be used
288 * as the first of a double, attempt to allocate an even pair of fp
289 * single regs (but if can't still attempt to allocate a single, preferring
290 * first to allocate an odd register.
291 */
292extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
293 bool doubleStart)
294{
295 int res = -1;
296 if (doubleStart) {
297 res = allocPreservedDouble(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700298 }
299 if (res == -1) {
300 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
301 }
302 if (res == -1)
303 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
304 return res;
305}
306
buzbee31a4a6f2012-02-28 15:36:15 -0800307int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
308 int* nextTemp, bool required)
buzbee67bf8852011-08-17 17:51:35 -0700309{
310 int i;
311 int next = *nextTemp;
312 for (i=0; i< numRegs; i++) {
313 if (next >= numRegs)
314 next = 0;
315 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
316 oatClobber(cUnit, p[next].reg);
317 p[next].inUse = true;
318 p[next].pair = false;
319 *nextTemp = next + 1;
320 return p[next].reg;
321 }
322 next++;
323 }
324 next = *nextTemp;
325 for (i=0; i< numRegs; i++) {
326 if (next >= numRegs)
327 next = 0;
328 if (p[next].isTemp && !p[next].inUse) {
329 oatClobber(cUnit, p[next].reg);
330 p[next].inUse = true;
331 p[next].pair = false;
332 *nextTemp = next + 1;
333 return p[next].reg;
334 }
335 next++;
336 }
337 if (required) {
buzbee6181f792011-09-29 11:14:04 -0700338 oatCodegenDump(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700339 dumpRegPool(cUnit->regPool->coreRegs,
340 cUnit->regPool->numCoreRegs);
341 LOG(FATAL) << "No free temp registers";
342 }
343 return -1; // No register available
344}
345
346//REDO: too many assumptions.
347extern int oatAllocTempDouble(CompilationUnit* cUnit)
348{
349 RegisterInfo* p = cUnit->regPool->FPRegs;
350 int numRegs = cUnit->regPool->numFPRegs;
buzbeea50638b2011-11-02 15:15:06 -0700351 /* Start looking at an even reg */
352 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700353
buzbeea50638b2011-11-02 15:15:06 -0700354 // First try to avoid allocating live registers
355 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700356 if (next >= numRegs)
357 next = 0;
358 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
359 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
360 oatClobber(cUnit, p[next].reg);
361 oatClobber(cUnit, p[next+1].reg);
362 p[next].inUse = true;
363 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700364 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
365 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700366 cUnit->regPool->nextFPReg = next + 2;
367 if (cUnit->regPool->nextFPReg >= numRegs) {
368 cUnit->regPool->nextFPReg = 0;
369 }
buzbee67bf8852011-08-17 17:51:35 -0700370 return p[next].reg;
371 }
372 next += 2;
373 }
buzbeea50638b2011-11-02 15:15:06 -0700374 next = cUnit->regPool->nextFPReg & ~0x1;
375
376 // No choice - find a pair and kill it.
377 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700378 if (next >= numRegs)
379 next = 0;
380 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
381 !p[next+1].inUse) {
382 oatClobber(cUnit, p[next].reg);
383 oatClobber(cUnit, p[next+1].reg);
384 p[next].inUse = true;
385 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700386 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
387 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700388 cUnit->regPool->nextFPReg = next + 2;
389 if (cUnit->regPool->nextFPReg >= numRegs) {
390 cUnit->regPool->nextFPReg = 0;
391 }
buzbee67bf8852011-08-17 17:51:35 -0700392 return p[next].reg;
393 }
394 next += 2;
395 }
buzbee6181f792011-09-29 11:14:04 -0700396 LOG(FATAL) << "No free temp registers (pair)";
buzbee67bf8852011-08-17 17:51:35 -0700397 return -1;
398}
399
400/* Return a temp if one is available, -1 otherwise */
401extern int oatAllocFreeTemp(CompilationUnit* cUnit)
402{
403 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
404 cUnit->regPool->numCoreRegs,
405 &cUnit->regPool->nextCoreReg, true);
406}
407
408extern int oatAllocTemp(CompilationUnit* cUnit)
409{
410 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
411 cUnit->regPool->numCoreRegs,
412 &cUnit->regPool->nextCoreReg, true);
413}
414
415extern int oatAllocTempFloat(CompilationUnit* cUnit)
416{
417 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
418 cUnit->regPool->numFPRegs,
419 &cUnit->regPool->nextFPReg, true);
420}
421
buzbee31a4a6f2012-02-28 15:36:15 -0800422RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700423{
424 int i;
425 if (sReg == -1)
426 return NULL;
427 for (i=0; i < numRegs; i++) {
428 if (p[i].live && (p[i].sReg == sReg)) {
429 if (p[i].isTemp)
430 p[i].inUse = true;
431 return &p[i];
432 }
433 }
434 return NULL;
435}
436
buzbee31a4a6f2012-02-28 15:36:15 -0800437RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg, int regClass)
buzbee67bf8852011-08-17 17:51:35 -0700438{
439 RegisterInfo* res = NULL;
440 switch(regClass) {
441 case kAnyReg:
442 res = allocLiveBody(cUnit->regPool->FPRegs,
443 cUnit->regPool->numFPRegs, sReg);
444 if (res)
445 break;
446 /* Intentional fallthrough */
447 case kCoreReg:
448 res = allocLiveBody(cUnit->regPool->coreRegs,
449 cUnit->regPool->numCoreRegs, sReg);
450 break;
451 case kFPReg:
452 res = allocLiveBody(cUnit->regPool->FPRegs,
453 cUnit->regPool->numFPRegs, sReg);
454 break;
455 default:
456 LOG(FATAL) << "Invalid register type";
457 }
458 return res;
459}
460
461extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
462{
463 RegisterInfo* p = cUnit->regPool->coreRegs;
464 int numRegs = cUnit->regPool->numCoreRegs;
465 int i;
466 for (i=0; i< numRegs; i++) {
467 if (p[i].reg == reg) {
468 if (p[i].isTemp) {
469 p[i].inUse = false;
470 }
471 p[i].pair = false;
472 return;
473 }
474 }
475 p = cUnit->regPool->FPRegs;
476 numRegs = cUnit->regPool->numFPRegs;
477 for (i=0; i< numRegs; i++) {
478 if (p[i].reg == reg) {
479 if (p[i].isTemp) {
480 p[i].inUse = false;
481 }
482 p[i].pair = false;
483 return;
484 }
485 }
486 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
487}
488
489extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
490{
491 RegisterInfo* p = cUnit->regPool->coreRegs;
492 int numRegs = cUnit->regPool->numCoreRegs;
493 int i;
494 for (i=0; i< numRegs; i++) {
495 if (p[i].reg == reg) {
496 return p[i].live ? &p[i] : NULL;
497 }
498 }
499 p = cUnit->regPool->FPRegs;
500 numRegs = cUnit->regPool->numFPRegs;
501 for (i=0; i< numRegs; i++) {
502 if (p[i].reg == reg) {
503 return p[i].live ? &p[i] : NULL;
504 }
505 }
506 return NULL;
507}
508
509extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
510{
buzbee68253262011-10-07 14:02:25 -0700511 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700512 return (p->isTemp) ? p : NULL;
513}
514
buzbeeb29e4d12011-09-26 15:05:48 -0700515extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
516{
buzbee68253262011-10-07 14:02:25 -0700517 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbeeb29e4d12011-09-26 15:05:48 -0700518 return (p->isTemp) ? NULL : p;
519}
520
buzbee67bf8852011-08-17 17:51:35 -0700521extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
522{
buzbee68253262011-10-07 14:02:25 -0700523 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700524 return p->dirty;
525}
526
527/*
528 * Similar to oatAllocTemp(), but forces the allocation of a specific
529 * register. No check is made to see if the register was previously
530 * allocated. Use with caution.
531 */
532extern void oatLockTemp(CompilationUnit* cUnit, int reg)
533{
534 RegisterInfo* p = cUnit->regPool->coreRegs;
535 int numRegs = cUnit->regPool->numCoreRegs;
536 int i;
537 for (i=0; i< numRegs; i++) {
538 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700539 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700540 p[i].inUse = true;
541 p[i].live = false;
542 return;
543 }
544 }
545 p = cUnit->regPool->FPRegs;
546 numRegs = cUnit->regPool->numFPRegs;
547 for (i=0; i< numRegs; i++) {
548 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700549 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700550 p[i].inUse = true;
551 p[i].live = false;
552 return;
553 }
554 }
555 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
556}
557
buzbee5abfa3e2012-01-31 17:01:43 -0800558static inline void resetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700559{
buzbee67bf8852011-08-17 17:51:35 -0700560 p->defStart = NULL;
561 p->defEnd = NULL;
562}
563
buzbee5abfa3e2012-01-31 17:01:43 -0800564extern void oatResetDef(CompilationUnit* cUnit, int reg)
565{
566 resetDefBody(oatGetRegInfo(cUnit, reg));
567}
568
buzbee31a4a6f2012-02-28 15:36:15 -0800569void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700570 int sReg1, int sReg2)
571{
572 if (start && finish) {
573 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700574 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700575 for (p = start; ;p = p->next) {
buzbeee3acd072012-02-25 17:03:10 -0800576 oatNopLIR(p);
buzbee67bf8852011-08-17 17:51:35 -0700577 if (p == finish)
578 break;
579 }
580 }
581}
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 oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
buzbee31a4a6f2012-02-28 15:36:15 -0800589 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700590{
buzbeeed3e9302011-09-23 17:34:19 -0700591 DCHECK(!rl.wide);
592 DCHECK(start && start->next);
593 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700594 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700595 p->defStart = start->next;
596 p->defEnd = finish;
597}
598
599/*
600 * Mark the beginning and end LIR of a def sequence. Note that
601 * on entry start points to the LIR prior to the beginning of the
602 * sequence.
603 */
604extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
buzbee31a4a6f2012-02-28 15:36:15 -0800605 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700606{
buzbeeed3e9302011-09-23 17:34:19 -0700607 DCHECK(rl.wide);
608 DCHECK(start && start->next);
609 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700610 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700611 oatResetDef(cUnit, rl.highReg); // Only track low of pair
612 p->defStart = start->next;
613 p->defEnd = finish;
614}
615
buzbee31a4a6f2012-02-28 15:36:15 -0800616extern RegLocation oatWideToNarrow(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700617{
buzbeeed3e9302011-09-23 17:34:19 -0700618 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700619 if (rl.location == kLocPhysReg) {
buzbee68253262011-10-07 14:02:25 -0700620 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
621 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700622 if (infoLo->isTemp) {
623 infoLo->pair = false;
624 infoLo->defStart = NULL;
625 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700626 }
buzbee0c7f26d2011-09-07 12:28:51 -0700627 if (infoHi->isTemp) {
628 infoHi->pair = false;
629 infoHi->defStart = NULL;
630 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700631 }
buzbee67bf8852011-08-17 17:51:35 -0700632 }
633 rl.wide = false;
634 return rl;
635}
636
637extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
638{
buzbeeed3e9302011-09-23 17:34:19 -0700639 DCHECK(!rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700640 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
641 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
buzbeeed3e9302011-09-23 17:34:19 -0700642 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700643 nullifyRange(cUnit, p->defStart, p->defEnd,
644 p->sReg, rl.sRegLow);
645 }
646 oatResetDef(cUnit, rl.lowReg);
647}
648
649extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
650{
buzbeeed3e9302011-09-23 17:34:19 -0700651 DCHECK(rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700652 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
653 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
654 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
655 DCHECK(pLow->pair);
656 nullifyRange(cUnit, pLow->defStart, pLow->defEnd,
657 pLow->sReg, rl.sRegLow);
658 }
659 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
660 DCHECK(pHigh->pair);
buzbee67bf8852011-08-17 17:51:35 -0700661 }
662 oatResetDef(cUnit, rl.lowReg);
663 oatResetDef(cUnit, rl.highReg);
664}
665
666extern void oatResetDefTracking(CompilationUnit* cUnit)
667{
668 int i;
669 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800670 resetDefBody(&cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700671 }
672 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800673 resetDefBody(&cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700674 }
675}
676
677extern void oatClobberAllRegs(CompilationUnit* cUnit)
678{
679 int i;
680 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800681 clobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700682 }
683 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800684 clobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700685 }
686}
687
buzbee67bf8852011-08-17 17:51:35 -0700688// Make sure nothing is live and dirty
buzbee31a4a6f2012-02-28 15:36:15 -0800689void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700690 int numRegs)
691{
692 int i;
693 for (i=0; i < numRegs; i++) {
694 if (info[i].live && info[i].dirty) {
695 if (info[i].pair) {
696 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
697 } else {
698 oatFlushReg(cUnit, info[i].reg);
699 }
700 }
701 }
702}
703
704extern void oatFlushAllRegs(CompilationUnit* cUnit)
705{
706 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
707 cUnit->regPool->numCoreRegs);
708 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
709 cUnit->regPool->numFPRegs);
710 oatClobberAllRegs(cUnit);
711}
712
713
714//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee31a4a6f2012-02-28 15:36:15 -0800715bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700716{
717 if (regClass == kAnyReg) {
718 return true;
719 } else if (regClass == kCoreReg) {
buzbeee3acd072012-02-25 17:03:10 -0800720 return !oatIsFpReg(reg);
buzbee67bf8852011-08-17 17:51:35 -0700721 } else {
buzbeee3acd072012-02-25 17:03:10 -0800722 return oatIsFpReg(reg);
buzbee67bf8852011-08-17 17:51:35 -0700723 }
724}
725
726extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
727{
buzbee68253262011-10-07 14:02:25 -0700728 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700729 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
730 return; /* already live */
731 } else if (sReg != INVALID_SREG) {
732 oatClobberSReg(cUnit, sReg);
733 if (info->isTemp) {
734 info->live = true;
735 }
736 } else {
737 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700738 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700739 info->live = false;
740 }
741 info->sReg = sReg;
742}
743
744extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
745{
buzbee68253262011-10-07 14:02:25 -0700746 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700747 info->isTemp = true;
748}
749
buzbee9e0f9b02011-08-24 15:32:46 -0700750extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
751{
buzbee68253262011-10-07 14:02:25 -0700752 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee9e0f9b02011-08-24 15:32:46 -0700753 info->isTemp = false;
754}
755
buzbee67bf8852011-08-17 17:51:35 -0700756extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
757{
buzbee68253262011-10-07 14:02:25 -0700758 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
759 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
buzbee67bf8852011-08-17 17:51:35 -0700760 infoLo->pair = infoHi->pair = true;
761 infoLo->partner = highReg;
762 infoHi->partner = lowReg;
763}
764
765extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
766{
buzbee68253262011-10-07 14:02:25 -0700767 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700768 info->dirty = false;
769 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700770 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700771 info->dirty = false;
772 }
773}
774
775extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
776{
777 if (loc.home) {
778 // If already home, can't be dirty
779 return;
780 }
buzbee68253262011-10-07 14:02:25 -0700781 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700782 info->dirty = true;
783 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700784 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700785 info->dirty = true;
786 }
787}
788
789extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
790{
buzbee68253262011-10-07 14:02:25 -0700791 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700792 info->inUse = true;
793}
794
buzbee31a4a6f2012-02-28 15:36:15 -0800795void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700796{
buzbee68253262011-10-07 14:02:25 -0700797 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
798 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700799 // Target temp status must not change
800 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700801 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700802 // Restore target's temp status
803 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700804 newInfo->reg = newReg;
805}
806
807/*
808 * Return an updated location record with current in-register status.
809 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700810 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700811 * clobber both low and high.
812 * TUNING: clobbering both is a bit heavy-handed, but the alternative
813 * is a bit complex when dealing with FP regs. Examine code to see
814 * if it's worthwhile trying to be more clever here.
815 */
816
817extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
818{
buzbeeed3e9302011-09-23 17:34:19 -0700819 DCHECK(!loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700820 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbeee1965672012-03-11 18:39:19 -0700821 if (loc.location != kLocPhysReg) {
822 DCHECK((loc.location == kLocDalvikFrame) ||
823 (loc.location == kLocCompilerTemp));
buzbee67bf8852011-08-17 17:51:35 -0700824 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
825 if (infoLo) {
826 if (infoLo->pair) {
827 oatClobber(cUnit, infoLo->reg);
828 oatClobber(cUnit, infoLo->partner);
buzbee58f92742011-10-01 11:22:17 -0700829 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700830 } else {
831 loc.lowReg = infoLo->reg;
832 loc.location = kLocPhysReg;
833 }
834 }
835 }
836
837 return loc;
838}
839
buzbee6181f792011-09-29 11:14:04 -0700840bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
841{
842 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
843 if (cUnit->regPool->coreRegs[i].pair) {
844 static int myReg = cUnit->regPool->coreRegs[i].reg;
845 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
846 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
buzbee68253262011-10-07 14:02:25 -0700847 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
buzbee6181f792011-09-29 11:14:04 -0700848 DCHECK(partner != NULL);
849 DCHECK(partner->pair);
850 DCHECK_EQ(myReg, partner->partner);
851 static int partnerSreg = partner->sReg;
852 if (mySreg == INVALID_SREG) {
853 DCHECK_EQ(partnerSreg, INVALID_SREG);
854 } else {
855 int diff = mySreg - partnerSreg;
856 DCHECK((diff == -1) || (diff == 1));
857 }
858 }
859 if (!cUnit->regPool->coreRegs[i].live) {
860 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
861 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
862 }
863 }
864 return true;
865}
866
buzbee67bf8852011-08-17 17:51:35 -0700867/* see comments for updateLoc */
buzbee31a4a6f2012-02-28 15:36:15 -0800868extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700869{
buzbeeed3e9302011-09-23 17:34:19 -0700870 DCHECK(loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700871 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbeee1965672012-03-11 18:39:19 -0700872 if (loc.location != kLocPhysReg) {
873 DCHECK((loc.location == kLocDalvikFrame) ||
874 (loc.location == kLocCompilerTemp));
buzbee67bf8852011-08-17 17:51:35 -0700875 // Are the dalvik regs already live in physical registers?
876 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
877 RegisterInfo* infoHi = allocLive(cUnit,
878 oatSRegHi(loc.sRegLow), kAnyReg);
879 bool match = true;
880 match = match && (infoLo != NULL);
881 match = match && (infoHi != NULL);
882 // Are they both core or both FP?
buzbeee3acd072012-02-25 17:03:10 -0800883 match = match && (oatIsFpReg(infoLo->reg) == oatIsFpReg(infoHi->reg));
buzbee67bf8852011-08-17 17:51:35 -0700884 // If a pair of floating point singles, are they properly aligned?
buzbeee3acd072012-02-25 17:03:10 -0800885 if (match && oatIsFpReg(infoLo->reg)) {
buzbee67bf8852011-08-17 17:51:35 -0700886 match &= ((infoLo->reg & 0x1) == 0);
887 match &= ((infoHi->reg - infoLo->reg) == 1);
888 }
889 // If previously used as a pair, it is the same pair?
890 if (match && (infoLo->pair || infoHi->pair)) {
891 match = (infoLo->pair == infoHi->pair);
892 match &= ((infoLo->reg == infoHi->partner) &&
893 (infoHi->reg == infoLo->partner));
894 }
895 if (match) {
896 // Can reuse - update the register usage info
897 loc.lowReg = infoLo->reg;
898 loc.highReg = infoHi->reg;
899 loc.location = kLocPhysReg;
900 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeee3acd072012-02-25 17:03:10 -0800901 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700902 return loc;
903 }
buzbee58f92742011-10-01 11:22:17 -0700904 // Can't easily reuse - clobber and free any overlaps
buzbee67bf8852011-08-17 17:51:35 -0700905 if (infoLo) {
906 oatClobber(cUnit, infoLo->reg);
buzbee58f92742011-10-01 11:22:17 -0700907 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700908 if (infoLo->pair)
909 oatClobber(cUnit, infoLo->partner);
910 }
911 if (infoHi) {
912 oatClobber(cUnit, infoHi->reg);
buzbee58f92742011-10-01 11:22:17 -0700913 oatFreeTemp(cUnit, infoHi->reg);
buzbee67bf8852011-08-17 17:51:35 -0700914 if (infoHi->pair)
915 oatClobber(cUnit, infoHi->partner);
916 }
917 }
918 return loc;
919}
920
buzbeeed3e9302011-09-23 17:34:19 -0700921
922/* For use in cases we don't know (or care) width */
buzbee31a4a6f2012-02-28 15:36:15 -0800923extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700924{
925 if (loc.wide)
926 return oatUpdateLocWide(cUnit, loc);
927 else
928 return oatUpdateLoc(cUnit, loc);
929}
930
buzbee31a4a6f2012-02-28 15:36:15 -0800931RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
932 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700933{
buzbeeed3e9302011-09-23 17:34:19 -0700934 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700935 int newRegs;
936 int lowReg;
937 int highReg;
938
939 loc = oatUpdateLocWide(cUnit, loc);
940
941 /* If already in registers, we can assume proper form. Right reg class? */
942 if (loc.location == kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -0800943 DCHECK_EQ(oatIsFpReg(loc.lowReg), oatIsFpReg(loc.highReg));
944 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700945 if (!regClassMatches(regClass, loc.lowReg)) {
946 /* Wrong register class. Reallocate and copy */
947 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
948 lowReg = newRegs & 0xff;
949 highReg = (newRegs >> 8) & 0xff;
950 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
951 loc.highReg);
952 copyRegInfo(cUnit, lowReg, loc.lowReg);
953 copyRegInfo(cUnit, highReg, loc.highReg);
954 oatClobber(cUnit, loc.lowReg);
955 oatClobber(cUnit, loc.highReg);
956 loc.lowReg = lowReg;
957 loc.highReg = highReg;
958 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeee3acd072012-02-25 17:03:10 -0800959 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700960 }
961 return loc;
962 }
963
buzbeeed3e9302011-09-23 17:34:19 -0700964 DCHECK_NE(loc.sRegLow, INVALID_SREG);
965 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700966
967 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
968 loc.lowReg = newRegs & 0xff;
969 loc.highReg = (newRegs >> 8) & 0xff;
970
971 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
972 if (update) {
973 loc.location = kLocPhysReg;
974 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
975 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
976 }
buzbeee3acd072012-02-25 17:03:10 -0800977 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700978 return loc;
979}
980
981extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
982 int regClass, bool update)
983{
984 int newReg;
985
986 if (loc.wide)
987 return evalLocWide(cUnit, loc, regClass, update);
988
989 loc = oatUpdateLoc(cUnit, loc);
990
991 if (loc.location == kLocPhysReg) {
992 if (!regClassMatches(regClass, loc.lowReg)) {
993 /* Wrong register class. Realloc, copy and transfer ownership */
994 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
995 oatRegCopy(cUnit, newReg, loc.lowReg);
996 copyRegInfo(cUnit, newReg, loc.lowReg);
997 oatClobber(cUnit, loc.lowReg);
998 loc.lowReg = newReg;
999 }
1000 return loc;
1001 }
1002
buzbeeed3e9302011-09-23 17:34:19 -07001003 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001004
1005 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1006 loc.lowReg = newReg;
1007
1008 if (update) {
1009 loc.location = kLocPhysReg;
1010 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1011 }
1012 return loc;
1013}
1014
1015extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1016{
buzbeee9a72f62011-09-04 17:59:07 -07001017 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001018 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001019 return res;
buzbee67bf8852011-08-17 17:51:35 -07001020}
1021extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1022{
buzbeee9a72f62011-09-04 17:59:07 -07001023 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001024 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001025 return res;
1026}
1027extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1028{
1029 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1030 return res;
buzbee67bf8852011-08-17 17:51:35 -07001031}
1032extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1033 int low, int high)
1034{
buzbeee9a72f62011-09-04 17:59:07 -07001035 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001036 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001037 return res;
buzbee67bf8852011-08-17 17:51:35 -07001038}
1039
1040extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1041 int low, int high)
1042{
buzbeee9a72f62011-09-04 17:59:07 -07001043 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001044 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001045 return res;
buzbee67bf8852011-08-17 17:51:35 -07001046}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001047
buzbeee3acd072012-02-25 17:03:10 -08001048/* USE SSA names to count references of base Dalvik vRegs. */
1049void oatCountRefs(CompilationUnit *cUnit, BasicBlock* bb,
buzbee31a4a6f2012-02-28 15:36:15 -08001050 RefCounts* coreCounts, RefCounts* fpCounts)
buzbeee3acd072012-02-25 17:03:10 -08001051{
buzbee239c4e72012-03-16 08:42:29 -07001052 if ((cUnit->disableOpt & (1 << kPromoteRegs)) ||
1053 !((bb->blockType == kEntryBlock) || (bb->blockType == kExitBlock) ||
1054 (bb->blockType == kDalvikByteCode))) {
buzbeee3acd072012-02-25 17:03:10 -08001055 return;
buzbee239c4e72012-03-16 08:42:29 -07001056 }
1057 for (int i = 0; i < cUnit->numSSARegs;) {
1058 RegLocation loc = cUnit->regLocation[i];
1059 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
buzbee9c044ce2012-03-18 13:24:07 -07001060 int pMapIdx = SRegToPMap(cUnit, loc.sRegLow);
buzbee239c4e72012-03-16 08:42:29 -07001061 if (loc.defined) {
buzbee9c044ce2012-03-18 13:24:07 -07001062 counts[pMapIdx].count += cUnit->useCounts.elemList[i];
buzbee239c4e72012-03-16 08:42:29 -07001063 }
1064 if (loc.wide) {
1065 if (loc.defined) {
1066 if (loc.fp) {
buzbee9c044ce2012-03-18 13:24:07 -07001067 counts[pMapIdx].doubleStart = true;
1068 counts[pMapIdx+1].count += cUnit->useCounts.elemList[i+1];
buzbeee3acd072012-02-25 17:03:10 -08001069 }
1070 }
buzbee239c4e72012-03-16 08:42:29 -07001071 i += 2;
1072 } else {
1073 i++;
buzbeee3acd072012-02-25 17:03:10 -08001074 }
1075 }
1076}
1077
1078/* qsort callback function, sort descending */
1079int oatSortCounts(const void *val1, const void *val2)
1080{
1081 const RefCounts* op1 = (const RefCounts*)val1;
1082 const RefCounts* op2 = (const RefCounts*)val2;
1083 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
1084}
1085
1086void oatDumpCounts(const RefCounts* arr, int size, const char* msg)
1087{
1088 LOG(INFO) << msg;
1089 for (int i = 0; i < size; i++) {
1090 LOG(INFO) << "sReg[" << arr[i].sReg << "]: " << arr[i].count;
1091 }
1092}
1093
1094/*
1095 * Note: some portions of this code required even if the kPromoteRegs
1096 * optimization is disabled.
1097 */
1098extern void oatDoPromotion(CompilationUnit* cUnit)
1099{
buzbee239c4e72012-03-16 08:42:29 -07001100 int regBias = cUnit->numCompilerTemps + 1;
1101 int dalvikRegs = cUnit->numDalvikRegisters;
1102 int numRegs = dalvikRegs + regBias;
buzbeea7c12682012-03-19 13:13:53 -07001103 const int promotionThreshold = 2;
buzbeee3acd072012-02-25 17:03:10 -08001104
1105 // Allow target code to add any special registers
1106 oatAdjustSpillMask(cUnit);
1107
1108 /*
1109 * Simple register promotion. Just do a static count of the uses
1110 * of Dalvik registers. Note that we examine the SSA names, but
1111 * count based on original Dalvik register name. Count refs
1112 * separately based on type in order to give allocation
1113 * preference to fp doubles - which must be allocated sequential
1114 * physical single fp registers started with an even-numbered
1115 * reg.
1116 * TUNING: replace with linear scan once we have the ability
1117 * to describe register live ranges for GC.
1118 */
1119 RefCounts *coreRegs = (RefCounts *)
1120 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1121 RefCounts *fpRegs = (RefCounts *)
1122 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
buzbee239c4e72012-03-16 08:42:29 -07001123 // Set ssa names for original Dalvik registers
1124 for (int i = 0; i < dalvikRegs; i++) {
buzbeee3acd072012-02-25 17:03:10 -08001125 coreRegs[i].sReg = fpRegs[i].sReg = i;
1126 }
buzbee9c044ce2012-03-18 13:24:07 -07001127 // Set ssa name for Method*
1128 coreRegs[dalvikRegs].sReg = cUnit->methodSReg;
1129 fpRegs[dalvikRegs].sReg = cUnit->methodSReg; // For consistecy
1130 // Set ssa names for compilerTemps
1131 for (int i = 1; i <= cUnit->numCompilerTemps; i++) {
1132 CompilerTemp* ct = (CompilerTemp*)cUnit->compilerTemps.elemList[i];
1133 coreRegs[dalvikRegs + i].sReg = ct->sReg;
1134 fpRegs[dalvikRegs + i].sReg = ct->sReg;
buzbee239c4e72012-03-16 08:42:29 -07001135 }
buzbee9c044ce2012-03-18 13:24:07 -07001136
buzbeee3acd072012-02-25 17:03:10 -08001137 GrowableListIterator iterator;
1138 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
1139 while (true) {
1140 BasicBlock* bb;
1141 bb = (BasicBlock*)oatGrowableListIteratorNext(&iterator);
1142 if (bb == NULL) break;
1143 oatCountRefs(cUnit, bb, coreRegs, fpRegs);
1144 }
1145
1146 /*
1147 * Ideally, we'd allocate doubles starting with an even-numbered
1148 * register. Bias the counts to try to allocate any vreg that's
1149 * used as the start of a pair first.
1150 */
1151 for (int i = 0; i < numRegs; i++) {
1152 if (fpRegs[i].doubleStart) {
1153 fpRegs[i].count *= 2;
1154 }
1155 }
1156
1157 // Sort the count arrays
1158 qsort(coreRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1159 qsort(fpRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1160
1161 if (cUnit->printMe) {
1162 oatDumpCounts(coreRegs, numRegs, "Core regs after sort");
1163 oatDumpCounts(fpRegs, numRegs, "Fp regs after sort");
1164 }
1165
1166 if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
1167 // Promote fpRegs
buzbeea7c12682012-03-19 13:13:53 -07001168 for (int i = 0; (i < numRegs) &&
1169 (fpRegs[i].count >= promotionThreshold ); i++) {
buzbee9c044ce2012-03-18 13:24:07 -07001170 int pMapIdx = SRegToPMap(cUnit, fpRegs[i].sReg);
1171 if (cUnit->promotionMap[pMapIdx].fpLocation != kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001172 int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
1173 fpRegs[i].doubleStart);
1174 if (reg < 0) {
1175 break; // No more left
1176 }
1177 }
1178 }
1179
1180 // Promote core regs
buzbeea7c12682012-03-19 13:13:53 -07001181 for (int i = 0; (i < numRegs) &&
1182 (coreRegs[i].count > promotionThreshold); i++) {
buzbee9c044ce2012-03-18 13:24:07 -07001183 int pMapIdx = SRegToPMap(cUnit, coreRegs[i].sReg);
1184 if (cUnit->promotionMap[pMapIdx].coreLocation !=
buzbeee3acd072012-02-25 17:03:10 -08001185 kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001186 int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
1187 if (reg < 0) {
1188 break; // No more left
1189 }
1190 }
1191 }
buzbeea7c12682012-03-19 13:13:53 -07001192 } else if (cUnit->qdMode) {
1193 oatAllocPreservedCoreReg(cUnit, cUnit->methodSReg);
1194 for (int i = 0; i < numRegs; i++) {
1195 int reg = oatAllocPreservedCoreReg(cUnit, i);
1196 if (reg < 0) {
1197 break; // No more left
1198 }
1199 }
buzbeee3acd072012-02-25 17:03:10 -08001200 }
1201
buzbeea7c12682012-03-19 13:13:53 -07001202
buzbeee3acd072012-02-25 17:03:10 -08001203 // Now, update SSA names to new home locations
1204 for (int i = 0; i < cUnit->numSSARegs; i++) {
1205 RegLocation *curr = &cUnit->regLocation[i];
buzbee9c044ce2012-03-18 13:24:07 -07001206 int pMapIdx = SRegToPMap(cUnit, curr->sRegLow);
buzbeee3acd072012-02-25 17:03:10 -08001207 if (!curr->wide) {
1208 if (curr->fp) {
buzbee9c044ce2012-03-18 13:24:07 -07001209 if (cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001210 curr->location = kLocPhysReg;
buzbee9c044ce2012-03-18 13:24:07 -07001211 curr->lowReg = cUnit->promotionMap[pMapIdx].fpReg;
buzbeee3acd072012-02-25 17:03:10 -08001212 curr->home = true;
1213 }
1214 } else {
buzbee9c044ce2012-03-18 13:24:07 -07001215 if (cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001216 curr->location = kLocPhysReg;
buzbee9c044ce2012-03-18 13:24:07 -07001217 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
buzbeee3acd072012-02-25 17:03:10 -08001218 curr->home = true;
1219 }
1220 }
1221 curr->highReg = INVALID_REG;
1222 } else {
1223 if (curr->highWord) {
1224 continue;
1225 }
1226 if (curr->fp) {
buzbee9c044ce2012-03-18 13:24:07 -07001227 if ((cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) &&
1228 (cUnit->promotionMap[pMapIdx+1].fpLocation ==
buzbeee3acd072012-02-25 17:03:10 -08001229 kLocPhysReg)) {
buzbee9c044ce2012-03-18 13:24:07 -07001230 int lowReg = cUnit->promotionMap[pMapIdx].fpReg;
1231 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
buzbeee3acd072012-02-25 17:03:10 -08001232 // Doubles require pair of singles starting at even reg
1233 if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
1234 curr->location = kLocPhysReg;
1235 curr->lowReg = lowReg;
1236 curr->highReg = highReg;
1237 curr->home = true;
1238 }
1239 }
1240 } else {
buzbee9c044ce2012-03-18 13:24:07 -07001241 if ((cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg)
1242 && (cUnit->promotionMap[pMapIdx+1].coreLocation ==
buzbeee3acd072012-02-25 17:03:10 -08001243 kLocPhysReg)) {
1244 curr->location = kLocPhysReg;
buzbee9c044ce2012-03-18 13:24:07 -07001245 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1246 curr->highReg = cUnit->promotionMap[pMapIdx+1].coreReg;
buzbeee3acd072012-02-25 17:03:10 -08001247 curr->home = true;
1248 }
1249 }
1250 }
1251 }
1252}
1253
1254/* Returns sp-relative offset in bytes for a VReg */
1255extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
1256{
buzbeeefccc562012-03-11 11:19:28 -07001257 return Frame::GetVRegOffset(cUnit->code_item, cUnit->coreSpillMask,
1258 cUnit->fpSpillMask, cUnit->frameSize, vReg);
buzbeee3acd072012-02-25 17:03:10 -08001259}
1260
1261/* Returns sp-relative offset in bytes for a SReg */
1262extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
1263{
buzbeee1965672012-03-11 18:39:19 -07001264 return oatVRegOffset(cUnit, SRegToVReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -08001265}
1266
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001267} // namespace art