1 /*
2 * Copyright (C) 2009 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 "compiler/CompilerUtility.h"
26 #include "compiler/CompilerIR.h"
27 #include "compiler/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 */
dvmCompilerResetRegPool(CompilationUnit * cUnit)46 extern void dvmCompilerResetRegPool(CompilationUnit *cUnit)
47 {
48 int i;
49 for (i=0; i < cUnit->regPool->numCoreTemps; i++) {
50 cUnit->regPool->coreTemps[i].inUse = false;
51 }
52 for (i=0; i < cUnit->regPool->numFPTemps; i++) {
53 cUnit->regPool->FPTemps[i].inUse = false;
54 }
55 }
56
57 /* Set up temp & preserved register pools specialized by target */
dvmCompilerInitPool(RegisterInfo * regs,int * regNums,int num)58 extern void dvmCompilerInitPool(RegisterInfo *regs, int *regNums, int num)
59 {
60 int i;
61 for (i=0; i < num; i++) {
62 regs[i].reg = regNums[i];
63 regs[i].inUse = false;
64 regs[i].pair = false;
65 regs[i].live = false;
66 regs[i].dirty = false;
67 regs[i].sReg = INVALID_SREG;
68 }
69 }
70
dumpRegPool(RegisterInfo * p,int numRegs)71 static void dumpRegPool(RegisterInfo *p, int numRegs)
72 {
73 int i;
74 LOGE("================================================");
75 for (i=0; i < numRegs; i++ ){
76 LOGE("R[%d]: U:%d, P:%d, part:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
77 p[i].reg, p[i].inUse, p[i].pair, p[i].partner, p[i].live,
78 p[i].dirty, p[i].sReg,(int)p[i].defStart, (int)p[i].defEnd);
79 }
80 LOGE("================================================");
81 }
82
getRegInfo(CompilationUnit * cUnit,int reg)83 static RegisterInfo *getRegInfo(CompilationUnit *cUnit, int reg)
84 {
85 int numTemps = cUnit->regPool->numCoreTemps;
86 RegisterInfo *p = cUnit->regPool->coreTemps;
87 int i;
88 for (i=0; i< numTemps; i++) {
89 if (p[i].reg == reg) {
90 return &p[i];
91 }
92 }
93 p = cUnit->regPool->FPTemps;
94 numTemps = cUnit->regPool->numFPTemps;
95 for (i=0; i< numTemps; i++) {
96 if (p[i].reg == reg) {
97 return &p[i];
98 }
99 }
100 LOGE("Tried to get info on a non-existant temp: r%d",reg);
101 dvmCompilerAbort(cUnit);
102 return NULL;
103 }
104
dvmCompilerFlushRegWide(CompilationUnit * cUnit,int reg1,int reg2)105 void dvmCompilerFlushRegWide(CompilationUnit *cUnit, int reg1, int reg2)
106 {
107 RegisterInfo *info1 = getRegInfo(cUnit, reg1);
108 RegisterInfo *info2 = getRegInfo(cUnit, reg2);
109 assert(info1 && info2 && info1->pair && info2->pair &&
110 (info1->partner == info2->reg) &&
111 (info2->partner == info1->reg));
112 if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
113 info1->dirty = false;
114 info2->dirty = false;
115 if (dvmCompilerS2VReg(cUnit, info2->sReg) <
116 dvmCompilerS2VReg(cUnit, info1->sReg))
117 info1 = info2;
118 dvmCompilerFlushRegWideImpl(cUnit, rFP,
119 dvmCompilerS2VReg(cUnit, info1->sReg) << 2,
120 info1->reg, info1->partner);
121 }
122 }
123
dvmCompilerFlushReg(CompilationUnit * cUnit,int reg)124 void dvmCompilerFlushReg(CompilationUnit *cUnit, int reg)
125 {
126 RegisterInfo *info = getRegInfo(cUnit, reg);
127 if (info->live && info->dirty) {
128 info->dirty = false;
129 dvmCompilerFlushRegImpl(cUnit, rFP,
130 dvmCompilerS2VReg(cUnit, info->sReg) << 2,
131 reg, kWord);
132 }
133 }
134
135 /* return true if found reg to clobber */
clobberRegBody(CompilationUnit * cUnit,RegisterInfo * p,int numTemps,int reg)136 static bool clobberRegBody(CompilationUnit *cUnit, RegisterInfo *p,
137 int numTemps, int reg)
138 {
139 int i;
140 for (i=0; i< numTemps; i++) {
141 if (p[i].reg == reg) {
142 if (p[i].live && p[i].dirty) {
143 if (p[i].pair) {
144 dvmCompilerFlushRegWide(cUnit, p[i].reg, p[i].partner);
145 } else {
146 dvmCompilerFlushReg(cUnit, p[i].reg);
147 }
148 }
149 p[i].live = false;
150 p[i].sReg = INVALID_SREG;
151 p[i].defStart = NULL;
152 p[i].defEnd = NULL;
153 if (p[i].pair) {
154 p[i].pair = false;
155 /* partners should be in same pool */
156 clobberRegBody(cUnit, p, numTemps, p[i].partner);
157 }
158 return true;
159 }
160 }
161 return false;
162 }
163
164 /* Mark a temp register as dead. Does not affect allocation state. */
dvmCompilerClobber(CompilationUnit * cUnit,int reg)165 void dvmCompilerClobber(CompilationUnit *cUnit, int reg)
166 {
167 if (!clobberRegBody(cUnit, cUnit->regPool->coreTemps,
168 cUnit->regPool->numCoreTemps, reg)) {
169 clobberRegBody(cUnit, cUnit->regPool->FPTemps,
170 cUnit->regPool->numFPTemps, reg);
171 }
172 }
173
clobberSRegBody(RegisterInfo * p,int numTemps,int sReg)174 static void clobberSRegBody(RegisterInfo *p, int numTemps, int sReg)
175 {
176 int i;
177 for (i=0; i< numTemps; i++) {
178 if (p[i].sReg == sReg) {
179 p[i].live = false;
180 p[i].defStart = NULL;
181 p[i].defEnd = NULL;
182 }
183 }
184 }
185
186 /* Clobber any temp associated with an sReg. Could be in either class */
dvmCompilerClobberSReg(CompilationUnit * cUnit,int sReg)187 extern void dvmCompilerClobberSReg(CompilationUnit *cUnit, int sReg)
188 {
189 clobberSRegBody(cUnit->regPool->coreTemps, cUnit->regPool->numCoreTemps,
190 sReg);
191 clobberSRegBody(cUnit->regPool->FPTemps, cUnit->regPool->numFPTemps,
192 sReg);
193 }
194
allocTempBody(CompilationUnit * cUnit,RegisterInfo * p,int numTemps,int * nextTemp,bool required)195 static int allocTempBody(CompilationUnit *cUnit, RegisterInfo *p, int numTemps,
196 int *nextTemp, bool required)
197 {
198 int i;
199 int next = *nextTemp;
200 for (i=0; i< numTemps; i++) {
201 if (next >= numTemps)
202 next = 0;
203 if (!p[next].inUse && !p[next].live) {
204 dvmCompilerClobber(cUnit, p[next].reg);
205 p[next].inUse = true;
206 p[next].pair = false;
207 *nextTemp = next + 1;
208 return p[next].reg;
209 }
210 next++;
211 }
212 next = *nextTemp;
213 for (i=0; i< numTemps; i++) {
214 if (next >= numTemps)
215 next = 0;
216 if (!p[next].inUse) {
217 dvmCompilerClobber(cUnit, p[next].reg);
218 p[next].inUse = true;
219 p[next].pair = false;
220 *nextTemp = next + 1;
221 return p[next].reg;
222 }
223 next++;
224 }
225 if (required) {
226 LOGE("No free temp registers");
227 dvmCompilerAbort(cUnit);
228 }
229 return -1; // No register available
230 }
231
232 //REDO: too many assumptions.
dvmCompilerAllocTempDouble(CompilationUnit * cUnit)233 extern int dvmCompilerAllocTempDouble(CompilationUnit *cUnit)
234 {
235 RegisterInfo *p = cUnit->regPool->FPTemps;
236 int numTemps = cUnit->regPool->numFPTemps;
237 int next = cUnit->regPool->nextFPTemp;
238 int i;
239
240 for (i=0; i < numTemps; i+=2) {
241 /* Cleanup - not all targets need aligned regs */
242 if (next & 1)
243 next++;
244 if (next >= numTemps)
245 next = 0;
246 if ((!p[next].inUse && !p[next].live) &&
247 (!p[next+1].inUse && !p[next+1].live)) {
248 dvmCompilerClobber(cUnit, p[next].reg);
249 dvmCompilerClobber(cUnit, p[next+1].reg);
250 p[next].inUse = true;
251 p[next+1].inUse = true;
252 assert((p[next].reg+1) == p[next+1].reg);
253 assert((p[next].reg & 0x1) == 0);
254 cUnit->regPool->nextFPTemp += 2;
255 return p[next].reg;
256 }
257 next += 2;
258 }
259 next = cUnit->regPool->nextFPTemp;
260 for (i=0; i < numTemps; i+=2) {
261 if (next >= numTemps)
262 next = 0;
263 if (!p[next].inUse && !p[next+1].inUse) {
264 dvmCompilerClobber(cUnit, p[next].reg);
265 dvmCompilerClobber(cUnit, p[next+1].reg);
266 p[next].inUse = true;
267 p[next+1].inUse = true;
268 assert((p[next].reg+1) == p[next+1].reg);
269 assert((p[next].reg & 0x1) == 0);
270 cUnit->regPool->nextFPTemp += 2;
271 return p[next].reg;
272 }
273 next += 2;
274 }
275 LOGE("No free temp registers");
276 dvmCompilerAbort(cUnit);
277 return -1;
278 }
279
280 /* Return a temp if one is available, -1 otherwise */
dvmCompilerAllocFreeTemp(CompilationUnit * cUnit)281 extern int dvmCompilerAllocFreeTemp(CompilationUnit *cUnit)
282 {
283 return allocTempBody(cUnit, cUnit->regPool->coreTemps,
284 cUnit->regPool->numCoreTemps,
285 &cUnit->regPool->nextCoreTemp, true);
286 }
287
dvmCompilerAllocTemp(CompilationUnit * cUnit)288 extern int dvmCompilerAllocTemp(CompilationUnit *cUnit)
289 {
290 return allocTempBody(cUnit, cUnit->regPool->coreTemps,
291 cUnit->regPool->numCoreTemps,
292 &cUnit->regPool->nextCoreTemp, true);
293 }
294
dvmCompilerAllocTempFloat(CompilationUnit * cUnit)295 extern int dvmCompilerAllocTempFloat(CompilationUnit *cUnit)
296 {
297 return allocTempBody(cUnit, cUnit->regPool->FPTemps,
298 cUnit->regPool->numFPTemps,
299 &cUnit->regPool->nextFPTemp, true);
300 }
301
allocLiveBody(RegisterInfo * p,int numTemps,int sReg)302 static RegisterInfo *allocLiveBody(RegisterInfo *p, int numTemps, int sReg)
303 {
304 int i;
305 if (sReg == -1)
306 return NULL;
307 for (i=0; i < numTemps; i++) {
308 if (p[i].live && (p[i].sReg == sReg)) {
309 p[i].inUse = true;
310 return &p[i];
311 }
312 }
313 return NULL;
314 }
315
allocLive(CompilationUnit * cUnit,int sReg,int regClass)316 static RegisterInfo *allocLive(CompilationUnit *cUnit, int sReg,
317 int regClass)
318 {
319 RegisterInfo *res = NULL;
320 switch(regClass) {
321 case kAnyReg:
322 res = allocLiveBody(cUnit->regPool->FPTemps,
323 cUnit->regPool->numFPTemps, sReg);
324 if (res)
325 break;
326 /* Intentional fallthrough */
327 case kCoreReg:
328 res = allocLiveBody(cUnit->regPool->coreTemps,
329 cUnit->regPool->numCoreTemps, sReg);
330 break;
331 case kFPReg:
332 res = allocLiveBody(cUnit->regPool->FPTemps,
333 cUnit->regPool->numFPTemps, sReg);
334 break;
335 default:
336 LOGE("Invalid register type");
337 dvmCompilerAbort(cUnit);
338 }
339 return res;
340 }
341
dvmCompilerFreeTemp(CompilationUnit * cUnit,int reg)342 extern void dvmCompilerFreeTemp(CompilationUnit *cUnit, int reg)
343 {
344 RegisterInfo *p = cUnit->regPool->coreTemps;
345 int numTemps = cUnit->regPool->numCoreTemps;
346 int i;
347 for (i=0; i< numTemps; i++) {
348 if (p[i].reg == reg) {
349 p[i].inUse = false;
350 p[i].pair = false;
351 return;
352 }
353 }
354 p = cUnit->regPool->FPTemps;
355 numTemps = cUnit->regPool->numFPTemps;
356 for (i=0; i< numTemps; i++) {
357 if (p[i].reg == reg) {
358 p[i].inUse = false;
359 p[i].pair = false;
360 return;
361 }
362 }
363 LOGE("Tried to free a non-existant temp: r%d",reg);
364 dvmCompilerAbort(cUnit);
365 }
366
dvmCompilerIsLive(CompilationUnit * cUnit,int reg)367 extern RegisterInfo *dvmCompilerIsLive(CompilationUnit *cUnit, int reg)
368 {
369 RegisterInfo *p = cUnit->regPool->coreTemps;
370 int numTemps = cUnit->regPool->numCoreTemps;
371 int i;
372 for (i=0; i< numTemps; i++) {
373 if (p[i].reg == reg) {
374 return p[i].live ? &p[i] : NULL;
375 }
376 }
377 p = cUnit->regPool->FPTemps;
378 numTemps = cUnit->regPool->numFPTemps;
379 for (i=0; i< numTemps; i++) {
380 if (p[i].reg == reg) {
381 return p[i].live ? &p[i] : NULL;
382 }
383 }
384 return NULL;
385 }
386
dvmCompilerIsTemp(CompilationUnit * cUnit,int reg)387 extern RegisterInfo *dvmCompilerIsTemp(CompilationUnit *cUnit, int reg)
388 {
389 RegisterInfo *p = cUnit->regPool->coreTemps;
390 int numTemps = cUnit->regPool->numCoreTemps;
391 int i;
392 for (i=0; i< numTemps; i++) {
393 if (p[i].reg == reg) {
394 return &p[i];
395 }
396 }
397 p = cUnit->regPool->FPTemps;
398 numTemps = cUnit->regPool->numFPTemps;
399 for (i=0; i< numTemps; i++) {
400 if (p[i].reg == reg) {
401 return &p[i];
402 }
403 }
404 return NULL;
405 }
406
407 /*
408 * Similar to dvmCompilerAllocTemp(), but forces the allocation of a specific
409 * register. No check is made to see if the register was previously
410 * allocated. Use with caution.
411 */
dvmCompilerLockTemp(CompilationUnit * cUnit,int reg)412 extern void dvmCompilerLockTemp(CompilationUnit *cUnit, int reg)
413 {
414 RegisterInfo *p = cUnit->regPool->coreTemps;
415 int numTemps = cUnit->regPool->numCoreTemps;
416 int i;
417 for (i=0; i< numTemps; i++) {
418 if (p[i].reg == reg) {
419 p[i].inUse = true;
420 p[i].live = false;
421 return;
422 }
423 }
424 p = cUnit->regPool->FPTemps;
425 numTemps = cUnit->regPool->numFPTemps;
426 for (i=0; i< numTemps; i++) {
427 if (p[i].reg == reg) {
428 p[i].inUse = true;
429 p[i].live = false;
430 return;
431 }
432 }
433 LOGE("Tried to lock a non-existant temp: r%d",reg);
434 dvmCompilerAbort(cUnit);
435 }
436
dvmCompilerResetDef(CompilationUnit * cUnit,int reg)437 extern void dvmCompilerResetDef(CompilationUnit *cUnit, int reg)
438 {
439 RegisterInfo *p = getRegInfo(cUnit, reg);
440 p->defStart = NULL;
441 p->defEnd = NULL;
442 }
443
nullifyRange(CompilationUnit * cUnit,LIR * start,LIR * finish,int sReg1,int sReg2)444 static void nullifyRange(CompilationUnit *cUnit, LIR *start, LIR *finish,
445 int sReg1, int sReg2)
446 {
447 if (start && finish) {
448 LIR *p;
449 assert(sReg1 == sReg2);
450 for (p = start; ;p = p->next) {
451 ((ArmLIR *)p)->flags.isNop = true;
452 if (p == finish)
453 break;
454 }
455 }
456 }
457
458 /*
459 * Mark the beginning and end LIR of a def sequence. Note that
460 * on entry start points to the LIR prior to the beginning of the
461 * sequence.
462 */
dvmCompilerMarkDef(CompilationUnit * cUnit,RegLocation rl,LIR * start,LIR * finish)463 extern void dvmCompilerMarkDef(CompilationUnit *cUnit, RegLocation rl,
464 LIR *start, LIR *finish)
465 {
466 assert(!rl.wide);
467 assert(start && start->next);
468 assert(finish);
469 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
470 p->defStart = start->next;
471 p->defEnd = finish;
472 }
473
474 /*
475 * Mark the beginning and end LIR of a def sequence. Note that
476 * on entry start points to the LIR prior to the beginning of the
477 * sequence.
478 */
dvmCompilerMarkDefWide(CompilationUnit * cUnit,RegLocation rl,LIR * start,LIR * finish)479 extern void dvmCompilerMarkDefWide(CompilationUnit *cUnit, RegLocation rl,
480 LIR *start, LIR *finish)
481 {
482 assert(rl.wide);
483 assert(start && start->next);
484 assert(finish);
485 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
486 dvmCompilerResetDef(cUnit, rl.highReg); // Only track low of pair
487 p->defStart = start->next;
488 p->defEnd = finish;
489 }
490
dvmCompilerWideToNarrow(CompilationUnit * cUnit,RegLocation rl)491 extern RegLocation dvmCompilerWideToNarrow(CompilationUnit *cUnit,
492 RegLocation rl)
493 {
494 assert(rl.wide);
495 if (rl.location == kLocPhysReg) {
496 RegisterInfo *infoLo = getRegInfo(cUnit, rl.lowReg);
497 RegisterInfo *infoHi = getRegInfo(cUnit, rl.highReg);
498 if (!infoLo->pair) {
499 dumpRegPool(cUnit->regPool->coreTemps,
500 cUnit->regPool->numCoreTemps);
501 assert(infoLo->pair);
502 }
503 if (!infoHi->pair) {
504 dumpRegPool(cUnit->regPool->coreTemps,
505 cUnit->regPool->numCoreTemps);
506 assert(infoHi->pair);
507 }
508 assert(infoLo->pair);
509 assert(infoHi->pair);
510 assert(infoLo->partner == infoHi->reg);
511 assert(infoHi->partner == infoLo->reg);
512 infoLo->pair = false;
513 infoHi->pair = false;
514 infoLo->defStart = NULL;
515 infoLo->defEnd = NULL;
516 infoHi->defStart = NULL;
517 infoHi->defEnd = NULL;
518 }
519 rl.wide = false;
520 return rl;
521 }
522
dvmCompilerResetDefLoc(CompilationUnit * cUnit,RegLocation rl)523 extern void dvmCompilerResetDefLoc(CompilationUnit *cUnit, RegLocation rl)
524 {
525 assert(!rl.wide);
526 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
527 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
528 assert(!p->pair);
529 nullifyRange(cUnit, p->defStart, p->defEnd,
530 p->sReg, rl.sRegLow);
531 }
532 dvmCompilerResetDef(cUnit, rl.lowReg);
533 }
534
dvmCompilerResetDefLocWide(CompilationUnit * cUnit,RegLocation rl)535 extern void dvmCompilerResetDefLocWide(CompilationUnit *cUnit, RegLocation rl)
536 {
537 assert(rl.wide);
538 if (!(gDvmJit.disableOpt & (1 << kSuppressLoads))) {
539 RegisterInfo *p = getRegInfo(cUnit, rl.lowReg);
540 assert(p->pair);
541 nullifyRange(cUnit, p->defStart, p->defEnd,
542 p->sReg, rl.sRegLow);
543 }
544 dvmCompilerResetDef(cUnit, rl.lowReg);
545 dvmCompilerResetDef(cUnit, rl.highReg);
546 }
547
dvmCompilerResetDefTracking(CompilationUnit * cUnit)548 extern void dvmCompilerResetDefTracking(CompilationUnit *cUnit)
549 {
550 int i;
551 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
552 dvmCompilerResetDef(cUnit, cUnit->regPool->coreTemps[i].reg);
553 }
554 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
555 dvmCompilerResetDef(cUnit, cUnit->regPool->FPTemps[i].reg);
556 }
557 }
558
dvmCompilerClobberAllRegs(CompilationUnit * cUnit)559 extern void dvmCompilerClobberAllRegs(CompilationUnit *cUnit)
560 {
561 int i;
562 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
563 dvmCompilerClobber(cUnit, cUnit->regPool->coreTemps[i].reg);
564 }
565 for (i=0; i< cUnit->regPool->numFPTemps; i++) {
566 dvmCompilerClobber(cUnit, cUnit->regPool->FPTemps[i].reg);
567 }
568 }
569
570 /* To be used when explicitly managing register use */
dvmCompilerLockAllTemps(CompilationUnit * cUnit)571 extern void dvmCompilerLockAllTemps(CompilationUnit *cUnit)
572 {
573 int i;
574 for (i=0; i< cUnit->regPool->numCoreTemps; i++) {
575 dvmCompilerLockTemp(cUnit, cUnit->regPool->coreTemps[i].reg);
576 }
577 }
578
579 // Make sure nothing is live and dirty
flushAllRegsBody(CompilationUnit * cUnit,RegisterInfo * info,int numRegs)580 static void flushAllRegsBody(CompilationUnit *cUnit, RegisterInfo *info,
581 int numRegs)
582 {
583 int i;
584 for (i=0; i < numRegs; i++) {
585 if (info[i].live && info[i].dirty) {
586 if (info[i].pair) {
587 dvmCompilerFlushRegWide(cUnit, info[i].reg, info[i].partner);
588 } else {
589 dvmCompilerFlushReg(cUnit, info[i].reg);
590 }
591 }
592 }
593 }
594
dvmCompilerFlushAllRegs(CompilationUnit * cUnit)595 extern void dvmCompilerFlushAllRegs(CompilationUnit *cUnit)
596 {
597 flushAllRegsBody(cUnit, cUnit->regPool->coreTemps,
598 cUnit->regPool->numCoreTemps);
599 flushAllRegsBody(cUnit, cUnit->regPool->FPTemps,
600 cUnit->regPool->numFPTemps);
601 dvmCompilerClobberAllRegs(cUnit);
602 }
603
604
605 //TUNING: rewrite all of this reg stuff. Probably use an attribute table
regClassMatches(int regClass,int reg)606 static bool regClassMatches(int regClass, int reg)
607 {
608 if (regClass == kAnyReg) {
609 return true;
610 } else if (regClass == kCoreReg) {
611 return !FPREG(reg);
612 } else {
613 return FPREG(reg);
614 }
615 }
616
dvmCompilerMarkLive(CompilationUnit * cUnit,int reg,int sReg)617 extern void dvmCompilerMarkLive(CompilationUnit *cUnit, int reg, int sReg)
618 {
619 RegisterInfo *info = getRegInfo(cUnit, reg);
620 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
621 return; /* already live */
622 } else if (sReg != INVALID_SREG) {
623 dvmCompilerClobberSReg(cUnit, sReg);
624 info->live = true;
625 } else {
626 /* Can't be live if no associated sReg */
627 info->live = false;
628 }
629 info->sReg = sReg;
630 }
631
dvmCompilerMarkPair(CompilationUnit * cUnit,int lowReg,int highReg)632 extern void dvmCompilerMarkPair(CompilationUnit *cUnit, int lowReg, int highReg)
633 {
634 RegisterInfo *infoLo = getRegInfo(cUnit, lowReg);
635 RegisterInfo *infoHi = getRegInfo(cUnit, highReg);
636 infoLo->pair = infoHi->pair = true;
637 infoLo->partner = highReg;
638 infoHi->partner = lowReg;
639 }
640
dvmCompilerMarkClean(CompilationUnit * cUnit,int reg)641 extern void dvmCompilerMarkClean(CompilationUnit *cUnit, int reg)
642 {
643 RegisterInfo *info = getRegInfo(cUnit, reg);
644 info->dirty = false;
645 }
646
dvmCompilerMarkDirty(CompilationUnit * cUnit,int reg)647 extern void dvmCompilerMarkDirty(CompilationUnit *cUnit, int reg)
648 {
649 RegisterInfo *info = getRegInfo(cUnit, reg);
650 info->dirty = true;
651 }
652
dvmCompilerMarkInUse(CompilationUnit * cUnit,int reg)653 extern void dvmCompilerMarkInUse(CompilationUnit *cUnit, int reg)
654 {
655 RegisterInfo *info = getRegInfo(cUnit, reg);
656 info->inUse = true;
657 }
658
copyRegInfo(CompilationUnit * cUnit,int newReg,int oldReg)659 static void copyRegInfo(CompilationUnit *cUnit, int newReg, int oldReg)
660 {
661 RegisterInfo *newInfo = getRegInfo(cUnit, newReg);
662 RegisterInfo *oldInfo = getRegInfo(cUnit, oldReg);
663 *newInfo = *oldInfo;
664 newInfo->reg = newReg;
665 }
666
667 /*
668 * Return an updated location record with current in-register status.
669 * If the value lives in live temps, reflect that fact. No code
670 * is generated. The the live value is part of an older pair,
671 * clobber both low and high.
672 * TUNING: clobbering both is a bit heavy-handed, but the alternative
673 * is a bit complex when dealing with FP regs. Examine code to see
674 * if it's worthwhile trying to be more clever here.
675 */
dvmCompilerUpdateLoc(CompilationUnit * cUnit,RegLocation loc)676 extern RegLocation dvmCompilerUpdateLoc(CompilationUnit *cUnit, RegLocation loc)
677 {
678 assert(!loc.wide);
679 if (loc.location == kLocDalvikFrame) {
680 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
681 if (infoLo) {
682 if (infoLo->pair) {
683 dvmCompilerClobber(cUnit, infoLo->reg);
684 dvmCompilerClobber(cUnit, infoLo->partner);
685 } else {
686 loc.lowReg = infoLo->reg;
687 loc.location = kLocPhysReg;
688 }
689 }
690 }
691
692 return loc;
693 }
694
695 /* see comments for updateLoc */
dvmCompilerUpdateLocWide(CompilationUnit * cUnit,RegLocation loc)696 extern RegLocation dvmCompilerUpdateLocWide(CompilationUnit *cUnit,
697 RegLocation loc)
698 {
699 assert(loc.wide);
700 if (loc.location == kLocDalvikFrame) {
701 // Are the dalvik regs already live in physical registers?
702 RegisterInfo *infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
703 RegisterInfo *infoHi = allocLive(cUnit,
704 dvmCompilerSRegHi(loc.sRegLow), kAnyReg);
705 bool match = true;
706 match = match && (infoLo != NULL);
707 match = match && (infoHi != NULL);
708 // Are they both core or both FP?
709 match = match && (FPREG(infoLo->reg) == FPREG(infoHi->reg));
710 // If a pair of floating point singles, are they properly aligned?
711 if (match && FPREG(infoLo->reg)) {
712 match &= ((infoLo->reg & 0x1) == 0);
713 match &= ((infoHi->reg - infoLo->reg) == 1);
714 }
715 // If previously used as a pair, it is the same pair?
716 if (match && (infoLo->pair || infoHi->pair)) {
717 match = (infoLo->pair == infoHi->pair);
718 match &= ((infoLo->reg == infoHi->partner) &&
719 (infoHi->reg == infoLo->partner));
720 }
721 if (match) {
722 // Can reuse - update the register usage info
723 loc.lowReg = infoLo->reg;
724 loc.highReg = infoHi->reg;
725 loc.location = kLocPhysReg;
726 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
727 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
728 return loc;
729 }
730 // Can't easily reuse - clobber any overlaps
731 if (infoLo) {
732 dvmCompilerClobber(cUnit, infoLo->reg);
733 if (infoLo->pair)
734 dvmCompilerClobber(cUnit, infoLo->partner);
735 }
736 if (infoHi) {
737 dvmCompilerClobber(cUnit, infoHi->reg);
738 if (infoHi->pair)
739 dvmCompilerClobber(cUnit, infoHi->partner);
740 }
741 }
742
743 return loc;
744 }
745
evalLocWide(CompilationUnit * cUnit,RegLocation loc,int regClass,bool update)746 static RegLocation evalLocWide(CompilationUnit *cUnit, RegLocation loc,
747 int regClass, bool update)
748 {
749 assert(loc.wide);
750 int newRegs;
751 int lowReg;
752 int highReg;
753
754 loc = dvmCompilerUpdateLocWide(cUnit, loc);
755
756 /* If already in registers, we can assume proper form. Right reg class? */
757 if (loc.location == kLocPhysReg) {
758 assert(FPREG(loc.lowReg) == FPREG(loc.highReg));
759 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
760 if (!regClassMatches(regClass, loc.lowReg)) {
761 /* Wrong register class. Reallocate and copy */
762 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
763 lowReg = newRegs & 0xff;
764 highReg = (newRegs >> 8) & 0xff;
765 dvmCompilerRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
766 loc.highReg);
767 copyRegInfo(cUnit, lowReg, loc.lowReg);
768 copyRegInfo(cUnit, highReg, loc.highReg);
769 dvmCompilerClobber(cUnit, loc.lowReg);
770 dvmCompilerClobber(cUnit, loc.highReg);
771 loc.lowReg = lowReg;
772 loc.highReg = highReg;
773 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
774 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
775 }
776 return loc;
777 }
778
779 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
780 assert((loc.location != kLocRetval) ||
781 (dvmCompilerSRegHi(loc.sRegLow) == INVALID_SREG));
782
783 newRegs = dvmCompilerAllocTypedTempPair(cUnit, loc.fp, regClass);
784 loc.lowReg = newRegs & 0xff;
785 loc.highReg = (newRegs >> 8) & 0xff;
786
787 dvmCompilerMarkPair(cUnit, loc.lowReg, loc.highReg);
788 if (update) {
789 loc.location = kLocPhysReg;
790 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
791 dvmCompilerMarkLive(cUnit, loc.highReg, dvmCompilerSRegHi(loc.sRegLow));
792 }
793 assert(!FPREG(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
794 return loc;
795 }
796
dvmCompilerEvalLoc(CompilationUnit * cUnit,RegLocation loc,int regClass,bool update)797 extern RegLocation dvmCompilerEvalLoc(CompilationUnit *cUnit, RegLocation loc,
798 int regClass, bool update)
799 {
800 int newReg;
801 if (loc.wide)
802 return evalLocWide(cUnit, loc, regClass, update);
803 loc = dvmCompilerUpdateLoc(cUnit, loc);
804
805 if (loc.location == kLocPhysReg) {
806 if (!regClassMatches(regClass, loc.lowReg)) {
807 /* Wrong register class. Realloc, copy and transfer ownership */
808 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
809 dvmCompilerRegCopy(cUnit, newReg, loc.lowReg);
810 copyRegInfo(cUnit, newReg, loc.lowReg);
811 dvmCompilerClobber(cUnit, loc.lowReg);
812 loc.lowReg = newReg;
813 }
814 return loc;
815 }
816
817 assert((loc.location != kLocRetval) || (loc.sRegLow == INVALID_SREG));
818
819 newReg = dvmCompilerAllocTypedTemp(cUnit, loc.fp, regClass);
820 loc.lowReg = newReg;
821
822 if (update) {
823 loc.location = kLocPhysReg;
824 dvmCompilerMarkLive(cUnit, loc.lowReg, loc.sRegLow);
825 }
826 return loc;
827 }
828
getDestSSAName(MIR * mir,int num)829 static inline int getDestSSAName(MIR *mir, int num)
830 {
831 assert(mir->ssaRep->numDefs > num);
832 return mir->ssaRep->defs[num];
833 }
834
835 // Get the LocRecord associated with an SSA name use.
dvmCompilerGetSrc(CompilationUnit * cUnit,MIR * mir,int num)836 extern RegLocation dvmCompilerGetSrc(CompilationUnit *cUnit, MIR *mir, int num)
837 {
838 RegLocation loc = cUnit->regLocation[
839 SREG(cUnit, dvmCompilerSSASrc(mir, num))];
840 loc.fp = cUnit->regLocation[dvmCompilerSSASrc(mir, num)].fp;
841 loc.wide = false;
842 return loc;
843 }
844
845 // Get the LocRecord associated with an SSA name def.
dvmCompilerGetDest(CompilationUnit * cUnit,MIR * mir,int num)846 extern RegLocation dvmCompilerGetDest(CompilationUnit *cUnit, MIR *mir,
847 int num)
848 {
849 RegLocation loc = cUnit->regLocation[SREG(cUnit, getDestSSAName(mir, num))];
850 loc.fp = cUnit->regLocation[getDestSSAName(mir, num)].fp;
851 loc.wide = false;
852 return loc;
853 }
854
getLocWide(CompilationUnit * cUnit,MIR * mir,int low,int high,bool isSrc)855 static RegLocation getLocWide(CompilationUnit *cUnit, MIR *mir,
856 int low, int high, bool isSrc)
857 {
858 RegLocation lowLoc;
859 RegLocation highLoc;
860 /* Copy loc record for low word and patch in data from high word */
861 if (isSrc) {
862 lowLoc = dvmCompilerGetSrc(cUnit, mir, low);
863 highLoc = dvmCompilerGetSrc(cUnit, mir, high);
864 } else {
865 lowLoc = dvmCompilerGetDest(cUnit, mir, low);
866 highLoc = dvmCompilerGetDest(cUnit, mir, high);
867 }
868 /* Avoid this case by either promoting both or neither. */
869 assert(lowLoc.location == highLoc.location);
870 if (lowLoc.location == kLocPhysReg) {
871 /* This case shouldn't happen if we've named correctly */
872 assert(lowLoc.fp == highLoc.fp);
873 }
874 lowLoc.wide = true;
875 lowLoc.highReg = highLoc.lowReg;
876 return lowLoc;
877 }
878
dvmCompilerGetDestWide(CompilationUnit * cUnit,MIR * mir,int low,int high)879 extern RegLocation dvmCompilerGetDestWide(CompilationUnit *cUnit, MIR *mir,
880 int low, int high)
881 {
882 return getLocWide(cUnit, mir, low, high, false);
883 }
884
dvmCompilerGetSrcWide(CompilationUnit * cUnit,MIR * mir,int low,int high)885 extern RegLocation dvmCompilerGetSrcWide(CompilationUnit *cUnit, MIR *mir,
886 int low, int high)
887 {
888 return getLocWide(cUnit, mir, low, high, true);
889 }
890
891 /* Kill the corresponding bit in the null-checked register list */
dvmCompilerKillNullCheckedLoc(CompilationUnit * cUnit,RegLocation loc)892 extern void dvmCompilerKillNullCheckedLoc(CompilationUnit *cUnit,
893 RegLocation loc)
894 {
895 if (loc.location != kLocRetval) {
896 assert(loc.sRegLow != INVALID_SREG);
897 dvmClearBit(cUnit->regPool->nullCheckedRegs, loc.sRegLow);
898 if (loc.wide) {
899 assert(dvmCompilerSRegHi(loc.sRegLow) != INVALID_SREG);
900 dvmClearBit(cUnit->regPool->nullCheckedRegs,
901 dvmCompilerSRegHi(loc.sRegLow));
902 }
903 }
904 }
905