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