blob: bb2abbaad5c662b69c1e28dca278c1e524e10466 [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
150/* Reserve a callee-save register. Return -1 if none available */
151extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
152{
153 int res = -1;
154 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
155 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
156 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
157 res = coreRegs[i].reg;
158 coreRegs[i].inUse = true;
159 cUnit->coreSpillMask |= (1 << res);
buzbeec41e5b52011-09-23 12:46:19 -0700160 cUnit->coreVmapTable.push_back(sReg);
buzbeebbaf8942011-10-02 13:08:29 -0700161 cUnit->numCoreSpills++;
buzbee67bc2362011-10-11 18:08:40 -0700162 // Should be promoting based on initial sReg set
163 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
164 cUnit->promotionMap[sReg].coreLocation = kLocPhysReg;
165 cUnit->promotionMap[sReg].coreReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700166 break;
167 }
168 }
169 return res;
170}
171
172/*
173 * Reserve a callee-save fp single register. Try to fullfill request for
174 * even/odd allocation, but go ahead and allocate anything if not
175 * available. If nothing's available, return -1.
176 */
buzbee31a4a6f2012-02-28 15:36:15 -0800177int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700178{
179 int res = -1;
180 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
181 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
182 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
183 ((FPRegs[i].reg & 0x1) == 0) == even) {
184 res = FPRegs[i].reg;
185 FPRegs[i].inUse = true;
buzbee67bc2362011-10-11 18:08:40 -0700186 // Should be promoting based on initial sReg set
187 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -0800188 oatMarkPreservedSingle(cUnit, sReg, res);
buzbee67bc2362011-10-11 18:08:40 -0700189 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
190 cUnit->promotionMap[sReg].fpReg = res;
buzbee67bf8852011-08-17 17:51:35 -0700191 break;
192 }
193 }
194 return res;
195}
196
197/*
198 * Somewhat messy code here. We want to allocate a pair of contiguous
199 * physical single-precision floating point registers starting with
200 * an even numbered reg. It is possible that the paired sReg (sReg+1)
201 * has already been allocated - try to fit if possible. Fail to
202 * allocate if we can't meet the requirements for the pair of
203 * sReg<=sX[even] & (sReg+1)<= sX+1.
204 */
buzbee31a4a6f2012-02-28 15:36:15 -0800205int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700206{
207 int res = -1; // Assume failure
buzbee67bc2362011-10-11 18:08:40 -0700208 // Should be promoting based on initial sReg set
209 DCHECK_EQ(sReg, oatS2VReg(cUnit, sReg));
210 if (cUnit->promotionMap[sReg+1].fpLocation == kLocPhysReg) {
buzbee67bf8852011-08-17 17:51:35 -0700211 // Upper reg is already allocated. Can we fit?
buzbee67bc2362011-10-11 18:08:40 -0700212 int highReg = cUnit->promotionMap[sReg+1].fpReg;
buzbee67bf8852011-08-17 17:51:35 -0700213 if ((highReg & 1) == 0) {
214 // High reg is even - fail.
215 return res;
216 }
217 // Is the low reg of the pair free?
buzbee68253262011-10-07 14:02:25 -0700218 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
buzbee67bf8852011-08-17 17:51:35 -0700219 if (p->inUse || p->isTemp) {
220 // Already allocated or not preserved - fail.
221 return res;
222 }
223 // OK - good to go.
224 res = p->reg;
225 p->inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700226 DCHECK_EQ((res & 1), 0);
buzbeee3acd072012-02-25 17:03:10 -0800227 oatMarkPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700228 } else {
229 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
230 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
231 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
232 ((FPRegs[i].reg & 0x1) == 0x0) &&
233 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
234 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
235 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
236 res = FPRegs[i].reg;
237 FPRegs[i].inUse = true;
buzbeee3acd072012-02-25 17:03:10 -0800238 oatMarkPreservedSingle(cUnit, sReg, res);
buzbee67bf8852011-08-17 17:51:35 -0700239 FPRegs[i+1].inUse = true;
buzbeebbaf8942011-10-02 13:08:29 -0700240 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
buzbeee3acd072012-02-25 17:03:10 -0800241 oatMarkPreservedSingle(cUnit, sReg+1, res+1);
buzbee67bf8852011-08-17 17:51:35 -0700242 break;
243 }
244 }
245 }
246 if (res != -1) {
buzbee67bc2362011-10-11 18:08:40 -0700247 cUnit->promotionMap[sReg].fpLocation = kLocPhysReg;
248 cUnit->promotionMap[sReg].fpReg = res;
249 cUnit->promotionMap[sReg+1].fpLocation = kLocPhysReg;
250 cUnit->promotionMap[sReg+1].fpReg = res + 1;
buzbee67bf8852011-08-17 17:51:35 -0700251 }
252 return res;
253}
254
255
256/*
257 * Reserve a callee-save fp register. If this register can be used
258 * as the first of a double, attempt to allocate an even pair of fp
259 * single regs (but if can't still attempt to allocate a single, preferring
260 * first to allocate an odd register.
261 */
262extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
263 bool doubleStart)
264{
265 int res = -1;
266 if (doubleStart) {
267 res = allocPreservedDouble(cUnit, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700268 }
269 if (res == -1) {
270 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
271 }
272 if (res == -1)
273 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
274 return res;
275}
276
buzbee31a4a6f2012-02-28 15:36:15 -0800277int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
278 int* nextTemp, bool required)
buzbee67bf8852011-08-17 17:51:35 -0700279{
280 int i;
281 int next = *nextTemp;
282 for (i=0; i< numRegs; i++) {
283 if (next >= numRegs)
284 next = 0;
285 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
286 oatClobber(cUnit, p[next].reg);
287 p[next].inUse = true;
288 p[next].pair = false;
289 *nextTemp = next + 1;
290 return p[next].reg;
291 }
292 next++;
293 }
294 next = *nextTemp;
295 for (i=0; i< numRegs; i++) {
296 if (next >= numRegs)
297 next = 0;
298 if (p[next].isTemp && !p[next].inUse) {
299 oatClobber(cUnit, p[next].reg);
300 p[next].inUse = true;
301 p[next].pair = false;
302 *nextTemp = next + 1;
303 return p[next].reg;
304 }
305 next++;
306 }
307 if (required) {
buzbee6181f792011-09-29 11:14:04 -0700308 oatCodegenDump(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700309 dumpRegPool(cUnit->regPool->coreRegs,
310 cUnit->regPool->numCoreRegs);
311 LOG(FATAL) << "No free temp registers";
312 }
313 return -1; // No register available
314}
315
316//REDO: too many assumptions.
317extern int oatAllocTempDouble(CompilationUnit* cUnit)
318{
319 RegisterInfo* p = cUnit->regPool->FPRegs;
320 int numRegs = cUnit->regPool->numFPRegs;
buzbeea50638b2011-11-02 15:15:06 -0700321 /* Start looking at an even reg */
322 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700323
buzbeea50638b2011-11-02 15:15:06 -0700324 // First try to avoid allocating live registers
325 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700326 if (next >= numRegs)
327 next = 0;
328 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
329 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
330 oatClobber(cUnit, p[next].reg);
331 oatClobber(cUnit, p[next+1].reg);
332 p[next].inUse = true;
333 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700334 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
335 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700336 cUnit->regPool->nextFPReg = next + 2;
337 if (cUnit->regPool->nextFPReg >= numRegs) {
338 cUnit->regPool->nextFPReg = 0;
339 }
buzbee67bf8852011-08-17 17:51:35 -0700340 return p[next].reg;
341 }
342 next += 2;
343 }
buzbeea50638b2011-11-02 15:15:06 -0700344 next = cUnit->regPool->nextFPReg & ~0x1;
345
346 // No choice - find a pair and kill it.
347 for (int i=0; i < numRegs; i+=2) {
buzbee67bf8852011-08-17 17:51:35 -0700348 if (next >= numRegs)
349 next = 0;
350 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
351 !p[next+1].inUse) {
352 oatClobber(cUnit, p[next].reg);
353 oatClobber(cUnit, p[next+1].reg);
354 p[next].inUse = true;
355 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700356 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
357 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeea50638b2011-11-02 15:15:06 -0700358 cUnit->regPool->nextFPReg = next + 2;
359 if (cUnit->regPool->nextFPReg >= numRegs) {
360 cUnit->regPool->nextFPReg = 0;
361 }
buzbee67bf8852011-08-17 17:51:35 -0700362 return p[next].reg;
363 }
364 next += 2;
365 }
buzbee6181f792011-09-29 11:14:04 -0700366 LOG(FATAL) << "No free temp registers (pair)";
buzbee67bf8852011-08-17 17:51:35 -0700367 return -1;
368}
369
370/* Return a temp if one is available, -1 otherwise */
371extern int oatAllocFreeTemp(CompilationUnit* cUnit)
372{
373 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
374 cUnit->regPool->numCoreRegs,
375 &cUnit->regPool->nextCoreReg, true);
376}
377
378extern int oatAllocTemp(CompilationUnit* cUnit)
379{
380 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
381 cUnit->regPool->numCoreRegs,
382 &cUnit->regPool->nextCoreReg, true);
383}
384
385extern int oatAllocTempFloat(CompilationUnit* cUnit)
386{
387 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
388 cUnit->regPool->numFPRegs,
389 &cUnit->regPool->nextFPReg, true);
390}
391
buzbee31a4a6f2012-02-28 15:36:15 -0800392RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700393{
394 int i;
395 if (sReg == -1)
396 return NULL;
397 for (i=0; i < numRegs; i++) {
398 if (p[i].live && (p[i].sReg == sReg)) {
399 if (p[i].isTemp)
400 p[i].inUse = true;
401 return &p[i];
402 }
403 }
404 return NULL;
405}
406
buzbee31a4a6f2012-02-28 15:36:15 -0800407RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg, int regClass)
buzbee67bf8852011-08-17 17:51:35 -0700408{
409 RegisterInfo* res = NULL;
410 switch(regClass) {
411 case kAnyReg:
412 res = allocLiveBody(cUnit->regPool->FPRegs,
413 cUnit->regPool->numFPRegs, sReg);
414 if (res)
415 break;
416 /* Intentional fallthrough */
417 case kCoreReg:
418 res = allocLiveBody(cUnit->regPool->coreRegs,
419 cUnit->regPool->numCoreRegs, sReg);
420 break;
421 case kFPReg:
422 res = allocLiveBody(cUnit->regPool->FPRegs,
423 cUnit->regPool->numFPRegs, sReg);
424 break;
425 default:
426 LOG(FATAL) << "Invalid register type";
427 }
428 return res;
429}
430
431extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
432{
433 RegisterInfo* p = cUnit->regPool->coreRegs;
434 int numRegs = cUnit->regPool->numCoreRegs;
435 int i;
436 for (i=0; i< numRegs; i++) {
437 if (p[i].reg == reg) {
438 if (p[i].isTemp) {
439 p[i].inUse = false;
440 }
441 p[i].pair = false;
442 return;
443 }
444 }
445 p = cUnit->regPool->FPRegs;
446 numRegs = cUnit->regPool->numFPRegs;
447 for (i=0; i< numRegs; i++) {
448 if (p[i].reg == reg) {
449 if (p[i].isTemp) {
450 p[i].inUse = false;
451 }
452 p[i].pair = false;
453 return;
454 }
455 }
456 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
457}
458
459extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
460{
461 RegisterInfo* p = cUnit->regPool->coreRegs;
462 int numRegs = cUnit->regPool->numCoreRegs;
463 int i;
464 for (i=0; i< numRegs; i++) {
465 if (p[i].reg == reg) {
466 return p[i].live ? &p[i] : NULL;
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 return p[i].live ? &p[i] : NULL;
474 }
475 }
476 return NULL;
477}
478
479extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
480{
buzbee68253262011-10-07 14:02:25 -0700481 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700482 return (p->isTemp) ? p : NULL;
483}
484
buzbeeb29e4d12011-09-26 15:05:48 -0700485extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
486{
buzbee68253262011-10-07 14:02:25 -0700487 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbeeb29e4d12011-09-26 15:05:48 -0700488 return (p->isTemp) ? NULL : p;
489}
490
buzbee67bf8852011-08-17 17:51:35 -0700491extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
492{
buzbee68253262011-10-07 14:02:25 -0700493 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700494 return p->dirty;
495}
496
497/*
498 * Similar to oatAllocTemp(), but forces the allocation of a specific
499 * register. No check is made to see if the register was previously
500 * allocated. Use with caution.
501 */
502extern void oatLockTemp(CompilationUnit* cUnit, int reg)
503{
504 RegisterInfo* p = cUnit->regPool->coreRegs;
505 int numRegs = cUnit->regPool->numCoreRegs;
506 int i;
507 for (i=0; i< numRegs; i++) {
508 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700509 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700510 p[i].inUse = true;
511 p[i].live = false;
512 return;
513 }
514 }
515 p = cUnit->regPool->FPRegs;
516 numRegs = cUnit->regPool->numFPRegs;
517 for (i=0; i< numRegs; i++) {
518 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700519 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700520 p[i].inUse = true;
521 p[i].live = false;
522 return;
523 }
524 }
525 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
526}
527
buzbee5abfa3e2012-01-31 17:01:43 -0800528static inline void resetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700529{
buzbee67bf8852011-08-17 17:51:35 -0700530 p->defStart = NULL;
531 p->defEnd = NULL;
532}
533
buzbee5abfa3e2012-01-31 17:01:43 -0800534extern void oatResetDef(CompilationUnit* cUnit, int reg)
535{
536 resetDefBody(oatGetRegInfo(cUnit, reg));
537}
538
buzbee31a4a6f2012-02-28 15:36:15 -0800539void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700540 int sReg1, int sReg2)
541{
542 if (start && finish) {
543 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700544 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700545 for (p = start; ;p = p->next) {
buzbeee3acd072012-02-25 17:03:10 -0800546 oatNopLIR(p);
buzbee67bf8852011-08-17 17:51:35 -0700547 if (p == finish)
548 break;
549 }
550 }
551}
552
553/*
554 * Mark the beginning and end LIR of a def sequence. Note that
555 * on entry start points to the LIR prior to the beginning of the
556 * sequence.
557 */
558extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
buzbee31a4a6f2012-02-28 15:36:15 -0800559 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700560{
buzbeeed3e9302011-09-23 17:34:19 -0700561 DCHECK(!rl.wide);
562 DCHECK(start && start->next);
563 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700564 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700565 p->defStart = start->next;
566 p->defEnd = finish;
567}
568
569/*
570 * Mark the beginning and end LIR of a def sequence. Note that
571 * on entry start points to the LIR prior to the beginning of the
572 * sequence.
573 */
574extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
buzbee31a4a6f2012-02-28 15:36:15 -0800575 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700576{
buzbeeed3e9302011-09-23 17:34:19 -0700577 DCHECK(rl.wide);
578 DCHECK(start && start->next);
579 DCHECK(finish);
buzbee68253262011-10-07 14:02:25 -0700580 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700581 oatResetDef(cUnit, rl.highReg); // Only track low of pair
582 p->defStart = start->next;
583 p->defEnd = finish;
584}
585
buzbee31a4a6f2012-02-28 15:36:15 -0800586extern RegLocation oatWideToNarrow(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700587{
buzbeeed3e9302011-09-23 17:34:19 -0700588 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700589 if (rl.location == kLocPhysReg) {
buzbee68253262011-10-07 14:02:25 -0700590 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
591 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700592 if (infoLo->isTemp) {
593 infoLo->pair = false;
594 infoLo->defStart = NULL;
595 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700596 }
buzbee0c7f26d2011-09-07 12:28:51 -0700597 if (infoHi->isTemp) {
598 infoHi->pair = false;
599 infoHi->defStart = NULL;
600 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700601 }
buzbee67bf8852011-08-17 17:51:35 -0700602 }
603 rl.wide = false;
604 return rl;
605}
606
607extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
608{
buzbeeed3e9302011-09-23 17:34:19 -0700609 DCHECK(!rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700610 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
611 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
buzbeeed3e9302011-09-23 17:34:19 -0700612 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700613 nullifyRange(cUnit, p->defStart, p->defEnd,
614 p->sReg, rl.sRegLow);
615 }
616 oatResetDef(cUnit, rl.lowReg);
617}
618
619extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
620{
buzbeeed3e9302011-09-23 17:34:19 -0700621 DCHECK(rl.wide);
buzbee6181f792011-09-29 11:14:04 -0700622 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
623 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
624 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
625 DCHECK(pLow->pair);
626 nullifyRange(cUnit, pLow->defStart, pLow->defEnd,
627 pLow->sReg, rl.sRegLow);
628 }
629 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
630 DCHECK(pHigh->pair);
buzbee67bf8852011-08-17 17:51:35 -0700631 }
632 oatResetDef(cUnit, rl.lowReg);
633 oatResetDef(cUnit, rl.highReg);
634}
635
636extern void oatResetDefTracking(CompilationUnit* cUnit)
637{
638 int i;
639 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800640 resetDefBody(&cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700641 }
642 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800643 resetDefBody(&cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700644 }
645}
646
647extern void oatClobberAllRegs(CompilationUnit* cUnit)
648{
649 int i;
650 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800651 clobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700652 }
653 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800654 clobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
buzbee67bf8852011-08-17 17:51:35 -0700655 }
656}
657
buzbee67bf8852011-08-17 17:51:35 -0700658// Make sure nothing is live and dirty
buzbee31a4a6f2012-02-28 15:36:15 -0800659void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700660 int numRegs)
661{
662 int i;
663 for (i=0; i < numRegs; i++) {
664 if (info[i].live && info[i].dirty) {
665 if (info[i].pair) {
666 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
667 } else {
668 oatFlushReg(cUnit, info[i].reg);
669 }
670 }
671 }
672}
673
674extern void oatFlushAllRegs(CompilationUnit* cUnit)
675{
676 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
677 cUnit->regPool->numCoreRegs);
678 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
679 cUnit->regPool->numFPRegs);
680 oatClobberAllRegs(cUnit);
681}
682
683
684//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee31a4a6f2012-02-28 15:36:15 -0800685bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700686{
687 if (regClass == kAnyReg) {
688 return true;
689 } else if (regClass == kCoreReg) {
buzbeee3acd072012-02-25 17:03:10 -0800690 return !oatIsFpReg(reg);
buzbee67bf8852011-08-17 17:51:35 -0700691 } else {
buzbeee3acd072012-02-25 17:03:10 -0800692 return oatIsFpReg(reg);
buzbee67bf8852011-08-17 17:51:35 -0700693 }
694}
695
696extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
697{
buzbee68253262011-10-07 14:02:25 -0700698 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700699 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
700 return; /* already live */
701 } else if (sReg != INVALID_SREG) {
702 oatClobberSReg(cUnit, sReg);
703 if (info->isTemp) {
704 info->live = true;
705 }
706 } else {
707 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700708 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700709 info->live = false;
710 }
711 info->sReg = sReg;
712}
713
714extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
715{
buzbee68253262011-10-07 14:02:25 -0700716 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700717 info->isTemp = true;
718}
719
buzbee9e0f9b02011-08-24 15:32:46 -0700720extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
721{
buzbee68253262011-10-07 14:02:25 -0700722 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee9e0f9b02011-08-24 15:32:46 -0700723 info->isTemp = false;
724}
725
buzbee67bf8852011-08-17 17:51:35 -0700726extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
727{
buzbee68253262011-10-07 14:02:25 -0700728 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
729 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
buzbee67bf8852011-08-17 17:51:35 -0700730 infoLo->pair = infoHi->pair = true;
731 infoLo->partner = highReg;
732 infoHi->partner = lowReg;
733}
734
735extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
736{
buzbee68253262011-10-07 14:02:25 -0700737 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700738 info->dirty = false;
739 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700740 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700741 info->dirty = false;
742 }
743}
744
745extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
746{
747 if (loc.home) {
748 // If already home, can't be dirty
749 return;
750 }
buzbee68253262011-10-07 14:02:25 -0700751 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700752 info->dirty = true;
753 if (loc.wide) {
buzbee68253262011-10-07 14:02:25 -0700754 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700755 info->dirty = true;
756 }
757}
758
759extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
760{
buzbee68253262011-10-07 14:02:25 -0700761 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
buzbee67bf8852011-08-17 17:51:35 -0700762 info->inUse = true;
763}
764
buzbee31a4a6f2012-02-28 15:36:15 -0800765void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700766{
buzbee68253262011-10-07 14:02:25 -0700767 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
768 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700769 // Target temp status must not change
770 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700771 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700772 // Restore target's temp status
773 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700774 newInfo->reg = newReg;
775}
776
777/*
778 * Return an updated location record with current in-register status.
779 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700780 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700781 * clobber both low and high.
782 * TUNING: clobbering both is a bit heavy-handed, but the alternative
783 * is a bit complex when dealing with FP regs. Examine code to see
784 * if it's worthwhile trying to be more clever here.
785 */
786
787extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
788{
buzbeeed3e9302011-09-23 17:34:19 -0700789 DCHECK(!loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700790 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700791 if (loc.location == kLocDalvikFrame) {
792 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
793 if (infoLo) {
794 if (infoLo->pair) {
795 oatClobber(cUnit, infoLo->reg);
796 oatClobber(cUnit, infoLo->partner);
buzbee58f92742011-10-01 11:22:17 -0700797 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700798 } else {
799 loc.lowReg = infoLo->reg;
800 loc.location = kLocPhysReg;
801 }
802 }
803 }
804
805 return loc;
806}
807
buzbee6181f792011-09-29 11:14:04 -0700808bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
809{
810 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
811 if (cUnit->regPool->coreRegs[i].pair) {
812 static int myReg = cUnit->regPool->coreRegs[i].reg;
813 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
814 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
buzbee68253262011-10-07 14:02:25 -0700815 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
buzbee6181f792011-09-29 11:14:04 -0700816 DCHECK(partner != NULL);
817 DCHECK(partner->pair);
818 DCHECK_EQ(myReg, partner->partner);
819 static int partnerSreg = partner->sReg;
820 if (mySreg == INVALID_SREG) {
821 DCHECK_EQ(partnerSreg, INVALID_SREG);
822 } else {
823 int diff = mySreg - partnerSreg;
824 DCHECK((diff == -1) || (diff == 1));
825 }
826 }
827 if (!cUnit->regPool->coreRegs[i].live) {
828 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
829 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
830 }
831 }
832 return true;
833}
834
buzbee67bf8852011-08-17 17:51:35 -0700835/* see comments for updateLoc */
buzbee31a4a6f2012-02-28 15:36:15 -0800836extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700837{
buzbeeed3e9302011-09-23 17:34:19 -0700838 DCHECK(loc.wide);
buzbee6181f792011-09-29 11:14:04 -0700839 DCHECK(oatCheckCorePoolSanity(cUnit));
buzbee67bf8852011-08-17 17:51:35 -0700840 if (loc.location == kLocDalvikFrame) {
841 // Are the dalvik regs already live in physical registers?
842 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
843 RegisterInfo* infoHi = allocLive(cUnit,
844 oatSRegHi(loc.sRegLow), kAnyReg);
845 bool match = true;
846 match = match && (infoLo != NULL);
847 match = match && (infoHi != NULL);
848 // Are they both core or both FP?
buzbeee3acd072012-02-25 17:03:10 -0800849 match = match && (oatIsFpReg(infoLo->reg) == oatIsFpReg(infoHi->reg));
buzbee67bf8852011-08-17 17:51:35 -0700850 // If a pair of floating point singles, are they properly aligned?
buzbeee3acd072012-02-25 17:03:10 -0800851 if (match && oatIsFpReg(infoLo->reg)) {
buzbee67bf8852011-08-17 17:51:35 -0700852 match &= ((infoLo->reg & 0x1) == 0);
853 match &= ((infoHi->reg - infoLo->reg) == 1);
854 }
855 // If previously used as a pair, it is the same pair?
856 if (match && (infoLo->pair || infoHi->pair)) {
857 match = (infoLo->pair == infoHi->pair);
858 match &= ((infoLo->reg == infoHi->partner) &&
859 (infoHi->reg == infoLo->partner));
860 }
861 if (match) {
862 // Can reuse - update the register usage info
863 loc.lowReg = infoLo->reg;
864 loc.highReg = infoHi->reg;
865 loc.location = kLocPhysReg;
866 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeee3acd072012-02-25 17:03:10 -0800867 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700868 return loc;
869 }
buzbee58f92742011-10-01 11:22:17 -0700870 // Can't easily reuse - clobber and free any overlaps
buzbee67bf8852011-08-17 17:51:35 -0700871 if (infoLo) {
872 oatClobber(cUnit, infoLo->reg);
buzbee58f92742011-10-01 11:22:17 -0700873 oatFreeTemp(cUnit, infoLo->reg);
buzbee67bf8852011-08-17 17:51:35 -0700874 if (infoLo->pair)
875 oatClobber(cUnit, infoLo->partner);
876 }
877 if (infoHi) {
878 oatClobber(cUnit, infoHi->reg);
buzbee58f92742011-10-01 11:22:17 -0700879 oatFreeTemp(cUnit, infoHi->reg);
buzbee67bf8852011-08-17 17:51:35 -0700880 if (infoHi->pair)
881 oatClobber(cUnit, infoHi->partner);
882 }
883 }
884 return loc;
885}
886
buzbeeed3e9302011-09-23 17:34:19 -0700887
888/* For use in cases we don't know (or care) width */
buzbee31a4a6f2012-02-28 15:36:15 -0800889extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700890{
891 if (loc.wide)
892 return oatUpdateLocWide(cUnit, loc);
893 else
894 return oatUpdateLoc(cUnit, loc);
895}
896
buzbee31a4a6f2012-02-28 15:36:15 -0800897RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
898 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700899{
buzbeeed3e9302011-09-23 17:34:19 -0700900 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700901 int newRegs;
902 int lowReg;
903 int highReg;
904
905 loc = oatUpdateLocWide(cUnit, loc);
906
907 /* If already in registers, we can assume proper form. Right reg class? */
908 if (loc.location == kLocPhysReg) {
buzbeee3acd072012-02-25 17:03:10 -0800909 DCHECK_EQ(oatIsFpReg(loc.lowReg), oatIsFpReg(loc.highReg));
910 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700911 if (!regClassMatches(regClass, loc.lowReg)) {
912 /* Wrong register class. Reallocate and copy */
913 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
914 lowReg = newRegs & 0xff;
915 highReg = (newRegs >> 8) & 0xff;
916 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
917 loc.highReg);
918 copyRegInfo(cUnit, lowReg, loc.lowReg);
919 copyRegInfo(cUnit, highReg, loc.highReg);
920 oatClobber(cUnit, loc.lowReg);
921 oatClobber(cUnit, loc.highReg);
922 loc.lowReg = lowReg;
923 loc.highReg = highReg;
924 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeee3acd072012-02-25 17:03:10 -0800925 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700926 }
927 return loc;
928 }
929
buzbeeed3e9302011-09-23 17:34:19 -0700930 DCHECK_NE(loc.sRegLow, INVALID_SREG);
931 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700932
933 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
934 loc.lowReg = newRegs & 0xff;
935 loc.highReg = (newRegs >> 8) & 0xff;
936
937 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
938 if (update) {
939 loc.location = kLocPhysReg;
940 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
941 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
942 }
buzbeee3acd072012-02-25 17:03:10 -0800943 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700944 return loc;
945}
946
947extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
948 int regClass, bool update)
949{
950 int newReg;
951
952 if (loc.wide)
953 return evalLocWide(cUnit, loc, regClass, update);
954
955 loc = oatUpdateLoc(cUnit, loc);
956
957 if (loc.location == kLocPhysReg) {
958 if (!regClassMatches(regClass, loc.lowReg)) {
959 /* Wrong register class. Realloc, copy and transfer ownership */
960 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
961 oatRegCopy(cUnit, newReg, loc.lowReg);
962 copyRegInfo(cUnit, newReg, loc.lowReg);
963 oatClobber(cUnit, loc.lowReg);
964 loc.lowReg = newReg;
965 }
966 return loc;
967 }
968
buzbeeed3e9302011-09-23 17:34:19 -0700969 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700970
971 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
972 loc.lowReg = newReg;
973
974 if (update) {
975 loc.location = kLocPhysReg;
976 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
977 }
978 return loc;
979}
980
981extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
982{
buzbeee9a72f62011-09-04 17:59:07 -0700983 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeeed3e9302011-09-23 17:34:19 -0700984 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -0700985 return res;
buzbee67bf8852011-08-17 17:51:35 -0700986}
987extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
988{
buzbeee9a72f62011-09-04 17:59:07 -0700989 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -0700990 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -0700991 return res;
992}
993extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
994{
995 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
996 return res;
buzbee67bf8852011-08-17 17:51:35 -0700997}
998extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
999 int low, int high)
1000{
buzbeee9a72f62011-09-04 17:59:07 -07001001 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001002 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001003 return res;
buzbee67bf8852011-08-17 17:51:35 -07001004}
1005
1006extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1007 int low, int high)
1008{
buzbeee9a72f62011-09-04 17:59:07 -07001009 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001010 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001011 return res;
buzbee67bf8852011-08-17 17:51:35 -07001012}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001013
buzbeee3acd072012-02-25 17:03:10 -08001014/* USE SSA names to count references of base Dalvik vRegs. */
1015void oatCountRefs(CompilationUnit *cUnit, BasicBlock* bb,
buzbee31a4a6f2012-02-28 15:36:15 -08001016 RefCounts* coreCounts, RefCounts* fpCounts)
buzbeee3acd072012-02-25 17:03:10 -08001017{
1018 MIR* mir;
1019 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock &&
1020 bb->blockType != kExitBlock)
1021 return;
1022
1023 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
1024 SSARepresentation *ssaRep = mir->ssaRep;
1025 if (ssaRep) {
1026 for (int i = 0; i < ssaRep->numDefs;) {
1027 RegLocation loc = cUnit->regLocation[ssaRep->defs[i]];
1028 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
1029 int vReg = oatS2VReg(cUnit, ssaRep->defs[i]);
1030 if (loc.defined) {
1031 counts[vReg].count++;
1032 }
1033 if (loc.wide) {
1034 if (loc.defined) {
1035 if (loc.fp) {
1036 counts[vReg].doubleStart = true;
1037 }
1038 counts[vReg+1].count++;
1039 }
1040 i += 2;
1041 } else {
1042 i++;
1043 }
1044 }
1045 for (int i = 0; i < ssaRep->numUses;) {
1046 RegLocation loc = cUnit->regLocation[ssaRep->uses[i]];
1047 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
1048 int vReg = oatS2VReg(cUnit, ssaRep->uses[i]);
1049 if (loc.defined) {
1050 counts[vReg].count++;
1051 }
1052 if (loc.wide) {
1053 if (loc.defined) {
1054 if (loc.fp) {
1055 counts[vReg].doubleStart = true;
1056 }
1057 counts[vReg+1].count++;
1058 }
1059 i += 2;
1060 } else {
1061 i++;
1062 }
1063 }
1064 }
1065 }
1066}
1067
1068/* qsort callback function, sort descending */
1069int oatSortCounts(const void *val1, const void *val2)
1070{
1071 const RefCounts* op1 = (const RefCounts*)val1;
1072 const RefCounts* op2 = (const RefCounts*)val2;
1073 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
1074}
1075
1076void oatDumpCounts(const RefCounts* arr, int size, const char* msg)
1077{
1078 LOG(INFO) << msg;
1079 for (int i = 0; i < size; i++) {
1080 LOG(INFO) << "sReg[" << arr[i].sReg << "]: " << arr[i].count;
1081 }
1082}
1083
1084/*
1085 * Note: some portions of this code required even if the kPromoteRegs
1086 * optimization is disabled.
1087 */
1088extern void oatDoPromotion(CompilationUnit* cUnit)
1089{
1090 int numRegs = cUnit->numDalvikRegisters;
1091
1092 // Allow target code to add any special registers
1093 oatAdjustSpillMask(cUnit);
1094
1095 /*
1096 * Simple register promotion. Just do a static count of the uses
1097 * of Dalvik registers. Note that we examine the SSA names, but
1098 * count based on original Dalvik register name. Count refs
1099 * separately based on type in order to give allocation
1100 * preference to fp doubles - which must be allocated sequential
1101 * physical single fp registers started with an even-numbered
1102 * reg.
1103 * TUNING: replace with linear scan once we have the ability
1104 * to describe register live ranges for GC.
1105 */
1106 RefCounts *coreRegs = (RefCounts *)
1107 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1108 RefCounts *fpRegs = (RefCounts *)
1109 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1110 for (int i = 0; i < numRegs; i++) {
1111 coreRegs[i].sReg = fpRegs[i].sReg = i;
1112 }
1113 GrowableListIterator iterator;
1114 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
1115 while (true) {
1116 BasicBlock* bb;
1117 bb = (BasicBlock*)oatGrowableListIteratorNext(&iterator);
1118 if (bb == NULL) break;
1119 oatCountRefs(cUnit, bb, coreRegs, fpRegs);
1120 }
1121
1122 /*
1123 * Ideally, we'd allocate doubles starting with an even-numbered
1124 * register. Bias the counts to try to allocate any vreg that's
1125 * used as the start of a pair first.
1126 */
1127 for (int i = 0; i < numRegs; i++) {
1128 if (fpRegs[i].doubleStart) {
1129 fpRegs[i].count *= 2;
1130 }
1131 }
1132
1133 // Sort the count arrays
1134 qsort(coreRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1135 qsort(fpRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1136
1137 if (cUnit->printMe) {
1138 oatDumpCounts(coreRegs, numRegs, "Core regs after sort");
1139 oatDumpCounts(fpRegs, numRegs, "Fp regs after sort");
1140 }
1141
1142 if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
1143 // Promote fpRegs
1144 for (int i = 0; (fpRegs[i].count > 0) && (i < numRegs); i++) {
1145 if (cUnit->promotionMap[fpRegs[i].sReg].fpLocation != kLocPhysReg) {
1146 if (fpRegs[i].sReg >= cUnit->numRegs) {
1147 // don't promote arg regs
1148 continue;
1149 }
1150 int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
1151 fpRegs[i].doubleStart);
1152 if (reg < 0) {
1153 break; // No more left
1154 }
1155 }
1156 }
1157
1158 // Promote core regs
1159 for (int i = 0; (coreRegs[i].count > 0) && i < numRegs; i++) {
1160 if (cUnit->promotionMap[coreRegs[i].sReg].coreLocation !=
1161 kLocPhysReg) {
1162 if (coreRegs[i].sReg >= cUnit->numRegs) {
1163 // don't promote arg regs
1164 continue;
1165 }
1166 int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
1167 if (reg < 0) {
1168 break; // No more left
1169 }
1170 }
1171 }
1172 }
1173
1174 // Now, update SSA names to new home locations
1175 for (int i = 0; i < cUnit->numSSARegs; i++) {
1176 RegLocation *curr = &cUnit->regLocation[i];
1177 int baseVReg = oatS2VReg(cUnit, curr->sRegLow);
1178 if (!curr->wide) {
1179 if (curr->fp) {
1180 if (cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) {
1181 curr->location = kLocPhysReg;
1182 curr->lowReg = cUnit->promotionMap[baseVReg].fpReg;
1183 curr->home = true;
1184 }
1185 } else {
1186 if (cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg) {
1187 curr->location = kLocPhysReg;
1188 curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
1189 curr->home = true;
1190 }
1191 }
1192 curr->highReg = INVALID_REG;
1193 } else {
1194 if (curr->highWord) {
1195 continue;
1196 }
1197 if (curr->fp) {
1198 if ((cUnit->promotionMap[baseVReg].fpLocation == kLocPhysReg) &&
1199 (cUnit->promotionMap[baseVReg+1].fpLocation ==
1200 kLocPhysReg)) {
1201 int lowReg = cUnit->promotionMap[baseVReg].fpReg;
1202 int highReg = cUnit->promotionMap[baseVReg+1].fpReg;
1203 // Doubles require pair of singles starting at even reg
1204 if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
1205 curr->location = kLocPhysReg;
1206 curr->lowReg = lowReg;
1207 curr->highReg = highReg;
1208 curr->home = true;
1209 }
1210 }
1211 } else {
1212 if ((cUnit->promotionMap[baseVReg].coreLocation == kLocPhysReg)
1213 && (cUnit->promotionMap[baseVReg+1].coreLocation ==
1214 kLocPhysReg)) {
1215 curr->location = kLocPhysReg;
1216 curr->lowReg = cUnit->promotionMap[baseVReg].coreReg;
1217 curr->highReg = cUnit->promotionMap[baseVReg+1].coreReg;
1218 curr->home = true;
1219 }
1220 }
1221 }
1222 }
1223}
1224
1225/* Returns sp-relative offset in bytes for a VReg */
1226extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
1227{
1228 return (vReg < cUnit->numRegs) ? cUnit->regsOffset + (vReg << 2) :
1229 cUnit->insOffset + ((vReg - cUnit->numRegs) << 2);
1230}
1231
1232/* Returns sp-relative offset in bytes for a SReg */
1233extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
1234{
1235 return oatVRegOffset(cUnit, oatS2VReg(cUnit, sReg));
1236}
1237
1238
1239/* Return sp-relative offset in bytes using Method* */
1240extern int oatVRegOffset(const DexFile::CodeItem* code_item,
1241 uint32_t core_spills, uint32_t fp_spills,
1242 size_t frame_size, int reg)
1243{
1244 int numIns = code_item->ins_size_;
1245 int numRegs = code_item->registers_size_ - numIns;
1246 int numOuts = code_item->outs_size_;
1247 int numSpills = __builtin_popcount(core_spills) +
1248 __builtin_popcount(fp_spills);
1249 int numPadding = (STACK_ALIGN_WORDS -
1250 (numSpills + numRegs + numOuts + 2)) & (STACK_ALIGN_WORDS-1);
1251 int regsOffset = (numOuts + numPadding + 1) * 4;
1252 int insOffset = frame_size + 4;
1253 return (reg < numRegs) ? regsOffset + (reg << 2) :
1254 insOffset + ((reg - numRegs) << 2);
1255}
1256
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001257} // namespace art