blob: 8b9ae1333eee1fd9e1be7bc9a1075f8cb0cc14b4 [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
74static void dumpRegPool(RegisterInfo* p, int numRegs)
75{
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. */
91static RegisterInfo* getRegInfo(CompilationUnit* cUnit, int reg)
92{
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);
116 assert(info1 && info2 && info1->pair && info2->pair &&
117 (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 */
150static bool clobberRegBody(CompilationUnit* cUnit, RegisterInfo* p,
151 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
190static void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
191{
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 */
239static int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
240{
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 */
269static int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
270{
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;
288 assert((res & 1) == 0);
289 cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
290 cUnit->numSpills++;
291 cUnit->numFPSpills ++;
292 } else {
293 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
294 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
295 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
296 ((FPRegs[i].reg & 0x1) == 0x0) &&
297 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
298 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
299 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
300 res = FPRegs[i].reg;
301 FPRegs[i].inUse = true;
302 cUnit->fpSpillMask |= (1 << (res & FP_REG_MASK));
303 FPRegs[i+1].inUse = true;
304 cUnit->fpSpillMask |= (1 << ((res+1) & FP_REG_MASK));
305 cUnit->numSpills += 2;
306 cUnit->numFPSpills += 2;
307 break;
308 }
309 }
310 }
311 if (res != -1) {
312 cUnit->regLocation[sReg].fpLocation = kLocPhysReg;
313 cUnit->regLocation[sReg].fpLowReg = res;
314 cUnit->regLocation[sReg].home = true;
315 cUnit->regLocation[sReg+1].fpLocation = kLocPhysReg;
316 cUnit->regLocation[sReg+1].fpLowReg = res + 1;
317 cUnit->regLocation[sReg+1].home = true;
318 }
319 return res;
320}
321
322
323/*
324 * Reserve a callee-save fp register. If this register can be used
325 * as the first of a double, attempt to allocate an even pair of fp
326 * single regs (but if can't still attempt to allocate a single, preferring
327 * first to allocate an odd register.
328 */
329extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
330 bool doubleStart)
331{
332 int res = -1;
333 if (doubleStart) {
334 res = allocPreservedDouble(cUnit, sReg);
335 } else {
336 }
337 if (res == -1) {
338 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
339 }
340 if (res == -1)
341 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
342 return res;
343}
344
345static int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
346 int* nextTemp, bool required)
347{
348 int i;
349 int next = *nextTemp;
350 for (i=0; i< numRegs; i++) {
351 if (next >= numRegs)
352 next = 0;
353 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
354 oatClobber(cUnit, p[next].reg);
355 p[next].inUse = true;
356 p[next].pair = false;
357 *nextTemp = next + 1;
358 return p[next].reg;
359 }
360 next++;
361 }
362 next = *nextTemp;
363 for (i=0; i< numRegs; i++) {
364 if (next >= numRegs)
365 next = 0;
366 if (p[next].isTemp && !p[next].inUse) {
367 oatClobber(cUnit, p[next].reg);
368 p[next].inUse = true;
369 p[next].pair = false;
370 *nextTemp = next + 1;
371 return p[next].reg;
372 }
373 next++;
374 }
375 if (required) {
376 dumpRegPool(cUnit->regPool->coreRegs,
377 cUnit->regPool->numCoreRegs);
378 LOG(FATAL) << "No free temp registers";
379 }
380 return -1; // No register available
381}
382
383//REDO: too many assumptions.
384extern int oatAllocTempDouble(CompilationUnit* cUnit)
385{
386 RegisterInfo* p = cUnit->regPool->FPRegs;
387 int numRegs = cUnit->regPool->numFPRegs;
388 int next = cUnit->regPool->nextFPReg;
389 int i;
390
391 for (i=0; i < numRegs; i+=2) {
392 /* Cleanup - not all targets need aligned regs */
393 if (next & 1)
394 next++;
395 if (next >= numRegs)
396 next = 0;
397 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
398 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
399 oatClobber(cUnit, p[next].reg);
400 oatClobber(cUnit, p[next+1].reg);
401 p[next].inUse = true;
402 p[next+1].inUse = true;
403 assert((p[next].reg+1) == p[next+1].reg);
404 assert((p[next].reg & 0x1) == 0);
405 cUnit->regPool->nextFPReg += 2;
406 return p[next].reg;
407 }
408 next += 2;
409 }
410 next = cUnit->regPool->nextFPReg;
411 for (i=0; i < numRegs; i+=2) {
412 if (next >= numRegs)
413 next = 0;
414 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
415 !p[next+1].inUse) {
416 oatClobber(cUnit, p[next].reg);
417 oatClobber(cUnit, p[next+1].reg);
418 p[next].inUse = true;
419 p[next+1].inUse = true;
420 assert((p[next].reg+1) == p[next+1].reg);
421 assert((p[next].reg & 0x1) == 0);
422 cUnit->regPool->nextFPReg += 2;
423 return p[next].reg;
424 }
425 next += 2;
426 }
427 LOG(FATAL) << "No free temp registers";
428 return -1;
429}
430
431/* Return a temp if one is available, -1 otherwise */
432extern int oatAllocFreeTemp(CompilationUnit* cUnit)
433{
434 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
435 cUnit->regPool->numCoreRegs,
436 &cUnit->regPool->nextCoreReg, true);
437}
438
439extern int oatAllocTemp(CompilationUnit* cUnit)
440{
441 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
442 cUnit->regPool->numCoreRegs,
443 &cUnit->regPool->nextCoreReg, true);
444}
445
446extern int oatAllocTempFloat(CompilationUnit* cUnit)
447{
448 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
449 cUnit->regPool->numFPRegs,
450 &cUnit->regPool->nextFPReg, true);
451}
452
453static RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
454{
455 int i;
456 if (sReg == -1)
457 return NULL;
458 for (i=0; i < numRegs; i++) {
459 if (p[i].live && (p[i].sReg == sReg)) {
460 if (p[i].isTemp)
461 p[i].inUse = true;
462 return &p[i];
463 }
464 }
465 return NULL;
466}
467
468static RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg,
469 int regClass)
470{
471 RegisterInfo* res = NULL;
472 switch(regClass) {
473 case kAnyReg:
474 res = allocLiveBody(cUnit->regPool->FPRegs,
475 cUnit->regPool->numFPRegs, sReg);
476 if (res)
477 break;
478 /* Intentional fallthrough */
479 case kCoreReg:
480 res = allocLiveBody(cUnit->regPool->coreRegs,
481 cUnit->regPool->numCoreRegs, sReg);
482 break;
483 case kFPReg:
484 res = allocLiveBody(cUnit->regPool->FPRegs,
485 cUnit->regPool->numFPRegs, sReg);
486 break;
487 default:
488 LOG(FATAL) << "Invalid register type";
489 }
490 return res;
491}
492
493extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
494{
495 RegisterInfo* p = cUnit->regPool->coreRegs;
496 int numRegs = cUnit->regPool->numCoreRegs;
497 int i;
498 for (i=0; i< numRegs; i++) {
499 if (p[i].reg == reg) {
500 if (p[i].isTemp) {
501 p[i].inUse = false;
502 }
503 p[i].pair = false;
504 return;
505 }
506 }
507 p = cUnit->regPool->FPRegs;
508 numRegs = cUnit->regPool->numFPRegs;
509 for (i=0; i< numRegs; i++) {
510 if (p[i].reg == reg) {
511 if (p[i].isTemp) {
512 p[i].inUse = false;
513 }
514 p[i].pair = false;
515 return;
516 }
517 }
518 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
519}
520
521extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
522{
523 RegisterInfo* p = cUnit->regPool->coreRegs;
524 int numRegs = cUnit->regPool->numCoreRegs;
525 int i;
526 for (i=0; i< numRegs; i++) {
527 if (p[i].reg == reg) {
528 return p[i].live ? &p[i] : NULL;
529 }
530 }
531 p = cUnit->regPool->FPRegs;
532 numRegs = cUnit->regPool->numFPRegs;
533 for (i=0; i< numRegs; i++) {
534 if (p[i].reg == reg) {
535 return p[i].live ? &p[i] : NULL;
536 }
537 }
538 return NULL;
539}
540
541extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
542{
543 RegisterInfo* p = getRegInfo(cUnit, reg);
544 return (p->isTemp) ? p : NULL;
545}
546
547extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
548{
549 RegisterInfo* p = getRegInfo(cUnit, reg);
550 return p->dirty;
551}
552
553/*
554 * Similar to oatAllocTemp(), but forces the allocation of a specific
555 * register. No check is made to see if the register was previously
556 * allocated. Use with caution.
557 */
558extern void oatLockTemp(CompilationUnit* cUnit, int reg)
559{
560 RegisterInfo* p = cUnit->regPool->coreRegs;
561 int numRegs = cUnit->regPool->numCoreRegs;
562 int i;
563 for (i=0; i< numRegs; i++) {
564 if (p[i].reg == reg) {
565 assert(p[i].isTemp);
566 p[i].inUse = true;
567 p[i].live = false;
568 return;
569 }
570 }
571 p = cUnit->regPool->FPRegs;
572 numRegs = cUnit->regPool->numFPRegs;
573 for (i=0; i< numRegs; i++) {
574 if (p[i].reg == reg) {
575 assert(p[i].isTemp);
576 p[i].inUse = true;
577 p[i].live = false;
578 return;
579 }
580 }
581 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
582}
583
584extern void oatResetDef(CompilationUnit* cUnit, int reg)
585{
586 RegisterInfo* p = getRegInfo(cUnit, reg);
587 p->defStart = NULL;
588 p->defEnd = NULL;
589}
590
591static void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
592 int sReg1, int sReg2)
593{
594 if (start && finish) {
595 LIR *p;
596 assert(sReg1 == sReg2);
597 for (p = start; ;p = p->next) {
598 ((ArmLIR *)p)->flags.isNop = true;
599 if (p == finish)
600 break;
601 }
602 }
603}
604
605/*
606 * Mark the beginning and end LIR of a def sequence. Note that
607 * on entry start points to the LIR prior to the beginning of the
608 * sequence.
609 */
610extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
611 LIR *start, LIR *finish)
612{
613 assert(!rl.wide);
614 assert(start && start->next);
615 assert(finish);
616 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
617 p->defStart = start->next;
618 p->defEnd = finish;
619}
620
621/*
622 * Mark the beginning and end LIR of a def sequence. Note that
623 * on entry start points to the LIR prior to the beginning of the
624 * sequence.
625 */
626extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
627 LIR *start, LIR *finish)
628{
629 assert(rl.wide);
630 assert(start && start->next);
631 assert(finish);
632 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
633 oatResetDef(cUnit, rl.highReg); // Only track low of pair
634 p->defStart = start->next;
635 p->defEnd = finish;
636}
637
638extern RegLocation oatWideToNarrow(CompilationUnit* cUnit,
639 RegLocation rl)
640{
641 assert(rl.wide);
642 if (rl.location == kLocPhysReg) {
643 RegisterInfo* infoLo = getRegInfo(cUnit, rl.lowReg);
644 RegisterInfo* infoHi = getRegInfo(cUnit, rl.highReg);
buzbee0c7f26d2011-09-07 12:28:51 -0700645 if (infoLo->isTemp) {
646 infoLo->pair = false;
647 infoLo->defStart = NULL;
648 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700649 }
buzbee0c7f26d2011-09-07 12:28:51 -0700650 if (infoHi->isTemp) {
651 infoHi->pair = false;
652 infoHi->defStart = NULL;
653 infoHi->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700654 }
buzbee67bf8852011-08-17 17:51:35 -0700655 }
656 rl.wide = false;
657 return rl;
658}
659
660extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
661{
662 assert(!rl.wide);
663 if (!(cUnit->disableOpt & (1 << kSuppressLoads))) {
664 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
665 assert(!p->pair);
666 nullifyRange(cUnit, p->defStart, p->defEnd,
667 p->sReg, rl.sRegLow);
668 }
669 oatResetDef(cUnit, rl.lowReg);
670}
671
672extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
673{
674 assert(rl.wide);
675 if (!(cUnit->disableOpt & (1 << kSuppressLoads))) {
676 RegisterInfo* p = getRegInfo(cUnit, rl.lowReg);
677 assert(p->pair);
678 nullifyRange(cUnit, p->defStart, p->defEnd,
679 p->sReg, rl.sRegLow);
680 }
681 oatResetDef(cUnit, rl.lowReg);
682 oatResetDef(cUnit, rl.highReg);
683}
684
685extern void oatResetDefTracking(CompilationUnit* cUnit)
686{
687 int i;
688 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
689 oatResetDef(cUnit, cUnit->regPool->coreRegs[i].reg);
690 }
691 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
692 oatResetDef(cUnit, cUnit->regPool->FPRegs[i].reg);
693 }
694}
695
696extern void oatClobberAllRegs(CompilationUnit* cUnit)
697{
698 int i;
699 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
700 oatClobber(cUnit, cUnit->regPool->coreRegs[i].reg);
701 }
702 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
703 oatClobber(cUnit, cUnit->regPool->FPRegs[i].reg);
704 }
705}
706
707/* To be used when explicitly managing register use */
buzbee2e748f32011-08-29 21:02:19 -0700708extern void oatLockCallTemps(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700709{
buzbee2e748f32011-08-29 21:02:19 -0700710 //TODO: Arm specific - move to target dependent code
711 oatLockTemp(cUnit, r0);
712 oatLockTemp(cUnit, r1);
713 oatLockTemp(cUnit, r2);
714 oatLockTemp(cUnit, r3);
buzbee67bf8852011-08-17 17:51:35 -0700715}
716
buzbee0d966cf2011-09-08 17:34:58 -0700717/* To be used when explicitly managing register use */
718extern void oatFreeCallTemps(CompilationUnit* cUnit)
719{
720 //TODO: Arm specific - move to target dependent code
721 oatFreeTemp(cUnit, r0);
722 oatFreeTemp(cUnit, r1);
723 oatFreeTemp(cUnit, r2);
724 oatFreeTemp(cUnit, r3);
725}
726
buzbee67bf8852011-08-17 17:51:35 -0700727// Make sure nothing is live and dirty
728static void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
729 int numRegs)
730{
731 int i;
732 for (i=0; i < numRegs; i++) {
733 if (info[i].live && info[i].dirty) {
734 if (info[i].pair) {
735 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
736 } else {
737 oatFlushReg(cUnit, info[i].reg);
738 }
739 }
740 }
741}
742
743extern void oatFlushAllRegs(CompilationUnit* cUnit)
744{
745 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
746 cUnit->regPool->numCoreRegs);
747 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
748 cUnit->regPool->numFPRegs);
749 oatClobberAllRegs(cUnit);
750}
751
752
753//TUNING: rewrite all of this reg stuff. Probably use an attribute table
754static bool regClassMatches(int regClass, int reg)
755{
756 if (regClass == kAnyReg) {
757 return true;
758 } else if (regClass == kCoreReg) {
759 return !FPREG(reg);
760 } else {
761 return FPREG(reg);
762 }
763}
764
765extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
766{
767 RegisterInfo* info = getRegInfo(cUnit, reg);
768 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
769 return; /* already live */
770 } else if (sReg != INVALID_SREG) {
771 oatClobberSReg(cUnit, sReg);
772 if (info->isTemp) {
773 info->live = true;
774 }
775 } else {
776 /* Can't be live if no associated sReg */
777 assert(info->isTemp);
778 info->live = false;
779 }
780 info->sReg = sReg;
781}
782
783extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
784{
785 RegisterInfo* info = getRegInfo(cUnit, reg);
786 info->isTemp = true;
787}
788
buzbee9e0f9b02011-08-24 15:32:46 -0700789extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
790{
791 RegisterInfo* info = getRegInfo(cUnit, reg);
792 info->isTemp = false;
793}
794
buzbee67bf8852011-08-17 17:51:35 -0700795extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
796{
797 RegisterInfo* infoLo = getRegInfo(cUnit, lowReg);
798 RegisterInfo* infoHi = getRegInfo(cUnit, highReg);
799 infoLo->pair = infoHi->pair = true;
800 infoLo->partner = highReg;
801 infoHi->partner = lowReg;
802}
803
804extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
805{
806 RegisterInfo* info = getRegInfo(cUnit, loc.lowReg);
807 info->dirty = false;
808 if (loc.wide) {
809 info = getRegInfo(cUnit, loc.highReg);
810 info->dirty = false;
811 }
812}
813
814extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
815{
816 if (loc.home) {
817 // If already home, can't be dirty
818 return;
819 }
820 RegisterInfo* info = getRegInfo(cUnit, loc.lowReg);
821 info->dirty = true;
822 if (loc.wide) {
823 info = getRegInfo(cUnit, loc.highReg);
824 info->dirty = true;
825 }
826}
827
828extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
829{
830 RegisterInfo* info = getRegInfo(cUnit, reg);
831 info->inUse = true;
832}
833
834static void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
835{
836 RegisterInfo* newInfo = getRegInfo(cUnit, newReg);
837 RegisterInfo* oldInfo = getRegInfo(cUnit, oldReg);
buzbeeec5adf32011-09-11 15:25:43 -0700838 // Target temp status must not change
839 bool isTemp = newInfo->isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700840 *newInfo = *oldInfo;
buzbeeec5adf32011-09-11 15:25:43 -0700841 // Restore target's temp status
842 newInfo->isTemp = isTemp;
buzbee67bf8852011-08-17 17:51:35 -0700843 newInfo->reg = newReg;
844}
845
846/*
847 * Return an updated location record with current in-register status.
848 * If the value lives in live temps, reflect that fact. No code
849 * is generated. The the live value is part of an older pair,
850 * clobber both low and high.
851 * TUNING: clobbering both is a bit heavy-handed, but the alternative
852 * is a bit complex when dealing with FP regs. Examine code to see
853 * if it's worthwhile trying to be more clever here.
854 */
855
856extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
857{
858 assert(!loc.wide);
859 if (loc.location == kLocDalvikFrame) {
860 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
861 if (infoLo) {
862 if (infoLo->pair) {
863 oatClobber(cUnit, infoLo->reg);
864 oatClobber(cUnit, infoLo->partner);
865 } else {
866 loc.lowReg = infoLo->reg;
867 loc.location = kLocPhysReg;
868 }
869 }
870 }
871
872 return loc;
873}
874
875/* see comments for updateLoc */
876extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit,
877 RegLocation loc)
878{
879 assert(loc.wide);
880 if (loc.location == kLocDalvikFrame) {
881 // Are the dalvik regs already live in physical registers?
882 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
883 RegisterInfo* infoHi = allocLive(cUnit,
884 oatSRegHi(loc.sRegLow), kAnyReg);
885 bool match = true;
886 match = match && (infoLo != NULL);
887 match = match && (infoHi != NULL);
888 // Are they both core or both FP?
889 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
890 // If a pair of floating point singles, are they properly aligned?
891 if (match && FPREG(infoLo->reg)) {
892 match &= ((infoLo->reg & 0x1) == 0);
893 match &= ((infoHi->reg - infoLo->reg) == 1);
894 }
895 // If previously used as a pair, it is the same pair?
896 if (match && (infoLo->pair || infoHi->pair)) {
897 match = (infoLo->pair == infoHi->pair);
898 match &= ((infoLo->reg == infoHi->partner) &&
899 (infoHi->reg == infoLo->partner));
900 }
901 if (match) {
902 // Can reuse - update the register usage info
903 loc.lowReg = infoLo->reg;
904 loc.highReg = infoHi->reg;
905 loc.location = kLocPhysReg;
906 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
907 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
908 return loc;
909 }
910 // Can't easily reuse - clobber any overlaps
911 if (infoLo) {
912 oatClobber(cUnit, infoLo->reg);
913 if (infoLo->pair)
914 oatClobber(cUnit, infoLo->partner);
915 }
916 if (infoHi) {
917 oatClobber(cUnit, infoHi->reg);
918 if (infoHi->pair)
919 oatClobber(cUnit, infoHi->partner);
920 }
921 }
922 return loc;
923}
924
925static RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
926 int regClass, bool update)
927{
928 assert(loc.wide);
929 int newRegs;
930 int lowReg;
931 int highReg;
932
933 loc = oatUpdateLocWide(cUnit, loc);
934
935 /* If already in registers, we can assume proper form. Right reg class? */
936 if (loc.location == kLocPhysReg) {
937 assert(FPREG(loc.lowReg) == FPREG(loc.highReg));
938 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
939 if (!regClassMatches(regClass, loc.lowReg)) {
940 /* Wrong register class. Reallocate and copy */
941 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
942 lowReg = newRegs & 0xff;
943 highReg = (newRegs >> 8) & 0xff;
944 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
945 loc.highReg);
946 copyRegInfo(cUnit, lowReg, loc.lowReg);
947 copyRegInfo(cUnit, highReg, loc.highReg);
948 oatClobber(cUnit, loc.lowReg);
949 oatClobber(cUnit, loc.highReg);
950 loc.lowReg = lowReg;
951 loc.highReg = highReg;
952 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
953 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
954 }
955 return loc;
956 }
957
958 assert(loc.sRegLow != INVALID_SREG);
959 assert(oatSRegHi(loc.sRegLow) != INVALID_SREG);
960
961 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
962 loc.lowReg = newRegs & 0xff;
963 loc.highReg = (newRegs >> 8) & 0xff;
964
965 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
966 if (update) {
967 loc.location = kLocPhysReg;
968 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
969 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
970 }
971 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
972 return loc;
973}
974
975extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
976 int regClass, bool update)
977{
978 int newReg;
979
980 if (loc.wide)
981 return evalLocWide(cUnit, loc, regClass, update);
982
983 loc = oatUpdateLoc(cUnit, loc);
984
985 if (loc.location == kLocPhysReg) {
986 if (!regClassMatches(regClass, loc.lowReg)) {
987 /* Wrong register class. Realloc, copy and transfer ownership */
988 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
989 oatRegCopy(cUnit, newReg, loc.lowReg);
990 copyRegInfo(cUnit, newReg, loc.lowReg);
991 oatClobber(cUnit, loc.lowReg);
992 loc.lowReg = newReg;
993 }
994 return loc;
995 }
996
997 assert(loc.sRegLow != INVALID_SREG);
998
999 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1000 loc.lowReg = newReg;
1001
1002 if (update) {
1003 loc.location = kLocPhysReg;
1004 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1005 }
1006 return loc;
1007}
1008
1009extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir, int num)
1010{
buzbeee9a72f62011-09-04 17:59:07 -07001011 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[num]];
buzbeee9a72f62011-09-04 17:59:07 -07001012 assert(!res.wide);
1013 return res;
buzbee67bf8852011-08-17 17:51:35 -07001014}
1015extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1016{
buzbeee9a72f62011-09-04 17:59:07 -07001017 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbeee9a72f62011-09-04 17:59:07 -07001018 assert(!res.wide);
1019 return res;
1020}
1021extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
1022{
1023 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1024 return res;
buzbee67bf8852011-08-17 17:51:35 -07001025}
1026extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir,
1027 int low, int high)
1028{
buzbeee9a72f62011-09-04 17:59:07 -07001029 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[low]];
buzbeee9a72f62011-09-04 17:59:07 -07001030 assert(res.wide);
1031 return res;
buzbee67bf8852011-08-17 17:51:35 -07001032}
1033
1034extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
1035 int low, int high)
1036{
buzbeee9a72f62011-09-04 17:59:07 -07001037 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[low]];
buzbeee9a72f62011-09-04 17:59:07 -07001038 assert(res.wide);
1039 return res;
buzbee67bf8852011-08-17 17:51:35 -07001040}