blob: c08b2e883a558929b4cf026b70d55ffd99dd6b3a [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
buzbeee1965672012-03-11 18:39:19 -0700156/* Sanity check */
157bool validSreg(CompilationUnit* cUnit, int sReg)
158{
159 bool res = ((-(cUnit->numCompilerTemps + 1) <= sReg) &&
160 (sReg < cUnit->numDalvikRegisters));
161 if (!res) {
162 LOG(WARNING) << "Bad sreg: " << sReg;
163 LOG(WARNING) << " low = " << -(cUnit->numCompilerTemps + 1);
164 LOG(WARNING) << " high = " << cUnit->numRegs;
165 }
166 return res;
167}
168
buzbee67bf8852011-08-17 17:51:35 -0700169/* Reserve a callee-save register. Return -1 if none available */
170extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
171{
172 int res = -1;
173 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
174 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
175 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
176 res = coreRegs[i].reg;
177 coreRegs[i].inUse = true;
178 cUnit->coreSpillMask |= (1 << res);
buzbeec41e5b52011-09-23 12:46:19 -0700179 cUnit->coreVmapTable.push_back(sReg);
buzbeebbaf8942011-10-02 13:08:29 -0700180 cUnit->numCoreSpills++;
buzbee67bc2362011-10-11 18:08:40 -0700181 // Should be promoting based on initial sReg set
buzbeee1965672012-03-11 18:39:19 -0700182 DCHECK_EQ(sReg, SRegToVReg(cUnit, sReg));
183 DCHECK(validSreg(cUnit,sReg));
buzbee67bc2362011-10-11 18:08:40 -0700184 cUnit->promotionMap[sReg].coreLocation = kLocPhysReg;
185 cUnit->promotionMap[sReg].coreReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700186 break;
187 }
188 }
189 return res;
190}
191
192/*
193 * Reserve a callee-save fp single register. Try to fullfill request for
194 * even/odd allocation, but go ahead and allocate anything if not
195 * available. If nothing's available, return -1.
196 */
buzbee31a4a6f2012-02-28 15:36:15 -0800197int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700198{
199 int res = -1;
200 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
201 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
202 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
203 ((FPRegs[i].reg & 0x1) == 0) == even) {
204 res = FPRegs[i].reg;
205 FPRegs[i].inUse = true;
buzbee67bc2362011-10-11 18:08:40 -0700206 // Should be promoting based on initial sReg set
buzbeee1965672012-03-11 18:39:19 -0700207 DCHECK_EQ(sReg, SRegToVReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -0800208 oatMarkPreservedSingle(cUnit, sReg, res);
buzbeee1965672012-03-11 18:39:19 -0700209 DCHECK(validSreg(cUnit,sReg));
buzbee67bc2362011-10-11 18:08:40 -0700210 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
211 cUnit->promotionMap[sReg].fpReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700212 break;
213 }
214 }
215 return res;
216}
217
218/*
219 * Somewhat messy code here. We want to allocate a pair of contiguous
220 * physical single-precision floating point registers starting with
221 * an even numbered reg. It is possible that the paired sReg (sReg+1)
222 * has already been allocated - try to fit if possible. Fail to
223 * allocate if we can't meet the requirements for the pair of
224 * sReg<=sX[even] & (sReg+1)<= sX+1.
225 */
buzbee31a4a6f2012-02-28 15:36:15 -0800226int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700227{
228 int res = -1; // Assume failure
buzbee67bc2362011-10-11 18:08:40 -0700229 // Should be promoting based on initial sReg set
buzbeee1965672012-03-11 18:39:19 -0700230 DCHECK_EQ(sReg, SRegToVReg(cUnit, sReg));
231 DCHECK(validSreg(cUnit,sReg+1));
buzbee67bc2362011-10-11 18:08:40 -0700232 if (cUnit->promotionMap[sReg+1].fpLocation == kLocPhysReg) {
buzbee67bf8852011-08-17 17:51:35 -0700233 // Upper reg is already allocated. Can we fit?
buzbee67bc2362011-10-11 18:08:40 -0700234 int highReg = cUnit->promotionMap[sReg+1].fpReg;
buzbee67bf8852011-08-17 17:51:35 -0700235 if ((highReg & 1) == 0) {
236 // High reg is even - fail.
237 return res;
238 }
239 // Is the low reg of the pair free?
buzbee68253262011-10-07 14:02:25 -0700240 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
buzbee67bf8852011-08-17 17:51:35 -0700241 if (p->inUse || p->isTemp) {
242 // Already allocated or not preserved - fail.
243 return res;
244 }
245 // OK - good to go.
246 res = p->reg;
247 p->inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700248 DCHECK_EQ((res & 1), 0);
buzbeee3acd072012-02-25 17:03:10 -0800249 oatMarkPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700250 } else {
251 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
252 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
253 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
254 ((FPRegs[i].reg & 0x1) == 0x0) &&
255 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
256 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
257 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
258 res = FPRegs[i].reg;
259 FPRegs[i].inUse = true;
buzbeee3acd072012-02-25 17:03:10 -0800260 oatMarkPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700261 FPRegs[i+1].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700262 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
buzbeee3acd072012-02-25 17:03:10 -0800263 oatMarkPreservedSingle(cUnit, sReg+1, res+1);
buzbee67bf8852011-08-17 17:51:35 -0700264 break;
265 }
266 }
267 }
268 if (res != -1) {
buzbeee1965672012-03-11 18:39:19 -0700269 DCHECK(validSreg(cUnit,sReg));
buzbee67bc2362011-10-11 18:08:40 -0700270 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
271 cUnit->promotionMap[sReg].fpReg = res;
buzbeee1965672012-03-11 18:39:19 -0700272 DCHECK(validSreg(cUnit,sReg+1));
buzbee67bc2362011-10-11 18:08:40 -0700273 cUnit->promotionMap[sReg+1].fpLocation = kLocPhysReg;
274 cUnit->promotionMap[sReg+1].fpReg = res + 1;
buzbee67bf8852011-08-17 17:51:35 -0700275 }
276 return res;
277}
278
279
280/*
281 * Reserve a callee-save fp register. If this register can be used
282 * as the first of a double, attempt to allocate an even pair of fp
283 * single regs (but if can't still attempt to allocate a single, preferring
284 * first to allocate an odd register.
285 */
286extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
287 bool doubleStart)
288{
289 int res = -1;
290 if (doubleStart) {
291 res = allocPreservedDouble(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700292 }
293 if (res == -1) {
294 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
295 }
296 if (res == -1)
297 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
298 return res;
299}
300
buzbee31a4a6f2012-02-28 15:36:15 -0800301int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
302 int* nextTemp, bool required)
buzbee67bf8852011-08-17 17:51:35 -0700303{
304 int i;
305 int next = *nextTemp;
306 for (i=0; i< numRegs; i++) {
307 if (next >= numRegs)
308 next = 0;
309 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
310 oatClobber(cUnit, p[next].reg);
311 p[next].inUse = true;
312 p[next].pair = false;
313 *nextTemp = next + 1;
314 return p[next].reg;
315 }
316 next++;
317 }
318 next = *nextTemp;
319 for (i=0; i< numRegs; i++) {
320 if (next >= numRegs)
321 next = 0;
322 if (p[next].isTemp && !p[next].inUse) {
323 oatClobber(cUnit, p[next].reg);
324 p[next].inUse = true;
325 p[next].pair = false;
326 *nextTemp = next + 1;
327 return p[next].reg;
328 }
329 next++;
330 }
331 if (required) {
buzbee6181f792011-09-29 11:14:04 -0700332 oatCodegenDump(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700333 dumpRegPool(cUnit->regPool->coreRegs,
334 cUnit->regPool->numCoreRegs);
335 LOG(FATAL) << "No free temp registers";
336 }
337 return -1; // No register available
338}
339
340//REDO: too many assumptions.
341extern int oatAllocTempDouble(CompilationUnit* cUnit)
342{
343 RegisterInfo* p = cUnit->regPool->FPRegs;
344 int numRegs = cUnit->regPool->numFPRegs;
buzbeea50638b2011-11-02 15:15:06 -0700345 /* Start looking at an even reg */
346 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700347
buzbeea50638b2011-11-02 15:15:06 -0700348 // First try to avoid allocating live registers
349 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700350 if (next >= numRegs)
351 next = 0;
352 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
353 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
354 oatClobber(cUnit, p[next].reg);
355 oatClobber(cUnit, p[next+1].reg);
356 p[next].inUse = true;
357 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700358 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
359 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700360 cUnit->regPool->nextFPReg = next + 2;
361 if (cUnit->regPool->nextFPReg >= numRegs) {
362 cUnit->regPool->nextFPReg = 0;
363 }
buzbee67bf8852011-08-17 17:51:35 -0700364 return p[next].reg;
365 }
366 next += 2;
367 }
buzbeea50638b2011-11-02 15:15:06 -0700368 next = cUnit->regPool->nextFPReg & ~0x1;
369
370 // No choice - find a pair and kill it.
371 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700372 if (next >= numRegs)
373 next = 0;
374 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
375 !p[next+1].inUse) {
376 oatClobber(cUnit, p[next].reg);
377 oatClobber(cUnit, p[next+1].reg);
378 p[next].inUse = true;
379 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700380 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
381 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700382 cUnit->regPool->nextFPReg = next + 2;
383 if (cUnit->regPool->nextFPReg >= numRegs) {
384 cUnit->regPool->nextFPReg = 0;
385 }
buzbee67bf8852011-08-17 17:51:35 -0700386 return p[next].reg;
387 }
388 next += 2;
389 }
buzbee6181f792011-09-29 11:14:04 -0700390 LOG(FATAL) << "No free temp registers (pair)";
buzbee67bf8852011-08-17 17:51:35 -0700391 return -1;
392}
393
394/* Return a temp if one is available, -1 otherwise */
395extern int oatAllocFreeTemp(CompilationUnit* cUnit)
396{
397 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
398 cUnit->regPool->numCoreRegs,
399 &cUnit->regPool->nextCoreReg, true);
400}
401
402extern int oatAllocTemp(CompilationUnit* cUnit)
403{
404 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
405 cUnit->regPool->numCoreRegs,
406 &cUnit->regPool->nextCoreReg, true);
407}
408
409extern int oatAllocTempFloat(CompilationUnit* cUnit)
410{
411 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
412 cUnit->regPool->numFPRegs,
413 &cUnit->regPool->nextFPReg, true);
414}
415
buzbee31a4a6f2012-02-28 15:36:15 -0800416RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700417{
418 int i;
419 if (sReg == -1)
420 return NULL;
421 for (i=0; i < numRegs; i++) {
422 if (p[i].live && (p[i].sReg == sReg)) {
423 if (p[i].isTemp)
424 p[i].inUse = true;
425 return &p[i];
426 }
427 }
428 return NULL;
429}
430
buzbee31a4a6f2012-02-28 15:36:15 -0800431RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg, int regClass)
buzbee67bf8852011-08-17 17:51:35 -0700432{
433 RegisterInfo* res = NULL;
434 switch(regClass) {
435 case kAnyReg:
436 res = allocLiveBody(cUnit->regPool->FPRegs,
437 cUnit->regPool->numFPRegs, sReg);
438 if (res)
439 break;
440 /* Intentional fallthrough */
441 case kCoreReg:
442 res = allocLiveBody(cUnit->regPool->coreRegs,
443 cUnit->regPool->numCoreRegs, sReg);
444 break;
445 case kFPReg:
446 res = allocLiveBody(cUnit->regPool->FPRegs,
447 cUnit->regPool->numFPRegs, sReg);
448 break;
449 default:
450 LOG(FATAL) << "Invalid register type";
451 }
452 return res;
453}
454
455extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
456{
457 RegisterInfo* p = cUnit->regPool->coreRegs;
458 int numRegs = cUnit->regPool->numCoreRegs;
459 int i;
460 for (i=0; i< numRegs; i++) {
461 if (p[i].reg == reg) {
462 if (p[i].isTemp) {
463 p[i].inUse = false;
464 }
465 p[i].pair = false;
466 return;
467 }
468 }
469 p = cUnit->regPool->FPRegs;
470 numRegs = cUnit->regPool->numFPRegs;
471 for (i=0; i< numRegs; i++) {
472 if (p[i].reg == reg) {
473 if (p[i].isTemp) {
474 p[i].inUse = false;
475 }
476 p[i].pair = false;
477 return;
478 }
479 }
480 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
481}
482
483extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
484{
485 RegisterInfo* p = cUnit->regPool->coreRegs;
486 int numRegs = cUnit->regPool->numCoreRegs;
487 int i;
488 for (i=0; i< numRegs; i++) {
489 if (p[i].reg == reg) {
490 return p[i].live ? &p[i] : NULL;
491 }
492 }
493 p = cUnit->regPool->FPRegs;
494 numRegs = cUnit->regPool->numFPRegs;
495 for (i=0; i< numRegs; i++) {
496 if (p[i].reg == reg) {
497 return p[i].live ? &p[i] : NULL;
498 }
499 }
500 return NULL;
501}
502
503extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
504{
buzbee68253262011-10-07 14:02:25 -0700505 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700506 return (p->isTemp) ? p : NULL;
507}
508
buzbeeb29e4d12011-09-26 15:05:48 -0700509extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
510{
buzbee68253262011-10-07 14:02:25 -0700511 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbeeb29e4d12011-09-26 15:05:48 -0700512 return (p->isTemp) ? NULL : p;
513}
514
buzbee67bf8852011-08-17 17:51:35 -0700515extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
516{
buzbee68253262011-10-07 14:02:25 -0700517 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700518 return p->dirty;
519}
520
521/*
522 * Similar to oatAllocTemp(), but forces the allocation of a specific
523 * register. No check is made to see if the register was previously
524 * allocated. Use with caution.
525 */
526extern void oatLockTemp(CompilationUnit* cUnit, int reg)
527{
528 RegisterInfo* p = cUnit->regPool->coreRegs;
529 int numRegs = cUnit->regPool->numCoreRegs;
530 int i;
531 for (i=0; i< numRegs; i++) {
532 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700533 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700534 p[i].inUse = true;
535 p[i].live = false;
536 return;
537 }
538 }
539 p = cUnit->regPool->FPRegs;
540 numRegs = cUnit->regPool->numFPRegs;
541 for (i=0; i< numRegs; i++) {
542 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700543 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700544 p[i].inUse = true;
545 p[i].live = false;
546 return;
547 }
548 }
549 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
550}
551
buzbee5abfa3e2012-01-31 17:01:43 -0800552static inline void resetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700553{
buzbee67bf8852011-08-17 17:51:35 -0700554 p->defStart = NULL;
555 p->defEnd = NULL;
556}
557
buzbee5abfa3e2012-01-31 17:01:43 -0800558extern void oatResetDef(CompilationUnit* cUnit, int reg)
559{
560 resetDefBody(oatGetRegInfo(cUnit, reg));
561}
562
buzbee31a4a6f2012-02-28 15:36:15 -0800563void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700564 int sReg1, int sReg2)
565{
566 if (start && finish) {
567 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700568 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700569 for (p = start; ;p = p->next) {
buzbeee3acd072012-02-25 17:03:10 -0800570 oatNopLIR(p);
buzbee67bf8852011-08-17 17:51:35 -0700571 if (p == finish)
572 break;
573 }
574 }
575}
576
577/*
578 * Mark the beginning and end LIR of a def sequence. Note that
579 * on entry start points to the LIR prior to the beginning of the
580 * sequence.
581 */
582extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
buzbee31a4a6f2012-02-28 15:36:15 -0800583 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700584{
buzbeeed3e9302011-09-23 17:34:19 -0700585 DCHECK(!rl.wide);
586 DCHECK(start && start->next);
587 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700588 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700589 p->defStart = start->next;
590 p->defEnd = finish;
591}
592
593/*
594 * Mark the beginning and end LIR of a def sequence. Note that
595 * on entry start points to the LIR prior to the beginning of the
596 * sequence.
597 */
598extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
buzbee31a4a6f2012-02-28 15:36:15 -0800599 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700600{
buzbeeed3e9302011-09-23 17:34:19 -0700601 DCHECK(rl.wide);
602 DCHECK(start && start->next);
603 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700604 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700605 oatResetDef(cUnit, rl.highReg); // Only track low of pair
606 p->defStart = start->next;
607 p->defEnd = finish;
608}
609
buzbee31a4a6f2012-02-28 15:36:15 -0800610extern RegLocation oatWideToNarrow(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700611{
buzbeeed3e9302011-09-23 17:34:19 -0700612 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700613 if (rl.location == kLocPhysReg) {
buzbee68253262011-10-07 14:02:25 -0700614 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
615 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700616 if (infoLo->isTemp) {
617 infoLo->pair = false;
618 infoLo->defStart = NULL;
619 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700620 }
buzbee0c7f26d2011-09-07 12:28:51 -0700621 if (infoHi->isTemp) {
622 infoHi->pair = false;
623 infoHi->defStart = NULL;
624 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700625 }
buzbee67bf8852011-08-17 17:51:35 -0700626 }
627 rl.wide = false;
628 return rl;
629}
630
631extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
632{
buzbeeed3e9302011-09-23 17:34:19 -0700633 DCHECK(!rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700634 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
635 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
buzbeeed3e9302011-09-23 17:34:19 -0700636 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700637 nullifyRange(cUnit, p->defStart, p->defEnd,
638 p->sReg, rl.sRegLow);
639 }
640 oatResetDef(cUnit, rl.lowReg);
641}
642
643extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
644{
buzbeeed3e9302011-09-23 17:34:19 -0700645 DCHECK(rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700646 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
647 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
648 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
649 DCHECK(pLow->pair);
650 nullifyRange(cUnit, pLow->defStart, pLow->defEnd,
651 pLow->sReg, rl.sRegLow);
652 }
653 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
654 DCHECK(pHigh->pair);
buzbee67bf8852011-08-17 17:51:35 -0700655 }
656 oatResetDef(cUnit, rl.lowReg);
657 oatResetDef(cUnit, rl.highReg);
658}
659
660extern void oatResetDefTracking(CompilationUnit* cUnit)
661{
662 int i;
663 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800664 resetDefBody(&cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700665 }
666 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800667 resetDefBody(&cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700668 }
669}
670
671extern void oatClobberAllRegs(CompilationUnit* cUnit)
672{
673 int i;
674 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800675 clobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700676 }
677 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800678 clobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700679 }
680}
681
buzbee67bf8852011-08-17 17:51:35 -0700682// Make sure nothing is live and dirty
buzbee31a4a6f2012-02-28 15:36:15 -0800683void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700684 int numRegs)
685{
686 int i;
687 for (i=0; i < numRegs; i++) {
688 if (info[i].live && info[i].dirty) {
689 if (info[i].pair) {
690 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
691 } else {
692 oatFlushReg(cUnit, info[i].reg);
693 }
694 }
695 }
696}
697
698extern void oatFlushAllRegs(CompilationUnit* cUnit)
699{
700 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
701 cUnit->regPool->numCoreRegs);
702 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
703 cUnit->regPool->numFPRegs);
704 oatClobberAllRegs(cUnit);
705}
706
707
708//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee31a4a6f2012-02-28 15:36:15 -0800709bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700710{
711 if (regClass == kAnyReg) {
712 return true;
713 } else if (regClass == kCoreReg) {
buzbeee3acd072012-02-25 17:03:10 -0800714 return !oatIsFpReg(reg);
buzbee67bf8852011-08-17 17:51:35 -0700715 } else {
buzbeee3acd072012-02-25 17:03:10 -0800716 return oatIsFpReg(reg);
buzbee67bf8852011-08-17 17:51:35 -0700717 }
718}
719
720extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
721{
buzbee68253262011-10-07 14:02:25 -0700722 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700723 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
724 return; /* already live */
725 } else if (sReg != INVALID_SREG) {
726 oatClobberSReg(cUnit, sReg);
727 if (info->isTemp) {
728 info->live = true;
729 }
730 } else {
731 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700732 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700733 info->live = false;
734 }
735 info->sReg = sReg;
736}
737
738extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
739{
buzbee68253262011-10-07 14:02:25 -0700740 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700741 info->isTemp = true;
742}
743
buzbee9e0f9b02011-08-24 15:32:46 -0700744extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
745{
buzbee68253262011-10-07 14:02:25 -0700746 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee9e0f9b02011-08-24 15:32:46 -0700747 info->isTemp = false;
748}
749
buzbee67bf8852011-08-17 17:51:35 -0700750extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
751{
buzbee68253262011-10-07 14:02:25 -0700752 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
753 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
buzbee67bf8852011-08-17 17:51:35 -0700754 infoLo->pair = infoHi->pair = true;
755 infoLo->partner = highReg;
756 infoHi->partner = lowReg;
757}
758
759extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
760{
buzbee68253262011-10-07 14:02:25 -0700761 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700762 info->dirty = false;
763 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700764 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700765 info->dirty = false;
766 }
767}
768
769extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
770{
771 if (loc.home) {
772 // If already home, can't be dirty
773 return;
774 }
buzbee68253262011-10-07 14:02:25 -0700775 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700776 info->dirty = true;
777 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700778 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700779 info->dirty = true;
780 }
781}
782
783extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
784{
buzbee68253262011-10-07 14:02:25 -0700785 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700786 info->inUse = true;
787}
788
buzbee31a4a6f2012-02-28 15:36:15 -0800789void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700790{
buzbee68253262011-10-07 14:02:25 -0700791 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
792 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700793 // Target temp status must not change
794 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700795 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700796 // Restore target's temp status
797 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700798 newInfo->reg = newReg;
799}
800
801/*
802 * Return an updated location record with current in-register status.
803 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700804 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700805 * clobber both low and high.
806 * TUNING: clobbering both is a bit heavy-handed, but the alternative
807 * is a bit complex when dealing with FP regs. Examine code to see
808 * if it's worthwhile trying to be more clever here.
809 */
810
811extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
812{
buzbeeed3e9302011-09-23 17:34:19 -0700813 DCHECK(!loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700814 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbeee1965672012-03-11 18:39:19 -0700815 if (loc.location != kLocPhysReg) {
816 DCHECK((loc.location == kLocDalvikFrame) ||
817 (loc.location == kLocCompilerTemp));
buzbee67bf8852011-08-17 17:51:35 -0700818 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
819 if (infoLo) {
820 if (infoLo->pair) {
821 oatClobber(cUnit, infoLo->reg);
822 oatClobber(cUnit, infoLo->partner);
buzbee58f92742011-10-01 11:22:17 -0700823 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700824 } else {
825 loc.lowReg = infoLo->reg;
826 loc.location = kLocPhysReg;
827 }
828 }
829 }
830
831 return loc;
832}
833
buzbee6181f792011-09-29 11:14:04 -0700834bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
835{
836 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
837 if (cUnit->regPool->coreRegs[i].pair) {
838 static int myReg = cUnit->regPool->coreRegs[i].reg;
839 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
840 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
buzbee68253262011-10-07 14:02:25 -0700841 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
buzbee6181f792011-09-29 11:14:04 -0700842 DCHECK(partner != NULL);
843 DCHECK(partner->pair);
844 DCHECK_EQ(myReg, partner->partner);
845 static int partnerSreg = partner->sReg;
846 if (mySreg == INVALID_SREG) {
847 DCHECK_EQ(partnerSreg, INVALID_SREG);
848 } else {
849 int diff = mySreg - partnerSreg;
850 DCHECK((diff == -1) || (diff == 1));
851 }
852 }
853 if (!cUnit->regPool->coreRegs[i].live) {
854 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
855 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
856 }
857 }
858 return true;
859}
860
buzbee67bf8852011-08-17 17:51:35 -0700861/* see comments for updateLoc */
buzbee31a4a6f2012-02-28 15:36:15 -0800862extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700863{
buzbeeed3e9302011-09-23 17:34:19 -0700864 DCHECK(loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700865 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbeee1965672012-03-11 18:39:19 -0700866 if (loc.location != kLocPhysReg) {
867 DCHECK((loc.location == kLocDalvikFrame) ||
868 (loc.location == kLocCompilerTemp));
buzbee67bf8852011-08-17 17:51:35 -0700869 // Are the dalvik regs already live in physical registers?
870 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
871 RegisterInfo* infoHi = allocLive(cUnit,
872 oatSRegHi(loc.sRegLow), kAnyReg);
873 bool match = true;
874 match = match && (infoLo != NULL);
875 match = match && (infoHi != NULL);
876 // Are they both core or both FP?
buzbeee3acd072012-02-25 17:03:10 -0800877 match = match && (oatIsFpReg(infoLo->reg) == oatIsFpReg(infoHi->reg));
buzbee67bf8852011-08-17 17:51:35 -0700878 // If a pair of floating point singles, are they properly aligned?
buzbeee3acd072012-02-25 17:03:10 -0800879 if (match && oatIsFpReg(infoLo->reg)) {
buzbee67bf8852011-08-17 17:51:35 -0700880 match &= ((infoLo->reg & 0x1) == 0);
881 match &= ((infoHi->reg - infoLo->reg) == 1);
882 }
883 // If previously used as a pair, it is the same pair?
884 if (match && (infoLo->pair || infoHi->pair)) {
885 match = (infoLo->pair == infoHi->pair);
886 match &= ((infoLo->reg == infoHi->partner) &&
887 (infoHi->reg == infoLo->partner));
888 }
889 if (match) {
890 // Can reuse - update the register usage info
891 loc.lowReg = infoLo->reg;
892 loc.highReg = infoHi->reg;
893 loc.location = kLocPhysReg;
894 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeee3acd072012-02-25 17:03:10 -0800895 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700896 return loc;
897 }
buzbee58f92742011-10-01 11:22:17 -0700898 // Can't easily reuse - clobber and free any overlaps
buzbee67bf8852011-08-17 17:51:35 -0700899 if (infoLo) {
900 oatClobber(cUnit, infoLo->reg);
buzbee58f92742011-10-01 11:22:17 -0700901 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700902 if (infoLo->pair)
903 oatClobber(cUnit, infoLo->partner);
904 }
905 if (infoHi) {
906 oatClobber(cUnit, infoHi->reg);
buzbee58f92742011-10-01 11:22:17 -0700907 oatFreeTemp(cUnit, infoHi->reg);
buzbee67bf8852011-08-17 17:51:35 -0700908 if (infoHi->pair)
909 oatClobber(cUnit, infoHi->partner);
910 }
911 }
912 return loc;
913}
914
buzbeeed3e9302011-09-23 17:34:19 -0700915
916/* For use in cases we don't know (or care) width */
buzbee31a4a6f2012-02-28 15:36:15 -0800917extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700918{
919 if (loc.wide)
920 return oatUpdateLocWide(cUnit, loc);
921 else
922 return oatUpdateLoc(cUnit, loc);
923}
924
buzbee31a4a6f2012-02-28 15:36:15 -0800925RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
926 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700927{
buzbeeed3e9302011-09-23 17:34:19 -0700928 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700929 int newRegs;
930 int lowReg;
931 int highReg;
932
933 loc = oatUpdateLocWide(cUnit, loc);
934
935 /* If already in registers, we can assume proper form. Right reg class? */
936 if (loc.location == kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -0800937 DCHECK_EQ(oatIsFpReg(loc.lowReg), oatIsFpReg(loc.highReg));
938 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700939 if (!regClassMatches(regClass, loc.lowReg)) {
940 /* Wrong register class. Reallocate and copy */
941 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
942 lowReg = newRegs & 0xff;
943 highReg = (newRegs >> 8) & 0xff;
944 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
945 loc.highReg);
946 copyRegInfo(cUnit, lowReg, loc.lowReg);
947 copyRegInfo(cUnit, highReg, loc.highReg);
948 oatClobber(cUnit, loc.lowReg);
949 oatClobber(cUnit, loc.highReg);
950 loc.lowReg = lowReg;
951 loc.highReg = highReg;
952 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeee3acd072012-02-25 17:03:10 -0800953 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700954 }
955 return loc;
956 }
957
buzbeeed3e9302011-09-23 17:34:19 -0700958 DCHECK_NE(loc.sRegLow, INVALID_SREG);
959 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700960
961 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
962 loc.lowReg = newRegs & 0xff;
963 loc.highReg = (newRegs >> 8) & 0xff;
964
965 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
966 if (update) {
967 loc.location = kLocPhysReg;
968 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
969 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
970 }
buzbeee3acd072012-02-25 17:03:10 -0800971 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700972 return loc;
973}
974
975extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
976 int regClass, bool update)
977{
978 int newReg;
979
980 if (loc.wide)
981 return evalLocWide(cUnit, loc, regClass, update);
982
983 loc = oatUpdateLoc(cUnit, loc);
984
985 if (loc.location == kLocPhysReg) {
986 if (!regClassMatches(regClass, loc.lowReg)) {
987 /* Wrong register class. Realloc, copy and transfer ownership */
988 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
989 oatRegCopy(cUnit, newReg, loc.lowReg);
990 copyRegInfo(cUnit, newReg, loc.lowReg);
991 oatClobber(cUnit, loc.lowReg);
992 loc.lowReg = newReg;
993 }
994 return loc;
995 }
996
buzbeeed3e9302011-09-23 17:34:19 -0700997 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700998
999 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1000 loc.lowReg = newReg;
1001
1002 if (update) {
1003 loc.location = kLocPhysReg;
1004 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1005 }
1006 return loc;
1007}
1008
1009extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1010{
buzbeee9a72f62011-09-04 17:59:07 -07001011 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001012 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001013 return res;
buzbee67bf8852011-08-17 17:51:35 -07001014}
1015extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1016{
buzbeee9a72f62011-09-04 17:59:07 -07001017 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001018 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001019 return res;
1020}
1021extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1022{
1023 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1024 return res;
buzbee67bf8852011-08-17 17:51:35 -07001025}
1026extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1027 int low, int high)
1028{
buzbeee9a72f62011-09-04 17:59:07 -07001029 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001030 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001031 return res;
buzbee67bf8852011-08-17 17:51:35 -07001032}
1033
1034extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1035 int low, int high)
1036{
buzbeee9a72f62011-09-04 17:59:07 -07001037 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001038 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001039 return res;
buzbee67bf8852011-08-17 17:51:35 -07001040}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001041
buzbeee3acd072012-02-25 17:03:10 -08001042/* USE SSA names to count references of base Dalvik vRegs. */
1043void oatCountRefs(CompilationUnit *cUnit, BasicBlock* bb,
buzbee31a4a6f2012-02-28 15:36:15 -08001044 RefCounts* coreCounts, RefCounts* fpCounts)
buzbeee3acd072012-02-25 17:03:10 -08001045{
buzbee239c4e72012-03-16 08:42:29 -07001046 if ((cUnit->disableOpt & (1 << kPromoteRegs)) ||
1047 !((bb->blockType == kEntryBlock) || (bb->blockType == kExitBlock) ||
1048 (bb->blockType == kDalvikByteCode))) {
buzbeee3acd072012-02-25 17:03:10 -08001049 return;
buzbee239c4e72012-03-16 08:42:29 -07001050 }
1051 for (int i = 0; i < cUnit->numSSARegs;) {
1052 RegLocation loc = cUnit->regLocation[i];
1053 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
1054 int vReg = SRegToVReg(cUnit, loc.sRegLow);
1055 if (vReg < 0) {
1056 vReg = cUnit->numDalvikRegisters - (vReg + 1);
1057 }
1058 if (loc.defined) {
1059 counts[vReg].count += cUnit->useCounts.elemList[i];
1060 }
1061 if (loc.wide) {
1062 if (loc.defined) {
1063 if (loc.fp) {
1064 counts[vReg].doubleStart = true;
1065 counts[vReg+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;
buzbeee3acd072012-02-25 17:03:10 -08001100
1101 // Allow target code to add any special registers
1102 oatAdjustSpillMask(cUnit);
1103
1104 /*
1105 * Simple register promotion. Just do a static count of the uses
1106 * of Dalvik registers. Note that we examine the SSA names, but
1107 * count based on original Dalvik register name. Count refs
1108 * separately based on type in order to give allocation
1109 * preference to fp doubles - which must be allocated sequential
1110 * physical single fp registers started with an even-numbered
1111 * reg.
1112 * TUNING: replace with linear scan once we have the ability
1113 * to describe register live ranges for GC.
1114 */
1115 RefCounts *coreRegs = (RefCounts *)
1116 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1117 RefCounts *fpRegs = (RefCounts *)
1118 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
buzbee239c4e72012-03-16 08:42:29 -07001119 // Set ssa names for original Dalvik registers
1120 for (int i = 0; i < dalvikRegs; i++) {
buzbeee3acd072012-02-25 17:03:10 -08001121 coreRegs[i].sReg = fpRegs[i].sReg = i;
1122 }
buzbee239c4e72012-03-16 08:42:29 -07001123 // Set ssa names for Method* and compiler temps
1124 for (int i = 0; i < regBias; i++) {
1125 coreRegs[dalvikRegs + i].sReg = fpRegs[dalvikRegs + i].sReg = (-1 - i);
1126 }
buzbeee3acd072012-02-25 17:03:10 -08001127 GrowableListIterator iterator;
1128 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
1129 while (true) {
1130 BasicBlock* bb;
1131 bb = (BasicBlock*)oatGrowableListIteratorNext(&iterator);
1132 if (bb == NULL) break;
1133 oatCountRefs(cUnit, bb, coreRegs, fpRegs);
1134 }
1135
1136 /*
1137 * Ideally, we'd allocate doubles starting with an even-numbered
1138 * register. Bias the counts to try to allocate any vreg that's
1139 * used as the start of a pair first.
1140 */
1141 for (int i = 0; i < numRegs; i++) {
1142 if (fpRegs[i].doubleStart) {
1143 fpRegs[i].count *= 2;
1144 }
1145 }
1146
1147 // Sort the count arrays
1148 qsort(coreRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1149 qsort(fpRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1150
1151 if (cUnit->printMe) {
1152 oatDumpCounts(coreRegs, numRegs, "Core regs after sort");
1153 oatDumpCounts(fpRegs, numRegs, "Fp regs after sort");
1154 }
1155
1156 if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
1157 // Promote fpRegs
buzbee98dc5d72012-03-16 19:12:11 -07001158 for (int i = 0; (i < numRegs) && (fpRegs[i].count > 0); i++) {
buzbeee1965672012-03-11 18:39:19 -07001159 DCHECK(validSreg(cUnit,fpRegs[i].sReg));
buzbeee3acd072012-02-25 17:03:10 -08001160 if (cUnit->promotionMap[fpRegs[i].sReg].fpLocation != kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001161 int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
1162 fpRegs[i].doubleStart);
1163 if (reg < 0) {
1164 break; // No more left
1165 }
1166 }
1167 }
1168
1169 // Promote core regs
buzbee98dc5d72012-03-16 19:12:11 -07001170 for (int i = 0; (i < numRegs) && (coreRegs[i].count > 0); i++) {
buzbeee1965672012-03-11 18:39:19 -07001171 DCHECK(validSreg(cUnit,coreRegs[i].sReg));
buzbeee3acd072012-02-25 17:03:10 -08001172 if (cUnit->promotionMap[coreRegs[i].sReg].coreLocation !=
1173 kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001174 int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
1175 if (reg < 0) {
1176 break; // No more left
1177 }
1178 }
1179 }
1180 }
1181
1182 // Now, update SSA names to new home locations
1183 for (int i = 0; i < cUnit->numSSARegs; i++) {
1184 RegLocation *curr = &cUnit->regLocation[i];
buzbeee1965672012-03-11 18:39:19 -07001185 int baseVReg = SRegToVReg(cUnit, curr->sRegLow);
buzbeee3acd072012-02-25 17:03:10 -08001186 if (!curr->wide) {
1187 if (curr->fp) {
buzbeee1965672012-03-11 18:39:19 -07001188 DCHECK(validSreg(cUnit,baseVReg));
buzbeee3acd072012-02-25 17:03:10 -08001189 if (cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) {
1190 curr->location = kLocPhysReg;
1191 curr->lowReg = cUnit->promotionMap[baseVReg].fpReg;
1192 curr->home = true;
1193 }
1194 } else {
buzbeee1965672012-03-11 18:39:19 -07001195 DCHECK(validSreg(cUnit,baseVReg));
buzbeee3acd072012-02-25 17:03:10 -08001196 if (cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg) {
1197 curr->location = kLocPhysReg;
1198 curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
1199 curr->home = true;
1200 }
1201 }
1202 curr->highReg = INVALID_REG;
1203 } else {
1204 if (curr->highWord) {
1205 continue;
1206 }
1207 if (curr->fp) {
buzbeee1965672012-03-11 18:39:19 -07001208 DCHECK(validSreg(cUnit,baseVReg));
1209 DCHECK(validSreg(cUnit,baseVReg+1));
buzbeee3acd072012-02-25 17:03:10 -08001210 if ((cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) &&
1211 (cUnit->promotionMap[baseVReg+1].fpLocation ==
1212 kLocPhysReg)) {
1213 int lowReg = cUnit->promotionMap[baseVReg].fpReg;
1214 int highReg = cUnit->promotionMap[baseVReg+1].fpReg;
1215 // Doubles require pair of singles starting at even reg
1216 if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
1217 curr->location = kLocPhysReg;
1218 curr->lowReg = lowReg;
1219 curr->highReg = highReg;
1220 curr->home = true;
1221 }
1222 }
1223 } else {
buzbeee1965672012-03-11 18:39:19 -07001224 DCHECK(validSreg(cUnit,baseVReg));
1225 DCHECK(validSreg(cUnit,baseVReg+1));
buzbeee3acd072012-02-25 17:03:10 -08001226 if ((cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg)
1227 && (cUnit->promotionMap[baseVReg+1].coreLocation ==
1228 kLocPhysReg)) {
1229 curr->location = kLocPhysReg;
1230 curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
1231 curr->highReg = cUnit->promotionMap[baseVReg+1].coreReg;
1232 curr->home = true;
1233 }
1234 }
1235 }
1236 }
1237}
1238
1239/* Returns sp-relative offset in bytes for a VReg */
1240extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
1241{
buzbeeefccc562012-03-11 11:19:28 -07001242 return Frame::GetVRegOffset(cUnit->code_item, cUnit->coreSpillMask,
1243 cUnit->fpSpillMask, cUnit->frameSize, vReg);
buzbeee3acd072012-02-25 17:03:10 -08001244}
1245
1246/* Returns sp-relative offset in bytes for a SReg */
1247extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
1248{
buzbeee1965672012-03-11 18:39:19 -07001249 return oatVRegOffset(cUnit, SRegToVReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -08001250}
1251
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001252} // namespace art