blob: 8f5d1bbe5a33219a959cd9d199af1016029bf8e0 [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{
144 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs,
145 sReg);
146 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs,
147 sReg);
148}
149
buzbeee1965672012-03-11 18:39:19 -0700150/* Sanity check */
151bool validSreg(CompilationUnit* cUnit, int sReg)
152{
153 bool res = ((-(cUnit->numCompilerTemps + 1) <= sReg) &&
154 (sReg < cUnit->numDalvikRegisters));
155 if (!res) {
156 LOG(WARNING) << "Bad sreg: " << sReg;
157 LOG(WARNING) << " low = " << -(cUnit->numCompilerTemps + 1);
158 LOG(WARNING) << " high = " << cUnit->numRegs;
159 }
160 return res;
161}
162
buzbee67bf8852011-08-17 17:51:35 -0700163/* Reserve a callee-save register. Return -1 if none available */
164extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
165{
166 int res = -1;
167 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
168 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
169 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
170 res = coreRegs[i].reg;
171 coreRegs[i].inUse = true;
172 cUnit->coreSpillMask |= (1 << res);
buzbeec41e5b52011-09-23 12:46:19 -0700173 cUnit->coreVmapTable.push_back(sReg);
buzbeebbaf8942011-10-02 13:08:29 -0700174 cUnit->numCoreSpills++;
buzbee67bc2362011-10-11 18:08:40 -0700175 // Should be promoting based on initial sReg set
buzbeee1965672012-03-11 18:39:19 -0700176 DCHECK_EQ(sReg, SRegToVReg(cUnit, sReg));
177 DCHECK(validSreg(cUnit,sReg));
buzbee67bc2362011-10-11 18:08:40 -0700178 cUnit->promotionMap[sReg].coreLocation = kLocPhysReg;
179 cUnit->promotionMap[sReg].coreReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700180 break;
181 }
182 }
183 return res;
184}
185
186/*
187 * Reserve a callee-save fp single register. Try to fullfill request for
188 * even/odd allocation, but go ahead and allocate anything if not
189 * available. If nothing's available, return -1.
190 */
buzbee31a4a6f2012-02-28 15:36:15 -0800191int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700192{
193 int res = -1;
194 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
195 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
196 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
197 ((FPRegs[i].reg & 0x1) == 0) == even) {
198 res = FPRegs[i].reg;
199 FPRegs[i].inUse = true;
buzbee67bc2362011-10-11 18:08:40 -0700200 // Should be promoting based on initial sReg set
buzbeee1965672012-03-11 18:39:19 -0700201 DCHECK_EQ(sReg, SRegToVReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -0800202 oatMarkPreservedSingle(cUnit, sReg, res);
buzbeee1965672012-03-11 18:39:19 -0700203 DCHECK(validSreg(cUnit,sReg));
buzbee67bc2362011-10-11 18:08:40 -0700204 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
205 cUnit->promotionMap[sReg].fpReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700206 break;
207 }
208 }
209 return res;
210}
211
212/*
213 * Somewhat messy code here. We want to allocate a pair of contiguous
214 * physical single-precision floating point registers starting with
215 * an even numbered reg. It is possible that the paired sReg (sReg+1)
216 * has already been allocated - try to fit if possible. Fail to
217 * allocate if we can't meet the requirements for the pair of
218 * sReg<=sX[even] & (sReg+1)<= sX+1.
219 */
buzbee31a4a6f2012-02-28 15:36:15 -0800220int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700221{
222 int res = -1; // Assume failure
buzbee67bc2362011-10-11 18:08:40 -0700223 // Should be promoting based on initial sReg set
buzbeee1965672012-03-11 18:39:19 -0700224 DCHECK_EQ(sReg, SRegToVReg(cUnit, sReg));
225 DCHECK(validSreg(cUnit,sReg+1));
buzbee67bc2362011-10-11 18:08:40 -0700226 if (cUnit->promotionMap[sReg+1].fpLocation == kLocPhysReg) {
buzbee67bf8852011-08-17 17:51:35 -0700227 // Upper reg is already allocated. Can we fit?
buzbee67bc2362011-10-11 18:08:40 -0700228 int highReg = cUnit->promotionMap[sReg+1].fpReg;
buzbee67bf8852011-08-17 17:51:35 -0700229 if ((highReg & 1) == 0) {
230 // High reg is even - fail.
231 return res;
232 }
233 // Is the low reg of the pair free?
buzbee68253262011-10-07 14:02:25 -0700234 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
buzbee67bf8852011-08-17 17:51:35 -0700235 if (p->inUse || p->isTemp) {
236 // Already allocated or not preserved - fail.
237 return res;
238 }
239 // OK - good to go.
240 res = p->reg;
241 p->inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700242 DCHECK_EQ((res & 1), 0);
buzbeee3acd072012-02-25 17:03:10 -0800243 oatMarkPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700244 } else {
245 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
246 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
247 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
248 ((FPRegs[i].reg & 0x1) == 0x0) &&
249 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
250 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
251 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
252 res = FPRegs[i].reg;
253 FPRegs[i].inUse = true;
buzbeee3acd072012-02-25 17:03:10 -0800254 oatMarkPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700255 FPRegs[i+1].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700256 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
buzbeee3acd072012-02-25 17:03:10 -0800257 oatMarkPreservedSingle(cUnit, sReg+1, res+1);
buzbee67bf8852011-08-17 17:51:35 -0700258 break;
259 }
260 }
261 }
262 if (res != -1) {
buzbeee1965672012-03-11 18:39:19 -0700263 DCHECK(validSreg(cUnit,sReg));
buzbee67bc2362011-10-11 18:08:40 -0700264 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
265 cUnit->promotionMap[sReg].fpReg = res;
buzbeee1965672012-03-11 18:39:19 -0700266 DCHECK(validSreg(cUnit,sReg+1));
buzbee67bc2362011-10-11 18:08:40 -0700267 cUnit->promotionMap[sReg+1].fpLocation = kLocPhysReg;
268 cUnit->promotionMap[sReg+1].fpReg = res + 1;
buzbee67bf8852011-08-17 17:51:35 -0700269 }
270 return res;
271}
272
273
274/*
275 * Reserve a callee-save fp register. If this register can be used
276 * as the first of a double, attempt to allocate an even pair of fp
277 * single regs (but if can't still attempt to allocate a single, preferring
278 * first to allocate an odd register.
279 */
280extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
281 bool doubleStart)
282{
283 int res = -1;
284 if (doubleStart) {
285 res = allocPreservedDouble(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700286 }
287 if (res == -1) {
288 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
289 }
290 if (res == -1)
291 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
292 return res;
293}
294
buzbee31a4a6f2012-02-28 15:36:15 -0800295int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
296 int* nextTemp, bool required)
buzbee67bf8852011-08-17 17:51:35 -0700297{
298 int i;
299 int next = *nextTemp;
300 for (i=0; i< numRegs; i++) {
301 if (next >= numRegs)
302 next = 0;
303 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
304 oatClobber(cUnit, p[next].reg);
305 p[next].inUse = true;
306 p[next].pair = false;
307 *nextTemp = next + 1;
308 return p[next].reg;
309 }
310 next++;
311 }
312 next = *nextTemp;
313 for (i=0; i< numRegs; i++) {
314 if (next >= numRegs)
315 next = 0;
316 if (p[next].isTemp && !p[next].inUse) {
317 oatClobber(cUnit, p[next].reg);
318 p[next].inUse = true;
319 p[next].pair = false;
320 *nextTemp = next + 1;
321 return p[next].reg;
322 }
323 next++;
324 }
325 if (required) {
buzbee6181f792011-09-29 11:14:04 -0700326 oatCodegenDump(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700327 dumpRegPool(cUnit->regPool->coreRegs,
328 cUnit->regPool->numCoreRegs);
329 LOG(FATAL) << "No free temp registers";
330 }
331 return -1; // No register available
332}
333
334//REDO: too many assumptions.
335extern int oatAllocTempDouble(CompilationUnit* cUnit)
336{
337 RegisterInfo* p = cUnit->regPool->FPRegs;
338 int numRegs = cUnit->regPool->numFPRegs;
buzbeea50638b2011-11-02 15:15:06 -0700339 /* Start looking at an even reg */
340 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700341
buzbeea50638b2011-11-02 15:15:06 -0700342 // First try to avoid allocating live registers
343 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700344 if (next >= numRegs)
345 next = 0;
346 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
347 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
348 oatClobber(cUnit, p[next].reg);
349 oatClobber(cUnit, p[next+1].reg);
350 p[next].inUse = true;
351 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700352 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
353 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700354 cUnit->regPool->nextFPReg = next + 2;
355 if (cUnit->regPool->nextFPReg >= numRegs) {
356 cUnit->regPool->nextFPReg = 0;
357 }
buzbee67bf8852011-08-17 17:51:35 -0700358 return p[next].reg;
359 }
360 next += 2;
361 }
buzbeea50638b2011-11-02 15:15:06 -0700362 next = cUnit->regPool->nextFPReg & ~0x1;
363
364 // No choice - find a pair and kill it.
365 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700366 if (next >= numRegs)
367 next = 0;
368 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
369 !p[next+1].inUse) {
370 oatClobber(cUnit, p[next].reg);
371 oatClobber(cUnit, p[next+1].reg);
372 p[next].inUse = true;
373 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700374 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
375 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700376 cUnit->regPool->nextFPReg = next + 2;
377 if (cUnit->regPool->nextFPReg >= numRegs) {
378 cUnit->regPool->nextFPReg = 0;
379 }
buzbee67bf8852011-08-17 17:51:35 -0700380 return p[next].reg;
381 }
382 next += 2;
383 }
buzbee6181f792011-09-29 11:14:04 -0700384 LOG(FATAL) << "No free temp registers (pair)";
buzbee67bf8852011-08-17 17:51:35 -0700385 return -1;
386}
387
388/* Return a temp if one is available, -1 otherwise */
389extern int oatAllocFreeTemp(CompilationUnit* cUnit)
390{
391 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
392 cUnit->regPool->numCoreRegs,
393 &cUnit->regPool->nextCoreReg, true);
394}
395
396extern int oatAllocTemp(CompilationUnit* cUnit)
397{
398 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
399 cUnit->regPool->numCoreRegs,
400 &cUnit->regPool->nextCoreReg, true);
401}
402
403extern int oatAllocTempFloat(CompilationUnit* cUnit)
404{
405 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
406 cUnit->regPool->numFPRegs,
407 &cUnit->regPool->nextFPReg, true);
408}
409
buzbee31a4a6f2012-02-28 15:36:15 -0800410RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700411{
412 int i;
413 if (sReg == -1)
414 return NULL;
415 for (i=0; i < numRegs; i++) {
416 if (p[i].live && (p[i].sReg == sReg)) {
417 if (p[i].isTemp)
418 p[i].inUse = true;
419 return &p[i];
420 }
421 }
422 return NULL;
423}
424
buzbee31a4a6f2012-02-28 15:36:15 -0800425RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg, int regClass)
buzbee67bf8852011-08-17 17:51:35 -0700426{
427 RegisterInfo* res = NULL;
428 switch(regClass) {
429 case kAnyReg:
430 res = allocLiveBody(cUnit->regPool->FPRegs,
431 cUnit->regPool->numFPRegs, sReg);
432 if (res)
433 break;
434 /* Intentional fallthrough */
435 case kCoreReg:
436 res = allocLiveBody(cUnit->regPool->coreRegs,
437 cUnit->regPool->numCoreRegs, sReg);
438 break;
439 case kFPReg:
440 res = allocLiveBody(cUnit->regPool->FPRegs,
441 cUnit->regPool->numFPRegs, sReg);
442 break;
443 default:
444 LOG(FATAL) << "Invalid register type";
445 }
446 return res;
447}
448
449extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
450{
451 RegisterInfo* p = cUnit->regPool->coreRegs;
452 int numRegs = cUnit->regPool->numCoreRegs;
453 int i;
454 for (i=0; i< numRegs; i++) {
455 if (p[i].reg == reg) {
456 if (p[i].isTemp) {
457 p[i].inUse = false;
458 }
459 p[i].pair = false;
460 return;
461 }
462 }
463 p = cUnit->regPool->FPRegs;
464 numRegs = cUnit->regPool->numFPRegs;
465 for (i=0; i< numRegs; i++) {
466 if (p[i].reg == reg) {
467 if (p[i].isTemp) {
468 p[i].inUse = false;
469 }
470 p[i].pair = false;
471 return;
472 }
473 }
474 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
475}
476
477extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
478{
479 RegisterInfo* p = cUnit->regPool->coreRegs;
480 int numRegs = cUnit->regPool->numCoreRegs;
481 int i;
482 for (i=0; i< numRegs; i++) {
483 if (p[i].reg == reg) {
484 return p[i].live ? &p[i] : NULL;
485 }
486 }
487 p = cUnit->regPool->FPRegs;
488 numRegs = cUnit->regPool->numFPRegs;
489 for (i=0; i< numRegs; i++) {
490 if (p[i].reg == reg) {
491 return p[i].live ? &p[i] : NULL;
492 }
493 }
494 return NULL;
495}
496
497extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
498{
buzbee68253262011-10-07 14:02:25 -0700499 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700500 return (p->isTemp) ? p : NULL;
501}
502
buzbeeb29e4d12011-09-26 15:05:48 -0700503extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
504{
buzbee68253262011-10-07 14:02:25 -0700505 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbeeb29e4d12011-09-26 15:05:48 -0700506 return (p->isTemp) ? NULL : p;
507}
508
buzbee67bf8852011-08-17 17:51:35 -0700509extern bool oatIsDirty(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->dirty;
513}
514
515/*
516 * Similar to oatAllocTemp(), but forces the allocation of a specific
517 * register. No check is made to see if the register was previously
518 * allocated. Use with caution.
519 */
520extern void oatLockTemp(CompilationUnit* cUnit, int reg)
521{
522 RegisterInfo* p = cUnit->regPool->coreRegs;
523 int numRegs = cUnit->regPool->numCoreRegs;
524 int i;
525 for (i=0; i< numRegs; i++) {
526 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700527 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700528 p[i].inUse = true;
529 p[i].live = false;
530 return;
531 }
532 }
533 p = cUnit->regPool->FPRegs;
534 numRegs = cUnit->regPool->numFPRegs;
535 for (i=0; i< numRegs; i++) {
536 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700537 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700538 p[i].inUse = true;
539 p[i].live = false;
540 return;
541 }
542 }
543 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
544}
545
buzbee5abfa3e2012-01-31 17:01:43 -0800546static inline void resetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700547{
buzbee67bf8852011-08-17 17:51:35 -0700548 p->defStart = NULL;
549 p->defEnd = NULL;
550}
551
buzbee5abfa3e2012-01-31 17:01:43 -0800552extern void oatResetDef(CompilationUnit* cUnit, int reg)
553{
554 resetDefBody(oatGetRegInfo(cUnit, reg));
555}
556
buzbee31a4a6f2012-02-28 15:36:15 -0800557void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700558 int sReg1, int sReg2)
559{
560 if (start && finish) {
561 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700562 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700563 for (p = start; ;p = p->next) {
buzbeee3acd072012-02-25 17:03:10 -0800564 oatNopLIR(p);
buzbee67bf8852011-08-17 17:51:35 -0700565 if (p == finish)
566 break;
567 }
568 }
569}
570
571/*
572 * Mark the beginning and end LIR of a def sequence. Note that
573 * on entry start points to the LIR prior to the beginning of the
574 * sequence.
575 */
576extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
buzbee31a4a6f2012-02-28 15:36:15 -0800577 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700578{
buzbeeed3e9302011-09-23 17:34:19 -0700579 DCHECK(!rl.wide);
580 DCHECK(start && start->next);
581 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700582 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700583 p->defStart = start->next;
584 p->defEnd = finish;
585}
586
587/*
588 * Mark the beginning and end LIR of a def sequence. Note that
589 * on entry start points to the LIR prior to the beginning of the
590 * sequence.
591 */
592extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
buzbee31a4a6f2012-02-28 15:36:15 -0800593 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700594{
buzbeeed3e9302011-09-23 17:34:19 -0700595 DCHECK(rl.wide);
596 DCHECK(start && start->next);
597 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700598 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700599 oatResetDef(cUnit, rl.highReg); // Only track low of pair
600 p->defStart = start->next;
601 p->defEnd = finish;
602}
603
buzbee31a4a6f2012-02-28 15:36:15 -0800604extern RegLocation oatWideToNarrow(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700605{
buzbeeed3e9302011-09-23 17:34:19 -0700606 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700607 if (rl.location == kLocPhysReg) {
buzbee68253262011-10-07 14:02:25 -0700608 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
609 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700610 if (infoLo->isTemp) {
611 infoLo->pair = false;
612 infoLo->defStart = NULL;
613 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700614 }
buzbee0c7f26d2011-09-07 12:28:51 -0700615 if (infoHi->isTemp) {
616 infoHi->pair = false;
617 infoHi->defStart = NULL;
618 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700619 }
buzbee67bf8852011-08-17 17:51:35 -0700620 }
621 rl.wide = false;
622 return rl;
623}
624
625extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
626{
buzbeeed3e9302011-09-23 17:34:19 -0700627 DCHECK(!rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700628 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
629 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
buzbeeed3e9302011-09-23 17:34:19 -0700630 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700631 nullifyRange(cUnit, p->defStart, p->defEnd,
632 p->sReg, rl.sRegLow);
633 }
634 oatResetDef(cUnit, rl.lowReg);
635}
636
637extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
638{
buzbeeed3e9302011-09-23 17:34:19 -0700639 DCHECK(rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700640 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
641 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
642 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
643 DCHECK(pLow->pair);
644 nullifyRange(cUnit, pLow->defStart, pLow->defEnd,
645 pLow->sReg, rl.sRegLow);
646 }
647 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
648 DCHECK(pHigh->pair);
buzbee67bf8852011-08-17 17:51:35 -0700649 }
650 oatResetDef(cUnit, rl.lowReg);
651 oatResetDef(cUnit, rl.highReg);
652}
653
654extern void oatResetDefTracking(CompilationUnit* cUnit)
655{
656 int i;
657 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800658 resetDefBody(&cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700659 }
660 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800661 resetDefBody(&cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700662 }
663}
664
665extern void oatClobberAllRegs(CompilationUnit* cUnit)
666{
667 int i;
668 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800669 clobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700670 }
671 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800672 clobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700673 }
674}
675
buzbee67bf8852011-08-17 17:51:35 -0700676// Make sure nothing is live and dirty
buzbee31a4a6f2012-02-28 15:36:15 -0800677void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700678 int numRegs)
679{
680 int i;
681 for (i=0; i < numRegs; i++) {
682 if (info[i].live && info[i].dirty) {
683 if (info[i].pair) {
684 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
685 } else {
686 oatFlushReg(cUnit, info[i].reg);
687 }
688 }
689 }
690}
691
692extern void oatFlushAllRegs(CompilationUnit* cUnit)
693{
694 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
695 cUnit->regPool->numCoreRegs);
696 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
697 cUnit->regPool->numFPRegs);
698 oatClobberAllRegs(cUnit);
699}
700
701
702//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee31a4a6f2012-02-28 15:36:15 -0800703bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700704{
705 if (regClass == kAnyReg) {
706 return true;
707 } else if (regClass == kCoreReg) {
buzbeee3acd072012-02-25 17:03:10 -0800708 return !oatIsFpReg(reg);
buzbee67bf8852011-08-17 17:51:35 -0700709 } else {
buzbeee3acd072012-02-25 17:03:10 -0800710 return oatIsFpReg(reg);
buzbee67bf8852011-08-17 17:51:35 -0700711 }
712}
713
714extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
715{
buzbee68253262011-10-07 14:02:25 -0700716 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700717 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
718 return; /* already live */
719 } else if (sReg != INVALID_SREG) {
720 oatClobberSReg(cUnit, sReg);
721 if (info->isTemp) {
722 info->live = true;
723 }
724 } else {
725 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700726 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700727 info->live = false;
728 }
729 info->sReg = sReg;
730}
731
732extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
733{
buzbee68253262011-10-07 14:02:25 -0700734 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700735 info->isTemp = true;
736}
737
buzbee9e0f9b02011-08-24 15:32:46 -0700738extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
739{
buzbee68253262011-10-07 14:02:25 -0700740 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee9e0f9b02011-08-24 15:32:46 -0700741 info->isTemp = false;
742}
743
buzbee67bf8852011-08-17 17:51:35 -0700744extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
745{
buzbee68253262011-10-07 14:02:25 -0700746 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
747 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
buzbee67bf8852011-08-17 17:51:35 -0700748 infoLo->pair = infoHi->pair = true;
749 infoLo->partner = highReg;
750 infoHi->partner = lowReg;
751}
752
753extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
754{
buzbee68253262011-10-07 14:02:25 -0700755 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700756 info->dirty = false;
757 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700758 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700759 info->dirty = false;
760 }
761}
762
763extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
764{
765 if (loc.home) {
766 // If already home, can't be dirty
767 return;
768 }
buzbee68253262011-10-07 14:02:25 -0700769 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700770 info->dirty = true;
771 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700772 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700773 info->dirty = true;
774 }
775}
776
777extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
778{
buzbee68253262011-10-07 14:02:25 -0700779 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700780 info->inUse = true;
781}
782
buzbee31a4a6f2012-02-28 15:36:15 -0800783void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700784{
buzbee68253262011-10-07 14:02:25 -0700785 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
786 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700787 // Target temp status must not change
788 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700789 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700790 // Restore target's temp status
791 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700792 newInfo->reg = newReg;
793}
794
795/*
796 * Return an updated location record with current in-register status.
797 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700798 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700799 * clobber both low and high.
800 * TUNING: clobbering both is a bit heavy-handed, but the alternative
801 * is a bit complex when dealing with FP regs. Examine code to see
802 * if it's worthwhile trying to be more clever here.
803 */
804
805extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
806{
buzbeeed3e9302011-09-23 17:34:19 -0700807 DCHECK(!loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700808 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbeee1965672012-03-11 18:39:19 -0700809 if (loc.location != kLocPhysReg) {
810 DCHECK((loc.location == kLocDalvikFrame) ||
811 (loc.location == kLocCompilerTemp));
buzbee67bf8852011-08-17 17:51:35 -0700812 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
813 if (infoLo) {
814 if (infoLo->pair) {
815 oatClobber(cUnit, infoLo->reg);
816 oatClobber(cUnit, infoLo->partner);
buzbee58f92742011-10-01 11:22:17 -0700817 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700818 } else {
819 loc.lowReg = infoLo->reg;
820 loc.location = kLocPhysReg;
821 }
822 }
823 }
824
825 return loc;
826}
827
buzbee6181f792011-09-29 11:14:04 -0700828bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
829{
830 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
831 if (cUnit->regPool->coreRegs[i].pair) {
832 static int myReg = cUnit->regPool->coreRegs[i].reg;
833 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
834 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
buzbee68253262011-10-07 14:02:25 -0700835 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
buzbee6181f792011-09-29 11:14:04 -0700836 DCHECK(partner != NULL);
837 DCHECK(partner->pair);
838 DCHECK_EQ(myReg, partner->partner);
839 static int partnerSreg = partner->sReg;
840 if (mySreg == INVALID_SREG) {
841 DCHECK_EQ(partnerSreg, INVALID_SREG);
842 } else {
843 int diff = mySreg - partnerSreg;
844 DCHECK((diff == -1) || (diff == 1));
845 }
846 }
847 if (!cUnit->regPool->coreRegs[i].live) {
848 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
849 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
850 }
851 }
852 return true;
853}
854
buzbee67bf8852011-08-17 17:51:35 -0700855/* see comments for updateLoc */
buzbee31a4a6f2012-02-28 15:36:15 -0800856extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700857{
buzbeeed3e9302011-09-23 17:34:19 -0700858 DCHECK(loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700859 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbeee1965672012-03-11 18:39:19 -0700860 if (loc.location != kLocPhysReg) {
861 DCHECK((loc.location == kLocDalvikFrame) ||
862 (loc.location == kLocCompilerTemp));
buzbee67bf8852011-08-17 17:51:35 -0700863 // Are the dalvik regs already live in physical registers?
864 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
865 RegisterInfo* infoHi = allocLive(cUnit,
866 oatSRegHi(loc.sRegLow), kAnyReg);
867 bool match = true;
868 match = match && (infoLo != NULL);
869 match = match && (infoHi != NULL);
870 // Are they both core or both FP?
buzbeee3acd072012-02-25 17:03:10 -0800871 match = match && (oatIsFpReg(infoLo->reg) == oatIsFpReg(infoHi->reg));
buzbee67bf8852011-08-17 17:51:35 -0700872 // If a pair of floating point singles, are they properly aligned?
buzbeee3acd072012-02-25 17:03:10 -0800873 if (match && oatIsFpReg(infoLo->reg)) {
buzbee67bf8852011-08-17 17:51:35 -0700874 match &= ((infoLo->reg & 0x1) == 0);
875 match &= ((infoHi->reg - infoLo->reg) == 1);
876 }
877 // If previously used as a pair, it is the same pair?
878 if (match && (infoLo->pair || infoHi->pair)) {
879 match = (infoLo->pair == infoHi->pair);
880 match &= ((infoLo->reg == infoHi->partner) &&
881 (infoHi->reg == infoLo->partner));
882 }
883 if (match) {
884 // Can reuse - update the register usage info
885 loc.lowReg = infoLo->reg;
886 loc.highReg = infoHi->reg;
887 loc.location = kLocPhysReg;
888 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeee3acd072012-02-25 17:03:10 -0800889 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700890 return loc;
891 }
buzbee58f92742011-10-01 11:22:17 -0700892 // Can't easily reuse - clobber and free any overlaps
buzbee67bf8852011-08-17 17:51:35 -0700893 if (infoLo) {
894 oatClobber(cUnit, infoLo->reg);
buzbee58f92742011-10-01 11:22:17 -0700895 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700896 if (infoLo->pair)
897 oatClobber(cUnit, infoLo->partner);
898 }
899 if (infoHi) {
900 oatClobber(cUnit, infoHi->reg);
buzbee58f92742011-10-01 11:22:17 -0700901 oatFreeTemp(cUnit, infoHi->reg);
buzbee67bf8852011-08-17 17:51:35 -0700902 if (infoHi->pair)
903 oatClobber(cUnit, infoHi->partner);
904 }
905 }
906 return loc;
907}
908
buzbeeed3e9302011-09-23 17:34:19 -0700909
910/* For use in cases we don't know (or care) width */
buzbee31a4a6f2012-02-28 15:36:15 -0800911extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700912{
913 if (loc.wide)
914 return oatUpdateLocWide(cUnit, loc);
915 else
916 return oatUpdateLoc(cUnit, loc);
917}
918
buzbee31a4a6f2012-02-28 15:36:15 -0800919RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
920 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700921{
buzbeeed3e9302011-09-23 17:34:19 -0700922 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700923 int newRegs;
924 int lowReg;
925 int highReg;
926
927 loc = oatUpdateLocWide(cUnit, loc);
928
929 /* If already in registers, we can assume proper form. Right reg class? */
930 if (loc.location == kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -0800931 DCHECK_EQ(oatIsFpReg(loc.lowReg), oatIsFpReg(loc.highReg));
932 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700933 if (!regClassMatches(regClass, loc.lowReg)) {
934 /* Wrong register class. Reallocate and copy */
935 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
936 lowReg = newRegs & 0xff;
937 highReg = (newRegs >> 8) & 0xff;
938 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
939 loc.highReg);
940 copyRegInfo(cUnit, lowReg, loc.lowReg);
941 copyRegInfo(cUnit, highReg, loc.highReg);
942 oatClobber(cUnit, loc.lowReg);
943 oatClobber(cUnit, loc.highReg);
944 loc.lowReg = lowReg;
945 loc.highReg = highReg;
946 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeee3acd072012-02-25 17:03:10 -0800947 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700948 }
949 return loc;
950 }
951
buzbeeed3e9302011-09-23 17:34:19 -0700952 DCHECK_NE(loc.sRegLow, INVALID_SREG);
953 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700954
955 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
956 loc.lowReg = newRegs & 0xff;
957 loc.highReg = (newRegs >> 8) & 0xff;
958
959 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
960 if (update) {
961 loc.location = kLocPhysReg;
962 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
963 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
964 }
buzbeee3acd072012-02-25 17:03:10 -0800965 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700966 return loc;
967}
968
969extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
970 int regClass, bool update)
971{
972 int newReg;
973
974 if (loc.wide)
975 return evalLocWide(cUnit, loc, regClass, update);
976
977 loc = oatUpdateLoc(cUnit, loc);
978
979 if (loc.location == kLocPhysReg) {
980 if (!regClassMatches(regClass, loc.lowReg)) {
981 /* Wrong register class. Realloc, copy and transfer ownership */
982 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
983 oatRegCopy(cUnit, newReg, loc.lowReg);
984 copyRegInfo(cUnit, newReg, loc.lowReg);
985 oatClobber(cUnit, loc.lowReg);
986 loc.lowReg = newReg;
987 }
988 return loc;
989 }
990
buzbeeed3e9302011-09-23 17:34:19 -0700991 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700992
993 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
994 loc.lowReg = newReg;
995
996 if (update) {
997 loc.location = kLocPhysReg;
998 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
999 }
1000 return loc;
1001}
1002
1003extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1004{
buzbeee9a72f62011-09-04 17:59:07 -07001005 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001006 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001007 return res;
buzbee67bf8852011-08-17 17:51:35 -07001008}
1009extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1010{
buzbeee9a72f62011-09-04 17:59:07 -07001011 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001012 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001013 return res;
1014}
1015extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1016{
1017 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1018 return res;
buzbee67bf8852011-08-17 17:51:35 -07001019}
1020extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1021 int low, int high)
1022{
buzbeee9a72f62011-09-04 17:59:07 -07001023 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001024 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001025 return res;
buzbee67bf8852011-08-17 17:51:35 -07001026}
1027
1028extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1029 int low, int high)
1030{
buzbeee9a72f62011-09-04 17:59:07 -07001031 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001032 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001033 return res;
buzbee67bf8852011-08-17 17:51:35 -07001034}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001035
buzbeee3acd072012-02-25 17:03:10 -08001036/* USE SSA names to count references of base Dalvik vRegs. */
1037void oatCountRefs(CompilationUnit *cUnit, BasicBlock* bb,
buzbee31a4a6f2012-02-28 15:36:15 -08001038 RefCounts* coreCounts, RefCounts* fpCounts)
buzbeee3acd072012-02-25 17:03:10 -08001039{
1040 MIR* mir;
1041 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
1042 bb->blockType != kExitBlock)
1043 return;
1044
1045 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
1046 SSARepresentation *ssaRep = mir->ssaRep;
1047 if (ssaRep) {
1048 for (int i = 0; i < ssaRep->numDefs;) {
1049 RegLocation loc = cUnit->regLocation[ssaRep->defs[i]];
1050 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
buzbeee1965672012-03-11 18:39:19 -07001051 int vReg = SRegToVReg(cUnit, ssaRep->defs[i]);
buzbeee3acd072012-02-25 17:03:10 -08001052 if (loc.defined) {
1053 counts[vReg].count++;
1054 }
1055 if (loc.wide) {
1056 if (loc.defined) {
1057 if (loc.fp) {
1058 counts[vReg].doubleStart = true;
1059 }
1060 counts[vReg+1].count++;
1061 }
1062 i += 2;
1063 } else {
1064 i++;
1065 }
1066 }
1067 for (int i = 0; i < ssaRep->numUses;) {
1068 RegLocation loc = cUnit->regLocation[ssaRep->uses[i]];
1069 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
buzbeee1965672012-03-11 18:39:19 -07001070 int vReg = SRegToVReg(cUnit, ssaRep->uses[i]);
buzbeee3acd072012-02-25 17:03:10 -08001071 if (loc.defined) {
1072 counts[vReg].count++;
1073 }
1074 if (loc.wide) {
1075 if (loc.defined) {
1076 if (loc.fp) {
1077 counts[vReg].doubleStart = true;
1078 }
1079 counts[vReg+1].count++;
1080 }
1081 i += 2;
1082 } else {
1083 i++;
1084 }
1085 }
1086 }
1087 }
1088}
1089
1090/* qsort callback function, sort descending */
1091int oatSortCounts(const void *val1, const void *val2)
1092{
1093 const RefCounts* op1 = (const RefCounts*)val1;
1094 const RefCounts* op2 = (const RefCounts*)val2;
1095 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
1096}
1097
1098void oatDumpCounts(const RefCounts* arr, int size, const char* msg)
1099{
1100 LOG(INFO) << msg;
1101 for (int i = 0; i < size; i++) {
1102 LOG(INFO) << "sReg[" << arr[i].sReg << "]: " << arr[i].count;
1103 }
1104}
1105
1106/*
1107 * Note: some portions of this code required even if the kPromoteRegs
1108 * optimization is disabled.
1109 */
1110extern void oatDoPromotion(CompilationUnit* cUnit)
1111{
1112 int numRegs = cUnit->numDalvikRegisters;
1113
1114 // Allow target code to add any special registers
1115 oatAdjustSpillMask(cUnit);
1116
1117 /*
1118 * Simple register promotion. Just do a static count of the uses
1119 * of Dalvik registers. Note that we examine the SSA names, but
1120 * count based on original Dalvik register name. Count refs
1121 * separately based on type in order to give allocation
1122 * preference to fp doubles - which must be allocated sequential
1123 * physical single fp registers started with an even-numbered
1124 * reg.
1125 * TUNING: replace with linear scan once we have the ability
1126 * to describe register live ranges for GC.
1127 */
1128 RefCounts *coreRegs = (RefCounts *)
1129 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1130 RefCounts *fpRegs = (RefCounts *)
1131 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1132 for (int i = 0; i < numRegs; i++) {
1133 coreRegs[i].sReg = fpRegs[i].sReg = i;
1134 }
1135 GrowableListIterator iterator;
1136 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
1137 while (true) {
1138 BasicBlock* bb;
1139 bb = (BasicBlock*)oatGrowableListIteratorNext(&iterator);
1140 if (bb == NULL) break;
1141 oatCountRefs(cUnit, bb, coreRegs, fpRegs);
1142 }
1143
1144 /*
1145 * Ideally, we'd allocate doubles starting with an even-numbered
1146 * register. Bias the counts to try to allocate any vreg that's
1147 * used as the start of a pair first.
1148 */
1149 for (int i = 0; i < numRegs; i++) {
1150 if (fpRegs[i].doubleStart) {
1151 fpRegs[i].count *= 2;
1152 }
1153 }
1154
1155 // Sort the count arrays
1156 qsort(coreRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1157 qsort(fpRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1158
1159 if (cUnit->printMe) {
1160 oatDumpCounts(coreRegs, numRegs, "Core regs after sort");
1161 oatDumpCounts(fpRegs, numRegs, "Fp regs after sort");
1162 }
1163
1164 if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
1165 // Promote fpRegs
1166 for (int i = 0; (fpRegs[i].count > 0) && (i < numRegs); i++) {
buzbeee1965672012-03-11 18:39:19 -07001167 DCHECK(validSreg(cUnit,fpRegs[i].sReg));
buzbeee3acd072012-02-25 17:03:10 -08001168 if (cUnit->promotionMap[fpRegs[i].sReg].fpLocation != kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001169 int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
1170 fpRegs[i].doubleStart);
1171 if (reg < 0) {
1172 break; // No more left
1173 }
1174 }
1175 }
1176
1177 // Promote core regs
1178 for (int i = 0; (coreRegs[i].count > 0) && i < numRegs; i++) {
buzbeee1965672012-03-11 18:39:19 -07001179 DCHECK(validSreg(cUnit,coreRegs[i].sReg));
buzbeee3acd072012-02-25 17:03:10 -08001180 if (cUnit->promotionMap[coreRegs[i].sReg].coreLocation !=
1181 kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -08001182 int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
1183 if (reg < 0) {
1184 break; // No more left
1185 }
1186 }
1187 }
1188 }
1189
1190 // Now, update SSA names to new home locations
1191 for (int i = 0; i < cUnit->numSSARegs; i++) {
1192 RegLocation *curr = &cUnit->regLocation[i];
buzbeee1965672012-03-11 18:39:19 -07001193 int baseVReg = SRegToVReg(cUnit, curr->sRegLow);
buzbeee3acd072012-02-25 17:03:10 -08001194 if (!curr->wide) {
1195 if (curr->fp) {
buzbeee1965672012-03-11 18:39:19 -07001196 DCHECK(validSreg(cUnit,baseVReg));
buzbeee3acd072012-02-25 17:03:10 -08001197 if (cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) {
1198 curr->location = kLocPhysReg;
1199 curr->lowReg = cUnit->promotionMap[baseVReg].fpReg;
1200 curr->home = true;
1201 }
1202 } else {
buzbeee1965672012-03-11 18:39:19 -07001203 DCHECK(validSreg(cUnit,baseVReg));
buzbeee3acd072012-02-25 17:03:10 -08001204 if (cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg) {
1205 curr->location = kLocPhysReg;
1206 curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
1207 curr->home = true;
1208 }
1209 }
1210 curr->highReg = INVALID_REG;
1211 } else {
1212 if (curr->highWord) {
1213 continue;
1214 }
1215 if (curr->fp) {
buzbeee1965672012-03-11 18:39:19 -07001216 DCHECK(validSreg(cUnit,baseVReg));
1217 DCHECK(validSreg(cUnit,baseVReg+1));
buzbeee3acd072012-02-25 17:03:10 -08001218 if ((cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) &&
1219 (cUnit->promotionMap[baseVReg+1].fpLocation ==
1220 kLocPhysReg)) {
1221 int lowReg = cUnit->promotionMap[baseVReg].fpReg;
1222 int highReg = cUnit->promotionMap[baseVReg+1].fpReg;
1223 // Doubles require pair of singles starting at even reg
1224 if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
1225 curr->location = kLocPhysReg;
1226 curr->lowReg = lowReg;
1227 curr->highReg = highReg;
1228 curr->home = true;
1229 }
1230 }
1231 } else {
buzbeee1965672012-03-11 18:39:19 -07001232 DCHECK(validSreg(cUnit,baseVReg));
1233 DCHECK(validSreg(cUnit,baseVReg+1));
buzbeee3acd072012-02-25 17:03:10 -08001234 if ((cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg)
1235 && (cUnit->promotionMap[baseVReg+1].coreLocation ==
1236 kLocPhysReg)) {
1237 curr->location = kLocPhysReg;
1238 curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
1239 curr->highReg = cUnit->promotionMap[baseVReg+1].coreReg;
1240 curr->home = true;
1241 }
1242 }
1243 }
1244 }
1245}
1246
1247/* Returns sp-relative offset in bytes for a VReg */
1248extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
1249{
buzbeeefccc562012-03-11 11:19:28 -07001250 return Frame::GetVRegOffset(cUnit->code_item, cUnit->coreSpillMask,
1251 cUnit->fpSpillMask, cUnit->frameSize, vReg);
buzbeee3acd072012-02-25 17:03:10 -08001252}
1253
1254/* Returns sp-relative offset in bytes for a SReg */
1255extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
1256{
buzbeee1965672012-03-11 18:39:19 -07001257 return oatVRegOffset(cUnit, SRegToVReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -08001258}
1259
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001260} // namespace art