blob: 69b98d481442c04acef23edb997d9989a461ec23 [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
30#define SREG(c, s) ((c)->regLocation[(s)].sRegLow)
31/*
32 * Get the "real" sreg number associated with an sReg slot. In general,
33 * sReg values passed through codegen are the SSA names created by
34 * dataflow analysis and refer to slot numbers in the cUnit->regLocation
35 * array. However, renaming is accomplished by simply replacing RegLocation
36 * entries in the cUnit->reglocation[] array. Therefore, when location
37 * records for operands are first created, we need to ask the locRecord
38 * identified by the dataflow pass what it's new name is.
39 */
40
41/*
42 * Free all allocated temps in the temp pools. Note that this does
43 * not affect the "liveness" of a temp register, which will stay
44 * live until it is either explicitly killed or reallocated.
45 */
46extern void oatResetRegPool(CompilationUnit* cUnit)
47{
48 int i;
49 for (i=0; i < cUnit->regPool->numCoreRegs; i++) {
50 if (cUnit->regPool->coreRegs[i].isTemp)
51 cUnit->regPool->coreRegs[i].inUse = false;
52 }
53 for (i=0; i < cUnit->regPool->numFPRegs; i++) {
54 if (cUnit->regPool->FPRegs[i].isTemp)
55 cUnit->regPool->FPRegs[i].inUse = false;
56 }
57}
58
59 /* Set up temp & preserved register pools specialized by target */
60extern void oatInitPool(RegisterInfo* regs, int* regNums, int num)
61{
62 int i;
63 for (i=0; i < num; i++) {
64 regs[i].reg = regNums[i];
65 regs[i].inUse = false;
66 regs[i].isTemp = false;
67 regs[i].pair = false;
68 regs[i].live = false;
69 regs[i].dirty = false;
70 regs[i].sReg = INVALID_SREG;
71 }
72}
73
buzbeeed3e9302011-09-23 17:34:19 -070074STATIC void dumpRegPool(RegisterInfo* p, int numRegs)
buzbee67bf8852011-08-17 17:51:35 -070075{
76 int i;
77 LOG(INFO) << "================================================";
78 for (i=0; i < numRegs; i++ ){
79 char buf[100];
80 snprintf(buf, 100,
81 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
82 p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
83 p[i].live, p[i].dirty, p[i].sReg,(int)p[i].defStart,
84 (int)p[i].defEnd);
85 LOG(INFO) << buf;
86 }
87 LOG(INFO) << "================================================";
88}
89
90/* Get info for a reg. */
buzbeeed3e9302011-09-23 17:34:19 -070091STATIC RegisterInfo* getRegInfo(CompilationUnit* cUnit, int reg)
buzbee67bf8852011-08-17 17:51:35 -070092{
93 int numRegs = cUnit->regPool->numCoreRegs;
94 RegisterInfo* p = cUnit->regPool->coreRegs;
95 int i;
96 for (i=0; i< numRegs; i++) {
97 if (p[i].reg == reg) {
98 return &p[i];
99 }
100 }
101 p = cUnit->regPool->FPRegs;
102 numRegs = cUnit->regPool->numFPRegs;
103 for (i=0; i< numRegs; i++) {
104 if (p[i].reg == reg) {
105 return &p[i];
106 }
107 }
108 LOG(FATAL) << "Tried to get info on a non-existant reg :r" << reg;
109 return NULL; // Quiet gcc
110}
111
112void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
113{
114 RegisterInfo* info1 = getRegInfo(cUnit, reg1);
115 RegisterInfo* info2 = getRegInfo(cUnit, reg2);
buzbeeed3e9302011-09-23 17:34:19 -0700116 DCHECK(info1 && info2 && info1->pair && info2->pair &&
buzbee67bf8852011-08-17 17:51:35 -0700117 (info1->partner == info2->reg) &&
118 (info2->partner == info1->reg));
119 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
120 if (!(info1->isTemp && info2->isTemp)) {
121 /* Should not happen. If it does, there's a problem in evalLoc */
122 LOG(FATAL) << "Long half-temp, half-promoted";
123 }
124
125 info1->dirty = false;
126 info2->dirty = false;
127 if (oatS2VReg(cUnit, info2->sReg) <
128 oatS2VReg(cUnit, info1->sReg))
129 info1 = info2;
130 int vReg = oatS2VReg(cUnit, info1->sReg);
131 oatFlushRegWideImpl(cUnit, rSP,
132 oatVRegOffset(cUnit, vReg),
133 info1->reg, info1->partner);
134 }
135}
136
137void oatFlushReg(CompilationUnit* cUnit, int reg)
138{
139 RegisterInfo* info = getRegInfo(cUnit, reg);
140 if (info->live && info->dirty) {
141 info->dirty = false;
142 int vReg = oatS2VReg(cUnit, info->sReg);
143 oatFlushRegImpl(cUnit, rSP,
144 oatVRegOffset(cUnit, vReg),
145 reg, kWord);
146 }
147}
148
149/* return true if found reg to clobber */
buzbeeed3e9302011-09-23 17:34:19 -0700150STATIC bool clobberRegBody(CompilationUnit* cUnit, RegisterInfo* p,
buzbee67bf8852011-08-17 17:51:35 -0700151 int numRegs, int reg)
152{
153 int i;
154 for (i=0; i< numRegs; i++) {
155 if (p[i].reg == reg) {
156 if (p[i].isTemp) {
157 if (p[i].isTemp && p[i].live && p[i].dirty) {
158 if (p[i].pair) {
159 oatFlushRegWide(cUnit, p[i].reg, p[i].partner);
160 } else {
161 oatFlushReg(cUnit, p[i].reg);
162 }
163 }
164 p[i].live = false;
165 p[i].sReg = INVALID_SREG;
166 }
167 p[i].defStart = NULL;
168 p[i].defEnd = NULL;
169 if (p[i].pair) {
170 p[i].pair = false;
171 /* partners should be in same pool */
172 clobberRegBody(cUnit, p, numRegs, p[i].partner);
173 }
174 return true;
175 }
176 }
177 return false;
178}
179
180/* Mark a temp register as dead. Does not affect allocation state. */
181void oatClobber(CompilationUnit* cUnit, int reg)
182{
183 if (!clobberRegBody(cUnit, cUnit->regPool->coreRegs,
184 cUnit->regPool->numCoreRegs, reg)) {
185 clobberRegBody(cUnit, cUnit->regPool->FPRegs,
186 cUnit->regPool->numFPRegs, reg);
187 }
188}
189
buzbeeed3e9302011-09-23 17:34:19 -0700190STATIC void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700191{
192 int i;
193 for (i=0; i< numRegs; i++) {
194 if (p[i].sReg == sReg) {
195 if (p[i].isTemp) {
196 p[i].live = false;
197 }
198 p[i].defStart = NULL;
199 p[i].defEnd = NULL;
200 }
201 }
202}
203
204/* Clobber any temp associated with an sReg. Could be in either class */
205extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
206{
207 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs,
208 sReg);
209 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs,
210 sReg);
211}
212
213/* Reserve a callee-save register. Return -1 if none available */
214extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
215{
216 int res = -1;
217 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
218 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
219 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
220 res = coreRegs[i].reg;
221 coreRegs[i].inUse = true;
222 cUnit->coreSpillMask |= (1 << res);
buzbeec41e5b52011-09-23 12:46:19 -0700223 cUnit->coreVmapTable.push_back(sReg);
buzbee67bf8852011-08-17 17:51:35 -0700224 cUnit->numSpills++;
225 cUnit->regLocation[sReg].location = kLocPhysReg;
226 cUnit->regLocation[sReg].lowReg = res;
227 cUnit->regLocation[sReg].home = true;
228 break;
229 }
230 }
231 return res;
232}
233
234/*
235 * Reserve a callee-save fp single register. Try to fullfill request for
236 * even/odd allocation, but go ahead and allocate anything if not
237 * available. If nothing's available, return -1.
238 */
buzbeeed3e9302011-09-23 17:34:19 -0700239STATIC int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700240{
241 int res = -1;
242 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
243 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
244 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
245 ((FPRegs[i].reg & 0x1) == 0) == even) {
246 res = FPRegs[i].reg;
247 FPRegs[i].inUse = true;
248 cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
buzbeec41e5b52011-09-23 12:46:19 -0700249 cUnit->fpVmapTable.push_back(sReg);
buzbee67bf8852011-08-17 17:51:35 -0700250 cUnit->numSpills++;
251 cUnit->numFPSpills++;
252 cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
253 cUnit->regLocation[sReg].fpLowReg = res;
254 cUnit->regLocation[sReg].home = true;
255 break;
256 }
257 }
258 return res;
259}
260
261/*
262 * Somewhat messy code here. We want to allocate a pair of contiguous
263 * physical single-precision floating point registers starting with
264 * an even numbered reg. It is possible that the paired sReg (sReg+1)
265 * has already been allocated - try to fit if possible. Fail to
266 * allocate if we can't meet the requirements for the pair of
267 * sReg<=sX[even] & (sReg+1)<= sX+1.
268 */
buzbeeed3e9302011-09-23 17:34:19 -0700269STATIC int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700270{
271 int res = -1; // Assume failure
272 if (cUnit->regLocation[sReg+1].fpLocation == kLocPhysReg) {
273 // Upper reg is already allocated. Can we fit?
274 int highReg = cUnit->regLocation[sReg+1].fpLowReg;
275 if ((highReg & 1) == 0) {
276 // High reg is even - fail.
277 return res;
278 }
279 // Is the low reg of the pair free?
280 RegisterInfo* p = getRegInfo(cUnit, highReg-1);
281 if (p->inUse || p->isTemp) {
282 // Already allocated or not preserved - fail.
283 return res;
284 }
285 // OK - good to go.
286 res = p->reg;
287 p->inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700288 DCHECK_EQ((res & 1), 0);
buzbee67bf8852011-08-17 17:51:35 -0700289 cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
buzbee042946d2011-09-23 15:49:27 -0700290 cUnit->fpVmapTable.push_back(sReg);
buzbee67bf8852011-08-17 17:51:35 -0700291 cUnit->numSpills++;
292 cUnit->numFPSpills ++;
293 } else {
294 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
295 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
296 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
297 ((FPRegs[i].reg & 0x1) == 0x0) &&
298 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
299 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
300 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
301 res = FPRegs[i].reg;
302 FPRegs[i].inUse = true;
303 cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
buzbee042946d2011-09-23 15:49:27 -0700304 cUnit->fpVmapTable.push_back(sReg);
buzbee67bf8852011-08-17 17:51:35 -0700305 FPRegs[i+1].inUse = true;
306 cUnit->fpSpillMask |= (1 << ((res+1) & FP_REG_MASK));
buzbee042946d2011-09-23 15:49:27 -0700307 cUnit->fpVmapTable.push_back(sReg);
buzbee67bf8852011-08-17 17:51:35 -0700308 cUnit->numSpills += 2;
309 cUnit->numFPSpills += 2;
310 break;
311 }
312 }
313 }
314 if (res != -1) {
315 cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
316 cUnit->regLocation[sReg].fpLowReg = res;
317 cUnit->regLocation[sReg].home = true;
318 cUnit->regLocation[sReg+1].fpLocation = kLocPhysReg;
319 cUnit->regLocation[sReg+1].fpLowReg = res + 1;
320 cUnit->regLocation[sReg+1].home = true;
321 }
322 return res;
323}
324
325
326/*
327 * Reserve a callee-save fp register. If this register can be used
328 * as the first of a double, attempt to allocate an even pair of fp
329 * single regs (but if can't still attempt to allocate a single, preferring
330 * first to allocate an odd register.
331 */
332extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
333 bool doubleStart)
334{
335 int res = -1;
336 if (doubleStart) {
337 res = allocPreservedDouble(cUnit, sReg);
338 } else {
339 }
340 if (res == -1) {
341 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
342 }
343 if (res == -1)
344 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
345 return res;
346}
347
buzbeeed3e9302011-09-23 17:34:19 -0700348STATIC int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
buzbee67bf8852011-08-17 17:51:35 -0700349 int* nextTemp, bool required)
350{
351 int i;
352 int next = *nextTemp;
353 for (i=0; i< numRegs; i++) {
354 if (next >= numRegs)
355 next = 0;
356 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
357 oatClobber(cUnit, p[next].reg);
358 p[next].inUse = true;
359 p[next].pair = false;
360 *nextTemp = next + 1;
361 return p[next].reg;
362 }
363 next++;
364 }
365 next = *nextTemp;
366 for (i=0; i< numRegs; i++) {
367 if (next >= numRegs)
368 next = 0;
369 if (p[next].isTemp && !p[next].inUse) {
370 oatClobber(cUnit, p[next].reg);
371 p[next].inUse = true;
372 p[next].pair = false;
373 *nextTemp = next + 1;
374 return p[next].reg;
375 }
376 next++;
377 }
378 if (required) {
379 dumpRegPool(cUnit->regPool->coreRegs,
380 cUnit->regPool->numCoreRegs);
381 LOG(FATAL) << "No free temp registers";
382 }
383 return -1; // No register available
384}
385
386//REDO: too many assumptions.
387extern int oatAllocTempDouble(CompilationUnit* cUnit)
388{
389 RegisterInfo* p = cUnit->regPool->FPRegs;
390 int numRegs = cUnit->regPool->numFPRegs;
391 int next = cUnit->regPool->nextFPReg;
392 int i;
393
394 for (i=0; i < numRegs; i+=2) {
395 /* Cleanup - not all targets need aligned regs */
396 if (next & 1)
397 next++;
398 if (next >= numRegs)
399 next = 0;
400 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
401 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
402 oatClobber(cUnit, p[next].reg);
403 oatClobber(cUnit, p[next+1].reg);
404 p[next].inUse = true;
405 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700406 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
407 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbee67bf8852011-08-17 17:51:35 -0700408 cUnit->regPool->nextFPReg += 2;
409 return p[next].reg;
410 }
411 next += 2;
412 }
413 next = cUnit->regPool->nextFPReg;
414 for (i=0; i < numRegs; i+=2) {
415 if (next >= numRegs)
416 next = 0;
417 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
418 !p[next+1].inUse) {
419 oatClobber(cUnit, p[next].reg);
420 oatClobber(cUnit, p[next+1].reg);
421 p[next].inUse = true;
422 p[next+1].inUse = true;
buzbeeed3e9302011-09-23 17:34:19 -0700423 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
424 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbee67bf8852011-08-17 17:51:35 -0700425 cUnit->regPool->nextFPReg += 2;
426 return p[next].reg;
427 }
428 next += 2;
429 }
430 LOG(FATAL) << "No free temp registers";
431 return -1;
432}
433
434/* Return a temp if one is available, -1 otherwise */
435extern int oatAllocFreeTemp(CompilationUnit* cUnit)
436{
437 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
438 cUnit->regPool->numCoreRegs,
439 &cUnit->regPool->nextCoreReg, true);
440}
441
442extern int oatAllocTemp(CompilationUnit* cUnit)
443{
444 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
445 cUnit->regPool->numCoreRegs,
446 &cUnit->regPool->nextCoreReg, true);
447}
448
449extern int oatAllocTempFloat(CompilationUnit* cUnit)
450{
451 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
452 cUnit->regPool->numFPRegs,
453 &cUnit->regPool->nextFPReg, true);
454}
455
buzbeeed3e9302011-09-23 17:34:19 -0700456STATIC RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700457{
458 int i;
459 if (sReg == -1)
460 return NULL;
461 for (i=0; i < numRegs; i++) {
462 if (p[i].live && (p[i].sReg == sReg)) {
463 if (p[i].isTemp)
464 p[i].inUse = true;
465 return &p[i];
466 }
467 }
468 return NULL;
469}
470
buzbeeed3e9302011-09-23 17:34:19 -0700471STATIC RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg,
buzbee67bf8852011-08-17 17:51:35 -0700472 int regClass)
473{
474 RegisterInfo* res = NULL;
475 switch(regClass) {
476 case kAnyReg:
477 res = allocLiveBody(cUnit->regPool->FPRegs,
478 cUnit->regPool->numFPRegs, sReg);
479 if (res)
480 break;
481 /* Intentional fallthrough */
482 case kCoreReg:
483 res = allocLiveBody(cUnit->regPool->coreRegs,
484 cUnit->regPool->numCoreRegs, sReg);
485 break;
486 case kFPReg:
487 res = allocLiveBody(cUnit->regPool->FPRegs,
488 cUnit->regPool->numFPRegs, sReg);
489 break;
490 default:
491 LOG(FATAL) << "Invalid register type";
492 }
493 return res;
494}
495
496extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
497{
498 RegisterInfo* p = cUnit->regPool->coreRegs;
499 int numRegs = cUnit->regPool->numCoreRegs;
500 int i;
501 for (i=0; i< numRegs; i++) {
502 if (p[i].reg == reg) {
503 if (p[i].isTemp) {
504 p[i].inUse = false;
505 }
506 p[i].pair = false;
507 return;
508 }
509 }
510 p = cUnit->regPool->FPRegs;
511 numRegs = cUnit->regPool->numFPRegs;
512 for (i=0; i< numRegs; i++) {
513 if (p[i].reg == reg) {
514 if (p[i].isTemp) {
515 p[i].inUse = false;
516 }
517 p[i].pair = false;
518 return;
519 }
520 }
521 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
522}
523
524extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
525{
526 RegisterInfo* p = cUnit->regPool->coreRegs;
527 int numRegs = cUnit->regPool->numCoreRegs;
528 int i;
529 for (i=0; i< numRegs; i++) {
530 if (p[i].reg == reg) {
531 return p[i].live ? &p[i] : NULL;
532 }
533 }
534 p = cUnit->regPool->FPRegs;
535 numRegs = cUnit->regPool->numFPRegs;
536 for (i=0; i< numRegs; i++) {
537 if (p[i].reg == reg) {
538 return p[i].live ? &p[i] : NULL;
539 }
540 }
541 return NULL;
542}
543
544extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
545{
546 RegisterInfo* p = getRegInfo(cUnit, reg);
547 return (p->isTemp) ? p : NULL;
548}
549
buzbeeb29e4d12011-09-26 15:05:48 -0700550extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
551{
552 RegisterInfo* p = getRegInfo(cUnit, reg);
553 return (p->isTemp) ? NULL : p;
554}
555
buzbee67bf8852011-08-17 17:51:35 -0700556extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
557{
558 RegisterInfo* p = getRegInfo(cUnit, reg);
559 return p->dirty;
560}
561
562/*
563 * Similar to oatAllocTemp(), but forces the allocation of a specific
564 * register. No check is made to see if the register was previously
565 * allocated. Use with caution.
566 */
567extern void oatLockTemp(CompilationUnit* cUnit, int reg)
568{
569 RegisterInfo* p = cUnit->regPool->coreRegs;
570 int numRegs = cUnit->regPool->numCoreRegs;
571 int i;
572 for (i=0; i< numRegs; i++) {
573 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700574 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700575 p[i].inUse = true;
576 p[i].live = false;
577 return;
578 }
579 }
580 p = cUnit->regPool->FPRegs;
581 numRegs = cUnit->regPool->numFPRegs;
582 for (i=0; i< numRegs; i++) {
583 if (p[i].reg == reg) {
buzbeeed3e9302011-09-23 17:34:19 -0700584 DCHECK(p[i].isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700585 p[i].inUse = true;
586 p[i].live = false;
587 return;
588 }
589 }
590 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
591}
592
593extern void oatResetDef(CompilationUnit* cUnit, int reg)
594{
595 RegisterInfo* p = getRegInfo(cUnit, reg);
596 p->defStart = NULL;
597 p->defEnd = NULL;
598}
599
buzbeeed3e9302011-09-23 17:34:19 -0700600STATIC void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
buzbee67bf8852011-08-17 17:51:35 -0700601 int sReg1, int sReg2)
602{
603 if (start && finish) {
604 LIR *p;
buzbeeed3e9302011-09-23 17:34:19 -0700605 DCHECK_EQ(sReg1, sReg2);
buzbee67bf8852011-08-17 17:51:35 -0700606 for (p = start; ;p = p->next) {
607 ((ArmLIR *)p)->flags.isNop = true;
608 if (p == finish)
609 break;
610 }
611 }
612}
613
614/*
615 * Mark the beginning and end LIR of a def sequence. Note that
616 * on entry start points to the LIR prior to the beginning of the
617 * sequence.
618 */
619extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
620 LIR *start, LIR *finish)
621{
buzbeeed3e9302011-09-23 17:34:19 -0700622 DCHECK(!rl.wide);
623 DCHECK(start && start->next);
624 DCHECK(finish);
buzbee67bf8852011-08-17 17:51:35 -0700625 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
626 p->defStart = start->next;
627 p->defEnd = finish;
628}
629
630/*
631 * Mark the beginning and end LIR of a def sequence. Note that
632 * on entry start points to the LIR prior to the beginning of the
633 * sequence.
634 */
635extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
636 LIR *start, LIR *finish)
637{
buzbeeed3e9302011-09-23 17:34:19 -0700638 DCHECK(rl.wide);
639 DCHECK(start && start->next);
640 DCHECK(finish);
buzbee67bf8852011-08-17 17:51:35 -0700641 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
642 oatResetDef(cUnit, rl.highReg); // Only track low of pair
643 p->defStart = start->next;
644 p->defEnd = finish;
645}
646
647extern RegLocation oatWideToNarrow(CompilationUnit* cUnit,
648 RegLocation rl)
649{
buzbeeed3e9302011-09-23 17:34:19 -0700650 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700651 if (rl.location == kLocPhysReg) {
652 RegisterInfo* infoLo = getRegInfo(cUnit, rl.lowReg);
653 RegisterInfo* infoHi = getRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700654 if (infoLo->isTemp) {
655 infoLo->pair = false;
656 infoLo->defStart = NULL;
657 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700658 }
buzbee0c7f26d2011-09-07 12:28:51 -0700659 if (infoHi->isTemp) {
660 infoHi->pair = false;
661 infoHi->defStart = NULL;
662 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700663 }
buzbee67bf8852011-08-17 17:51:35 -0700664 }
665 rl.wide = false;
666 return rl;
667}
668
669extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
670{
buzbeeed3e9302011-09-23 17:34:19 -0700671 DCHECK(!rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700672 if (!(cUnit->disableOpt & (1 << kSuppressLoads))) {
673 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
buzbeeed3e9302011-09-23 17:34:19 -0700674 DCHECK(!p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700675 nullifyRange(cUnit, p->defStart, p->defEnd,
676 p->sReg, rl.sRegLow);
677 }
678 oatResetDef(cUnit, rl.lowReg);
679}
680
681extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
682{
buzbeeed3e9302011-09-23 17:34:19 -0700683 DCHECK(rl.wide);
buzbee67bf8852011-08-17 17:51:35 -0700684 if (!(cUnit->disableOpt & (1 << kSuppressLoads))) {
685 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
buzbeeed3e9302011-09-23 17:34:19 -0700686 DCHECK(p->pair);
buzbee67bf8852011-08-17 17:51:35 -0700687 nullifyRange(cUnit, p->defStart, p->defEnd,
688 p->sReg, rl.sRegLow);
689 }
690 oatResetDef(cUnit, rl.lowReg);
691 oatResetDef(cUnit, rl.highReg);
692}
693
694extern void oatResetDefTracking(CompilationUnit* cUnit)
695{
696 int i;
697 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
698 oatResetDef(cUnit, cUnit->regPool->coreRegs[i].reg);
699 }
700 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
701 oatResetDef(cUnit, cUnit->regPool->FPRegs[i].reg);
702 }
703}
704
705extern void oatClobberAllRegs(CompilationUnit* cUnit)
706{
707 int i;
708 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
709 oatClobber(cUnit, cUnit->regPool->coreRegs[i].reg);
710 }
711 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
712 oatClobber(cUnit, cUnit->regPool->FPRegs[i].reg);
713 }
714}
715
716/* To be used when explicitly managing register use */
buzbee2e748f32011-08-29 21:02:19 -0700717extern void oatLockCallTemps(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700718{
buzbee2e748f32011-08-29 21:02:19 -0700719 //TODO: Arm specific - move to target dependent code
720 oatLockTemp(cUnit, r0);
721 oatLockTemp(cUnit, r1);
722 oatLockTemp(cUnit, r2);
723 oatLockTemp(cUnit, r3);
buzbee67bf8852011-08-17 17:51:35 -0700724}
725
buzbee0d966cf2011-09-08 17:34:58 -0700726/* To be used when explicitly managing register use */
727extern void oatFreeCallTemps(CompilationUnit* cUnit)
728{
729 //TODO: Arm specific - move to target dependent code
730 oatFreeTemp(cUnit, r0);
731 oatFreeTemp(cUnit, r1);
732 oatFreeTemp(cUnit, r2);
733 oatFreeTemp(cUnit, r3);
734}
735
buzbee67bf8852011-08-17 17:51:35 -0700736// Make sure nothing is live and dirty
buzbeeed3e9302011-09-23 17:34:19 -0700737STATIC void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
buzbee67bf8852011-08-17 17:51:35 -0700738 int numRegs)
739{
740 int i;
741 for (i=0; i < numRegs; i++) {
742 if (info[i].live && info[i].dirty) {
743 if (info[i].pair) {
744 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
745 } else {
746 oatFlushReg(cUnit, info[i].reg);
747 }
748 }
749 }
750}
751
752extern void oatFlushAllRegs(CompilationUnit* cUnit)
753{
754 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
755 cUnit->regPool->numCoreRegs);
756 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
757 cUnit->regPool->numFPRegs);
758 oatClobberAllRegs(cUnit);
759}
760
761
762//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbeeed3e9302011-09-23 17:34:19 -0700763STATIC bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700764{
765 if (regClass == kAnyReg) {
766 return true;
767 } else if (regClass == kCoreReg) {
768 return !FPREG(reg);
769 } else {
770 return FPREG(reg);
771 }
772}
773
774extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
775{
776 RegisterInfo* info = getRegInfo(cUnit, reg);
777 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
778 return; /* already live */
779 } else if (sReg != INVALID_SREG) {
780 oatClobberSReg(cUnit, sReg);
781 if (info->isTemp) {
782 info->live = true;
783 }
784 } else {
785 /* Can't be live if no associated sReg */
buzbeeed3e9302011-09-23 17:34:19 -0700786 DCHECK(info->isTemp);
buzbee67bf8852011-08-17 17:51:35 -0700787 info->live = false;
788 }
789 info->sReg = sReg;
790}
791
792extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
793{
794 RegisterInfo* info = getRegInfo(cUnit, reg);
795 info->isTemp = true;
796}
797
buzbee9e0f9b02011-08-24 15:32:46 -0700798extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
799{
800 RegisterInfo* info = getRegInfo(cUnit, reg);
801 info->isTemp = false;
802}
803
buzbee67bf8852011-08-17 17:51:35 -0700804extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
805{
806 RegisterInfo* infoLo = getRegInfo(cUnit, lowReg);
807 RegisterInfo* infoHi = getRegInfo(cUnit, highReg);
808 infoLo->pair = infoHi->pair = true;
809 infoLo->partner = highReg;
810 infoHi->partner = lowReg;
811}
812
813extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
814{
815 RegisterInfo* info = getRegInfo(cUnit, loc.lowReg);
816 info->dirty = false;
817 if (loc.wide) {
818 info = getRegInfo(cUnit, loc.highReg);
819 info->dirty = false;
820 }
821}
822
823extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
824{
825 if (loc.home) {
826 // If already home, can't be dirty
827 return;
828 }
829 RegisterInfo* info = getRegInfo(cUnit, loc.lowReg);
830 info->dirty = true;
831 if (loc.wide) {
832 info = getRegInfo(cUnit, loc.highReg);
833 info->dirty = true;
834 }
835}
836
837extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
838{
839 RegisterInfo* info = getRegInfo(cUnit, reg);
840 info->inUse = true;
841}
842
buzbeeed3e9302011-09-23 17:34:19 -0700843STATIC void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700844{
845 RegisterInfo* newInfo = getRegInfo(cUnit, newReg);
846 RegisterInfo* oldInfo = getRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700847 // Target temp status must not change
848 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700849 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700850 // Restore target's temp status
851 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700852 newInfo->reg = newReg;
853}
854
855/*
856 * Return an updated location record with current in-register status.
857 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700858 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700859 * clobber both low and high.
860 * TUNING: clobbering both is a bit heavy-handed, but the alternative
861 * is a bit complex when dealing with FP regs. Examine code to see
862 * if it's worthwhile trying to be more clever here.
863 */
864
865extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
866{
buzbeeed3e9302011-09-23 17:34:19 -0700867 DCHECK(!loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700868 if (loc.location == kLocDalvikFrame) {
869 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
870 if (infoLo) {
871 if (infoLo->pair) {
872 oatClobber(cUnit, infoLo->reg);
873 oatClobber(cUnit, infoLo->partner);
874 } else {
875 loc.lowReg = infoLo->reg;
876 loc.location = kLocPhysReg;
877 }
878 }
879 }
880
881 return loc;
882}
883
884/* see comments for updateLoc */
885extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit,
886 RegLocation loc)
887{
buzbeeed3e9302011-09-23 17:34:19 -0700888 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700889 if (loc.location == kLocDalvikFrame) {
890 // Are the dalvik regs already live in physical registers?
891 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
892 RegisterInfo* infoHi = allocLive(cUnit,
893 oatSRegHi(loc.sRegLow), kAnyReg);
894 bool match = true;
895 match = match && (infoLo != NULL);
896 match = match && (infoHi != NULL);
897 // Are they both core or both FP?
898 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
899 // If a pair of floating point singles, are they properly aligned?
900 if (match && FPREG(infoLo->reg)) {
901 match &= ((infoLo->reg & 0x1) == 0);
902 match &= ((infoHi->reg - infoLo->reg) == 1);
903 }
904 // If previously used as a pair, it is the same pair?
905 if (match && (infoLo->pair || infoHi->pair)) {
906 match = (infoLo->pair == infoHi->pair);
907 match &= ((infoLo->reg == infoHi->partner) &&
908 (infoHi->reg == infoLo->partner));
909 }
910 if (match) {
911 // Can reuse - update the register usage info
912 loc.lowReg = infoLo->reg;
913 loc.highReg = infoHi->reg;
914 loc.location = kLocPhysReg;
915 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -0700916 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700917 return loc;
918 }
919 // Can't easily reuse - clobber any overlaps
920 if (infoLo) {
921 oatClobber(cUnit, infoLo->reg);
922 if (infoLo->pair)
923 oatClobber(cUnit, infoLo->partner);
924 }
925 if (infoHi) {
926 oatClobber(cUnit, infoHi->reg);
927 if (infoHi->pair)
928 oatClobber(cUnit, infoHi->partner);
929 }
930 }
931 return loc;
932}
933
buzbeeed3e9302011-09-23 17:34:19 -0700934
935/* For use in cases we don't know (or care) width */
936extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit,
937 RegLocation loc)
938{
939 if (loc.wide)
940 return oatUpdateLocWide(cUnit, loc);
941 else
942 return oatUpdateLoc(cUnit, loc);
943}
944
945STATIC RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
buzbee67bf8852011-08-17 17:51:35 -0700946 int regClass, bool update)
947{
buzbeeed3e9302011-09-23 17:34:19 -0700948 DCHECK(loc.wide);
buzbee67bf8852011-08-17 17:51:35 -0700949 int newRegs;
950 int lowReg;
951 int highReg;
952
953 loc = oatUpdateLocWide(cUnit, loc);
954
955 /* If already in registers, we can assume proper form. Right reg class? */
956 if (loc.location == kLocPhysReg) {
buzbeeed3e9302011-09-23 17:34:19 -0700957 DCHECK_EQ(FPREG(loc.lowReg), FPREG(loc.highReg));
958 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700959 if (!regClassMatches(regClass, loc.lowReg)) {
960 /* Wrong register class. Reallocate and copy */
961 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
962 lowReg = newRegs & 0xff;
963 highReg = (newRegs >> 8) & 0xff;
964 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
965 loc.highReg);
966 copyRegInfo(cUnit, lowReg, loc.lowReg);
967 copyRegInfo(cUnit, highReg, loc.highReg);
968 oatClobber(cUnit, loc.lowReg);
969 oatClobber(cUnit, loc.highReg);
970 loc.lowReg = lowReg;
971 loc.highReg = highReg;
972 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
buzbeeed3e9302011-09-23 17:34:19 -0700973 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700974 }
975 return loc;
976 }
977
buzbeeed3e9302011-09-23 17:34:19 -0700978 DCHECK_NE(loc.sRegLow, INVALID_SREG);
979 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700980
981 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
982 loc.lowReg = newRegs & 0xff;
983 loc.highReg = (newRegs >> 8) & 0xff;
984
985 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
986 if (update) {
987 loc.location = kLocPhysReg;
988 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
989 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
990 }
buzbeeed3e9302011-09-23 17:34:19 -0700991 DCHECK(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
buzbee67bf8852011-08-17 17:51:35 -0700992 return loc;
993}
994
995extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
996 int regClass, bool update)
997{
998 int newReg;
999
1000 if (loc.wide)
1001 return evalLocWide(cUnit, loc, regClass, update);
1002
1003 loc = oatUpdateLoc(cUnit, loc);
1004
1005 if (loc.location == kLocPhysReg) {
1006 if (!regClassMatches(regClass, loc.lowReg)) {
1007 /* Wrong register class. Realloc, copy and transfer ownership */
1008 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1009 oatRegCopy(cUnit, newReg, loc.lowReg);
1010 copyRegInfo(cUnit, newReg, loc.lowReg);
1011 oatClobber(cUnit, loc.lowReg);
1012 loc.lowReg = newReg;
1013 }
1014 return loc;
1015 }
1016
buzbeeed3e9302011-09-23 17:34:19 -07001017 DCHECK_NE(loc.sRegLow, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001018
1019 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1020 loc.lowReg = newReg;
1021
1022 if (update) {
1023 loc.location = kLocPhysReg;
1024 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1025 }
1026 return loc;
1027}
1028
1029extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1030{
buzbeee9a72f62011-09-04 17:59:07 -07001031 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
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}
1035extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1036{
buzbeee9a72f62011-09-04 17:59:07 -07001037 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeeed3e9302011-09-23 17:34:19 -07001038 DCHECK(!res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001039 return res;
1040}
1041extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1042{
1043 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1044 return res;
buzbee67bf8852011-08-17 17:51:35 -07001045}
1046extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1047 int low, int high)
1048{
buzbeee9a72f62011-09-04 17:59:07 -07001049 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001050 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001051 return res;
buzbee67bf8852011-08-17 17:51:35 -07001052}
1053
1054extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1055 int low, int high)
1056{
buzbeee9a72f62011-09-04 17:59:07 -07001057 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeeed3e9302011-09-23 17:34:19 -07001058 DCHECK(res.wide);
buzbeee9a72f62011-09-04 17:59:07 -07001059 return res;
buzbee67bf8852011-08-17 17:51:35 -07001060}