• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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