1/*
2 * Copyright (C) 2012 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/*! \file AnalysisO1.cpp
19  \brief This file implements register allocator, constant folding
20*/
21#include "libdex/DexOpcodes.h"
22#include "libdex/DexFile.h"
23#include "Lower.h"
24#include "interp/InterpState.h"
25#include "interp/InterpDefs.h"
26#include "libdex/Leb128.h"
27
28/* compilation flags to turn on debug printout */
29//#define DEBUG_COMPILE_TABLE
30//#define DEBUG_ALLOC_CONSTRAINT
31//#define DEBUG_REGALLOC
32//#define DEBUG_REG_USED
33//#define DEBUG_REFCOUNT
34//#define DEBUG_REACHING_DEF2
35//#define DEBUG_REACHING_DEF
36//#define DEBUG_LIVE_RANGE
37//#define DEBUG_MOVE_OPT
38//#define DEBUG_SPILL
39//#define DEBUG_ENDOFBB
40//#define DEBUG_CONST
41/*
42  #define DEBUG_XFER_POINTS
43  #define DEBUG_DSE
44  #define DEBUG_CFG
45  #define DEBUG_GLOBALTYPE
46  #define DEBUG_STATE
47  #define DEBUG_COMPILE_TABLE
48  #define DEBUG_VIRTUAL_INFO
49  #define DEBUG_MOVE_OPT
50  #define DEBUG_MERGE_ENTRY
51  #define DEBUG_INVALIDATE
52*/
53#include "AnalysisO1.h"
54
55void dumpCompileTable();
56
57/* There are 3 kinds of variables that are handled in this file:
58   1> virtual register (isVirtualReg())
59   2> temporary (!isVirtualReg() && regNum < PhysicalReg_GLUE_DVMDEX)
60   3> glue variables: regNum >= PhysicalReg_GLUE_DVMDEX
61*/
62/** check whether a variable is a virtual register
63 */
64bool isVirtualReg(int type) {
65    if((type & LowOpndRegType_virtual) != 0) return true;
66    return false;
67}
68bool isTemporary(int type, int regNum) {
69    if(!isVirtualReg(type) && regNum < PhysicalReg_GLUE_DVMDEX) return true;
70    return false;
71}
72
73/** convert type defined in lowering module to type defined in register allocator
74    in lowering module <type, isPhysical>
75    in register allocator: LowOpndRegType_hard LowOpndRegType_virtual LowOpndRegType_scratch
76*/
77int convertType(int type, int reg, bool isPhysical) {
78    int newType = type;
79    if(isPhysical) newType |= LowOpndRegType_hard;
80    if(isVirtualReg(type)) newType |= LowOpndRegType_virtual;
81    else {
82        /* reg number for a VR can exceed PhysicalReg_SCRATCH_1 */
83        if(reg >= PhysicalReg_SCRATCH_1 && reg < PhysicalReg_GLUE_DVMDEX)
84            newType |= LowOpndRegType_scratch;
85    }
86    return newType;
87}
88
89/** return the size of a variable
90 */
91OpndSize getRegSize(int type) {
92    if((type & MASK_FOR_TYPE) == LowOpndRegType_xmm) return OpndSize_64;
93    if((type & MASK_FOR_TYPE) == LowOpndRegType_fs) return OpndSize_64;
94    /* for type _gp, _fs_s, _ss */
95    return OpndSize_32;
96}
97
98/*
99   Overlapping cases between two variables A and B
100   layout for A,B   isAPartiallyOverlapB  isBPartiallyOverlapA
101   1> |__|  |____|         OVERLAP_ALIGN        OVERLAP_B_COVER_A
102      |__|  |____|
103   2> |____|           OVERLAP_B_IS_LOW_OF_A    OVERLAP_B_COVER_LOW_OF_A
104        |__|
105   3> |____|           OVERLAP_B_IS_HIGH_OF_A   OVERLAP_B_COVER_HIGH_OF_A
106      |__|
107   4> |____|      OVERLAP_LOW_OF_A_IS_HIGH_OF_B OVERLAP_B_COVER_LOW_OF_A
108         |____|
109   5>    |____|   OVERLAP_HIGH_OF_A_IS_LOW_OF_B OVERLAP_B_COVER_HIGH_OF_A
110      |____|
111   6>   |__|           OVERLAP_A_IS_LOW_OF_B    OVERLAP_B_COVER_A
112      |____|
113   7> |__|             OVERLAP_A_IS_HIGH_OF_B   OVERLAP_B_COVER_A
114      |____|
115*/
116/** determine the overlapping between variable B and A
117*/
118OverlapCase getBPartiallyOverlapA(int regB, LowOpndRegType tB, int regA, LowOpndRegType tA) {
119    if(getRegSize(tA) == getRegSize(tB) && regA == regB) return OVERLAP_B_COVER_A;
120    if(getRegSize(tA) == OpndSize_64 && getRegSize(tB) == OpndSize_32 && regA == regB) return OVERLAP_B_COVER_LOW_OF_A;
121    if(getRegSize(tA) == OpndSize_64 && getRegSize(tB) == OpndSize_32 && regB == regA + 1) return OVERLAP_B_COVER_HIGH_OF_A;
122    if(getRegSize(tA) == OpndSize_32 && getRegSize(tB) == OpndSize_64 && (regA == regB || regA == regB+1)) return OVERLAP_B_COVER_A;
123    if(getRegSize(tB) == OpndSize_64 && getRegSize(tA) == OpndSize_64 && regA == regB+1) return OVERLAP_B_COVER_LOW_OF_A;
124    if(getRegSize(tB) == OpndSize_64 && getRegSize(tA) == OpndSize_64 && regB == regA+1) return OVERLAP_B_COVER_HIGH_OF_A;
125    return OVERLAP_NO;
126}
127
128/** determine overlapping between variable A and B
129*/
130OverlapCase getAPartiallyOverlapB(int regA, LowOpndRegType tA, int regB, LowOpndRegType tB) {
131    if(getRegSize(tA) == getRegSize(tB) && regA == regB) return OVERLAP_ALIGN;
132    if(getRegSize(tA) == OpndSize_64 && getRegSize(tB) == OpndSize_32 && regA == regB)
133        return OVERLAP_B_IS_LOW_OF_A;
134    if(getRegSize(tA) == OpndSize_64 && getRegSize(tB) == OpndSize_32 && regB == regA+1)
135        return OVERLAP_B_IS_HIGH_OF_A;
136    if(getRegSize(tB) == OpndSize_64 && getRegSize(tA) == OpndSize_64 && regA == regB+1)
137        return OVERLAP_LOW_OF_A_IS_HIGH_OF_B;
138    if(getRegSize(tB) == OpndSize_64 && getRegSize(tA) == OpndSize_64 && regB == regA+1)
139        return OVERLAP_HIGH_OF_A_IS_LOW_OF_B;
140    if(getRegSize(tA) == OpndSize_32 && getRegSize(tB) == OpndSize_64 && regA == regB)
141        return OVERLAP_A_IS_LOW_OF_B;
142    if(getRegSize(tA) == OpndSize_32 && getRegSize(tB) == OpndSize_64 && regA == regB+1)
143        return OVERLAP_A_IS_HIGH_OF_B;
144    return OVERLAP_NO;
145}
146
147/** determine whether variable A fully covers B
148 */
149bool isAFullyCoverB(int regA, LowOpndRegType tA, int regB, LowOpndRegType tB) {
150    if(getRegSize(tB) == OpndSize_32) return true;
151    if(getRegSize(tA) == getRegSize(tB) && regA == regB) return true;
152    return false;
153}
154
155/*
156   RegAccessType accessType
157   1> DefOrUse.accessType
158      can only be D(VR), L(low part of VR), H(high part of VR), N(none)
159      for def, it means which part of the VR is live
160      for use, it means which part of the VR comes from the def
161   2> VirtualRegInfo.accessType
162      for currentInfo, it can only be a combination of U & D
163      for entries in infoBasicBlock, it can be a combination of U & D|L|H
164*/
165
166/*
167   Key data structures used:
168   1> BasicBlock_O1
169      VirtualRegInfo infoBasicBlock[]
170      DefUsePair* defUseTable
171      XferPoint xferPoints[]
172   2> MemoryVRInfo memVRTable[]
173      LiveRange* ranges
174   3> compileTableEntry compileTable[]
175   4> VirtualRegInfo
176      DefOrUse reachingDefs[3]
177   5> DefUsePair, LiveRange
178*/
179
180//! one entry for each variable used
181
182//! a variable can be virtual register, or a temporary (can be hard-coded)
183compileTableEntry compileTable[COMPILE_TABLE_SIZE];
184int num_compile_entries;
185//! tables to save the states of register allocation
186regAllocStateEntry1 stateTable1_1[COMPILE_TABLE_SIZE];
187regAllocStateEntry1 stateTable1_2[COMPILE_TABLE_SIZE];
188regAllocStateEntry1 stateTable1_3[COMPILE_TABLE_SIZE];
189regAllocStateEntry1 stateTable1_4[COMPILE_TABLE_SIZE];
190regAllocStateEntry2 stateTable2_1[COMPILE_TABLE_SIZE];
191regAllocStateEntry2 stateTable2_2[COMPILE_TABLE_SIZE];
192regAllocStateEntry2 stateTable2_3[COMPILE_TABLE_SIZE];
193regAllocStateEntry2 stateTable2_4[COMPILE_TABLE_SIZE];
194
195//! array of VirtualRegInfo to store VRs accessed by a single bytecode
196VirtualRegInfo infoByteCode[MAX_REG_PER_BYTECODE];
197int num_regs_per_bytecode;
198//! array of TempRegInfo to store temporaries accessed by a single bytecode
199TempRegInfo infoByteCodeTemp[MAX_TEMP_REG_PER_BYTECODE];
200int num_temp_regs_per_bytecode;
201//! array of MemoryVRInfo to store whether a VR is in memory
202#define NUM_MEM_VR_ENTRY 140
203MemoryVRInfo memVRTable[NUM_MEM_VR_ENTRY];
204int num_memory_vr;
205
206CompilationUnit* currentUnit = NULL;
207
208//! the current basic block
209BasicBlock_O1* currentBB = NULL;
210//! array of RegisterInfo for all the physical registers
211RegisterInfo allRegs[PhysicalReg_GLUE+1]; //initialized in codeGen
212
213VirtualRegInfo currentInfo;
214VirtualRegInfo tmpInfo;
215
216//! this array says whether a spill location is used (0 means not used, 1 means used)
217int spillIndexUsed[MAX_SPILL_JIT_IA];
218int indexForGlue = -1;
219
220int num_bbs_for_method;
221//! array of basic blocks in a method in program order
222BasicBlock_O1* method_bbs_sorted[MAX_NUM_BBS_PER_METHOD];
223//! the entry basic block
224BasicBlock_O1* bb_entry;
225int pc_start = -1;
226int pc_end = -1;
227
228//!array of PCs for exception handlers
229int exceptionHandlers[10];
230int num_exception_handlers;
231
232bool canSpillReg[PhysicalReg_Null]; //physical registers that should not be spilled
233int inGetVR_num = -1;
234int inGetVR_type;
235
236///////////////////////////////////////////////////////////////////////////////
237// FORWARD FUNCTION DECLARATION
238void addExceptionHandler(s4 tmp);
239
240int createCFG(Method* method);
241int collectInfoOfBasicBlock(Method* method, BasicBlock_O1* bb);
242void dumpVirtualInfoOfBasicBlock(BasicBlock_O1* bb);
243void setTypeOfVR();
244void insertGlueReg();
245void dumpVirtualInfoOfMethod();
246int codeGenBasicBlock(const Method* method, BasicBlock_O1* bb);
247
248//used in collectInfoOfBasicBlock: getVirtualRegInfo
249int mergeEntry2(BasicBlock_O1* bb);
250int sortAllocConstraint(RegAllocConstraint* allocConstraints,
251                        RegAllocConstraint* allocConstraintsSorted, bool fromHighToLow);
252
253//used in codeGenBasicBlock
254void insertFromVirtualInfo(BasicBlock_O1* bb, int k); //update compileTable
255void insertFromTempInfo(int k); //update compileTable
256int updateXferPoints();
257void updateLiveTable();
258void printDefUseTable();
259bool isFirstOfHandler(BasicBlock_O1* bb);
260
261//used in mergeEntry2
262//following functions will not update global data structure
263RegAccessType mergeAccess2(RegAccessType A, RegAccessType B, OverlapCase isBPartiallyOverlapA);
264RegAccessType updateAccess1(RegAccessType A, OverlapCase isAPartiallyOverlapB); //will not update global data structure
265RegAccessType updateAccess2(RegAccessType C1, RegAccessType C2);
266RegAccessType updateAccess3(RegAccessType C, RegAccessType B);
267
268void updateDefUseTable();
269void updateReachingDefA(int indexToA, OverlapCase isBPartiallyOverlapA);
270void updateReachingDefB1(int indexToA);
271void updateReachingDefB2();
272void updateReachingDefB3();
273
274RegAccessType insertAUse(DefUsePair* ptr, int offsetPC, int regNum, LowOpndRegType physicalType);
275DefUsePair* insertADef(int offsetPC, int regNum, LowOpndRegType pType, RegAccessType rType);
276RegAccessType insertDefUsePair(int reachingDefIndex);
277
278//used in updateXferPoints
279int fakeUsageAtEndOfBB(BasicBlock_O1* bb);
280void insertLoadXfer(int offset, int regNum, LowOpndRegType pType);
281int searchMemTable(int regNum);
282void mergeLiveRange(int tableIndex, int rangeStart, int rangeEnd);
283//used in updateLiveTable
284RegAccessType setAccessTypeOfUse(OverlapCase isDefPartiallyOverlapUse, RegAccessType reachingDefLive);
285DefUsePair* searchDefUseTable(int offsetPC, int regNum, LowOpndRegType pType);
286void insertAccess(int tableIndex, LiveRange* startP, int rangeStart);
287
288//register allocation
289int spillLogicalReg(int spill_index, bool updateTable);
290
291/** check whether the current bytecode is IF or GOTO or SWITCH
292 */
293bool isCurrentByteCodeJump() {
294    u2 inst_op = INST_INST(inst);
295    if(inst_op == OP_IF_EQ || inst_op == OP_IF_NE || inst_op == OP_IF_LT ||
296       inst_op == OP_IF_GE || inst_op == OP_IF_GT || inst_op == OP_IF_LE) return true;
297    if(inst_op == OP_IF_EQZ || inst_op == OP_IF_NEZ || inst_op == OP_IF_LTZ ||
298       inst_op == OP_IF_GEZ || inst_op == OP_IF_GTZ || inst_op == OP_IF_LEZ) return true;
299    if(inst_op == OP_GOTO || inst_op == OP_GOTO_16 || inst_op == OP_GOTO_32) return true;
300    if(inst_op == OP_PACKED_SWITCH || inst_op == OP_SPARSE_SWITCH) return true;
301    return false;
302}
303
304/* this function is called before code generation of basic blocks
305   initialize data structure allRegs, which stores information for each physical register,
306   whether it is used, when it was last freed, whether it is callee-saved */
307void initializeAllRegs() {
308    int k;
309    for(k = PhysicalReg_EAX; k <= PhysicalReg_EBP; k++) {
310        allRegs[k].physicalReg = (PhysicalReg) k;
311        if(k == PhysicalReg_EDI || k == PhysicalReg_ESP || k == PhysicalReg_EBP)
312            allRegs[k].isUsed = true;
313        else {
314            allRegs[k].isUsed = false;
315            allRegs[k].freeTimeStamp = -1;
316        }
317        if(k == PhysicalReg_EBX || k == PhysicalReg_EBP || k == PhysicalReg_ESI || k == PhysicalReg_EDI)
318            allRegs[k].isCalleeSaved = true;
319        else
320            allRegs[k].isCalleeSaved = false;
321    }
322    for(k = PhysicalReg_XMM0; k <= PhysicalReg_XMM7; k++) {
323        allRegs[k].physicalReg = (PhysicalReg) k;
324        allRegs[k].isUsed = false;
325        allRegs[k].freeTimeStamp = -1;
326        allRegs[k].isCalleeSaved = false;
327    }
328}
329
330/** sync up allRegs (isUsed & freeTimeStamp) with compileTable
331    global data: RegisterInfo allRegs[PhysicalReg_Null]
332    update allRegs[EAX to XMM7] except EDI,ESP,EBP
333    update RegisterInfo.isUsed & RegisterInfo.freeTimeStamp
334        if the physical register was used and is not used now
335*/
336void syncAllRegs() {
337    int k, k2;
338    for(k = PhysicalReg_EAX; k <= PhysicalReg_XMM7; k++) {
339        if(k == PhysicalReg_EDI || k == PhysicalReg_ESP || k == PhysicalReg_EBP)
340            continue;
341        //check whether the physical register is used by any logical register
342        bool stillUsed = false;
343        for(k2 = 0; k2 < num_compile_entries; k2++) {
344            if(compileTable[k2].physicalReg == k) {
345                stillUsed = true;
346                break;
347            }
348        }
349        if(stillUsed && !allRegs[k].isUsed) {
350            allRegs[k].isUsed = true;
351        }
352        if(!stillUsed && allRegs[k].isUsed) {
353            allRegs[k].isUsed = false;
354            allRegs[k].freeTimeStamp = lowOpTimeStamp;
355        }
356    }
357    return;
358}
359
360//!sync up spillIndexUsed with compileTable
361
362//!
363void updateSpillIndexUsed() {
364    int k;
365    for(k = 0; k <= MAX_SPILL_JIT_IA-1; k++) spillIndexUsed[k] = 0;
366    for(k = 0; k < num_compile_entries; k++) {
367        if(isVirtualReg(compileTable[k].physicalType)) continue;
368        if(compileTable[k].spill_loc_index >= 0) {
369            if(compileTable[k].spill_loc_index > 4*(MAX_SPILL_JIT_IA-1))
370                ALOGE("spill_loc_index is wrong for entry %d: %d",
371                      k, compileTable[k].spill_loc_index);
372            spillIndexUsed[compileTable[k].spill_loc_index >> 2] = 1;
373        }
374    }
375}
376
377/* free memory used in all basic blocks */
378void freeCFG() {
379    int k;
380    for(k = 0; k < num_bbs_for_method; k++) {
381        /* free defUseTable for method_bbs_sorted[k] */
382        DefUsePair* ptr = method_bbs_sorted[k]->defUseTable;
383        while(ptr != NULL) {
384            DefUsePair* tmp = ptr->next;
385            /* free ptr->uses */
386            DefOrUseLink* ptrUse = ptr->uses;
387            while(ptrUse != NULL) {
388                DefOrUseLink* tmp2 = ptrUse->next;
389                free(ptrUse);
390                ptrUse = tmp2;
391            }
392            free(ptr);
393            ptr = tmp;
394        }
395        free(method_bbs_sorted[k]);
396    }
397}
398
399/* update compileTable.physicalReg, compileTable.spill_loc_index & allRegs.isUsed
400   for glue-related variables, they do not exist
401       not in a physical register (physicalReg is Null)
402       not in a spilled memory location (spill_loc_index is -1)
403*/
404void initializeRegStateOfBB(BasicBlock_O1* bb) {
405    //for GLUE variables, do not exist
406    int k;
407    for(k = 0; k < num_compile_entries; k++) {
408        /* trace-based JIT: there is no VR with GG type */
409        if(isVirtualReg(compileTable[k].physicalType) && compileTable[k].gType == GLOBALTYPE_GG) {
410            if(bb->bb_index > 0) { //non-entry block
411                if(isFirstOfHandler(bb)) {
412                    /* at the beginning of an exception handler, GG VR is in the interpreted stack */
413                    compileTable[k].physicalReg = PhysicalReg_Null;
414#ifdef DEBUG_COMPILE_TABLE
415                    ALOGI("at the first basic block of an exception handler, GG VR %d type %d is in memory",
416                          compileTable[k].regNum, compileTable[k].physicalType);
417#endif
418                } else {
419                    if(compileTable[k].physicalReg == PhysicalReg_Null) {
420                        /* GG VR is in a specific physical register */
421                        compileTable[k].physicalReg = compileTable[k].physicalReg_prev;
422                    }
423                    int tReg = compileTable[k].physicalReg;
424                    allRegs[tReg].isUsed = true;
425#ifdef DEBUG_REG_USED
426                    ALOGI("REGALLOC: physical reg %d is used by a GG VR %d %d at beginning of BB", tReg, compileTable[k].regNum, compileTable[k].physicalType);
427#endif
428                }
429            } //non-entry block
430        } //if GG VR
431        if(compileTable[k].regNum != PhysicalReg_GLUE &&
432           compileTable[k].regNum >= PhysicalReg_GLUE_DVMDEX) {
433            /* glue related registers */
434            compileTable[k].physicalReg = PhysicalReg_Null;
435            compileTable[k].spill_loc_index = -1;
436        }
437    }
438}
439
440/* update memVRTable[].nullCheckDone */
441void initializeNullCheck(int indexToMemVR) {
442    bool found = false;
443#ifdef GLOBAL_NULLCHECK_OPT
444    /* search nullCheck_inB of the current Basic Block */
445    for(k = 0; k < nullCheck_inSize[currentBB->bb_index2]; k++) {
446        if(nullCheck_inB[currentBB->bb_index2][k] == memVRTable[indexToMemVR].regNum) {
447            found = true;
448            break;
449        }
450    }
451#endif
452    memVRTable[indexToMemVR].nullCheckDone = found;
453}
454
455/* initialize memVRTable */
456void initializeMemVRTable() {
457    num_memory_vr = 0;
458    int k;
459    for(k = 0; k < num_compile_entries; k++) {
460        if(!isVirtualReg(compileTable[k].physicalType)) continue;
461        /* VRs in compileTable */
462        bool setToInMemory = (compileTable[k].physicalReg == PhysicalReg_Null);
463        int regNum = compileTable[k].regNum;
464        OpndSize sizeVR = getRegSize(compileTable[k].physicalType);
465        /* search memVRTable for the VR in compileTable */
466        int kk;
467        int indexL = -1;
468        int indexH = -1;
469        for(kk = 0; kk < num_memory_vr; kk++) {
470            if(memVRTable[kk].regNum == regNum) {
471                indexL = kk;
472                continue;
473            }
474            if(memVRTable[kk].regNum == regNum+1 && sizeVR == OpndSize_64) {
475                indexH = kk;
476                continue;
477            }
478        }
479        if(indexL < 0) {
480            /* the low half of VR is not in memVRTable
481               add an entry for the low half in memVRTable */
482            if(num_memory_vr >= NUM_MEM_VR_ENTRY) {
483                ALOGE("exceeds size of memVRTable");
484                dvmAbort();
485            }
486            memVRTable[num_memory_vr].regNum = regNum;
487            memVRTable[num_memory_vr].inMemory = setToInMemory;
488            initializeNullCheck(num_memory_vr); //set nullCheckDone
489            memVRTable[num_memory_vr].boundCheck.checkDone = false;
490            memVRTable[num_memory_vr].num_ranges = 0;
491            memVRTable[num_memory_vr].ranges = NULL;
492            memVRTable[num_memory_vr].delayFreeFlags = VRDELAY_NONE;
493            num_memory_vr++;
494        }
495        if(sizeVR == OpndSize_64 && indexH < 0) {
496            /* the high half of VR is not in memVRTable
497               add an entry for the high half in memVRTable */
498            if(num_memory_vr >= NUM_MEM_VR_ENTRY) {
499                ALOGE("exceeds size of memVRTable");
500                dvmAbort();
501            }
502            memVRTable[num_memory_vr].regNum = regNum+1;
503            memVRTable[num_memory_vr].inMemory = setToInMemory;
504            initializeNullCheck(num_memory_vr);
505            memVRTable[num_memory_vr].boundCheck.checkDone = false;
506            memVRTable[num_memory_vr].num_ranges = 0;
507            memVRTable[num_memory_vr].ranges = NULL;
508            memVRTable[num_memory_vr].delayFreeFlags = VRDELAY_NONE;
509            num_memory_vr++;
510        }
511    }
512}
513
514/* create a O1 basic block from basic block constructed in JIT MIR */
515BasicBlock_O1* createBasicBlockO1(BasicBlock* bb) {
516    BasicBlock_O1* bb1 = createBasicBlock(0, -1);
517    bb1->jitBasicBlock = bb;
518    return bb1;
519}
520
521/* a basic block in JIT MIR can contain bytecodes that are not in program order
522   for example, a "goto" bytecode will be followed by the goto target */
523void preprocessingBB(BasicBlock* bb) {
524    currentBB = createBasicBlockO1(bb);
525    /* initialize currentBB->allocConstraints */
526    int ii;
527    for(ii = 0; ii < 8; ii++) {
528        currentBB->allocConstraints[ii].physicalReg = (PhysicalReg)ii;
529        currentBB->allocConstraints[ii].count = 0;
530    }
531    collectInfoOfBasicBlock(currentMethod, currentBB);
532#ifdef DEBUG_COMPILE_TABLE
533    dumpVirtualInfoOfBasicBlock(currentBB);
534#endif
535    currentBB = NULL;
536}
537
538void preprocessingTrace() {
539    int k, k2, k3, jj;
540    /* this is a simplified verson of setTypeOfVR()
541        all VRs are assumed to be GL, no VR will be GG
542    */
543    for(k = 0; k < num_bbs_for_method; k++)
544        for(jj = 0; jj < method_bbs_sorted[k]->num_regs; jj++)
545            method_bbs_sorted[k]->infoBasicBlock[jj].gType = GLOBALTYPE_GL;
546
547    /* insert a glue-related register GLUE_DVMDEX to compileTable */
548    insertGlueReg();
549
550    int compile_entries_old = num_compile_entries;
551    for(k2 = 0; k2 < num_bbs_for_method; k2++) {
552        currentBB = method_bbs_sorted[k2];
553        /* update compileTable with virtual register from currentBB */
554        for(k3 = 0; k3 < currentBB->num_regs; k3++) {
555            insertFromVirtualInfo(currentBB, k3);
556        }
557
558        /* for each GL|GG type VR, insert fake usage at end of basic block to keep it live */
559        int offsetPC_back = offsetPC;
560        offsetPC = PC_FOR_END_OF_BB;
561        for(k = 0; k < num_compile_entries; k++) {
562            currentInfo.regNum = compileTable[k].regNum;
563            currentInfo.physicalType = (LowOpndRegType)compileTable[k].physicalType;
564            if(isVirtualReg(compileTable[k].physicalType) &&
565               compileTable[k].gType == GLOBALTYPE_GL) {
566                /* update defUseTable by assuming a fake usage at END of a basic block for variable @ currentInfo */
567                fakeUsageAtEndOfBB(currentBB);
568            }
569            if(isVirtualReg(compileTable[k].physicalType) &&
570               compileTable[k].gType == GLOBALTYPE_GG) {
571                fakeUsageAtEndOfBB(currentBB);
572            }
573        }
574        offsetPC = offsetPC_back;
575        num_compile_entries = compile_entries_old;
576    }
577    /* initialize data structure allRegs */
578    initializeAllRegs();
579#ifdef DEBUG_COMPILE_TABLE
580    dumpCompileTable();
581#endif
582    currentBB = NULL;
583}
584
585void printJitTraceInfoAtRunTime(const Method* method, int offset) {
586    ALOGI("execute trace for %s%s at offset %x", method->clazz->descriptor, method->name, offset);
587}
588
589void startOfTraceO1(const Method* method, LowOpBlockLabel* labelList, int exceptionBlockId, CompilationUnit *cUnit) {
590    num_exception_handlers = 0;
591    num_compile_entries = 0;
592    currentBB = NULL;
593    pc_start = -1;
594    bb_entry = NULL;
595    num_bbs_for_method = 0;
596    currentUnit = cUnit;
597    lowOpTimeStamp = 0;
598
599// dumpDebuggingInfo is gone in CompilationUnit struct
600#if 0
601    /* add code to dump debugging information */
602    if(cUnit->dumpDebuggingInfo) {
603        move_imm_to_mem(OpndSize_32, cUnit->startOffset, -4, PhysicalReg_ESP, true); //2nd argument: offset
604        move_imm_to_mem(OpndSize_32, (int)currentMethod, -8, PhysicalReg_ESP, true); //1st argument: method
605        load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
606
607        typedef void (*vmHelper)(const Method*, int);
608        vmHelper funcPtr = printJitTraceInfoAtRunTime;
609        move_imm_to_reg(OpndSize_32, (int)funcPtr, PhysicalReg_ECX, true);
610        call_reg(PhysicalReg_ECX, true);
611
612        load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
613    }
614#endif
615}
616
617
618/* Code generation for a basic block defined for JIT
619   We have two data structures for a basic block:
620       BasicBlock defined in vm/compiler by JIT
621       BasicBlock_O1 defined in o1 */
622int codeGenBasicBlockJit(const Method* method, BasicBlock* bb) {
623    /* search method_bbs_sorted to find the O1 basic block corresponding to bb */
624    int k;
625    for(k = 0; k < num_bbs_for_method; k++) {
626        if(method_bbs_sorted[k]->jitBasicBlock == bb) {
627            lowOpTimeStamp = 0; //reset time stamp at start of a basic block
628            currentBB = method_bbs_sorted[k];
629            int cg_ret = codeGenBasicBlock(method, currentBB);
630            currentBB = NULL;
631            return cg_ret;
632        }
633    }
634    ALOGE("can't find the corresponding O1 basic block for id %d type %d",
635         bb->id, bb->blockType);
636    return -1;
637}
638void endOfBasicBlock(BasicBlock* bb) {
639    isScratchPhysical = true;
640    currentBB = NULL;
641}
642void endOfTraceO1() {
643     freeCFG();
644}
645
646/** entry point to collect information about virtual registers used in a basic block
647    Initialize data structure BasicBlock_O1
648    The usage information of virtual registers is stoerd in bb->infoBasicBlock
649
650    Global variables accessed: offsetPC, rPC
651*/
652int collectInfoOfBasicBlock(Method* method, BasicBlock_O1* bb) {
653    bb->num_regs = 0;
654    bb->num_defs = 0;
655    bb->defUseTable = NULL;
656    bb->defUseTail = NULL;
657    u2* rPC_start = (u2*)method->insns;
658    int kk;
659    bb->endsWithReturn = false;
660    bb->hasAccessToGlue = false;
661
662    MIR* mir;
663    int seqNum = 0;
664    /* traverse the MIR in basic block
665       sequence number is used to make sure next bytecode will have a larger sequence number */
666    for(mir = bb->jitBasicBlock->firstMIRInsn; mir; mir = mir->next) {
667        offsetPC = seqNum;
668        mir->seqNum = seqNum++;
669        rPC = rPC_start + mir->offset;
670#ifdef WITH_JIT_INLINING
671        if(mir->dalvikInsn.opcode >= kMirOpFirst &&
672           mir->dalvikInsn.opcode != kMirOpCheckInlinePrediction) continue;
673        if(ir->dalvikInsn.opcode == kMirOpCheckInlinePrediction) { //TODO
674        }
675#else
676        if(mir->dalvikInsn.opcode >= kNumPackedOpcodes) continue;
677#endif
678        inst = FETCH(0);
679        u2 inst_op = INST_INST(inst);
680        /* update bb->hasAccessToGlue */
681        if((inst_op >= OP_MOVE_RESULT && inst_op <= OP_RETURN_OBJECT) ||
682           (inst_op >= OP_MONITOR_ENTER && inst_op <= OP_INSTANCE_OF) ||
683           (inst_op == OP_FILLED_NEW_ARRAY) ||
684           (inst_op == OP_FILLED_NEW_ARRAY_RANGE) ||
685           (inst_op == OP_THROW) ||
686           (inst_op >= OP_INVOKE_VIRTUAL && inst_op <= OP_INVOKE_INTERFACE_RANGE) ||
687           (inst_op >= OP_THROW_VERIFICATION_ERROR &&
688            inst_op <= OP_EXECUTE_INLINE_RANGE) ||
689           (inst_op >= OP_INVOKE_VIRTUAL_QUICK && inst_op <= OP_INVOKE_SUPER_QUICK_RANGE))
690            bb->hasAccessToGlue = true;
691        /* update bb->endsWithReturn */
692        if(inst_op == OP_RETURN_VOID || inst_op == OP_RETURN || inst_op == OP_RETURN_VOID_BARRIER ||
693           inst_op == OP_RETURN_OBJECT || inst_op == OP_RETURN_WIDE)
694            bb->endsWithReturn = true;
695
696        /* get virtual register usage in current bytecode */
697        getVirtualRegInfo(infoByteCode);
698        int num_regs = num_regs_per_bytecode;
699        for(kk = 0; kk < num_regs; kk++) {
700            currentInfo = infoByteCode[kk];
701#ifdef DEBUG_MERGE_ENTRY
702            ALOGI("call mergeEntry2 at offsetPC %x kk %d VR %d %d", offsetPC, kk,
703                  currentInfo.regNum, currentInfo.physicalType);
704#endif
705            mergeEntry2(bb); //update defUseTable of the basic block
706        }
707
708        //dumpVirtualInfoOfBasicBlock(bb);
709    }//for each bytecode
710
711    bb->pc_end = seqNum;
712
713    //sort allocConstraints of each basic block
714    for(kk = 0; kk < bb->num_regs; kk++) {
715#ifdef DEBUG_ALLOC_CONSTRAINT
716        ALOGI("sort virtual reg %d type %d -------", bb->infoBasicBlock[kk].regNum,
717              bb->infoBasicBlock[kk].physicalType);
718#endif
719        sortAllocConstraint(bb->infoBasicBlock[kk].allocConstraints,
720                            bb->infoBasicBlock[kk].allocConstraintsSorted, true);
721    }
722#ifdef DEBUG_ALLOC_CONSTRAINT
723    ALOGI("sort constraints for BB %d --------", bb->bb_index);
724#endif
725    sortAllocConstraint(bb->allocConstraints, bb->allocConstraintsSorted, false);
726    return 0;
727}
728
729/** entry point to generate native code for a O1 basic block
730    There are 3 kinds of virtual registers in a O1 basic block:
731    1> L VR: local within the basic block
732    2> GG VR: is live in other basic blocks,
733              its content is in a pre-defined GPR at the beginning of a basic block
734    3> GL VR: is live in other basic blocks,
735              its content is in the interpreted stack at the beginning of a basic block
736    compileTable is updated with infoBasicBlock at the start of the basic block;
737    Before lowering each bytecode, compileTable is updated with infoByteCodeTemp;
738    At end of the basic block, right before the jump instruction, handles constant VRs and GG VRs
739*/
740int codeGenBasicBlock(const Method* method, BasicBlock_O1* bb) {
741    /* we assume at the beginning of each basic block,
742       all GL VRs reside in memory and all GG VRs reside in predefined physical registers,
743       so at the end of a basic block, recover a spilled GG VR, store a GL VR to memory */
744    /* update compileTable with entries in bb->infoBasicBlock */
745    int k;
746    for(k = 0; k < bb->num_regs; k++) {
747        insertFromVirtualInfo(bb, k);
748    }
749    updateXferPoints(); //call fakeUsageAtEndOfBB
750#ifdef DEBUG_REACHING_DEF
751    printDefUseTable();
752#endif
753#ifdef DSE_OPT
754    removeDeadDefs();
755    printDefUseTable();
756#endif
757    //clear const section of compileTable
758    for(k = 0; k < num_compile_entries; k++) compileTable[k].isConst = false;
759    num_const_vr = 0;
760#ifdef DEBUG_COMPILE_TABLE
761    ALOGI("At start of basic block %d (num of VRs %d) -------", bb->bb_index, bb->num_regs);
762    dumpCompileTable();
763#endif
764    initializeRegStateOfBB(bb);
765    initializeMemVRTable();
766    updateLiveTable();
767    freeReg(true);  //before code gen of a basic block, also called at end of a basic block?
768#ifdef DEBUG_COMPILE_TABLE
769    ALOGI("At start of basic block %d (num of VRs %d) -------", bb->bb_index, bb->num_regs);
770#endif
771
772    u2* rPC_start = (u2*)method->insns;
773    bool lastByteCodeIsJump = false;
774    MIR* mir;
775    for(mir = bb->jitBasicBlock->firstMIRInsn; mir; mir = mir->next) {
776        offsetPC = mir->seqNum;
777        rPC = rPC_start + mir->offset;
778#ifdef WITH_JIT_INLINING
779        if(mir->dalvikInsn.opcode >= kMirOpFirst &&
780           mir->dalvikInsn.opcode != kMirOpCheckInlinePrediction) {
781#else
782        if(mir->dalvikInsn.opcode >= kNumPackedOpcodes) {
783#endif
784            handleExtendedMIR(currentUnit, mir);
785            continue;
786        }
787
788        inst = FETCH(0);
789        //before handling a bytecode, import info of temporary registers to compileTable including refCount
790        num_temp_regs_per_bytecode = getTempRegInfo(infoByteCodeTemp);
791        for(k = 0; k < num_temp_regs_per_bytecode; k++) {
792            if(infoByteCodeTemp[k].versionNum > 0) continue;
793            insertFromTempInfo(k);
794        }
795        startNativeCode(-1, -1);
796        for(k = 0; k <= MAX_SPILL_JIT_IA-1; k++) spillIndexUsed[k] = 0;
797        //update spillIndexUsed if a glue variable was spilled
798        for(k = 0; k < num_compile_entries; k++) {
799            if(compileTable[k].regNum >= PhysicalReg_GLUE_DVMDEX) {
800                if(compileTable[k].spill_loc_index >= 0)
801                    spillIndexUsed[compileTable[k].spill_loc_index >> 2] = 1;
802            }
803        }
804#ifdef DEBUG_COMPILE_TABLE
805        ALOGI("compile table size after importing temporary info %d", num_compile_entries);
806        ALOGI("before one bytecode %d (num of VRs %d) -------", bb->bb_index, bb->num_regs);
807#endif
808        //set isConst to true for CONST & MOVE MOVE_OBJ?
809        //clear isConst to true for MOVE, MOVE_OBJ, MOVE_RESULT, MOVE_EXCEPTION ...
810        bool isConst = getConstInfo(bb); //will reset isConst if a VR is updated by the bytecode
811        bool isDeadStmt = false;
812#ifdef DSE_OPT
813        for(k = 0; k < num_dead_pc; k++) {
814            if(deadPCs[k] == offsetPC) {
815                isDeadStmt = true;
816                break;
817            }
818        }
819#endif
820        getVirtualRegInfo(infoByteCode);
821        //call something similar to mergeEntry2, but only update refCount
822        //clear refCount
823        for(k = 0; k < num_regs_per_bytecode; k++) {
824            int indexT = searchCompileTable(LowOpndRegType_virtual | infoByteCode[k].physicalType,
825                                            infoByteCode[k].regNum);
826            if(indexT >= 0)
827                compileTable[indexT].refCount = 0;
828        }
829        for(k = 0; k < num_regs_per_bytecode; k++) {
830            int indexT = searchCompileTable(LowOpndRegType_virtual | infoByteCode[k].physicalType,
831                                            infoByteCode[k].regNum);
832            if(indexT >= 0)
833                compileTable[indexT].refCount += infoByteCode[k].refCount;
834        } //for k
835#ifdef DSE_OPT
836        if(isDeadStmt) { //search compileTable
837            getVirtualRegInfo(infoByteCode);
838#ifdef DEBUG_DSE
839            ALOGI("DSE: stmt at offsetPC %d is dead", offsetPC);
840#endif
841            for(k = 0; k < num_regs_per_bytecode; k++) {
842                int indexT = searchCompileTable(LowOpndRegType_virtual | infoByteCode[k].physicalType,
843                                                infoByteCode[k].regNum);
844                if(indexT >= 0)
845                    compileTable[indexT].refCount -= infoByteCode[k].refCount;
846            }
847        }
848#endif
849        lastByteCodeIsJump = false;
850        if(!isConst && !isDeadStmt)  //isDeadStmt is false when DSE_OPT is not enabled
851        {
852#ifdef DEBUG_COMPILE_TABLE
853            dumpCompileTable();
854#endif
855            globalShortMap = NULL;
856            if(isCurrentByteCodeJump()) lastByteCodeIsJump = true;
857            //lowerByteCode will call globalVREndOfBB if it is jump
858            int retCode = lowerByteCodeJit(method, rPC, mir);
859            if(gDvmJit.codeCacheByteUsed + (stream - streamStart) +
860                 CODE_CACHE_PADDING > gDvmJit.codeCacheSize) {
861                 ALOGE("JIT code cache full");
862                 gDvmJit.codeCacheFull = true;
863                 return -1;
864            }
865
866            if (retCode == 1) {
867                // We always fall back to the interpreter for OP_INVOKE_OBJECT_INIT_RANGE,
868                // but any other failure is unexpected and should be logged.
869                if (mir->dalvikInsn.opcode != OP_INVOKE_OBJECT_INIT_RANGE) {
870                    ALOGE("JIT couldn't compile %s%s dex_pc=%d opcode=%d",
871                          method->clazz->descriptor,
872                          method->name,
873                          offsetPC,
874                          mir->dalvikInsn.opcode);
875                }
876                return -1;
877            }
878            updateConstInfo(bb);
879            freeShortMap();
880            if(retCode < 0) {
881                ALOGE("error in lowering the bytecode");
882                return retCode;
883            }
884            freeReg(true); //may dump GL VR to memory (this is necessary)
885            //after each bytecode, make sure non-VRs have refCount of zero
886            for(k = 0; k < num_compile_entries; k++) {
887                if(isTemporary(compileTable[k].physicalType, compileTable[k].regNum)) {
888#ifdef PRINT_WARNING
889                    if(compileTable[k].refCount > 0) {
890                        ALOGW("refCount for a temporary reg %d %d is %d after a bytecode", compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].refCount);
891                    }
892#endif
893                    compileTable[k].refCount = 0;
894                }
895            }
896        } else { //isConst || isDeadStmt
897            //if this bytecode is the target of a jump, the mapFromBCtoNCG should be updated
898            offsetNCG = stream - streamMethodStart;
899            mapFromBCtoNCG[offsetPC] = offsetNCG;
900#ifdef DEBUG_COMPILE_TABLE
901            ALOGI("this bytecode generates a constant and has no side effect");
902#endif
903            freeReg(true); //may dump GL VR to memory (this is necessary)
904        }
905#ifdef DEBUG_COMPILE_TABLE
906        ALOGI("after one bytecode BB %d (num of VRs %d)", bb->bb_index, bb->num_regs);
907#endif
908    }//for each bytecode
909#ifdef DEBUG_COMPILE_TABLE
910    dumpCompileTable();
911#endif
912    if(!lastByteCodeIsJump) constVREndOfBB();
913    //at end of a basic block, get spilled GG VR & dump GL VR
914    if(!lastByteCodeIsJump) globalVREndOfBB(method);
915    //remove entries for temporary registers, L VR and GL VR
916    int jj;
917    for(k = 0; k < num_compile_entries; ) {
918        bool removeEntry = false;
919        if(isVirtualReg(compileTable[k].physicalType) && compileTable[k].gType != GLOBALTYPE_GG) {
920            removeEntry = true;
921        }
922        if(isTemporary(compileTable[k].physicalType, compileTable[k].regNum))
923            removeEntry = true;
924        if(removeEntry) {
925#ifdef PRINT_WARNING
926            if(compileTable[k].refCount > 0)
927                ALOGW("refCount for REG %d %d is %d at end of a basic block", compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].refCount);
928#endif
929            compileTable[k].refCount = 0;
930            for(jj = k+1; jj < num_compile_entries; jj++) {
931                compileTable[jj-1] = compileTable[jj];
932            }
933            num_compile_entries--;
934        } else {
935            k++;
936        }
937    }
938    freeReg(true);
939    //free LIVE TABLE
940    for(k = 0; k < num_memory_vr; k++) {
941        LiveRange* ptr2 = memVRTable[k].ranges;
942        while(ptr2 != NULL) {
943            LiveRange* tmpP = ptr2->next;
944            free(ptr2->accessPC);
945            free(ptr2);
946            ptr2 = tmpP;
947        }
948    }
949#ifdef DEBUG_COMPILE_TABLE
950    ALOGI("At end of basic block -------");
951    dumpCompileTable();
952#endif
953    return 0;
954}
955
956/** update infoBasicBlock & defUseTable
957    input: currentInfo
958    side effect: update currentInfo.reachingDefs
959
960    update entries in infoBasicBlock by calling updateReachingDefA
961    if there is no entry in infoBasicBlock for B, an entry will be created and inserted to infoBasicBlock
962
963    defUseTable is updated to account for the access at currentInfo
964    if accessType of B is U or UD, we call updateReachingDefB to update currentInfo.reachingDefs
965        in order to correctly insert the usage to defUseTable
966*/
967int mergeEntry2(BasicBlock_O1* bb) {
968    LowOpndRegType typeB = currentInfo.physicalType;
969    int regB = currentInfo.regNum;
970    int jj, k;
971    int jjend = bb->num_regs;
972    bool isMerged = false;
973    bool hasAlias = false;
974    OverlapCase isBPartiallyOverlapA, isAPartiallyOverlapB;
975    RegAccessType tmpType = REGACCESS_N;
976    currentInfo.num_reaching_defs = 0;
977
978    /* traverse variable A in infoBasicBlock */
979    for(jj = 0; jj < jjend; jj++) {
980        int regA = bb->infoBasicBlock[jj].regNum;
981        LowOpndRegType typeA = bb->infoBasicBlock[jj].physicalType;
982        isBPartiallyOverlapA = getBPartiallyOverlapA(regB, typeB, regA, typeA);
983        isAPartiallyOverlapB = getAPartiallyOverlapB(regA, typeA, regB, typeB);
984        if(regA == regB && typeA == typeB) {
985            /* variable A and B are aligned */
986            bb->infoBasicBlock[jj].accessType = mergeAccess2(bb->infoBasicBlock[jj].accessType, currentInfo.accessType,
987                                                             OVERLAP_B_COVER_A);
988            bb->infoBasicBlock[jj].refCount += currentInfo.refCount;
989            /* copy reaching defs of variable B from variable A */
990            currentInfo.num_reaching_defs = bb->infoBasicBlock[jj].num_reaching_defs;
991            for(k = 0; k < currentInfo.num_reaching_defs; k++)
992                currentInfo.reachingDefs[k] = bb->infoBasicBlock[jj].reachingDefs[k];
993            updateDefUseTable(); //use currentInfo to update defUseTable
994            updateReachingDefA(jj, OVERLAP_B_COVER_A); //update reachingDefs of A
995            isMerged = true;
996            hasAlias = true;
997            if(typeB == LowOpndRegType_gp) {
998                //merge allocConstraints
999                for(k = 0; k < 8; k++) {
1000                    bb->infoBasicBlock[jj].allocConstraints[k].count += currentInfo.allocConstraints[k].count;
1001                }
1002            }
1003        }
1004        else if(isBPartiallyOverlapA != OVERLAP_NO) {
1005            tmpType = updateAccess2(tmpType, updateAccess1(bb->infoBasicBlock[jj].accessType, isAPartiallyOverlapB));
1006            bb->infoBasicBlock[jj].accessType = mergeAccess2(bb->infoBasicBlock[jj].accessType, currentInfo.accessType,
1007                                                             isBPartiallyOverlapA);
1008#ifdef DEBUG_MERGE_ENTRY
1009            ALOGI("update accessType in case 2: VR %d %d accessType %d", regA, typeA, bb->infoBasicBlock[jj].accessType);
1010#endif
1011            hasAlias = true;
1012            if(currentInfo.accessType == REGACCESS_U || currentInfo.accessType == REGACCESS_UD) {
1013                /* update currentInfo.reachingDefs */
1014                updateReachingDefB1(jj);
1015                updateReachingDefB2();
1016            }
1017            updateReachingDefA(jj, isBPartiallyOverlapA);
1018        }
1019        else {
1020            //even if B does not overlap with A, B can affect the reaching defs of A
1021            //for example, B is a def of "v0", A is "v1"
1022            //  B can kill some reaching defs of A or affect the accessType of a reaching def
1023            updateReachingDefA(jj, OVERLAP_NO); //update reachingDefs of A
1024        }
1025    }//for each variable A in infoBasicBlock
1026    if(!isMerged) {
1027        /* create a new entry in infoBasicBlock */
1028        bb->infoBasicBlock[bb->num_regs].refCount = currentInfo.refCount;
1029        bb->infoBasicBlock[bb->num_regs].physicalType = typeB;
1030        if(hasAlias)
1031            bb->infoBasicBlock[bb->num_regs].accessType = updateAccess3(tmpType, currentInfo.accessType);
1032        else
1033            bb->infoBasicBlock[bb->num_regs].accessType = currentInfo.accessType;
1034#ifdef DEBUG_MERGE_ENTRY
1035        ALOGI("update accessType in case 3: VR %d %d accessType %d", regB, typeB, bb->infoBasicBlock[bb->num_regs].accessType);
1036#endif
1037        bb->infoBasicBlock[bb->num_regs].regNum = regB;
1038        for(k = 0; k < 8; k++)
1039            bb->infoBasicBlock[bb->num_regs].allocConstraints[k] = currentInfo.allocConstraints[k];
1040#ifdef DEBUG_MERGE_ENTRY
1041        ALOGI("isMerged is false, call updateDefUseTable");
1042#endif
1043        updateDefUseTable(); //use currentInfo to update defUseTable
1044        updateReachingDefB3(); //update currentInfo.reachingDefs if currentInfo defines variable B
1045
1046        //copy from currentInfo.reachingDefs to bb->infoBasicBlock[bb->num_regs]
1047        bb->infoBasicBlock[bb->num_regs].num_reaching_defs = currentInfo.num_reaching_defs;
1048        for(k = 0; k < currentInfo.num_reaching_defs; k++)
1049            bb->infoBasicBlock[bb->num_regs].reachingDefs[k] = currentInfo.reachingDefs[k];
1050#ifdef DEBUG_MERGE_ENTRY
1051        ALOGI("try to update reaching defs for VR %d %d", regB, typeB);
1052        for(k = 0; k < bb->infoBasicBlock[bb->num_regs].num_reaching_defs; k++)
1053            ALOGI("reaching def %d @ %d for VR %d %d access %d", k, currentInfo.reachingDefs[k].offsetPC,
1054                  currentInfo.reachingDefs[k].regNum, currentInfo.reachingDefs[k].physicalType,
1055                  currentInfo.reachingDefs[k].accessType);
1056#endif
1057        bb->num_regs++;
1058        if(bb->num_regs >= MAX_REG_PER_BASICBLOCK) {
1059            ALOGE("too many VRs in a basic block");
1060            dvmAbort();
1061        }
1062        return -1;
1063    }
1064    return 0;
1065}
1066
1067//!update reaching defs for infoBasicBlock[indexToA]
1068
1069//!use currentInfo.reachingDefs to update reaching defs for variable A
1070void updateReachingDefA(int indexToA, OverlapCase isBPartiallyOverlapA) {
1071    if(indexToA < 0) return;
1072    int k, k2;
1073    OverlapCase isBPartiallyOverlapDef;
1074    if(currentInfo.accessType == REGACCESS_U) {
1075        return; //no update to reachingDefs of the VR
1076    }
1077    /* access in currentInfo is DU, D, or UD */
1078    if(isBPartiallyOverlapA == OVERLAP_B_COVER_A) {
1079        /* from this point on, the reachingDefs for variable A is a single def to currentInfo at offsetPC */
1080        currentBB->infoBasicBlock[indexToA].num_reaching_defs = 1;
1081        currentBB->infoBasicBlock[indexToA].reachingDefs[0].offsetPC = offsetPC;
1082        currentBB->infoBasicBlock[indexToA].reachingDefs[0].regNum = currentInfo.regNum;
1083        currentBB->infoBasicBlock[indexToA].reachingDefs[0].physicalType = currentInfo.physicalType;
1084        currentBB->infoBasicBlock[indexToA].reachingDefs[0].accessType = REGACCESS_D;
1085#ifdef DEBUG_REACHING_DEF
1086        ALOGI("single reaching def @ %d for VR %d %d", offsetPC, currentInfo.regNum, currentInfo.physicalType);
1087#endif
1088        return;
1089    }
1090    /* update reachingDefs for variable A to get rid of dead defs */
1091    /* Bug fix: it is possible that more than one reaching defs need to be removed
1092                after one reaching def is removed, num_reaching_defs--, but k should not change
1093    */
1094    for(k = 0; k < currentBB->infoBasicBlock[indexToA].num_reaching_defs; ) {
1095        /* remove one reaching def in one interation of the loop */
1096        //check overlapping between def & B
1097        isBPartiallyOverlapDef = getBPartiallyOverlapA(currentInfo.regNum, currentInfo.physicalType,
1098                                                       currentBB->infoBasicBlock[indexToA].reachingDefs[k].regNum,
1099                                                       currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType);
1100#ifdef DEBUG_REACHING_DEF
1101        ALOGI("DEBUG B %d %d def %d %d %d", currentInfo.regNum, currentInfo.physicalType,
1102              currentBB->infoBasicBlock[indexToA].reachingDefs[k].regNum,
1103              currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType,
1104              currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType);
1105#endif
1106        /* cases where one def nees to be removed:
1107           if B fully covers def, def is removed
1108           if B overlaps high half of def & def's accessType is H, def is removed
1109           if B overlaps low half of def & def's accessType is L, def is removed
1110        */
1111        if((isBPartiallyOverlapDef == OVERLAP_B_COVER_HIGH_OF_A &&
1112            currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType == REGACCESS_H) ||
1113           (isBPartiallyOverlapDef == OVERLAP_B_COVER_LOW_OF_A &&
1114            currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType == REGACCESS_L) ||
1115           isBPartiallyOverlapDef == OVERLAP_B_COVER_A
1116           ) { //remove def
1117            //shift from k+1 to end
1118            for(k2 = k+1; k2 < currentBB->infoBasicBlock[indexToA].num_reaching_defs; k2++)
1119                currentBB->infoBasicBlock[indexToA].reachingDefs[k2-1] = currentBB->infoBasicBlock[indexToA].reachingDefs[k2];
1120            currentBB->infoBasicBlock[indexToA].num_reaching_defs--;
1121        }
1122        /*
1123           if B overlaps high half of def & def's accessType is not H --> update accessType of def
1124        */
1125        else if(isBPartiallyOverlapDef == OVERLAP_B_COVER_HIGH_OF_A &&
1126                currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType != REGACCESS_H) {
1127            //low half is still valid
1128            if(getRegSize(currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType) == OpndSize_32)
1129                currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType = REGACCESS_D;
1130            else
1131                currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType = REGACCESS_L;
1132#ifdef DEBUG_REACHING_DEF
1133            ALOGI("DEBUG: set accessType of def to L");
1134#endif
1135            k++;
1136        }
1137        /*
1138           if B overlaps low half of def & def's accessType is not L --> update accessType of def
1139        */
1140        else if(isBPartiallyOverlapDef == OVERLAP_B_COVER_LOW_OF_A &&
1141                currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType != REGACCESS_L) {
1142            //high half of def is still valid
1143            currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType = REGACCESS_H;
1144#ifdef DEBUG_REACHING_DEF
1145            ALOGI("DEBUG: set accessType of def to H");
1146#endif
1147            k++;
1148        }
1149        else {
1150            k++;
1151        }
1152    }//for k
1153    if(isBPartiallyOverlapA != OVERLAP_NO) {
1154        //insert the def to variable @ currentInfo
1155        k = currentBB->infoBasicBlock[indexToA].num_reaching_defs;
1156        if(k >= 3) {
1157          ALOGE("more than 3 reaching defs");
1158        }
1159        currentBB->infoBasicBlock[indexToA].reachingDefs[k].offsetPC = offsetPC;
1160        currentBB->infoBasicBlock[indexToA].reachingDefs[k].regNum = currentInfo.regNum;
1161        currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType = currentInfo.physicalType;
1162        currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType = REGACCESS_D;
1163        currentBB->infoBasicBlock[indexToA].num_reaching_defs++;
1164    }
1165#ifdef DEBUG_REACHING_DEF2
1166    ALOGI("IN updateReachingDefA for VR %d %d", currentBB->infoBasicBlock[indexToA].regNum,
1167          currentBB->infoBasicBlock[indexToA].physicalType);
1168    for(k = 0; k < currentBB->infoBasicBlock[indexToA].num_reaching_defs; k++)
1169        ALOGI("reaching def %d @ %d for VR %d %d access %d", k,
1170              currentBB->infoBasicBlock[indexToA].reachingDefs[k].offsetPC,
1171              currentBB->infoBasicBlock[indexToA].reachingDefs[k].regNum,
1172              currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType,
1173              currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType);
1174#endif
1175}
1176
1177/** Given a variable B @currentInfo,
1178    updates its reaching defs by checking reaching defs of variable A @currentBB->infoBasicBlock[indexToA]
1179    The result is stored in tmpInfo.reachingDefs
1180*/
1181void updateReachingDefB1(int indexToA) {
1182    if(indexToA < 0) return;
1183    int k;
1184    tmpInfo.num_reaching_defs = 0;
1185    for(k = 0; k < currentBB->infoBasicBlock[indexToA].num_reaching_defs; k++) {
1186        /* go through reachingDefs of variable A @currentBB->infoBasicBlock[indexToA]
1187           for each def, check whether it overlaps with variable B @currentInfo
1188               if the def overlaps with variable B, insert it to tmpInfo.reachingDefs
1189        */
1190        OverlapCase isDefPartiallyOverlapB = getAPartiallyOverlapB(
1191                                                 currentBB->infoBasicBlock[indexToA].reachingDefs[k].regNum,
1192                                                 currentBB->infoBasicBlock[indexToA].reachingDefs[k].physicalType,
1193                                                 currentInfo.regNum, currentInfo.physicalType
1194                                                 );
1195        bool insert1 = false; //whether to insert the def to tmpInfo.reachingDefs
1196        if(isDefPartiallyOverlapB == OVERLAP_ALIGN ||
1197           isDefPartiallyOverlapB == OVERLAP_A_IS_LOW_OF_B ||
1198           isDefPartiallyOverlapB == OVERLAP_A_IS_HIGH_OF_B) {
1199            /* B aligns with def */
1200            /* def is low half of B, def is high half of B
1201               in these two cases, def is 32 bits */
1202            insert1 = true;
1203        }
1204        RegAccessType deftype = currentBB->infoBasicBlock[indexToA].reachingDefs[k].accessType;
1205        if(isDefPartiallyOverlapB == OVERLAP_B_IS_LOW_OF_A ||
1206           isDefPartiallyOverlapB == OVERLAP_LOW_OF_A_IS_HIGH_OF_B) {
1207            /* B is the low half of def */
1208            /* the low half of def is the high half of B */
1209            if(deftype != REGACCESS_H) insert1 = true;
1210        }
1211        if(isDefPartiallyOverlapB == OVERLAP_B_IS_HIGH_OF_A ||
1212           isDefPartiallyOverlapB == OVERLAP_HIGH_OF_A_IS_LOW_OF_B) {
1213            /* B is the high half of def */
1214            /* the high half of def is the low half of B */
1215            if(deftype != REGACCESS_L) insert1 = true;
1216        }
1217        if(insert1) {
1218            if(tmpInfo.num_reaching_defs >= 3) {
1219                ALOGE("more than 3 reaching defs for tmpInfo");
1220            }
1221            tmpInfo.reachingDefs[tmpInfo.num_reaching_defs] = currentBB->infoBasicBlock[indexToA].reachingDefs[k];
1222            tmpInfo.num_reaching_defs++;
1223#ifdef DEBUG_REACHING_DEF2
1224            ALOGI("insert from entry %d %d: index %d", currentBB->infoBasicBlock[indexToA].regNum,
1225                  currentBB->infoBasicBlock[indexToA].physicalType, k);
1226#endif
1227        }
1228    }
1229}
1230
1231/** update currentInfo.reachingDefs by merging currentInfo.reachingDefs with tmpInfo.reachingDefs
1232*/
1233void updateReachingDefB2() {
1234    int k, k2;
1235    for(k2 = 0; k2 < tmpInfo.num_reaching_defs; k2++ ) {
1236        bool merged = false;
1237        for(k = 0; k < currentInfo.num_reaching_defs; k++) {
1238            /* check whether it is the same def, if yes, do nothing */
1239            if(currentInfo.reachingDefs[k].regNum == tmpInfo.reachingDefs[k2].regNum &&
1240               currentInfo.reachingDefs[k].physicalType == tmpInfo.reachingDefs[k2].physicalType) {
1241                merged = true;
1242                if(currentInfo.reachingDefs[k].offsetPC != tmpInfo.reachingDefs[k2].offsetPC) {
1243                    ALOGE("defs on the same VR %d %d with different offsetPC %d vs %d",
1244                          currentInfo.reachingDefs[k].regNum, currentInfo.reachingDefs[k].physicalType,
1245                          currentInfo.reachingDefs[k].offsetPC, tmpInfo.reachingDefs[k2].offsetPC);
1246                }
1247                if(currentInfo.reachingDefs[k].accessType != tmpInfo.reachingDefs[k2].accessType)
1248                    ALOGE("defs on the same VR %d %d with different accessType",
1249                          currentInfo.reachingDefs[k].regNum, currentInfo.reachingDefs[k].physicalType);
1250                break;
1251            }
1252        }
1253        if(!merged) {
1254            if(currentInfo.num_reaching_defs >= 3) {
1255               ALOGE("more than 3 reaching defs for currentInfo");
1256            }
1257            currentInfo.reachingDefs[currentInfo.num_reaching_defs] = tmpInfo.reachingDefs[k2];
1258            currentInfo.num_reaching_defs++;
1259        }
1260    }
1261}
1262
1263//!update currentInfo.reachingDefs with currentInfo if variable is defined in currentInfo
1264
1265//!
1266void updateReachingDefB3() {
1267    if(currentInfo.accessType == REGACCESS_U) {
1268        return; //no need to update currentInfo.reachingDefs
1269    }
1270    currentInfo.num_reaching_defs = 1;
1271    currentInfo.reachingDefs[0].regNum = currentInfo.regNum;
1272    currentInfo.reachingDefs[0].physicalType = currentInfo.physicalType;
1273    currentInfo.reachingDefs[0].offsetPC = offsetPC;
1274    currentInfo.reachingDefs[0].accessType = REGACCESS_D;
1275}
1276
1277/** update defUseTable by checking currentInfo
1278*/
1279void updateDefUseTable() {
1280    /* no access */
1281    if(currentInfo.accessType == REGACCESS_N) return;
1282    /* define then use, or define only */
1283    if(currentInfo.accessType == REGACCESS_DU || currentInfo.accessType == REGACCESS_D) {
1284        /* insert a definition at offsetPC to variable @ currentInfo */
1285        DefUsePair* ptr = insertADef(offsetPC, currentInfo.regNum, currentInfo.physicalType, REGACCESS_D);
1286        if(currentInfo.accessType != REGACCESS_D) {
1287             /* if access is define then use, insert a use at offsetPC */
1288            insertAUse(ptr, offsetPC, currentInfo.regNum, currentInfo.physicalType);
1289        }
1290        return;
1291    }
1292    /* use only or use then define
1293       check the reaching defs for the usage */
1294    int k;
1295    bool isLCovered = false, isHCovered = false, isDCovered = false;
1296    for(k = 0; k < currentInfo.num_reaching_defs; k++) {
1297        /* insert a def currentInfo.reachingDefs[k] and a use of variable at offsetPC */
1298        RegAccessType useType = insertDefUsePair(k);
1299        if(useType == REGACCESS_D) isDCovered = true;
1300        if(useType == REGACCESS_L) isLCovered = true;
1301        if(useType == REGACCESS_H) isHCovered = true;
1302    }
1303    OpndSize useSize = getRegSize(currentInfo.physicalType);
1304    if((!isDCovered) && (!isLCovered)) {
1305        /* the low half of variable is not defined in the basic block
1306           so insert a def to the low half at START of the basic block */
1307        insertDefUsePair(-1);
1308    }
1309    if(useSize == OpndSize_64 && (!isDCovered) && (!isHCovered)) {
1310        /* the high half of variable is not defined in the basic block
1311           so insert a def to the high half at START of the basic block */
1312        insertDefUsePair(-2);
1313    }
1314    if(currentInfo.accessType == REGACCESS_UD) {
1315        /* insert a def at offsetPC to variable @ currentInfo */
1316        insertADef(offsetPC, currentInfo.regNum, currentInfo.physicalType, REGACCESS_D);
1317        return;
1318    }
1319}
1320
1321//! insert a use at offsetPC of given variable at end of DefUsePair
1322
1323//!
1324RegAccessType insertAUse(DefUsePair* ptr, int offsetPC, int regNum, LowOpndRegType physicalType) {
1325    DefOrUseLink* tLink = (DefOrUseLink*)malloc(sizeof(DefOrUseLink));
1326    if(tLink == NULL) {
1327        ALOGE("Memory allocation failed");
1328        return REGACCESS_UNKNOWN;
1329    }
1330    tLink->offsetPC = offsetPC;
1331    tLink->regNum = regNum;
1332    tLink->physicalType = physicalType;
1333    tLink->next = NULL;
1334    if(ptr->useTail != NULL)
1335        ptr->useTail->next = tLink;
1336    ptr->useTail = tLink;
1337    if(ptr->uses == NULL)
1338        ptr->uses = tLink;
1339    ptr->num_uses++;
1340
1341    //check whether the def is partially overlapping with the variable
1342    OverlapCase isDefPartiallyOverlapB = getBPartiallyOverlapA(ptr->def.regNum,
1343                                                       ptr->def.physicalType,
1344                                                       regNum, physicalType);
1345    RegAccessType useType = setAccessTypeOfUse(isDefPartiallyOverlapB, ptr->def.accessType);
1346    tLink->accessType = useType;
1347    return useType;
1348}
1349
1350//! insert a def to currentBB->defUseTable
1351
1352//! update currentBB->defUseTail if necessary
1353DefUsePair* insertADef(int offsetPC, int regNum, LowOpndRegType pType, RegAccessType rType) {
1354    DefUsePair* ptr = (DefUsePair*)malloc(sizeof(DefUsePair));
1355    if(ptr == NULL) {
1356        ALOGE("Memory allocation failed");
1357        return NULL;
1358    }
1359    ptr->next = NULL;
1360    ptr->def.offsetPC = offsetPC;
1361    ptr->def.regNum = regNum;
1362    ptr->def.physicalType = pType;
1363    ptr->def.accessType = rType;
1364    ptr->num_uses = 0;
1365    ptr->useTail = NULL;
1366    ptr->uses = NULL;
1367    if(currentBB->defUseTail != NULL) {
1368        currentBB->defUseTail->next = ptr;
1369    }
1370    currentBB->defUseTail = ptr;
1371    if(currentBB->defUseTable == NULL)
1372        currentBB->defUseTable = ptr;
1373    currentBB->num_defs++;
1374#ifdef DEBUG_REACHING_DEF
1375    ALOGI("insert a def at %d to defUseTable for VR %d %d", offsetPC,
1376          regNum, pType);
1377#endif
1378    return ptr;
1379}
1380
1381/** insert a def to defUseTable, then insert a use of variable @ currentInfo
1382    if reachingDefIndex >= 0, the def is currentInfo.reachingDefs[index]
1383    if reachingDefIndex is -1, the low half is defined at START of the basic block
1384    if reachingDefIndex is -2, the high half is defined at START of the basic block
1385*/
1386RegAccessType insertDefUsePair(int reachingDefIndex) {
1387    int k = reachingDefIndex;
1388    DefUsePair* tableIndex = NULL;
1389    DefOrUse theDef;
1390    theDef.regNum = 0;
1391    if(k < 0) {
1392        /* def at start of the basic blcok */
1393        theDef.offsetPC = PC_FOR_START_OF_BB;
1394        theDef.accessType = REGACCESS_D;
1395        if(k == -1) //low half of variable
1396            theDef.regNum = currentInfo.regNum;
1397        if(k == -2) //high half of variable
1398            theDef.regNum = currentInfo.regNum+1;
1399        theDef.physicalType = LowOpndRegType_gp;
1400    }
1401    else {
1402        theDef = currentInfo.reachingDefs[k];
1403    }
1404    tableIndex = searchDefUseTable(theDef.offsetPC, theDef.regNum, theDef.physicalType);
1405    if(tableIndex == NULL) //insert an entry
1406        tableIndex = insertADef(theDef.offsetPC, theDef.regNum, theDef.physicalType, theDef.accessType);
1407    else
1408        tableIndex->def.accessType = theDef.accessType;
1409    RegAccessType useType = insertAUse(tableIndex, offsetPC, currentInfo.regNum, currentInfo.physicalType);
1410    return useType;
1411}
1412
1413//! insert a XFER_MEM_TO_XMM to currentBB->xferPoints
1414
1415//!
1416void insertLoadXfer(int offset, int regNum, LowOpndRegType pType) {
1417    //check whether it is already in currentBB->xferPoints
1418    int k;
1419    for(k = 0; k < currentBB->num_xfer_points; k++) {
1420        if(currentBB->xferPoints[k].xtype == XFER_MEM_TO_XMM &&
1421           currentBB->xferPoints[k].offsetPC == offset &&
1422           currentBB->xferPoints[k].regNum == regNum &&
1423           currentBB->xferPoints[k].physicalType == pType)
1424            return;
1425    }
1426    currentBB->xferPoints[currentBB->num_xfer_points].xtype = XFER_MEM_TO_XMM;
1427    currentBB->xferPoints[currentBB->num_xfer_points].regNum = regNum;
1428    currentBB->xferPoints[currentBB->num_xfer_points].offsetPC = offset;
1429    currentBB->xferPoints[currentBB->num_xfer_points].physicalType = pType;
1430#ifdef DEBUG_XFER_POINTS
1431    ALOGI("insert to xferPoints %d: XFER_MEM_TO_XMM of VR %d %d at %d", currentBB->num_xfer_points, regNum, pType, offset);
1432#endif
1433    currentBB->num_xfer_points++;
1434    if(currentBB->num_xfer_points >= MAX_XFER_PER_BB) {
1435        ALOGE("too many xfer points");
1436        dvmAbort();
1437    }
1438}
1439
1440/** update defUseTable by assuming a fake usage at END of a basic block for variable @ currentInfo
1441    create a fake usage at end of a basic block for variable B (currentInfo.physicalType, currentInfo.regNum)
1442    get reaching def info for variable B and store the info in currentInfo.reachingDefs
1443        for each virtual register (variable A) accessed in the basic block
1444            update reaching defs of B by checking reaching defs of variable A
1445    update defUseTable
1446*/
1447int fakeUsageAtEndOfBB(BasicBlock_O1* bb) {
1448    currentInfo.accessType = REGACCESS_U;
1449    LowOpndRegType typeB = currentInfo.physicalType;
1450    int regB = currentInfo.regNum;
1451    int jj, k;
1452    currentInfo.num_reaching_defs = 0;
1453    for(jj = 0; jj < bb->num_regs; jj++) {
1454        int regA = bb->infoBasicBlock[jj].regNum;
1455        LowOpndRegType typeA = bb->infoBasicBlock[jj].physicalType;
1456        OverlapCase isBPartiallyOverlapA = getBPartiallyOverlapA(regB, typeB, regA, typeA);
1457        if(regA == regB && typeA == typeB) {
1458            /* copy reachingDefs from variable A */
1459            currentInfo.num_reaching_defs = bb->infoBasicBlock[jj].num_reaching_defs;
1460            for(k = 0; k < currentInfo.num_reaching_defs; k++)
1461                currentInfo.reachingDefs[k] = bb->infoBasicBlock[jj].reachingDefs[k];
1462            break;
1463        }
1464        else if(isBPartiallyOverlapA != OVERLAP_NO) {
1465            /* B overlaps with A */
1466            /* update reaching defs of variable B by checking reaching defs of bb->infoBasicBlock[jj] */
1467            updateReachingDefB1(jj);
1468            updateReachingDefB2(); //merge currentInfo with tmpInfo
1469        }
1470    }
1471    /* update defUseTable by checking currentInfo */
1472    updateDefUseTable();
1473    return 0;
1474}
1475
1476/** update xferPoints of currentBB
1477    Traverse currentBB->defUseTable
1478*/
1479int updateXferPoints() {
1480    int k = 0;
1481    currentBB->num_xfer_points = 0;
1482    DefUsePair* ptr = currentBB->defUseTable;
1483    DefOrUseLink* ptrUse = NULL;
1484    /* traverse the def use chain of the basic block */
1485    while(ptr != NULL) {
1486        LowOpndRegType defType = ptr->def.physicalType;
1487        //if definition is for a variable of 32 bits
1488        if(getRegSize(defType) == OpndSize_32) {
1489            /* check usages of the definition, whether it reaches a GPR, a XMM, a FS, or a SS */
1490            bool hasGpUsage = false;
1491            bool hasGpUsage2 = false; //not a fake usage
1492            bool hasXmmUsage = false;
1493            bool hasFSUsage = false;
1494            bool hasSSUsage = false;
1495            ptrUse = ptr->uses;
1496            while(ptrUse != NULL) {
1497                if(ptrUse->physicalType == LowOpndRegType_gp) {
1498                    hasGpUsage = true;
1499                    if(ptrUse->offsetPC != PC_FOR_END_OF_BB)
1500                        hasGpUsage2 = true;
1501                }
1502                if(ptrUse->physicalType == LowOpndRegType_ss) hasSSUsage = true;
1503                if(ptrUse->physicalType == LowOpndRegType_fs ||
1504                   ptrUse->physicalType == LowOpndRegType_fs_s)
1505                    hasFSUsage = true;
1506                if(ptrUse->physicalType == LowOpndRegType_xmm) {
1507                    hasXmmUsage = true;
1508                }
1509                if(ptrUse->physicalType == LowOpndRegType_xmm ||
1510                   ptrUse->physicalType == LowOpndRegType_ss) {
1511                    /* if a 32-bit definition reaches a xmm usage or a SS usage,
1512                       insert a XFER_MEM_TO_XMM */
1513                    insertLoadXfer(ptrUse->offsetPC,
1514                                   ptrUse->regNum, LowOpndRegType_xmm);
1515                }
1516                ptrUse = ptrUse->next;
1517            }
1518            if(((hasXmmUsage || hasFSUsage || hasSSUsage) && defType == LowOpndRegType_gp) ||
1519               (hasGpUsage && defType == LowOpndRegType_fs) ||
1520               (defType == LowOpndRegType_ss && (hasGpUsage || hasXmmUsage || hasFSUsage))) {
1521                /* insert a transfer if def is on a GPR, usage is on a XMM, FS or SS
1522                                     if def is on a FS, usage is on a GPR
1523                                     if def is on a SS, usage is on a GPR, XMM or FS
1524                   transfer type is XFER_DEF_TO_GP_MEM if a real GPR usage exisits
1525                   transfer type is XFER_DEF_TO_GP otherwise*/
1526                currentBB->xferPoints[currentBB->num_xfer_points].offsetPC = ptr->def.offsetPC;
1527                currentBB->xferPoints[currentBB->num_xfer_points].regNum = ptr->def.regNum;
1528                currentBB->xferPoints[currentBB->num_xfer_points].physicalType = ptr->def.physicalType;
1529                if(hasGpUsage2) { //create an entry XFER_DEF_TO_GP_MEM
1530                    currentBB->xferPoints[currentBB->num_xfer_points].xtype = XFER_DEF_TO_GP_MEM;
1531                }
1532                else { //create an entry XFER_DEF_TO_MEM
1533                    currentBB->xferPoints[currentBB->num_xfer_points].xtype = XFER_DEF_TO_MEM;
1534                }
1535                currentBB->xferPoints[currentBB->num_xfer_points].tableIndex = k;
1536#ifdef DEBUG_XFER_POINTS
1537                ALOGI("insert XFER %d at def %d: V%d %d", currentBB->num_xfer_points, ptr->def.offsetPC, ptr->def.regNum, defType);
1538#endif
1539                currentBB->num_xfer_points++;
1540                if(currentBB->num_xfer_points >= MAX_XFER_PER_BB) {
1541                    ALOGE("too many xfer points");
1542                    dvmAbort();
1543                }
1544            }
1545        }
1546        else { /* def is on 64 bits */
1547            bool hasGpUsageOfL = false; //exist a GPR usage of the low half
1548            bool hasGpUsageOfH = false; //exist a GPR usage of the high half
1549            bool hasGpUsageOfL2 = false;
1550            bool hasGpUsageOfH2 = false;
1551            bool hasMisaligned = false;
1552            bool hasAligned = false;
1553            bool hasFSUsage = false;
1554            bool hasSSUsage = false;
1555            ptrUse = ptr->uses;
1556            while(ptrUse != NULL) {
1557                if(ptrUse->physicalType == LowOpndRegType_gp &&
1558                   ptrUse->regNum == ptr->def.regNum) {
1559                    hasGpUsageOfL = true;
1560                    if(ptrUse->offsetPC != PC_FOR_END_OF_BB)
1561                        hasGpUsageOfL2 = true;
1562                }
1563                if(ptrUse->physicalType == LowOpndRegType_gp &&
1564                   ptrUse->regNum == ptr->def.regNum + 1) {
1565                    hasGpUsageOfH = true;
1566                    if(ptrUse->offsetPC != PC_FOR_END_OF_BB)
1567                        hasGpUsageOfH2 = true;
1568                }
1569                if(ptrUse->physicalType == LowOpndRegType_xmm &&
1570                   ptrUse->regNum == ptr->def.regNum) {
1571                    hasAligned = true;
1572                    /* if def is on FS and use is on XMM, insert a XFER_MEM_TO_XMM */
1573                    if(defType == LowOpndRegType_fs)
1574                        insertLoadXfer(ptrUse->offsetPC,
1575                                       ptrUse->regNum, LowOpndRegType_xmm);
1576                }
1577                if(ptrUse->physicalType == LowOpndRegType_fs ||
1578                   ptrUse->physicalType == LowOpndRegType_fs_s)
1579                    hasFSUsage = true;
1580                if(ptrUse->physicalType == LowOpndRegType_xmm &&
1581                   ptrUse->regNum != ptr->def.regNum) {
1582                    hasMisaligned = true;
1583                    /* if use is on XMM and use and def are misaligned, insert a XFER_MEM_TO_XMM */
1584                    insertLoadXfer(ptrUse->offsetPC,
1585                                   ptrUse->regNum, LowOpndRegType_xmm);
1586                }
1587                if(ptrUse->physicalType == LowOpndRegType_ss) {
1588                    hasSSUsage = true;
1589                    /* if use is on SS, insert a XFER_MEM_TO_XMM */
1590                    insertLoadXfer(ptrUse->offsetPC,
1591                                   ptrUse->regNum, LowOpndRegType_ss);
1592                }
1593                ptrUse = ptrUse->next;
1594            }
1595            if(defType == LowOpndRegType_fs && !hasGpUsageOfL && !hasGpUsageOfH) {
1596                ptr = ptr->next;
1597                continue;
1598            }
1599            if(defType == LowOpndRegType_xmm && !hasFSUsage &&
1600               !hasGpUsageOfL && !hasGpUsageOfH && !hasMisaligned && !hasSSUsage) {
1601                ptr = ptr->next;
1602                continue;
1603            }
1604            /* insert a XFER_DEF_IS_XMM */
1605            currentBB->xferPoints[currentBB->num_xfer_points].regNum = ptr->def.regNum;
1606            currentBB->xferPoints[currentBB->num_xfer_points].offsetPC = ptr->def.offsetPC;
1607            currentBB->xferPoints[currentBB->num_xfer_points].physicalType = ptr->def.physicalType;
1608            currentBB->xferPoints[currentBB->num_xfer_points].xtype = XFER_DEF_IS_XMM;
1609            currentBB->xferPoints[currentBB->num_xfer_points].vr_gpl = -1;
1610            currentBB->xferPoints[currentBB->num_xfer_points].vr_gph = -1;
1611            if(hasGpUsageOfL2) currentBB->xferPoints[currentBB->num_xfer_points].vr_gpl = ptr->def.regNum;
1612            if(hasGpUsageOfH2) currentBB->xferPoints[currentBB->num_xfer_points].vr_gph = ptr->def.regNum+1;
1613            currentBB->xferPoints[currentBB->num_xfer_points].dumpToMem = true;
1614            currentBB->xferPoints[currentBB->num_xfer_points].dumpToXmm = false; //not used in updateVirtualReg
1615            if(hasAligned) currentBB->xferPoints[currentBB->num_xfer_points].dumpToXmm = true;
1616            currentBB->xferPoints[currentBB->num_xfer_points].tableIndex = k;
1617#ifdef DEBUG_XFER_POINTS
1618            ALOGI("insert XFER %d at def %d: V%d %d", currentBB->num_xfer_points, ptr->def.offsetPC, ptr->def.regNum, defType);
1619#endif
1620            currentBB->num_xfer_points++;
1621            if(currentBB->num_xfer_points >= MAX_XFER_PER_BB) {
1622                ALOGE("too many xfer points");
1623                dvmAbort();
1624            }
1625        }
1626        ptr = ptr->next;
1627    } //while ptr
1628#ifdef DEBUG_XFER_POINTS
1629    ALOGI("XFER points for current basic block ------");
1630    for(k = 0; k < currentBB->num_xfer_points; k++) {
1631        ALOGI("  at offset %x, VR %d %d: type %d, vr_gpl %d, vr_gph %d, dumpToMem %d, dumpToXmm %d",
1632              currentBB->xferPoints[k].offsetPC, currentBB->xferPoints[k].regNum,
1633              currentBB->xferPoints[k].physicalType, currentBB->xferPoints[k].xtype,
1634              currentBB->xferPoints[k].vr_gpl, currentBB->xferPoints[k].vr_gph,
1635              currentBB->xferPoints[k].dumpToMem, currentBB->xferPoints[k].dumpToXmm);
1636    }
1637#endif
1638    return -1;
1639}
1640
1641//! update memVRTable[].ranges by browsing the defUseTable
1642
1643//! each virtual register has a list of live ranges, and each live range has a list of PCs that access the VR
1644void updateLiveTable() {
1645    DefUsePair* ptr = currentBB->defUseTable;
1646    while(ptr != NULL) {
1647        bool updateUse = false;
1648        if(ptr->num_uses == 0) {
1649            ptr->num_uses = 1;
1650            ptr->uses = (DefOrUseLink*)malloc(sizeof(DefOrUseLink));
1651            if(ptr->uses == NULL) {
1652                ALOGE("Memory allocation failed");
1653                return;
1654            }
1655            ptr->uses->accessType = REGACCESS_D;
1656            ptr->uses->regNum = ptr->def.regNum;
1657            ptr->uses->offsetPC = ptr->def.offsetPC;
1658            ptr->uses->physicalType = ptr->def.physicalType;
1659            ptr->uses->next = NULL;
1660            ptr->useTail = ptr->uses;
1661            updateUse = true;
1662        }
1663        DefOrUseLink* ptrUse = ptr->uses;
1664        while(ptrUse != NULL) {
1665            RegAccessType useType = ptrUse->accessType;
1666            if(useType == REGACCESS_L || useType == REGACCESS_D) {
1667                int indexL = searchMemTable(ptrUse->regNum);
1668                if(indexL >= 0)
1669                    mergeLiveRange(indexL, ptr->def.offsetPC,
1670                                   ptrUse->offsetPC); //tableIndex, start PC, end PC
1671            }
1672            if(getRegSize(ptrUse->physicalType) == OpndSize_64 &&
1673               (useType == REGACCESS_H || useType == REGACCESS_D)) {
1674                int indexH = searchMemTable(ptrUse->regNum+1);
1675                if(indexH >= 0)
1676                    mergeLiveRange(indexH, ptr->def.offsetPC,
1677                                   ptrUse->offsetPC);
1678            }
1679            ptrUse = ptrUse->next;
1680        }//while ptrUse
1681        if(updateUse) {
1682            ptr->num_uses = 0;
1683            free(ptr->uses);
1684            ptr->uses = NULL;
1685            ptr->useTail = NULL;
1686        }
1687        ptr = ptr->next;
1688    }//while ptr
1689#ifdef DEBUG_LIVE_RANGE
1690    ALOGI("LIVE TABLE");
1691    for(int k = 0; k < num_memory_vr; k++) {
1692        ALOGI("VR %d live ", memVRTable[k].regNum);
1693        LiveRange* ptr = memVRTable[k].ranges;
1694        while(ptr != NULL) {
1695            ALOGI("[%x %x] (", ptr->start, ptr->end);
1696            for(int k3 = 0; k3 < ptr->num_access; k3++)
1697                ALOGI("%x ", ptr->accessPC[k3]);
1698            ALOGI(") ");
1699            ptr = ptr->next;
1700        }
1701        ALOGI("");
1702    }
1703#endif
1704}
1705
1706//!add a live range [rangeStart, rangeEnd] to ranges of memVRTable, merge to existing live ranges if necessary
1707
1708//!ranges are in increasing order of startPC
1709void mergeLiveRange(int tableIndex, int rangeStart, int rangeEnd) {
1710    if(rangeStart == PC_FOR_START_OF_BB) rangeStart = currentBB->pc_start;
1711    if(rangeEnd == PC_FOR_END_OF_BB) rangeEnd = currentBB->pc_end;
1712#ifdef DEBUG_LIVE_RANGE
1713    ALOGI("LIVERANGE call mergeLiveRange on tableIndex %d with [%x %x]", tableIndex, rangeStart, rangeEnd);
1714#endif
1715    int startIndex = -1, endIndex = -1;
1716    bool startBeforeRange = false, endBeforeRange = false; //before the index or in the range
1717    bool startDone = false, endDone = false;
1718    LiveRange* ptr = memVRTable[tableIndex].ranges;
1719    LiveRange* ptrStart = NULL;
1720    LiveRange* ptrStart_prev = NULL;
1721    LiveRange* ptrEnd = NULL;
1722    LiveRange* ptrEnd_prev = NULL;
1723    int k = 0;
1724    while(ptr != NULL) {
1725        if(!startDone) {
1726            if(ptr->start <= rangeStart &&
1727               ptr->end >= rangeStart) {
1728                startIndex = k;
1729                ptrStart = ptr;
1730                startBeforeRange = false;
1731                startDone = true;
1732            }
1733            else if(ptr->start > rangeStart) {
1734                startIndex = k;
1735                ptrStart = ptr;
1736                startBeforeRange = true;
1737                startDone = true;
1738            }
1739        }
1740        if(!startDone) ptrStart_prev = ptr;
1741        if(!endDone) {
1742            if(ptr->start <= rangeEnd &&
1743               ptr->end >= rangeEnd) {
1744                endIndex = k;
1745                ptrEnd = ptr;
1746                endBeforeRange = false;
1747                endDone = true;
1748            }
1749            else if(ptr->start > rangeEnd) {
1750                endIndex = k;
1751                ptrEnd = ptr;
1752                endBeforeRange = true;
1753                endDone = true;
1754            }
1755        }
1756        if(!endDone) ptrEnd_prev = ptr;
1757        ptr = ptr->next;
1758        k++;
1759    } //while
1760    if(!startDone) { //both can be NULL
1761        startIndex = memVRTable[tableIndex].num_ranges;
1762        ptrStart = NULL; //ptrStart_prev should be the last live range
1763        startBeforeRange = true;
1764    }
1765    //if endDone, ptrEnd is not NULL, ptrEnd_prev can be NULL
1766    if(!endDone) { //both can be NULL
1767        endIndex = memVRTable[tableIndex].num_ranges;
1768        ptrEnd = NULL;
1769        endBeforeRange = true;
1770    }
1771    if(startIndex == endIndex && startBeforeRange && endBeforeRange) { //insert at startIndex
1772        //3 cases depending on BeforeRange when startIndex == endIndex
1773        //insert only if both true
1774        //merge otherwise
1775        /////////// insert before ptrStart
1776        LiveRange* currRange = (LiveRange *)malloc(sizeof(LiveRange));
1777        if(ptrStart_prev == NULL) {
1778            currRange->next = memVRTable[tableIndex].ranges;
1779            memVRTable[tableIndex].ranges = currRange;
1780        } else {
1781            currRange->next = ptrStart_prev->next;
1782            ptrStart_prev->next = currRange;
1783        }
1784        currRange->start = rangeStart;
1785        currRange->end = rangeEnd;
1786        currRange->accessPC = (int *)malloc(sizeof(int) * NUM_ACCESS_IN_LIVERANGE);
1787        currRange->num_alloc = NUM_ACCESS_IN_LIVERANGE;
1788        if(rangeStart != rangeEnd) {
1789            currRange->num_access = 2;
1790            currRange->accessPC[0] = rangeStart;
1791            currRange->accessPC[1] = rangeEnd;
1792        } else {
1793            currRange->num_access = 1;
1794            currRange->accessPC[0] = rangeStart;
1795        }
1796        memVRTable[tableIndex].num_ranges++;
1797#ifdef DEBUG_LIVE_RANGE
1798        ALOGI("LIVERANGE insert one live range [%x %x] to tableIndex %d", rangeStart, rangeEnd, tableIndex);
1799#endif
1800        return;
1801    }
1802    if(!endBeforeRange) { //here ptrEnd is not NULL
1803        endIndex++; //next
1804        ptrEnd_prev = ptrEnd; //ptrEnd_prev is not NULL
1805        ptrEnd = ptrEnd->next; //ptrEnd can be NULL
1806    }
1807    if(endIndex < startIndex+1) ALOGE("mergeLiveRange endIndex %d startIndex %d", endIndex, startIndex);
1808    ///////// use ptrStart & ptrEnd_prev
1809    if(ptrStart == NULL || ptrEnd_prev == NULL) {
1810        ALOGE("mergeLiveRange ptr is NULL");
1811        return;
1812    }
1813    //endIndex > startIndex (merge the ranges between startIndex and endIndex-1)
1814    //update ptrStart
1815    if(ptrStart->start > rangeStart)
1816        ptrStart->start = rangeStart; //min of old start & rangeStart
1817    ptrStart->end = ptrEnd_prev->end; //max of old end & rangeEnd
1818    if(rangeEnd > ptrStart->end)
1819        ptrStart->end = rangeEnd;
1820#ifdef DEBUG_LIVE_RANGE
1821    ALOGI("LIVERANGE merge entries for tableIndex %d from %d to %d", tableIndex, startIndex+1, endIndex-1);
1822#endif
1823    if(ptrStart->num_access <= 0) ALOGE("mergeLiveRange number of access");
1824#ifdef DEBUG_LIVE_RANGE
1825    ALOGI("LIVERANGE tableIndex %d startIndex %d num_access %d (", tableIndex, startIndex, ptrStart->num_access);
1826    for(k = 0; k < ptrStart->num_access; k++)
1827        ALOGI("%x ", ptrStart->accessPC[k]);
1828    ALOGI(")");
1829#endif
1830    ///// go through pointers from ptrStart->next to ptrEnd
1831    //from startIndex+1 to endIndex-1
1832    ptr = ptrStart->next;
1833    while(ptr != NULL && ptr != ptrEnd) {
1834        int k2;
1835        for(k2 = 0; k2 < ptr->num_access; k2++) { //merge to startIndex
1836            insertAccess(tableIndex, ptrStart, ptr->accessPC[k2]);
1837        }//k2
1838        ptr = ptr->next;
1839    }
1840    insertAccess(tableIndex, ptrStart, rangeStart);
1841    insertAccess(tableIndex, ptrStart, rangeEnd);
1842    //remove startIndex+1 to endIndex-1
1843    if(startIndex+1 < endIndex) {
1844        ptr = ptrStart->next;
1845        while(ptr != NULL && ptr != ptrEnd) {
1846            LiveRange* tmpP = ptr->next;
1847            free(ptr->accessPC);
1848            free(ptr);
1849            ptr = tmpP;
1850        }
1851        ptrStart->next = ptrEnd;
1852    }
1853    memVRTable[tableIndex].num_ranges -= (endIndex - startIndex - 1);
1854#ifdef DEBUG_LIVE_RANGE
1855    ALOGI("num_ranges for VR %d: %d", memVRTable[tableIndex].regNum, memVRTable[tableIndex].num_ranges);
1856#endif
1857}
1858//! insert an access to a given live range, in order
1859
1860//!
1861void insertAccess(int tableIndex, LiveRange* startP, int rangeStart) {
1862    int k3, k4;
1863#ifdef DEBUG_LIVE_RANGE
1864    ALOGI("LIVERANGE insertAccess %d %x", tableIndex, rangeStart);
1865#endif
1866    int insertIndex = -1;
1867    for(k3 = 0; k3 < startP->num_access; k3++) {
1868        if(startP->accessPC[k3] == rangeStart) {
1869            return;
1870        }
1871        if(startP->accessPC[k3] > rangeStart) {
1872            insertIndex = k3;
1873            break;
1874        }
1875    }
1876
1877    //insert here
1878    k3 = insertIndex;
1879    if(insertIndex == -1) {
1880        k3 = startP->num_access;
1881    }
1882    if(startP->num_access == startP->num_alloc) {
1883        int currentAlloc = startP->num_alloc;
1884        startP->num_alloc += NUM_ACCESS_IN_LIVERANGE;
1885        int* tmpPtr = (int *)malloc(sizeof(int) * startP->num_alloc);
1886        for(k4 = 0; k4 < currentAlloc; k4++)
1887            tmpPtr[k4] = startP->accessPC[k4];
1888        free(startP->accessPC);
1889        startP->accessPC = tmpPtr;
1890    }
1891    //insert accessPC
1892    for(k4 = startP->num_access-1; k4 >= k3; k4--)
1893        startP->accessPC[k4+1] = startP->accessPC[k4];
1894    startP->accessPC[k3] = rangeStart;
1895#ifdef DEBUG_LIVE_RANGE
1896    ALOGI("LIVERANGE insert %x to tableIndex %d", rangeStart, tableIndex);
1897#endif
1898    startP->num_access++;
1899    return;
1900}
1901
1902/////////////////////////////////////////////////////////////////////
1903bool isInMemory(int regNum, OpndSize size);
1904void setVRToMemory(int regNum, OpndSize size);
1905bool isVRLive(int vA);
1906int getSpillIndex(bool isGLUE, OpndSize size);
1907void clearVRToMemory(int regNum, OpndSize size);
1908void clearVRNullCheck(int regNum, OpndSize size);
1909
1910inline int getSpillLocDisp(int offset) {
1911#ifdef SPILL_IN_THREAD
1912    return offset+offsetof(Thread, spillRegion);;
1913#else
1914    return offset+offEBP_spill;
1915#endif
1916}
1917#if 0
1918/* used if we keep self pointer in a physical register */
1919inline int getSpillLocReg(int offset) {
1920    return PhysicalReg_Glue;
1921}
1922#endif
1923#ifdef SPILL_IN_THREAD
1924inline void loadFromSpillRegion_with_self(OpndSize size, int reg_self, bool selfPhysical, int reg, int offset) {
1925    /* only 1 instruction is generated by move_mem_to_reg_noalloc */
1926    move_mem_to_reg_noalloc(size,
1927                            getSpillLocDisp(offset), reg_self, selfPhysical,
1928                            MemoryAccess_SPILL, offset,
1929                            reg, true);
1930}
1931inline void loadFromSpillRegion(OpndSize size, int reg, int offset) {
1932    get_self_pointer(C_SCRATCH_1, isScratchPhysical);
1933    int reg_self = registerAlloc(LowOpndRegType_scratch, C_SCRATCH_1, isScratchPhysical, false);
1934    /* only 1 instruction is generated by move_mem_to_reg_noalloc */
1935    move_mem_to_reg_noalloc(size,
1936                            getSpillLocDisp(offset), reg_self, true,
1937                            MemoryAccess_SPILL, offset,
1938                            reg, true);
1939}
1940inline void saveToSpillRegion_with_self(OpndSize size, int selfReg, bool selfPhysical, int reg, int offset) {
1941    move_reg_to_mem_noalloc(size,
1942                            reg, true,
1943                            getSpillLocDisp(offset), selfReg, selfPhysical,
1944                            MemoryAccess_SPILL, offset);
1945}
1946inline void saveToSpillRegion(OpndSize size, int reg, int offset) {
1947    get_self_pointer(C_SCRATCH_1, isScratchPhysical);
1948    int reg_self = registerAlloc(LowOpndRegType_scratch, C_SCRATCH_1, isScratchPhysical, false);
1949    move_reg_to_mem_noalloc(size,
1950                            reg, true,
1951                            getSpillLocDisp(offset), reg_self, true,
1952                            MemoryAccess_SPILL, offset);
1953}
1954#else
1955inline void loadFromSpillRegion(OpndSize size, int reg, int offset) {
1956    /* only 1 instruction is generated by move_mem_to_reg_noalloc */
1957    move_mem_to_reg_noalloc(size,
1958                            getSpillLocDisp(offset), PhysicalReg_EBP, true,
1959                            MemoryAccess_SPILL, offset,
1960                            reg, true);
1961}
1962inline void saveToSpillRegion(OpndSize size, int reg, int offset) {
1963    move_reg_to_mem_noalloc(size,
1964                            reg, true,
1965                            getSpillLocDisp(offset), PhysicalReg_EBP, true,
1966                            MemoryAccess_SPILL, offset);
1967}
1968#endif
1969
1970//! dump an immediate to memory, set inMemory to true
1971
1972//!
1973void dumpImmToMem(int vrNum, OpndSize size, int value) {
1974    if(isInMemory(vrNum, size)) {
1975#ifdef DEBUG_SPILL
1976        ALOGI("Skip dumpImmToMem vA %d size %d", vrNum, size);
1977#endif
1978        return;
1979    }
1980    set_VR_to_imm_noalloc(vrNum, size, value);
1981    setVRToMemory(vrNum, size);
1982}
1983//! dump content of a VR to memory, set inMemory to true
1984
1985//!
1986void dumpToMem(int vrNum, LowOpndRegType type, int regAll) { //ss,gp,xmm
1987    if(isInMemory(vrNum, getRegSize(type))) {
1988#ifdef DEBUG_SPILL
1989        ALOGI("Skip dumpToMem vA %d type %d", vrNum, type);
1990#endif
1991        return;
1992    }
1993    if(type == LowOpndRegType_gp || type == LowOpndRegType_xmm)
1994        set_virtual_reg_noalloc(vrNum, getRegSize(type), regAll, true);
1995    if(type == LowOpndRegType_ss)
1996        move_ss_reg_to_mem_noalloc(regAll, true,
1997                                   4*vrNum, PhysicalReg_FP, true,
1998                                   MemoryAccess_VR, vrNum);
1999    setVRToMemory(vrNum, getRegSize(type));
2000}
2001//! dump part of a 64-bit VR to memory and update inMemory
2002
2003//! isLow tells whether low half or high half is dumped
2004void dumpPartToMem(int reg /*xmm physical reg*/, int vA, bool isLow) {
2005    if(isLow) {
2006        if(isInMemory(vA, OpndSize_32)) {
2007#ifdef DEBUG_SPILL
2008            ALOGI("Skip dumpPartToMem isLow %d vA %d", isLow, vA);
2009#endif
2010            return;
2011        }
2012    }
2013    else {
2014        if(isInMemory(vA+1, OpndSize_32)) {
2015#ifdef DEBUG_SPILL
2016            ALOGI("Skip dumpPartToMem isLow %d vA %d", isLow, vA);
2017#endif
2018            return;
2019        }
2020    }
2021    if(isLow) {
2022        if(!isVRLive(vA)) return;
2023    }
2024    else {
2025        if(!isVRLive(vA+1)) return;
2026    }
2027    //move part to vA or vA+1
2028    if(isLow) {
2029        move_ss_reg_to_mem_noalloc(reg, true,
2030                                   4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA);
2031    } else {
2032        int k = getSpillIndex(false, OpndSize_64);
2033        //H, L in 4*k+4 & 4*k
2034#ifdef SPILL_IN_THREAD
2035        get_self_pointer(PhysicalReg_SCRATCH_1, isScratchPhysical);
2036        saveToSpillRegion_with_self(OpndSize_64, PhysicalReg_SCRATCH_1, isScratchPhysical, reg, 4*k);
2037        //update low 32 bits of xmm reg from 4*k+4
2038        move_ss_mem_to_reg(NULL,
2039                                   getSpillLocDisp(4*k+4), PhysicalReg_SCRATCH_1, isScratchPhysical,
2040                                   reg, true);
2041#else
2042        saveToSpillRegion(OpndSize_64, reg, 4*k);
2043        //update low 32 bits of xmm reg from 4*k+4
2044        move_ss_mem_to_reg_noalloc(
2045                                   getSpillLocDisp(4*k+4), PhysicalReg_EBP, true,
2046                                   MemoryAccess_SPILL, 4*k+4,
2047                                   reg, true);
2048#endif
2049        //move low 32 bits of xmm reg to vA+1
2050        move_ss_reg_to_mem_noalloc(reg, true, 4*(vA+1), PhysicalReg_FP, true, MemoryAccess_VR, vA+1);
2051    }
2052    if(isLow)
2053        setVRToMemory(vA, OpndSize_32);
2054    else
2055        setVRToMemory(vA+1, OpndSize_32);
2056}
2057void clearVRBoundCheck(int regNum, OpndSize size);
2058//! the content of a VR is no longer in memory or in physical register if the latest content of a VR is constant
2059
2060//! clear nullCheckDone; if another VR is overlapped with the given VR, the content of that VR is no longer in physical register
2061void invalidateVRDueToConst(int reg, OpndSize size) {
2062    clearVRToMemory(reg, size); //memory content is out-dated
2063    clearVRNullCheck(reg, size);
2064    clearVRBoundCheck(reg, size);
2065    //check reg,gp reg,ss reg,xmm reg-1,xmm
2066    //if size is 64: check reg+1,gp|ss reg+1,xmm
2067    int index;
2068    //if VR is xmm, check whether we need to dump part of VR to memory
2069    index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg);
2070    if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2071#ifdef DEBUG_INVALIDATE
2072        ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_xmm);
2073#endif
2074        if(size == OpndSize_32)
2075            dumpPartToMem(compileTable[index].physicalReg, reg, false); //dump high of xmm to memory
2076        compileTable[index].physicalReg = PhysicalReg_Null;
2077    }
2078    index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg-1);
2079    if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2080#ifdef DEBUG_INVALIDATE
2081        ALOGI("INVALIDATE virtual reg %d type %d", reg-1, LowOpndRegType_xmm);
2082#endif
2083        dumpPartToMem(compileTable[index].physicalReg, reg-1, true); //dump low of xmm to memory
2084        compileTable[index].physicalReg = PhysicalReg_Null;
2085    }
2086    index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_gp, reg);
2087    if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2088#ifdef DEBUG_INVALIDATE
2089        ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_gp);
2090#endif
2091        compileTable[index].physicalReg = PhysicalReg_Null;
2092    }
2093    index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_ss, reg);
2094    if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2095#ifdef DEBUG_INVALIDATE
2096        ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_ss);
2097#endif
2098        compileTable[index].physicalReg = PhysicalReg_Null;
2099    }
2100    if(size == OpndSize_64) {
2101        index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg+1);
2102        if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2103#ifdef DEBUG_INVALIDATE
2104            ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_xmm);
2105#endif
2106            dumpPartToMem(compileTable[index].physicalReg, reg+1, false); //dump high of xmm to memory
2107            compileTable[index].physicalReg = PhysicalReg_Null;
2108        }
2109        index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_gp, reg+1);
2110        if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2111#ifdef DEBUG_INVALIDATE
2112            ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_gp);
2113#endif
2114            compileTable[index].physicalReg = PhysicalReg_Null;
2115        }
2116        index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_ss, reg+1);
2117        if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2118#ifdef DEBUG_INVALIDATE
2119            ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_ss);
2120#endif
2121            compileTable[index].physicalReg = PhysicalReg_Null;
2122        }
2123    }
2124}
2125//! check which physical registers hold out-dated content if there is a def
2126
2127//! if another VR is overlapped with the given VR, the content of that VR is no longer in physical register
2128//! should we update inMemory?
2129void invalidateVR(int reg, LowOpndRegType pType) {
2130    //def at fs: content of xmm & gp & ss are out-dated (reg-1,xmm reg,xmm reg+1,xmm) (reg,gp|ss reg+1,gp|ss)
2131    //def at xmm: content of misaligned xmm & gp are out-dated (reg-1,xmm reg+1,xmm) (reg,gp|ss reg+1,gp|ss)
2132    //def at fs_s: content of xmm & gp are out-dated (reg-1,xmm reg,xmm) (reg,gp|ss)
2133    //def at gp:   content of xmm is out-dated (reg-1,xmm reg,xmm) (reg,ss)
2134    //def at ss:   content of xmm & gp are out-dated (reg-1,xmm reg,xmm) (reg,gp)
2135    int index;
2136    if(pType != LowOpndRegType_xmm) { //check xmm @reg
2137        index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg);
2138        if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2139#ifdef DEBUG_INVALIDATE
2140            ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_xmm);
2141#endif
2142            if(getRegSize(pType) == OpndSize_32)
2143                dumpPartToMem(compileTable[index].physicalReg, reg, false); //dump high of xmm to memory
2144            compileTable[index].physicalReg = PhysicalReg_Null;
2145        }
2146    }
2147    //check misaligned xmm @ reg-1
2148    index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg-1);
2149    if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2150#ifdef DEBUG_INVALIDATE
2151        ALOGI("INVALIDATE virtual reg %d type %d", reg-1, LowOpndRegType_xmm);
2152#endif
2153        dumpPartToMem(compileTable[index].physicalReg, reg-1, true); //dump low of xmm to memory
2154        compileTable[index].physicalReg = PhysicalReg_Null;
2155    }
2156    //check misaligned xmm @ reg+1
2157    if(pType == LowOpndRegType_xmm || pType == LowOpndRegType_fs) {
2158        //check reg+1,xmm
2159        index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_xmm, reg+1);
2160        if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2161#ifdef DEBUG_INVALIDATE
2162            ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_xmm);
2163#endif
2164            dumpPartToMem(compileTable[index].physicalReg, reg+1, false); //dump high of xmm to memory
2165            compileTable[index].physicalReg = PhysicalReg_Null;
2166        }
2167    }
2168    if(pType != LowOpndRegType_gp) {
2169        //check reg,gp
2170        index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_gp, reg);
2171        if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2172#ifdef DEBUG_INVALIDATE
2173            ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_gp);
2174#endif
2175            compileTable[index].physicalReg = PhysicalReg_Null;
2176        }
2177    }
2178    if(pType == LowOpndRegType_xmm || pType == LowOpndRegType_fs) {
2179        //check reg+1,gp
2180        index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_gp, reg+1);
2181        if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2182#ifdef DEBUG_INVALIDATE
2183            ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_gp);
2184#endif
2185            compileTable[index].physicalReg = PhysicalReg_Null;
2186        }
2187    }
2188    if(pType != LowOpndRegType_ss) {
2189        //check reg,ss
2190        index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_ss, reg);
2191        if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2192#ifdef DEBUG_INVALIDATE
2193            ALOGI("INVALIDATE virtual reg %d type %d", reg, LowOpndRegType_ss);
2194#endif
2195            compileTable[index].physicalReg = PhysicalReg_Null;
2196        }
2197    }
2198    if(pType == LowOpndRegType_xmm || pType == LowOpndRegType_fs) {
2199        //check reg+1,ss
2200        index = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_ss, reg+1);
2201        if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
2202#ifdef DEBUG_INVALIDATE
2203            ALOGI("INVALIDATE virtual reg %d type %d", reg+1, LowOpndRegType_ss);
2204#endif
2205            compileTable[index].physicalReg = PhysicalReg_Null;
2206        }
2207    }
2208}
2209//! bookkeeping when a VR is updated
2210
2211//! invalidate contents of some physical registers, clear nullCheckDone, and update inMemory;
2212//! check whether there exist tranfer points for this bytecode, if yes, perform the transfer
2213int updateVirtualReg(int reg, LowOpndRegType pType) {
2214    int k;
2215    OpndSize size = getRegSize(pType);
2216    //WAS only invalidate xmm VRs for the following cases:
2217    //if def reaches a use of vA,xmm and (the def is not xmm or is misaligned xmm)
2218    //  invalidate "vA,xmm"
2219    invalidateVR(reg, pType);
2220    clearVRNullCheck(reg, size);
2221    clearVRBoundCheck(reg, size);
2222    if(pType == LowOpndRegType_fs || pType == LowOpndRegType_fs_s)
2223        setVRToMemory(reg, size);
2224    else {
2225        clearVRToMemory(reg, size);
2226    }
2227    for(k = 0; k < currentBB->num_xfer_points; k++) {
2228        if(currentBB->xferPoints[k].offsetPC == offsetPC &&
2229           currentBB->xferPoints[k].regNum == reg &&
2230           currentBB->xferPoints[k].physicalType == pType &&
2231           currentBB->xferPoints[k].xtype != XFER_MEM_TO_XMM) {
2232            //perform the corresponding action for the def
2233            PhysicalReg regAll;
2234            if(currentBB->xferPoints[k].xtype == XFER_DEF_IS_XMM) {
2235                //def at fs: content of xmm is out-dated
2236                //def at xmm: content of misaligned xmm is out-dated
2237                //invalidateXmmVR(currentBB->xferPoints[k].tableIndex);
2238#ifdef DEBUG_XFER_POINTS
2239                if(currentBB->xferPoints[k].dumpToXmm) ALOGI("XFER set_virtual_reg to xmm: xmm VR %d", reg);
2240#endif
2241                if(pType == LowOpndRegType_xmm)  {
2242#ifdef DEBUG_XFER_POINTS
2243                    ALOGI("XFER set_virtual_reg to memory: xmm VR %d", reg);
2244#endif
2245                    PhysicalReg regAll = (PhysicalReg)checkVirtualReg(reg, LowOpndRegType_xmm, 0 /* do not update*/);
2246                    dumpToMem(reg, LowOpndRegType_xmm, regAll);
2247                }
2248                if(currentBB->xferPoints[k].vr_gpl >= 0) { //
2249                }
2250                if(currentBB->xferPoints[k].vr_gph >= 0) {
2251                }
2252            }
2253            if((pType == LowOpndRegType_gp || pType == LowOpndRegType_ss) &&
2254               (currentBB->xferPoints[k].xtype == XFER_DEF_TO_MEM ||
2255                currentBB->xferPoints[k].xtype == XFER_DEF_TO_GP_MEM)) {
2256                //the defined gp VR already in register
2257                //invalidateXmmVR(currentBB->xferPoints[k].tableIndex);
2258                regAll = (PhysicalReg)checkVirtualReg(reg, pType, 0 /* do not update*/);
2259                dumpToMem(reg, pType, regAll);
2260#ifdef DEBUG_XFER_POINTS
2261                ALOGI("XFER set_virtual_reg to memory: gp VR %d", reg);
2262#endif
2263            }
2264            if((pType == LowOpndRegType_fs_s || pType == LowOpndRegType_ss) &&
2265               currentBB->xferPoints[k].xtype == XFER_DEF_TO_GP_MEM) {
2266            }
2267        }
2268    }
2269    return -1;
2270}
2271////////////////////////////////////////////////////////////////
2272//REGISTER ALLOCATION
2273int spillForHardReg(int regNum, int type);
2274void decreaseRefCount(int index);
2275int getFreeReg(int type, int reg, int indexToCompileTable);
2276PhysicalReg spillForLogicalReg(int type, int reg, int indexToCompileTable);
2277int unspillLogicalReg(int spill_index, int physicalReg);
2278int searchVirtualInfoOfBB(LowOpndRegType type, int regNum, BasicBlock_O1* bb);
2279bool isTemp8Bit(int type, int reg);
2280bool matchType(int typeA, int typeB);
2281int getNextAccess(int compileIndex);
2282void dumpCompileTable();
2283
2284//! allocate a register for a variable
2285
2286//!if no physical register is free, call spillForLogicalReg to free up a physical register;
2287//!if the variable is a temporary and it was spilled, call unspillLogicalReg to load from spill location to the allocated physical register;
2288//!if updateRefCount is true, reduce reference count of the variable by 1
2289int registerAlloc(int type, int reg, bool isPhysical, bool updateRefCount) {
2290#ifdef DEBUG_REGALLOC
2291    ALOGI("%p: try to allocate register %d type %d isPhysical %d", currentBB, reg, type, isPhysical);
2292#endif
2293    if(currentBB == NULL) {
2294        if(type & LowOpndRegType_virtual) return PhysicalReg_Null;
2295        if(isPhysical) return reg; //for helper functions
2296        return PhysicalReg_Null;
2297    }
2298    //ignore EDI, ESP, EBP (glue)
2299    if(isPhysical && (reg == PhysicalReg_EDI || reg == PhysicalReg_ESP ||
2300                      reg == PhysicalReg_EBP || reg == PhysicalReg_Null))
2301        return reg;
2302
2303    int newType = convertType(type, reg, isPhysical);
2304    if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
2305    int tIndex = searchCompileTable(newType, reg);
2306    if(tIndex < 0) {
2307      ALOGE("reg %d type %d not found in registerAlloc", reg, newType);
2308      return PhysicalReg_Null;
2309    }
2310
2311    //physical register
2312    if(isPhysical) {
2313        if(allRegs[reg].isUsed) { //if used by a non hard-coded register
2314            spillForHardReg(reg, newType);
2315        }
2316        allRegs[reg].isUsed = true;
2317#ifdef DEBUG_REG_USED
2318        ALOGI("REGALLOC: allocate a reg %d", reg);
2319#endif
2320        compileTable[tIndex].physicalReg = reg;
2321        if(updateRefCount)
2322            decreaseRefCount(tIndex);
2323#ifdef DEBUG_REGALLOC
2324        ALOGI("REGALLOC: allocate register %d for logical register %d %d",
2325               compileTable[tIndex].physicalReg, reg, newType);
2326#endif
2327        return reg;
2328    }
2329    //already allocated
2330    if(compileTable[tIndex].physicalReg != PhysicalReg_Null) {
2331#ifdef DEBUG_REGALLOC
2332        ALOGI("already allocated to physical register %d", compileTable[tIndex].physicalReg);
2333#endif
2334        if(updateRefCount)
2335            decreaseRefCount(tIndex);
2336        return compileTable[tIndex].physicalReg;
2337    }
2338
2339    //at this point, the logical register is not hard-coded and is mapped to Reg_Null
2340    //first check whether there is a free reg
2341    //if not, call spillForLogicalReg
2342    int index = getFreeReg(newType, reg, tIndex);
2343    if(index >= 0 && index < PhysicalReg_Null) {
2344        //update compileTable & allRegs
2345        compileTable[tIndex].physicalReg = allRegs[index].physicalReg;
2346        allRegs[index].isUsed = true;
2347#ifdef DEBUG_REG_USED
2348        ALOGI("REGALLOC: register %d is free", allRegs[index].physicalReg);
2349#endif
2350    } else {
2351        PhysicalReg allocR = spillForLogicalReg(newType, reg, tIndex);
2352        compileTable[tIndex].physicalReg = allocR;
2353    }
2354    if(compileTable[tIndex].spill_loc_index >= 0) {
2355        unspillLogicalReg(tIndex, compileTable[tIndex].physicalReg);
2356    }
2357    if(updateRefCount)
2358        decreaseRefCount(tIndex);
2359#ifdef DEBUG_REGALLOC
2360    ALOGI("REGALLOC: allocate register %d for logical register %d %d",
2361           compileTable[tIndex].physicalReg, reg, newType);
2362#endif
2363    return compileTable[tIndex].physicalReg;
2364}
2365//!a variable will use a physical register allocated for another variable
2366
2367//!This is used when MOVE_OPT is on, it tries to alias a virtual register with a temporary to remove a move
2368int registerAllocMove(int reg, int type, bool isPhysical, int srcReg) {
2369    if(srcReg == PhysicalReg_EDI || srcReg == PhysicalReg_ESP || srcReg == PhysicalReg_EBP)
2370        ALOGE("can't move from srcReg EDI or ESP or EBP");
2371#ifdef DEBUG_REGALLOC
2372    ALOGI("in registerAllocMove: reg %d type %d srcReg %d", reg, type, srcReg);
2373#endif
2374    int newType = convertType(type, reg, isPhysical);
2375    if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
2376    int index = searchCompileTable(newType, reg);
2377    if(index < 0) {
2378        ALOGE("reg %d type %d not found in registerAllocMove", reg, newType);
2379        return -1;
2380    }
2381
2382    decreaseRefCount(index);
2383    compileTable[index].physicalReg = srcReg;
2384#ifdef DEBUG_REGALLOC
2385    ALOGI("REGALLOC: registerAllocMove %d for logical register %d %d",
2386           compileTable[index].physicalReg, reg, newType);
2387#endif
2388    return srcReg;
2389}
2390
2391//! check whether a physical register is available to be used by a variable
2392
2393//! data structures accessed:
2394//! 1> currentBB->infoBasicBlock[index].allocConstraintsSorted
2395//!    sorted from high count to low count
2396//! 2> currentBB->allocConstraintsSorted
2397//!    sorted from low count to high count
2398//! 3> allRegs: whether a physical register is available, indexed by PhysicalReg
2399//! NOTE: if a temporary variable is 8-bit, only %eax, %ebx, %ecx, %edx can be used
2400int getFreeReg(int type, int reg, int indexToCompileTable) {
2401    syncAllRegs();
2402    /* handles requests for xmm or ss registers */
2403    int k;
2404    if(((type & MASK_FOR_TYPE) == LowOpndRegType_xmm) ||
2405       ((type & MASK_FOR_TYPE) == LowOpndRegType_ss)) {
2406        for(k = PhysicalReg_XMM0; k <= PhysicalReg_XMM7; k++) {
2407            if(!allRegs[k].isUsed) return k;
2408        }
2409        return -1;
2410    }
2411#ifdef DEBUG_REGALLOC
2412    ALOGI("USED registers: ");
2413    for(k = 0; k < 8; k++)
2414        ALOGI("%d used: %d time freed: %d callee-saveld: %d", k, allRegs[k].isUsed,
2415             allRegs[k].freeTimeStamp, allRegs[k].isCalleeSaved);
2416    ALOGI("");
2417#endif
2418
2419    /* a VR is requesting a physical register */
2420    if(isVirtualReg(type)) { //find a callee-saved register
2421        /* if VR is type GG, check the pre-allocated physical register first */
2422        bool isGGVR = compileTable[indexToCompileTable].gType == GLOBALTYPE_GG;
2423        if(isGGVR) {
2424            int regCandidateT = compileTable[indexToCompileTable].physicalReg_prev;
2425            if(!allRegs[regCandidateT].isUsed) return regCandidateT;
2426        }
2427
2428        int index = searchVirtualInfoOfBB((LowOpndRegType)(type&MASK_FOR_TYPE), reg, currentBB);
2429        if(index < 0) {
2430            ALOGE("VR %d %d not found in infoBasicBlock of currentBB %d (num of VRs %d)",
2431                  reg, type, currentBB->bb_index, currentBB->num_regs);
2432            dvmAbort();
2433        }
2434
2435        /* check allocConstraints for this VR,
2436           return an available physical register with the highest constraint > 0 */
2437        for(k = 0; k < 8; k++) {
2438            if(currentBB->infoBasicBlock[index].allocConstraintsSorted[k].count == 0) break;
2439            int regCandidateT = currentBB->infoBasicBlock[index].allocConstraintsSorted[k].physicalReg;
2440            assert(regCandidateT < PhysicalReg_Null);
2441            if(!allRegs[regCandidateT].isUsed) return regCandidateT;
2442        }
2443
2444        /* WAS: return an available physical register with the lowest constraint
2445           NOW: consider a new factor (freeTime) when there is a tie
2446                if 2 available physical registers have the same number of constraints
2447                choose the one with smaller free time stamp */
2448        int currentCount = -1;
2449        int index1 = -1;
2450        int smallestTime = -1;
2451        for(k = 0; k < 8; k++) {
2452            int regCandidateT = currentBB->allocConstraintsSorted[k].physicalReg;
2453            assert(regCandidateT < PhysicalReg_Null);
2454            if(index1 >= 0 && currentBB->allocConstraintsSorted[k].count > currentCount)
2455                break; //candidate has higher count than index1
2456            if(!allRegs[regCandidateT].isUsed) {
2457                if(index1 < 0) {
2458                    index1 = k;
2459                    currentCount = currentBB->allocConstraintsSorted[k].count;
2460                    smallestTime = allRegs[regCandidateT].freeTimeStamp;
2461                } else if(allRegs[regCandidateT].freeTimeStamp < smallestTime) {
2462                    index1 = k;
2463                    smallestTime = allRegs[regCandidateT].freeTimeStamp;
2464                }
2465            }
2466        }
2467        if(index1 >= 0) return currentBB->allocConstraintsSorted[index1].physicalReg;
2468        return -1;
2469    }
2470    /* handle request from a temporary variable or a glue variable */
2471    else {
2472        bool is8Bit = isTemp8Bit(type, reg);
2473
2474        /* if the temporary variable is linked to a VR and
2475              the VR is not yet allocated to any physical register */
2476        int vr_num = compileTable[indexToCompileTable].linkageToVR;
2477        if(vr_num >= 0) {
2478            int index3 = searchCompileTable(LowOpndRegType_gp | LowOpndRegType_virtual, vr_num);
2479            if(index3 < 0) {
2480                ALOGE("2 in tracing linkage to VR %d", vr_num);
2481                dvmAbort();
2482            }
2483
2484            if(compileTable[index3].physicalReg == PhysicalReg_Null) {
2485                int index2 = searchVirtualInfoOfBB(LowOpndRegType_gp, vr_num, currentBB);
2486                if(index2 < 0) {
2487                    ALOGE("1 in tracing linkage to VR %d", vr_num);
2488                    dvmAbort();
2489                }
2490#ifdef DEBUG_REGALLOC
2491                ALOGI("in getFreeReg for temporary reg %d, trace the linkage to VR %d",
2492                     reg, vr_num);
2493#endif
2494
2495                /* check allocConstraints on the VR
2496                   return an available physical register with the highest constraint > 0
2497                */
2498                for(k = 0; k < 8; k++) {
2499                    if(currentBB->infoBasicBlock[index2].allocConstraintsSorted[k].count == 0) break;
2500                    int regCandidateT = currentBB->infoBasicBlock[index2].allocConstraintsSorted[k].physicalReg;
2501#ifdef DEBUG_REGALLOC
2502                    ALOGI("check register %d with count %d", regCandidateT,
2503                          currentBB->infoBasicBlock[index2].allocConstraintsSorted[k].count);
2504#endif
2505                    /* if the requesting variable is 8 bit */
2506                    if(is8Bit && regCandidateT > PhysicalReg_EDX) continue;
2507                    assert(regCandidateT < PhysicalReg_Null);
2508                    if(!allRegs[regCandidateT].isUsed) return regCandidateT;
2509                }
2510            }
2511        }
2512        /* check allocConstraints of the basic block
2513           if 2 available physical registers have the same constraint count,
2514              return the non callee-saved physical reg */
2515        /* enhancement: record the time when a register is freed (freeTimeStamp)
2516                        the purpose is to reduce false dependency
2517           priority: constraint count, non callee-saved, time freed
2518               let x be the lowest constraint count
2519               set A be available callee-saved physical registers with count == x
2520               set B be available non callee-saved physical registers with count == x
2521               if set B is not null, return the one with smallest free time
2522               otherwise, return the one in A with smallest free time
2523           To ignore whether it is callee-saved, add all candidates to set A
2524        */
2525        int setAIndex[8];
2526        int num_A = 0;
2527        int setBIndex[8];
2528        int num_B = 0;
2529        int index1 = -1; //points to an available physical reg with lowest count
2530        int currentCount = -1;
2531        for(k = 0; k < 8; k++) {
2532            int regCandidateT = currentBB->allocConstraintsSorted[k].physicalReg;
2533            if(is8Bit && regCandidateT > PhysicalReg_EDX) continue;
2534
2535            if(index1 >= 0 && currentBB->allocConstraintsSorted[k].count > currentCount)
2536                break; //candidate has higher count than index1
2537            assert(regCandidateT < PhysicalReg_Null);
2538            if(!allRegs[regCandidateT].isUsed) {
2539                /*To ignore whether it is callee-saved, add all candidates to set A */
2540                if(false) {//!allRegs[regCandidateT].isCalleeSaved) { //add to set B
2541                    setBIndex[num_B++] = k;
2542                } else { //add to set A
2543                    setAIndex[num_A++] = k;
2544                }
2545                if(index1 < 0) {
2546                    /* index1 points to a physical reg with lowest count */
2547                    index1 = k;
2548                    currentCount = currentBB->allocConstraintsSorted[k].count;
2549                }
2550            }
2551        }
2552
2553        int kk;
2554        int smallestTime = -1;
2555        index1 = -1;
2556        for(kk = 0; kk < num_B; kk++) {
2557            k = setBIndex[kk];
2558            int regCandidateT = currentBB->allocConstraintsSorted[k].physicalReg;
2559            assert(regCandidateT < PhysicalReg_Null);
2560            if(kk == 0 || allRegs[regCandidateT].freeTimeStamp < smallestTime) {
2561                index1 = k;
2562                smallestTime = allRegs[regCandidateT].freeTimeStamp;
2563            }
2564        }
2565        if(index1 >= 0)
2566            return currentBB->allocConstraintsSorted[index1].physicalReg;
2567        index1 = -1;
2568        for(kk = 0; kk < num_A; kk++) {
2569            k = setAIndex[kk];
2570            int regCandidateT = currentBB->allocConstraintsSorted[k].physicalReg;
2571            if(kk == 0 || allRegs[regCandidateT].freeTimeStamp < smallestTime) {
2572                index1 = k;
2573                smallestTime = allRegs[regCandidateT].freeTimeStamp;
2574            }
2575        }
2576        if(index1 >= 0) return currentBB->allocConstraintsSorted[index1].physicalReg;
2577        return -1;
2578    }
2579    return -1;
2580}
2581
2582//! find a candidate physical register for a variable and spill all variables that are mapped to the candidate
2583
2584//!
2585PhysicalReg spillForLogicalReg(int type, int reg, int indexToCompileTable) {
2586    //choose a used register to spill
2587    //when a GG virtual register is spilled, write it to interpretd stack, set physicalReg to Null
2588    //  at end of the basic block, load spilled GG VR to physical reg
2589    //when other types of VR is spilled, write it to interpreted stack, set physicalReg to Null
2590    //when a temporary (non-virtual) register is spilled, write it to stack, set physicalReg to Null
2591    //can we spill a hard-coded temporary register? YES
2592    int k, k2;
2593    PhysicalReg allocR;
2594
2595    //do not try to free a physical reg that is used by more than one logical registers
2596    //fix on sep 28, 2009
2597    //do not try to spill a hard-coded logical register
2598    //do not try to free a physical reg that is outside of the range for 8-bit logical reg
2599    /* for each physical register,
2600       collect number of non-hardcode entries that are mapped to the physical register */
2601    int numOfUses[PhysicalReg_Null];
2602    for(k = PhysicalReg_EAX; k < PhysicalReg_Null; k++)
2603        numOfUses[k] = 0;
2604    for(k = 0; k < num_compile_entries; k++) {
2605        if((compileTable[k].physicalReg != PhysicalReg_Null) &&
2606           matchType(type, compileTable[k].physicalType) &&
2607           (compileTable[k].physicalType & LowOpndRegType_hard) == 0) {
2608            numOfUses[compileTable[k].physicalReg]++;
2609        }
2610    }
2611
2612    /* candidates: all non-hardcode entries that are mapped to
2613           a physical register that is used by only one entry*/
2614    bool is8Bit = isTemp8Bit(type, reg);
2615    int candidates[COMPILE_TABLE_SIZE];
2616    int num_cand = 0;
2617    for(k = 0; k < num_compile_entries; k++) {
2618        if(matchType(type, compileTable[k].physicalType) &&
2619           compileTable[k].physicalReg != PhysicalReg_Null) {
2620            if(is8Bit && compileTable[k].physicalReg > PhysicalReg_EDX) continue; //not a candidate
2621            if(!canSpillReg[compileTable[k].physicalReg]) continue; //not a candidate
2622            if((compileTable[k].physicalType & LowOpndRegType_hard) == 0 &&
2623               numOfUses[compileTable[k].physicalReg] <= 1) {
2624                candidates[num_cand++] = k;
2625            }
2626        }
2627    }
2628
2629    /* go through all candidates:
2630       first check GLUE-related entries */
2631    int spill_index = -1;
2632    for(k2 = 0; k2 < num_cand; k2++) {
2633        k = candidates[k2];
2634        if((compileTable[k].physicalReg != PhysicalReg_Null) &&
2635           matchType(type, compileTable[k].physicalType) &&
2636           (compileTable[k].regNum >= PhysicalReg_GLUE_DVMDEX &&
2637            compileTable[k].regNum != PhysicalReg_GLUE)) {
2638            allocR = (PhysicalReg)spillLogicalReg(k, true);
2639#ifdef DEBUG_REGALLOC
2640            ALOGI("SPILL register used by num %d type %d it is a GLUE register with refCount %d",
2641                  compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].refCount);
2642#endif
2643            return allocR;
2644        }
2645    }
2646
2647    /* out of the candates, find a VR that has the furthest next use */
2648    int furthestUse = offsetPC;
2649    for(k2 = 0; k2 < num_cand; k2++) {
2650        k = candidates[k2];
2651        if((compileTable[k].physicalReg != PhysicalReg_Null) &&
2652           matchType(type, compileTable[k].physicalType) &&
2653           isVirtualReg(compileTable[k].physicalType)) {
2654            int nextUse = getNextAccess(k);
2655            if(spill_index < 0 || nextUse > furthestUse) {
2656                spill_index = k;
2657                furthestUse = nextUse;
2658            }
2659        }
2660    }
2661
2662    /* spill the VR with the furthest next use */
2663    if(spill_index >= 0) {
2664        allocR = (PhysicalReg)spillLogicalReg(spill_index, true);
2665        return allocR; //the register is still being used
2666    }
2667
2668    /* spill an entry with the smallest refCount */
2669    int baseLeftOver = 0;
2670    int index = -1;
2671    for(k2 = 0; k2 < num_cand; k2++) {
2672        k = candidates[k2];
2673        if(k != indexForGlue &&
2674           (compileTable[k].physicalReg != PhysicalReg_Null) &&
2675           (compileTable[k].physicalType & LowOpndRegType_hard) == 0 && //not hard-coded
2676           matchType(type, compileTable[k].physicalType)) {
2677            if((index < 0) || (compileTable[k].refCount < baseLeftOver)) {
2678                baseLeftOver = compileTable[k].refCount;
2679                index = k;
2680            }
2681        }
2682    }
2683    if(index < 0) {
2684        dumpCompileTable();
2685        ALOGE("no register to spill for logical %d %d", reg, type);
2686        dvmAbort();
2687    }
2688    allocR = (PhysicalReg)spillLogicalReg(index, true);
2689#ifdef DEBUG_REGALLOC
2690    ALOGI("SPILL register used by num %d type %d it is a temporary register with refCount %d",
2691           compileTable[index].regNum, compileTable[index].physicalType, compileTable[index].refCount);
2692#endif
2693    return allocR;
2694}
2695//!spill a variable to memory, the variable is specified by an index to compileTable
2696
2697//!If the variable is a temporary, get a spill location that is not in use and spill the content to the spill location;
2698//!If updateTable is true, set physicalReg to Null;
2699//!Return the physical register that was allocated to the variable
2700int spillLogicalReg(int spill_index, bool updateTable) {
2701    if((compileTable[spill_index].physicalType & LowOpndRegType_hard) != 0) {
2702        ALOGE("can't spill a hard-coded register");
2703        dvmAbort();
2704    }
2705    int physicalReg = compileTable[spill_index].physicalReg;
2706    if(!canSpillReg[physicalReg]) {
2707#ifdef PRINT_WARNING
2708        ALOGW("can't spill register %d", physicalReg);
2709#endif
2710        //dvmAbort(); //this happens in get_virtual_reg where VR is allocated to the same reg as the hardcoded temporary
2711    }
2712    if(isVirtualReg(compileTable[spill_index].physicalType)) {
2713        //spill back to memory
2714        dumpToMem(compileTable[spill_index].regNum,
2715                  (LowOpndRegType)(compileTable[spill_index].physicalType&MASK_FOR_TYPE),
2716                  compileTable[spill_index].physicalReg);
2717    }
2718    else {
2719        //update spill_loc_index
2720        int k = getSpillIndex(spill_index == indexForGlue,
2721                    getRegSize(compileTable[spill_index].physicalType));
2722        compileTable[spill_index].spill_loc_index = 4*k;
2723        if(k >= 0)
2724            spillIndexUsed[k] = 1;
2725        saveToSpillRegion(getRegSize(compileTable[spill_index].physicalType),
2726                          compileTable[spill_index].physicalReg, 4*k);
2727    }
2728    //compileTable[spill_index].physicalReg_prev = compileTable[spill_index].physicalReg;
2729#ifdef DEBUG_REGALLOC
2730    ALOGI("REGALLOC: SPILL logical reg %d %d with refCount %d allocated to %d",
2731           compileTable[spill_index].regNum,
2732           compileTable[spill_index].physicalType, compileTable[spill_index].refCount,
2733           compileTable[spill_index].physicalReg);
2734#endif
2735    if(!updateTable) return PhysicalReg_Null;
2736
2737    int allocR = compileTable[spill_index].physicalReg;
2738    compileTable[spill_index].physicalReg = PhysicalReg_Null;
2739    return allocR;
2740}
2741//! load a varible from memory to physical register, the variable is specified with an index to compileTable
2742
2743//!If the variable is a temporary, load from spill location and set the flag for the spill location to not used
2744int unspillLogicalReg(int spill_index, int physicalReg) {
2745    //can't un-spill to %eax in afterCall!!!
2746    //what if GG VR is allocated to %eax!!!
2747    if(isVirtualReg(compileTable[spill_index].physicalType)) {
2748        get_virtual_reg_noalloc(compileTable[spill_index].regNum,
2749                                getRegSize(compileTable[spill_index].physicalType),
2750                                physicalReg, true);
2751    }
2752    else {
2753        loadFromSpillRegion(getRegSize(compileTable[spill_index].physicalType),
2754                            physicalReg, compileTable[spill_index].spill_loc_index);
2755        spillIndexUsed[compileTable[spill_index].spill_loc_index >> 2] = 0;
2756        compileTable[spill_index].spill_loc_index = -1;
2757    }
2758#ifdef DEBUG_REGALLOC
2759    ALOGI("REGALLOC: UNSPILL logical reg %d %d with refCount %d", compileTable[spill_index].regNum,
2760           compileTable[spill_index].physicalType, compileTable[spill_index].refCount);
2761#endif
2762    return PhysicalReg_Null;
2763}
2764
2765//!spill a virtual register to memory
2766
2767//!if the current value of a VR is constant, write immediate to memory;
2768//!if the current value of a VR is in a physical register, call spillLogicalReg to dump content of the physical register to memory;
2769//!ifupdateTable is true, set the physical register for VR to Null and decrease reference count of the virtual register
2770int spillVirtualReg(int vrNum, LowOpndRegType type, bool updateTable) {
2771    int index = searchCompileTable(type | LowOpndRegType_virtual, vrNum);
2772    if(index < 0) {
2773        ALOGE("can't find VR %d %d in spillVirtualReg", vrNum, type);
2774        return -1;
2775    }
2776    //check whether it is const
2777    int value[2];
2778    int isConst = isVirtualRegConstant(vrNum, type, value, false); //do not update refCount
2779    if(isConst == 1 || isConst == 3) {
2780        dumpImmToMem(vrNum, OpndSize_32, value[0]);
2781    }
2782    if(getRegSize(type) == OpndSize_64 && (isConst == 2 || isConst == 3)) {
2783        dumpImmToMem(vrNum+1, OpndSize_32, value[1]);
2784    }
2785    if(isConst != 3 && compileTable[index].physicalReg != PhysicalReg_Null)
2786        spillLogicalReg(index, updateTable);
2787    if(updateTable) decreaseRefCount(index);
2788    return -1;
2789}
2790
2791//! spill variables that are mapped to physical register (regNum)
2792
2793//!
2794int spillForHardReg(int regNum, int type) {
2795    //find an entry that uses the physical register
2796    int spill_index = -1;
2797    int k;
2798    for(k = 0; k < num_compile_entries; k++) {
2799        if(k != indexForGlue &&
2800           compileTable[k].physicalReg == regNum &&
2801           matchType(type, compileTable[k].physicalType)) {
2802            spill_index = k;
2803            if(compileTable[k].regNum == regNum && compileTable[k].physicalType == type)
2804                continue;
2805            if(inGetVR_num >= 0 && compileTable[k].regNum == inGetVR_num && compileTable[k].physicalType == (type | LowOpndRegType_virtual))
2806                continue;
2807#ifdef DEBUG_REGALLOC
2808            ALOGI("SPILL logical reg %d %d to free hard-coded reg %d %d",
2809                   compileTable[spill_index].regNum, compileTable[spill_index].physicalType,
2810                   regNum, type);
2811            if(compileTable[spill_index].physicalType & LowOpndRegType_hard) dumpCompileTable();
2812#endif
2813            assert(spill_index < COMPILE_TABLE_SIZE);
2814            spillLogicalReg(spill_index, true);
2815        }
2816    }
2817    return regNum;
2818}
2819////////////////////////////////////////////////////////////////
2820//! update allocConstraints of the current basic block
2821
2822//! allocConstraints specify how many times a hardcoded register is used in this basic block
2823void updateCurrentBBWithConstraints(PhysicalReg reg) {
2824    if(reg > PhysicalReg_EBP) {
2825        ALOGE("register %d out of range in updateCurrentBBWithConstraints", reg);
2826    }
2827    currentBB->allocConstraints[reg].count++;
2828}
2829//! sort allocConstraints and save the result in allocConstraintsSorted
2830
2831//! allocConstraints specify how many times a virtual register is linked to a hardcode register
2832//! it is updated in getVirtualRegInfo and merged by mergeEntry2
2833int sortAllocConstraint(RegAllocConstraint* allocConstraints,
2834                        RegAllocConstraint* allocConstraintsSorted, bool fromHighToLow) {
2835    int ii, jj;
2836    int num_sorted = 0;
2837    for(jj = 0; jj < 8; jj++) {
2838        //figure out where to insert allocConstraints[jj]
2839        int count = allocConstraints[jj].count;
2840        int regT = allocConstraints[jj].physicalReg;
2841        assert(regT < PhysicalReg_Null);
2842        int insertIndex = -1;
2843        for(ii = 0; ii < num_sorted; ii++) {
2844            int regT2 = allocConstraintsSorted[ii].physicalReg;
2845            assert(regT2 < PhysicalReg_Null);
2846            if(allRegs[regT].isCalleeSaved &&
2847               count == allocConstraintsSorted[ii].count) {
2848                insertIndex = ii;
2849                break;
2850            }
2851            if((!allRegs[regT].isCalleeSaved) &&
2852               count == allocConstraintsSorted[ii].count &&
2853               (!allRegs[regT2].isCalleeSaved)) { //skip until found one that is not callee-saved
2854                insertIndex = ii;
2855                break;
2856            }
2857            if((fromHighToLow && count > allocConstraintsSorted[ii].count) ||
2858               ((!fromHighToLow) && count < allocConstraintsSorted[ii].count)) {
2859                insertIndex = ii;
2860                break;
2861            }
2862        }
2863        if(insertIndex < 0) {
2864            allocConstraintsSorted[num_sorted].physicalReg = (PhysicalReg)regT;
2865            allocConstraintsSorted[num_sorted].count = count;
2866            num_sorted++;
2867        } else {
2868            for(ii = num_sorted-1; ii >= insertIndex; ii--) {
2869                allocConstraintsSorted[ii+1] = allocConstraintsSorted[ii];
2870            }
2871            allocConstraintsSorted[insertIndex] = allocConstraints[jj];
2872            num_sorted++;
2873        }
2874    } //for jj
2875#ifdef DEBUG_ALLOC_CONSTRAINT
2876    for(jj = 0; jj < 8; jj++) {
2877        if(allocConstraintsSorted[jj].count > 0)
2878            ALOGI("%d: register %d has count %d", jj, allocConstraintsSorted[jj].physicalReg, allocConstraintsSorted[jj].count);
2879    }
2880#endif
2881    return 0;
2882}
2883//! find the entry for a given virtual register in compileTable
2884
2885//!
2886int findVirtualRegInTable(u2 vA, LowOpndRegType type, bool printError) {
2887    int k = searchCompileTable(type | LowOpndRegType_virtual, vA);
2888    if(k < 0 && printError) {
2889        ALOGE("findVirtualRegInTable virtual register %d type %d", vA, type);
2890        dvmAbort();
2891    }
2892    return k;
2893}
2894
2895//! check whether a virtual register is constant
2896
2897//! the value of the constant is stored in valuePtr; if updateRefCount is true & the VR is constant, reference count for the VR will be reduced by 1
2898int isVirtualRegConstant(int regNum, LowOpndRegType type, int* valuePtr, bool updateRefCount) {
2899
2900    OpndSize size = getRegSize(type);
2901    int k;
2902    int indexL = -1;
2903    int indexH = -1;
2904    for(k = 0; k < num_const_vr; k++) {
2905#ifdef DEBUG_CONST
2906        ALOGI("constVRTable VR %d isConst %d value %x", constVRTable[k].regNum, constVRTable[k].isConst, constVRTable[k].value);
2907#endif
2908        if(constVRTable[k].regNum == regNum) {
2909            indexL = k;
2910            continue;
2911        }
2912        if(constVRTable[k].regNum == regNum + 1 && size == OpndSize_64) {
2913            indexH = k;
2914            continue;
2915        }
2916    }
2917    bool isConstL = false;
2918    bool isConstH = false;
2919    if(indexL >= 0) {
2920        isConstL = constVRTable[indexL].isConst;
2921    }
2922    if(size == OpndSize_64 && indexH >= 0) {
2923        isConstH = constVRTable[indexH].isConst;
2924    }
2925
2926    if((isConstL || isConstH)) {
2927        if(size == OpndSize_64 && isConstH)
2928            valuePtr[1] = constVRTable[indexH].value;
2929        if(isConstL)
2930            *valuePtr = constVRTable[indexL].value;
2931    }
2932    if((isConstL && size == OpndSize_32) || (isConstL && isConstH)) {
2933        if(updateRefCount) {
2934            int indexOrig = searchCompileTable(type | LowOpndRegType_virtual, regNum);
2935            if(indexOrig < 0) ALOGE("can't find VR in isVirtualRegConstant num %d type %d", regNum, type);
2936            decreaseRefCount(indexOrig);
2937        }
2938#ifdef DEBUG_CONST
2939        ALOGI("VR %d %d is const case", regNum, type);
2940#endif
2941        return 3;
2942    }
2943    if(size == OpndSize_32) return 0;
2944    if(isConstL) return 1;
2945    if(isConstH) return 2;
2946    return 0;
2947}
2948
2949//!update RegAccessType of virtual register vB given RegAccessType of vA
2950
2951//!RegAccessType can be D, L, H
2952//!D means full definition, L means only lower-half is defined, H means only higher half is defined
2953//!we say a VR has no exposed usage in a basic block if the accessType is D or DU
2954//!we say a VR has exposed usage in a basic block if the accessType is not D nor DU
2955//!we say a VR has exposed usage in other basic blocks (hasOtherExposedUsage) if
2956//!  there exists another basic block where VR has exposed usage in that basic block
2957//!A can be U, D, L, H, UD, UL, UH, DU, LU, HU (merged result)
2958//!B can be U, D, UD, DU (an entry for the current bytecode)
2959//!input isAPartiallyOverlapB can be any value between -1 to 6
2960//!if A is xmm: gp B lower half of A, (isAPartiallyOverlapB is 1)
2961//!             gp B higher half of A, (isAPartiallyOverlapB is 2)
2962//!             lower half of A covers the higher half of xmm B  (isAPartiallyOverlapB is 4)
2963//!             higher half of A covers the lower half of xmm B   (isAPartiallyOverlapB is 3)
2964//!if A is gp:  A covers the lower half of xmm B, (isAPartiallyOverlapB is 5)
2965//!             A covers the higher half of xmm B (isAPartiallyOverlapB is 6)
2966RegAccessType updateAccess1(RegAccessType A, OverlapCase isAPartiallyOverlapB) {
2967    if(A == REGACCESS_D || A == REGACCESS_DU || A == REGACCESS_UD) {
2968        if(isAPartiallyOverlapB == OVERLAP_ALIGN) return REGACCESS_D;
2969        if(isAPartiallyOverlapB == OVERLAP_B_IS_LOW_OF_A || isAPartiallyOverlapB == OVERLAP_B_IS_HIGH_OF_A)
2970            return REGACCESS_D;
2971        if(isAPartiallyOverlapB == OVERLAP_LOW_OF_A_IS_HIGH_OF_B || isAPartiallyOverlapB == OVERLAP_A_IS_LOW_OF_B)
2972            return REGACCESS_L;
2973        return REGACCESS_H;
2974    }
2975    if(A == REGACCESS_L || A == REGACCESS_LU || A == REGACCESS_UL) {
2976        if(isAPartiallyOverlapB == OVERLAP_ALIGN || isAPartiallyOverlapB == OVERLAP_A_IS_LOW_OF_B)
2977            return REGACCESS_L;
2978        if(isAPartiallyOverlapB == OVERLAP_B_IS_LOW_OF_A) return REGACCESS_D;
2979        if(isAPartiallyOverlapB == OVERLAP_B_IS_HIGH_OF_A || isAPartiallyOverlapB == OVERLAP_LOW_OF_A_IS_HIGH_OF_B)
2980            return REGACCESS_N;
2981        if(isAPartiallyOverlapB == OVERLAP_HIGH_OF_A_IS_LOW_OF_B || isAPartiallyOverlapB == OVERLAP_A_IS_HIGH_OF_B)
2982            return REGACCESS_H;
2983    }
2984    if(A == REGACCESS_H || A == REGACCESS_HU || A == REGACCESS_UH) {
2985        if(isAPartiallyOverlapB == OVERLAP_ALIGN || isAPartiallyOverlapB == OVERLAP_A_IS_HIGH_OF_B)
2986            return REGACCESS_H;
2987        if(isAPartiallyOverlapB == OVERLAP_B_IS_LOW_OF_A || isAPartiallyOverlapB == OVERLAP_HIGH_OF_A_IS_LOW_OF_B)
2988            return REGACCESS_N;
2989        if(isAPartiallyOverlapB == OVERLAP_B_IS_HIGH_OF_A) return REGACCESS_D;
2990        if(isAPartiallyOverlapB == OVERLAP_LOW_OF_A_IS_HIGH_OF_B || isAPartiallyOverlapB == OVERLAP_A_IS_LOW_OF_B)
2991            return REGACCESS_L;
2992    }
2993    return REGACCESS_N;
2994}
2995//! merge RegAccessType C1 with RegAccessType C2
2996
2997//!C can be N,L,H,D
2998RegAccessType updateAccess2(RegAccessType C1, RegAccessType C2) {
2999    if(C1 == REGACCESS_D || C2 == REGACCESS_D) return REGACCESS_D;
3000    if(C1 == REGACCESS_N) return C2;
3001    if(C2 == REGACCESS_N) return C1;
3002    if(C1 == REGACCESS_L && C2 == REGACCESS_H) return REGACCESS_D;
3003    if(C1 == REGACCESS_H && C2 == REGACCESS_L) return REGACCESS_D;
3004    return C1;
3005}
3006//! merge RegAccessType C with RegAccessType B
3007
3008//!C can be N,L,H,D
3009//!B can be U, D, UD, DU
3010RegAccessType updateAccess3(RegAccessType C, RegAccessType B) {
3011    if(B == REGACCESS_D || B == REGACCESS_DU) return B; //no exposed usage
3012    if(B == REGACCESS_U || B == REGACCESS_UD) {
3013        if(C == REGACCESS_N) return B;
3014        if(C == REGACCESS_L) return REGACCESS_LU;
3015        if(C == REGACCESS_H) return REGACCESS_HU;
3016        if(C == REGACCESS_D) return REGACCESS_DU;
3017    }
3018    return B;
3019}
3020//! merge RegAccessType A with RegAccessType B
3021
3022//!argument isBPartiallyOverlapA can be any value between -1 and 2
3023//!0 means fully overlapping, 1 means B is the lower half, 2 means B is the higher half
3024RegAccessType mergeAccess2(RegAccessType A, RegAccessType B, OverlapCase isBPartiallyOverlapA) {
3025    if(A == REGACCESS_UD || A == REGACCESS_UL || A == REGACCESS_UH ||
3026       A == REGACCESS_DU || A == REGACCESS_LU || A == REGACCESS_HU) return A;
3027    if(A == REGACCESS_D) {
3028        if(B == REGACCESS_D) return REGACCESS_D;
3029        if(B == REGACCESS_U) return REGACCESS_DU;
3030        if(B == REGACCESS_UD) return REGACCESS_DU;
3031        if(B == REGACCESS_DU) return B;
3032    }
3033    if(A == REGACCESS_U) {
3034        if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_UL;
3035        if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_UH;
3036        if(B == REGACCESS_D && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_UD;
3037        if(B == REGACCESS_U) return A;
3038        if(B == REGACCESS_UD && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_UL;
3039        if(B == REGACCESS_UD && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_UH;
3040        if(B == REGACCESS_UD && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_UD;
3041        if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_UL;
3042        if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_UH;
3043        if(B == REGACCESS_DU && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_UD;
3044    }
3045    if(A == REGACCESS_L) {
3046        if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_L;
3047        if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_D;
3048        if(B == REGACCESS_D && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_D;
3049        if(B == REGACCESS_U) return REGACCESS_LU;
3050        if(B == REGACCESS_UD) return REGACCESS_LU;
3051        if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_LU;
3052        if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_DU;
3053        if(B == REGACCESS_DU && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_DU;
3054    }
3055    if(A == REGACCESS_H) {
3056        if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_D;
3057        if(B == REGACCESS_D && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_H;
3058        if(B == REGACCESS_D && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_D;
3059        if(B == REGACCESS_U) return REGACCESS_HU;
3060        if(B == REGACCESS_UD) return REGACCESS_HU;
3061        if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_LOW_OF_A) return REGACCESS_DU;
3062        if(B == REGACCESS_DU && isBPartiallyOverlapA == OVERLAP_B_COVER_HIGH_OF_A) return REGACCESS_HU;
3063        if(B == REGACCESS_DU && (isBPartiallyOverlapA == OVERLAP_B_COVER_A)) return REGACCESS_DU;
3064    }
3065    return REGACCESS_N;
3066}
3067
3068//!determines which part of a use is from a given definition
3069
3070//!reachingDefLive tells us which part of the def is live at this point
3071//!isDefPartiallyOverlapUse can be any value between -1 and 2
3072RegAccessType setAccessTypeOfUse(OverlapCase isDefPartiallyOverlapUse, RegAccessType reachingDefLive) {
3073    if(isDefPartiallyOverlapUse == OVERLAP_B_COVER_A)
3074        return reachingDefLive;
3075    if(isDefPartiallyOverlapUse == OVERLAP_B_COVER_LOW_OF_A) { //def covers the low half of use
3076        return REGACCESS_L;
3077    }
3078    if(isDefPartiallyOverlapUse == OVERLAP_B_COVER_HIGH_OF_A) {
3079        return REGACCESS_H;
3080    }
3081    return REGACCESS_N;
3082}
3083
3084//! search currentBB->defUseTable to find a def for regNum at offsetPC
3085
3086//!
3087DefUsePair* searchDefUseTable(int offsetPC, int regNum, LowOpndRegType pType) {
3088    DefUsePair* ptr = currentBB->defUseTable;
3089    while(ptr != NULL) {
3090        if(ptr->def.offsetPC == offsetPC &&
3091           ptr->def.regNum == regNum &&
3092           ptr->def.physicalType == pType) {
3093            return ptr;
3094        }
3095        ptr = ptr->next;
3096    }
3097    return NULL;
3098}
3099void printDefUseTable() {
3100    ALOGI("PRINT defUseTable --------");
3101    DefUsePair* ptr = currentBB->defUseTable;
3102    while(ptr != NULL) {
3103        ALOGI("  def @ %x of VR %d %d has %d uses", ptr->def.offsetPC,
3104              ptr->def.regNum, ptr->def.physicalType,
3105              ptr->num_uses);
3106        DefOrUseLink* ptr2 = ptr->uses;
3107        while(ptr2 != NULL) {
3108            ALOGI("    use @ %x of VR %d %d accessType %d", ptr2->offsetPC,
3109                  ptr2->regNum,
3110                  ptr2->physicalType,
3111                  ptr2->accessType);
3112            ptr2 = ptr2->next;
3113        }
3114        ptr = ptr->next;
3115    }
3116}
3117//! when a VR is used, check whether a transfer from memory to XMM is necessary
3118
3119//!
3120int updateVRAtUse(int reg, LowOpndRegType pType, int regAll) {
3121    int k;
3122    for(k = 0; k < currentBB->num_xfer_points; k++) {
3123        if(currentBB->xferPoints[k].offsetPC == offsetPC &&
3124           currentBB->xferPoints[k].xtype == XFER_MEM_TO_XMM &&
3125           currentBB->xferPoints[k].regNum == reg &&
3126           currentBB->xferPoints[k].physicalType == pType) {
3127#ifdef DEBUG_XFER_POINTS
3128            ALOGI("XFER from memory to xmm %d", reg);
3129#endif
3130            move_mem_to_reg_noalloc(OpndSize_64,
3131                                    4*currentBB->xferPoints[k].regNum, PhysicalReg_FP, true,
3132                                    MemoryAccess_VR, currentBB->xferPoints[k].regNum,
3133                                    regAll, true);
3134        }
3135    }
3136    return 0;
3137}
3138///////////////////////////////////////////////////////////////////////////////
3139// DEAD/USELESS STATEMENT ELMINATION
3140// bytecodes can be removed if a bytecode has no side effect and the defs are not used
3141// this optimization is guarded with DSE_OPT
3142// currently, this optimization is not on, since it does not provide observable performance improvement
3143//     and it increases compilation time
3144
3145/* we remove a maximal of 40 bytecodes within a single basic block */
3146#define MAX_NUM_DEAD_PC_IN_BB 40
3147int deadPCs[MAX_NUM_DEAD_PC_IN_BB];
3148int num_dead_pc = 0;
3149//! collect all PCs that can be removed
3150
3151//! traverse each byte code in the current basic block and check whether it can be removed, if yes, update deadPCs
3152void getDeadStmts() {
3153    BasicBlock_O1* bb = currentBB;
3154    int k;
3155    num_dead_pc = 0;
3156    //traverse each bytecode in the basic block
3157    //update offsetPC, rPC & inst
3158    u2* rPC_start = (u2*)currentMethod->insns;
3159    MIR* mir;
3160    for(mir = bb->jitBasicBlock->firstMIRInsn; mir; mir = mir->next) {
3161        offsetPC = mir->seqNum;
3162        rPC = rPC_start + mir->offset;
3163        if(mir->dalvikInsn.opcode >= kNumPackedOpcodes) continue;
3164#ifdef DEBUG_DSE
3165        ALOGI("DSE: offsetPC %x", offsetPC);
3166#endif
3167        inst = FETCH(0);
3168        bool isDeadStmt = true;
3169        getVirtualRegInfo(infoByteCode);
3170        u2 inst_op = INST_INST(inst);
3171	//skip bytecodes with side effect
3172        if(inst_op != OP_CONST_STRING && inst_op != OP_CONST_STRING_JUMBO &&
3173           inst_op != OP_MOVE && inst_op != OP_MOVE_OBJECT &&
3174           inst_op != OP_MOVE_FROM16 && inst_op != OP_MOVE_OBJECT_FROM16 &&
3175           inst_op != OP_MOVE_16 && inst_op != OP_CONST_CLASS &&
3176           inst_op != OP_MOVE_OBJECT_16 && inst_op != OP_MOVE_WIDE &&
3177           inst_op != OP_MOVE_WIDE_FROM16 && inst_op != OP_MOVE_WIDE_16 &&
3178           inst_op != OP_MOVE_RESULT && inst_op != OP_MOVE_RESULT_OBJECT) {
3179            continue;
3180        }
3181        //some statements do not define any VR!!!
3182        int num_defs = 0;
3183        for(k = 0; k < num_regs_per_bytecode; k++) {
3184            if(infoByteCode[k].accessType == REGACCESS_D ||
3185               infoByteCode[k].accessType == REGACCESS_UD ||
3186               infoByteCode[k].accessType == REGACCESS_DU) { //search defUseTable
3187                num_defs++;
3188                DefUsePair* indexT = searchDefUseTable(offsetPC, infoByteCode[k].regNum, infoByteCode[k].physicalType);
3189                if(indexT == NULL) {
3190                    ALOGE("def at %x of VR %d %d not in table",
3191                           offsetPC, infoByteCode[k].regNum, infoByteCode[k].physicalType);
3192                    return;
3193                }
3194                if(indexT->num_uses > 0) {
3195                    isDeadStmt = false;
3196                    break;
3197                } else {
3198#ifdef DEBUG_DSE
3199                    ALOGI("DSE: num_uses is %d for def at %d for VR %d %d", indexT->num_uses,
3200                          offsetPC, infoByteCode[k].regNum, infoByteCode[k].physicalType);
3201#endif
3202                }
3203            }
3204        } //for k
3205        if(num_defs == 0) isDeadStmt = false;
3206        if(isDeadStmt && num_dead_pc < MAX_NUM_DEAD_PC_IN_BB) {
3207#ifdef DEBUG_DSE
3208            ALOGI("DSE: stmt at %x is dead", offsetPC);
3209#endif
3210            deadPCs[num_dead_pc++] = offsetPC;
3211        }
3212    } //for offsetPC
3213#ifdef DEBUG_DSE
3214    ALOGI("Dead Stmts: ");
3215    for(k = 0; k < num_dead_pc; k++) ALOGI("%x ", deadPCs[k]);
3216    ALOGI("");
3217#endif
3218}
3219//! entry point to remove dead statements
3220
3221//! recursively call getDeadStmts and remove uses in defUseTable that are from a dead PC
3222//! until there is no change to number of dead PCs
3223void removeDeadDefs() {
3224    int k;
3225    int deadPCs_2[MAX_NUM_DEAD_PC_IN_BB];
3226    int num_dead_pc_2 = 0;
3227    getDeadStmts();
3228    if(num_dead_pc == 0) return;
3229    DefUsePair* ptr = NULL;
3230    DefOrUseLink* ptrUse = NULL;
3231    DefOrUseLink* ptrUse_prev = NULL;
3232    while(true) {
3233        //check all the uses in defUseTable and remove any use that is from a dead PC
3234        ptr = currentBB->defUseTable;
3235        while(ptr != NULL) {
3236            int k3;
3237            ptrUse = ptr->uses;
3238            ptrUse_prev = NULL;
3239            while(ptrUse != NULL) {
3240                bool isIn = false;
3241                for(k3 = 0; k3 < num_dead_pc; k3++) {
3242                    if(ptrUse->offsetPC == deadPCs[k3]) {
3243                        isIn = true;
3244                        break;
3245                    }
3246                }//k3
3247                if(!isIn) {
3248                    ptrUse_prev = ptrUse;
3249                    ptrUse = ptrUse->next; //next use
3250                }
3251                else {
3252                    //go to next use and remove ptrUse
3253#ifdef DEBUG_DSE
3254                    ALOGI("DSE: remove usage at offsetPC %d reached by def at %d", ptrUse->offsetPC,
3255                           ptr->def.offsetPC);
3256#endif
3257                    DefOrUseLink* nextP = ptrUse->next;
3258                    if(ptrUse == ptr->useTail) ptr->useTail = ptrUse_prev;
3259                    free(ptrUse);
3260                    if(ptrUse_prev == NULL) {
3261                        ptr->uses = nextP;
3262                    } else {
3263                        ptrUse_prev->next = nextP;
3264                    }
3265                    ptrUse = nextP; //do not update ptrUse_prev
3266                    ptr->num_uses--;
3267                }
3268            }//while ptrUse
3269            ptr = ptr->next;
3270        }//while ptr
3271	//save deadPCs in deadPCs_2
3272        num_dead_pc_2 = num_dead_pc;
3273        for(k = 0; k < num_dead_pc_2; k++)
3274            deadPCs_2[k] = deadPCs[k];
3275	//update deadPCs
3276        getDeadStmts();
3277	//if no change to number of dead PCs, break out of the while loop
3278        if(num_dead_pc_2 == num_dead_pc) break;
3279    }//while
3280#ifdef DEBUG_DSE
3281    ALOGI("DSE: DEAD STMTS: ");
3282    for(k = 0; k < num_dead_pc; k++) {
3283        ALOGI("%d ", deadPCs[k]);
3284    }
3285    ALOGI("");
3286#endif
3287}
3288/////////////////////////////////////////////////////////////
3289//!search memVRTable for a given virtual register
3290
3291//!
3292int searchMemTable(int regNum) {
3293    int k;
3294    for(k = 0; k < num_memory_vr; k++) {
3295        if(memVRTable[k].regNum == regNum) {
3296            return k;
3297        }
3298    }
3299    ALOGW("in searchMemTable can't find VR %d num_memory_vr %d", regNum, num_memory_vr);
3300    return -1;
3301}
3302/////////////////////////////////////////////////////////////////////////
3303// A VR is already in memory && NULL CHECK
3304//!check whether the latest content of a VR is in memory
3305
3306//!
3307bool isInMemory(int regNum, OpndSize size) {
3308    int indexL = searchMemTable(regNum);
3309    int indexH = -1;
3310    if(size == OpndSize_64) indexH = searchMemTable(regNum+1);
3311    if(indexL < 0) return false;
3312    if(size == OpndSize_64 && indexH < 0) return false;
3313    if(!memVRTable[indexL].inMemory) return false;
3314    if(size == OpndSize_64 && (!memVRTable[indexH].inMemory)) return false;
3315    return true;
3316}
3317//!set field inMemory of memVRTable to true
3318
3319//!
3320void setVRToMemory(int regNum, OpndSize size) {
3321    int indexL = searchMemTable(regNum);
3322    int indexH = -1;
3323    if(size == OpndSize_64) indexH = searchMemTable(regNum+1);
3324    if(indexL < 0) {
3325        ALOGE("VR %d not in memVRTable", regNum);
3326        return;
3327    }
3328    memVRTable[indexL].inMemory = true;
3329    if(size == OpndSize_64) {
3330        if(indexH < 0) {
3331            ALOGE("VR %d not in memVRTable", regNum+1);
3332            return;
3333        }
3334        memVRTable[indexH].inMemory = true;
3335    }
3336}
3337//! check whether null check for a VR is performed previously
3338
3339//!
3340bool isVRNullCheck(int regNum, OpndSize size) {
3341    if(size != OpndSize_32) {
3342        ALOGE("isVRNullCheck size should be 32");
3343        dvmAbort();
3344    }
3345    int indexL = searchMemTable(regNum);
3346    if(indexL < 0) {
3347        ALOGE("VR %d not in memVRTable", regNum);
3348        return false;
3349    }
3350    return memVRTable[indexL].nullCheckDone;
3351}
3352bool isVRBoundCheck(int vr_array, int vr_index) {
3353    int indexL = searchMemTable(vr_array);
3354    if(indexL < 0) {
3355        ALOGE("isVRBoundCheck: VR %d not in memVRTable", vr_array);
3356        return false;
3357    }
3358    if(memVRTable[indexL].boundCheck.indexVR == vr_index)
3359        return memVRTable[indexL].boundCheck.checkDone;
3360    return false;
3361}
3362//! set nullCheckDone in memVRTable to true
3363
3364//!
3365void setVRNullCheck(int regNum, OpndSize size) {
3366    if(size != OpndSize_32) {
3367        ALOGE("setVRNullCheck size should be 32");
3368        dvmAbort();
3369    }
3370    int indexL = searchMemTable(regNum);
3371    if(indexL < 0) {
3372        ALOGE("VR %d not in memVRTable", regNum);
3373        return;
3374    }
3375    memVRTable[indexL].nullCheckDone = true;
3376}
3377void setVRBoundCheck(int vr_array, int vr_index) {
3378    int indexL = searchMemTable(vr_array);
3379    if(indexL < 0) {
3380        ALOGE("setVRBoundCheck: VR %d not in memVRTable", vr_array);
3381        return;
3382    }
3383    memVRTable[indexL].boundCheck.indexVR = vr_index;
3384    memVRTable[indexL].boundCheck.checkDone = true;
3385}
3386void clearVRBoundCheck(int regNum, OpndSize size) {
3387    int k;
3388    for(k = 0; k < num_memory_vr; k++) {
3389        if(memVRTable[k].regNum == regNum ||
3390           (size == OpndSize_64 && memVRTable[k].regNum == regNum+1)) {
3391            memVRTable[k].boundCheck.checkDone = false;
3392        }
3393        if(memVRTable[k].boundCheck.indexVR == regNum ||
3394           (size == OpndSize_64 && memVRTable[k].boundCheck.indexVR == regNum+1)) {
3395            memVRTable[k].boundCheck.checkDone = false;
3396        }
3397    }
3398}
3399//! set inMemory of memVRTable to false
3400
3401//!
3402void clearVRToMemory(int regNum, OpndSize size) {
3403    int indexL = searchMemTable(regNum);
3404    int indexH = -1;
3405    if(size == OpndSize_64) indexH = searchMemTable(regNum+1);
3406    if(indexL >= 0) {
3407        memVRTable[indexL].inMemory = false;
3408    }
3409    if(size == OpndSize_64 && indexH >= 0) {
3410        memVRTable[indexH].inMemory = false;
3411    }
3412}
3413//! set nullCheckDone of memVRTable to false
3414
3415//!
3416void clearVRNullCheck(int regNum, OpndSize size) {
3417    int indexL = searchMemTable(regNum);
3418    int indexH = -1;
3419    if(size == OpndSize_64) indexH = searchMemTable(regNum+1);
3420    if(indexL >= 0) {
3421        memVRTable[indexL].nullCheckDone = false;
3422    }
3423    if(size == OpndSize_64 && indexH >= 0) {
3424        memVRTable[indexH].nullCheckDone = false;
3425    }
3426}
3427
3428//! Extend Virtual Register life
3429
3430//! Requests that the life of a specific virtual register be extended. This ensures
3431//! that its mapping to a physical register won't be canceled while the extension
3432//! request is valid. NOTE: This does not support 64-bit values (when two adjacent
3433//! VRs are used)
3434//! @see cancelVRFreeDelayRequest
3435//! @see getVRFreeDelayRequested
3436//! @see VRFreeDelayFlags
3437//! @param regNum is the VR number
3438//! @param reason explains why freeing must be delayed. A single or combination
3439//! of VRFreeDelayFlags should be used.
3440//! @return negative value if request failed
3441int requestVRFreeDelay(int regNum, u4 reason) {
3442    //TODO Add 64-bit operand support when needed
3443    int indexL = searchMemTable(regNum);
3444    if(indexL >= 0) {
3445        memVRTable[indexL].delayFreeFlags |= reason;
3446    } else {
3447        ALOGE("requestVRFreeDelay: VR %d not in memVRTable", regNum);
3448    }
3449    return indexL;
3450}
3451
3452//! Cancel request for virtual register life extension
3453
3454//! Cancels any outstanding requests to extended liveness of VR. Additionally,
3455//! this ensures that if the VR is no longer life after this point, it will
3456//! no longer be associated with a physical register which can then be reused.
3457//! NOTE: This does not support 64-bit values (when two adjacent VRs are used)
3458//! @see requestVRFreeDelay
3459//! @see getVRFreeDelayRequested
3460//! @see VRFreeDelayFlags
3461//! @param regNum is the VR number
3462//! @param reason explains what freeing delay request should be canceled. A single
3463//! or combination of VRFreeDelayFlags should be used.
3464void cancelVRFreeDelayRequest(int regNum, u4 reason) {
3465    //TODO Add 64-bit operand support when needed
3466    bool needCallToFreeReg = false;
3467    int indexL = searchMemTable(regNum);
3468    if(indexL >= 0) {
3469        if((memVRTable[indexL].delayFreeFlags & reason) != VRDELAY_NONE) { // don't cancel delay if it wasn't requested
3470            memVRTable[indexL].delayFreeFlags ^= reason; // only cancel this particular reason, not all others
3471            if(memVRTable[indexL].delayFreeFlags == VRDELAY_NONE)
3472                needCallToFreeReg = true; // freeReg might want to free this VR now if there is no longer a valid delay
3473        }
3474    }
3475    if(needCallToFreeReg)
3476        freeReg(true);
3477}
3478
3479//! Gets status of virtual register free delay request
3480
3481//! Finds out if there was a delay request for freeing this VR.
3482//! NOTE: This does not support 64-bit values (when two adjacent VRs are used)
3483//! @see requestVRFreeDelay
3484//! @see cancelVRFreeDelayRequest
3485//! @param regNum is the VR number
3486//! @return true if VR has an active delay request
3487bool getVRFreeDelayRequested(int regNum) {
3488    //TODO Add 64-bit operand support when needed
3489    int indexL = searchMemTable(regNum);
3490    if(indexL >= 0) {
3491        if(memVRTable[indexL].delayFreeFlags != VRDELAY_NONE)
3492            return true;
3493        return false;
3494    }
3495    return false;
3496}
3497
3498//! find the basic block that a bytecode is in
3499
3500//!
3501BasicBlock_O1* findForOffset(int offset) {
3502    int k;
3503    for(k = 0; k < num_bbs_for_method; k++) {
3504        if(method_bbs_sorted[k]->pc_start <= offset && method_bbs_sorted[k]->pc_end > offset)
3505            return method_bbs_sorted[k];
3506    }
3507    return NULL;
3508}
3509void dump_CFG(Method* method);
3510
3511int current_bc_size = -1;
3512
3513//! check whether a virtual register is used in a basic block
3514
3515//!
3516bool isUsedInBB(int regNum, int type, BasicBlock_O1* bb) {
3517    int k;
3518    for(k = 0; k < bb->num_regs; k++) {
3519        if(bb->infoBasicBlock[k].physicalType == (type&MASK_FOR_TYPE) && bb->infoBasicBlock[k].regNum == regNum)
3520            return true;
3521    }
3522    return false;
3523}
3524//! return the index to infoBasicBlock for a given virtual register
3525
3526//! return -1 if not found
3527int searchVirtualInfoOfBB(LowOpndRegType type, int regNum, BasicBlock_O1* bb) {
3528    int k;
3529    for(k = 0; k < bb->num_regs; k++) {
3530        if(bb->infoBasicBlock[k].physicalType == type && bb->infoBasicBlock[k].regNum == regNum)
3531            return k;
3532    }
3533    return -1;
3534}
3535//! return the index to compileTable for a given virtual register
3536
3537//! return -1 if not found
3538int searchCompileTable(int type, int regNum) { //returns the index
3539    int k;
3540    for(k = 0; k < num_compile_entries; k++) {
3541        if(compileTable[k].physicalType == type && compileTable[k].regNum == regNum)
3542            return k;
3543    }
3544    return -1;
3545}
3546//!check whether a physical register for a variable with typeA will work for another variable with typeB
3547
3548//!Type LowOpndRegType_ss is compatible with type LowOpndRegType_xmm
3549bool matchType(int typeA, int typeB) {
3550    if((typeA & MASK_FOR_TYPE) == (typeB & MASK_FOR_TYPE)) return true;
3551    if((typeA & MASK_FOR_TYPE) == LowOpndRegType_ss &&
3552       (typeB & MASK_FOR_TYPE) == LowOpndRegType_xmm) return true;
3553    if((typeA & MASK_FOR_TYPE) == LowOpndRegType_xmm &&
3554       (typeB & MASK_FOR_TYPE) == LowOpndRegType_ss) return true;
3555    return false;
3556}
3557//!check whether a virtual register is used in the current bytecode
3558
3559//!
3560bool isUsedInByteCode(int regNum, int type) {
3561    getVirtualRegInfo(infoByteCode);
3562    int k;
3563    for(k = 0; k < num_regs_per_bytecode; k++) {
3564        if(infoByteCode[k].physicalType == (type&MASK_FOR_TYPE) && infoByteCode[k].regNum == regNum)
3565            return true;
3566    }
3567    return false;
3568}
3569//! obsolete
3570bool defineFirst(int atype) {
3571    if(atype == REGACCESS_D || atype == REGACCESS_L || atype == REGACCESS_H || atype == REGACCESS_DU)
3572        return true;
3573    return false;
3574}
3575//!check whether a virtual register is updated in a basic block
3576
3577//!
3578bool notUpdated(RegAccessType atype) {
3579    if(atype == REGACCESS_U) return true;
3580    return false;
3581}
3582//!check whether a virtual register has exposed usage within a given basic block
3583
3584//!
3585bool hasExposedUsage2(BasicBlock_O1* bb, int index) {
3586    RegAccessType atype = bb->infoBasicBlock[index].accessType;
3587    if(atype == REGACCESS_D || atype == REGACCESS_L || atype == REGACCESS_H || atype == REGACCESS_DU)
3588        return false;
3589    return true;
3590}
3591//! return the spill location that is not used
3592
3593//!
3594int getSpillIndex(bool isGLUE, OpndSize size) {
3595    if(isGLUE) return 0;
3596    int k;
3597    for(k = 1; k <= MAX_SPILL_JIT_IA-1; k++) {
3598        if(size == OpndSize_64) {
3599            if(k < MAX_SPILL_JIT_IA-1 && spillIndexUsed[k] == 0 && spillIndexUsed[k+1] == 0)
3600                return k;
3601        }
3602        else if(spillIndexUsed[k] == 0) {
3603            return k;
3604        }
3605    }
3606    ALOGE("can't find spill position in spillLogicalReg");
3607    return -1;
3608}
3609//!this is called before generating a native code, it sets entries in array canSpillReg to true
3610
3611//!startNativeCode must be paired with endNativeCode
3612void startNativeCode(int vr_num, int vr_type) {
3613    int k;
3614    for(k = 0; k < PhysicalReg_Null; k++) {
3615        canSpillReg[k] = true;
3616    }
3617    inGetVR_num = vr_num;
3618    inGetVR_type = vr_type;
3619}
3620//! called right after generating a native code
3621
3622//!It sets entries in array canSpillReg to true and reset inGetVR_num to -1
3623void endNativeCode() {
3624    int k;
3625    for(k = 0; k < PhysicalReg_Null; k++) {
3626        canSpillReg[k] = true;
3627    }
3628    inGetVR_num = -1;
3629}
3630//! set canSpillReg[physicalReg] to false
3631
3632//!
3633void donotSpillReg(int physicalReg) {
3634    canSpillReg[physicalReg] = false;
3635}
3636//! set canSpillReg[physicalReg] to true
3637
3638//!
3639void doSpillReg(int physicalReg) {
3640    canSpillReg[physicalReg] = true;
3641}
3642//! touch hardcoded register %ecx and reduce its reference count
3643
3644//!
3645int touchEcx() {
3646    //registerAlloc will spill logical reg that is mapped to ecx
3647    //registerAlloc will reduce refCount
3648    registerAlloc(LowOpndRegType_gp, PhysicalReg_ECX, true, true);
3649    return 0;
3650}
3651//! touch hardcoded register %eax and reduce its reference count
3652
3653//!
3654int touchEax() {
3655    registerAlloc(LowOpndRegType_gp, PhysicalReg_EAX, true, true);
3656    return 0;
3657}
3658int touchEsi() {
3659    registerAlloc(LowOpndRegType_gp, PhysicalReg_ESI, true, true);
3660    return 0;
3661}
3662int touchXmm1() {
3663    registerAlloc(LowOpndRegType_xmm, XMM_1, true, true);
3664    return 0;
3665}
3666int touchEbx() {
3667    registerAlloc(LowOpndRegType_gp, PhysicalReg_EBX, true, true);
3668    return 0;
3669}
3670
3671//! touch hardcoded register %edx and reduce its reference count
3672
3673//!
3674int touchEdx() {
3675    registerAlloc(LowOpndRegType_gp, PhysicalReg_EDX, true, true);
3676    return 0;
3677}
3678
3679#ifdef HACK_FOR_DEBUG
3680//for debugging purpose, instructions are added at a certain place
3681bool hacked = false;
3682void hackBug() {
3683  if(!hacked && iget_obj_inst == 13) {
3684#if 0
3685    move_reg_to_reg_noalloc(OpndSize_32, PhysicalReg_EBX, true, PhysicalReg_ECX, true);
3686    //move from ebx to ecx & update compileTable for v3
3687    int tIndex = searchCompileTable(LowOpndRegType_virtual | LowOpndRegType_gp, 3);
3688    if(tIndex < 0) ALOGE("hack can't find VR3");
3689    compileTable[tIndex].physicalReg = PhysicalReg_ECX;
3690#else
3691    move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EBX, true, 12, PhysicalReg_FP, true);
3692#endif
3693  }
3694}
3695void hackBug2() {
3696  if(!hacked && iget_obj_inst == 13) {
3697    dump_imm_mem_noalloc(Mnemonic_MOV, OpndSize_32, 0, 12, PhysicalReg_FP, true);
3698    hacked = true;
3699  }
3700}
3701#endif
3702
3703//! this function is called before calling a helper function or a vm function
3704int beforeCall(const char* target) { //spill all live registers
3705    if(currentBB == NULL) return -1;
3706
3707    /* special case for ncgGetEIP: this function only updates %edx */
3708    if(!strcmp(target, "ncgGetEIP")) {
3709        touchEdx();
3710        return -1;
3711    }
3712
3713    /* these functions use %eax for the return value */
3714    if((!strcmp(target, "dvmInstanceofNonTrivial")) ||
3715       (!strcmp(target, "dvmUnlockObject")) ||
3716       (!strcmp(target, "dvmAllocObject")) ||
3717       (!strcmp(target, "dvmAllocArrayByClass")) ||
3718       (!strcmp(target, "dvmAllocPrimitiveArray")) ||
3719       (!strcmp(target, "dvmInterpHandleFillArrayData")) ||
3720       (!strcmp(target, "dvmFindInterfaceMethodInCache")) ||
3721       (!strcmp(target, "dvmNcgHandlePackedSwitch")) ||
3722       (!strcmp(target, "dvmNcgHandleSparseSwitch")) ||
3723       (!strcmp(target, "dvmCanPutArrayElement")) ||
3724       (!strcmp(target, "moddi3")) || (!strcmp(target, "divdi3")) ||
3725       (!strcmp(target, "execute_inline"))
3726       || (!strcmp(target, "dvmJitToPatchPredictedChain"))
3727       || (!strcmp(target, "dvmJitHandlePackedSwitch"))
3728       || (!strcmp(target, "dvmJitHandleSparseSwitch"))
3729       ) {
3730        touchEax();
3731    }
3732
3733    //these two functions also use %edx for the return value
3734    if((!strcmp(target, "moddi3")) || (!strcmp(target, "divdi3"))) {
3735        touchEdx();
3736    }
3737    if((!strcmp(target, ".new_instance_helper"))) {
3738        touchEsi(); touchEax();
3739    }
3740#if defined(ENABLE_TRACING)
3741    if((!strcmp(target, "common_periodicChecks4"))) {
3742        touchEdx();
3743    }
3744#endif
3745    if((!strcmp(target, ".const_string_helper"))) {
3746        touchEcx(); touchEax();
3747    }
3748    if((!strcmp(target, ".check_cast_helper"))) {
3749        touchEbx(); touchEsi();
3750    }
3751    if((!strcmp(target, ".instance_of_helper"))) {
3752        touchEbx(); touchEsi(); touchEcx();
3753    }
3754    if((!strcmp(target, ".monitor_enter_helper"))) {
3755        touchEbx();
3756    }
3757    if((!strcmp(target, ".monitor_exit_helper"))) {
3758        touchEbx();
3759    }
3760    if((!strcmp(target, ".aget_wide_helper"))) {
3761        touchEbx(); touchEcx(); touchXmm1();
3762    }
3763    if((!strcmp(target, ".aget_helper")) || (!strcmp(target, ".aget_char_helper")) ||
3764       (!strcmp(target, ".aget_short_helper")) || (!strcmp(target, ".aget_bool_helper")) ||
3765       (!strcmp(target, ".aget_byte_helper"))) {
3766        touchEbx(); touchEcx(); touchEdx();
3767    }
3768    if((!strcmp(target, ".aput_helper")) || (!strcmp(target, ".aput_char_helper")) ||
3769       (!strcmp(target, ".aput_short_helper")) || (!strcmp(target, ".aput_bool_helper")) ||
3770       (!strcmp(target, ".aput_byte_helper")) || (!strcmp(target, ".aput_wide_helper"))) {
3771        touchEbx(); touchEcx(); touchEdx();
3772    }
3773    if((!strcmp(target, ".sput_helper")) || (!strcmp(target, ".sput_wide_helper"))) {
3774        touchEdx(); touchEax();
3775    }
3776    if((!strcmp(target, ".sget_helper"))) {
3777        touchEdx(); touchEcx();
3778    }
3779    if((!strcmp(target, ".sget_wide_helper"))) {
3780        touchEdx(); touchXmm1();
3781    }
3782    if((!strcmp(target, ".aput_obj_helper"))) {
3783        touchEdx(); touchEcx(); touchEax();
3784    }
3785    if((!strcmp(target, ".iput_helper")) || (!strcmp(target, ".iput_wide_helper"))) {
3786        touchEbx(); touchEcx(); touchEsi();
3787    }
3788    if((!strcmp(target, ".iget_helper"))) {
3789        touchEbx(); touchEcx(); touchEdx();
3790    }
3791    if((!strcmp(target, ".iget_wide_helper"))) {
3792        touchEbx(); touchEcx(); touchXmm1();
3793    }
3794    if((!strcmp(target, ".new_array_helper"))) {
3795        touchEbx(); touchEdx(); touchEax();
3796    }
3797    if((!strcmp(target, ".invoke_virtual_helper"))) {
3798        touchEbx(); touchEcx();
3799    }
3800    if((!strcmp(target, ".invoke_direct_helper"))) {
3801        touchEsi(); touchEcx();
3802    }
3803    if((!strcmp(target, ".invoke_super_helper"))) {
3804        touchEbx(); touchEcx();
3805    }
3806    if((!strcmp(target, ".invoke_interface_helper"))) {
3807        touchEbx(); touchEcx();
3808    }
3809    if((!strcmp(target, ".invokeMethodNoRange_5_helper")) ||
3810       (!strcmp(target, ".invokeMethodNoRange_4_helper"))) {
3811        touchEbx(); touchEsi(); touchEax(); touchEdx();
3812    }
3813    if((!strcmp(target, ".invokeMethodNoRange_3_helper"))) {
3814        touchEbx(); touchEsi(); touchEax();
3815    }
3816    if((!strcmp(target, ".invokeMethodNoRange_2_helper"))) {
3817        touchEbx(); touchEsi();
3818    }
3819    if((!strcmp(target, ".invokeMethodNoRange_1_helper"))) {
3820        touchEbx();
3821    }
3822    if((!strcmp(target, ".invokeMethodRange_helper"))) {
3823        touchEdx(); touchEsi();
3824    }
3825#ifdef DEBUG_REGALLOC
3826    ALOGI("enter beforeCall");
3827#endif
3828    if(!strncmp(target, ".invokeArgsDone", 15)) resetGlue(PhysicalReg_GLUE_DVMDEX);
3829
3830    freeReg(true); //to avoid spilling dead logical registers
3831    int k;
3832    for(k = 0; k < num_compile_entries; k++) {
3833        /* before throwing an exception, if GLUE is spilled, load to %ebp
3834           this should happen at last */
3835        if(k == indexForGlue) continue;
3836        if(compileTable[k].physicalReg != PhysicalReg_Null &&
3837           (compileTable[k].physicalType & LowOpndRegType_hard) == 0) {
3838            /* handles non hardcoded variables that are in physical registers */
3839            if(!strcmp(target, "exception")) {
3840                /* before throwing an exception
3841                   update contents of all VRs in Java stack */
3842                if(!isVirtualReg(compileTable[k].physicalType)) continue;
3843                /* to have correct GC, we should update contents for L VRs as well */
3844                //if(compileTable[k].gType == GLOBALTYPE_L) continue;
3845            }
3846            if((!strcmp(target, ".const_string_resolve")) ||
3847               (!strcmp(target, ".static_field_resolve")) ||
3848               (!strcmp(target, ".inst_field_resolve")) ||
3849               (!strcmp(target, ".class_resolve")) ||
3850               (!strcmp(target, ".direct_method_resolve")) ||
3851               (!strcmp(target, ".virtual_method_resolve")) ||
3852               (!strcmp(target, ".static_method_resolve"))) {
3853               /* physical register %ebx will keep its content
3854                  but to have correct GC, we should dump content of a VR
3855                     that is mapped to %ebx */
3856                if(compileTable[k].physicalReg == PhysicalReg_EBX &&
3857                   (!isVirtualReg(compileTable[k].physicalType)))
3858                    continue;
3859            }
3860            if((!strncmp(target, "dvm", 3)) || (!strcmp(target, "moddi3")) ||
3861               (!strcmp(target, "divdi3")) ||
3862               (!strcmp(target, "fmod")) || (!strcmp(target, "fmodf"))) {
3863                /* callee-saved registers (%ebx, %esi, %ebp, %edi) will keep the content
3864                   but to have correct GC, we should dump content of a VR
3865                      that is mapped to a callee-saved register */
3866                if((compileTable[k].physicalReg == PhysicalReg_EBX ||
3867                    compileTable[k].physicalReg == PhysicalReg_ESI) &&
3868                   (!isVirtualReg(compileTable[k].physicalType)))
3869                    continue;
3870            }
3871#ifdef DEBUG_REGALLOC
3872            ALOGI("SPILL logical register %d %d in beforeCall",
3873                  compileTable[k].regNum, compileTable[k].physicalType);
3874#endif
3875            spillLogicalReg(k, true);
3876        }
3877    }
3878    if(indexForGlue >= 0 && !strcmp(target, "exception") &&
3879       compileTable[indexForGlue].physicalReg == PhysicalReg_Null) {
3880        unspillLogicalReg(indexForGlue, PhysicalReg_EBP); //load %ebp
3881    }
3882#ifdef DEBUG_REGALLOC
3883    ALOGI("exit beforeCall");
3884#endif
3885    return 0;
3886}
3887int getFreeReg(int type, int reg, int indexToCompileTable);
3888//! after calling a helper function or a VM function
3889
3890//!
3891int afterCall(const char* target) { //un-spill
3892    if(currentBB == NULL) return -1;
3893    if(!strcmp(target, "ncgGetEIP")) return -1;
3894
3895    return 0;
3896}
3897//! check whether a temporary is 8-bit
3898
3899//!
3900bool isTemp8Bit(int type, int reg) {
3901    if(currentBB == NULL) return false;
3902    if(!isTemporary(type, reg)) return false;
3903    int k;
3904    for(k = 0; k < num_temp_regs_per_bytecode; k++) {
3905        if(infoByteCodeTemp[k].physicalType == type &&
3906           infoByteCodeTemp[k].regNum == reg) {
3907            return infoByteCodeTemp[k].is8Bit;
3908        }
3909    }
3910    ALOGE("isTemp8Bit %d %d", type, reg);
3911    return false;
3912}
3913
3914/* functions to access live ranges of a VR
3915   Live range info is stored in memVRTable[].ranges, which is a linked list
3916*/
3917//! check whether a VR is live at the current bytecode
3918
3919//!
3920bool isVRLive(int vA) {
3921    int index = searchMemTable(vA);
3922    if(index < 0) {
3923        ALOGE("couldn't find VR %d in memTable", vA);
3924        return false;
3925    }
3926    LiveRange* ptr = memVRTable[index].ranges;
3927    while(ptr != NULL) {
3928        if(offsetPC >= ptr->start && offsetPC <= ptr->end) return true;
3929        ptr = ptr->next;
3930    }
3931    return false;
3932}
3933
3934//! check whether the current bytecode is the last access to a VR within a live range
3935
3936//!for 64-bit VR, return true only when true for both low half and high half
3937bool isLastByteCodeOfLiveRange(int compileIndex) {
3938    int k = compileIndex;
3939    OpndSize tSize = getRegSize(compileTable[k].physicalType);
3940    int index;
3941    LiveRange* ptr = NULL;
3942    if(tSize == OpndSize_32) {
3943        /* check live ranges for the VR */
3944        index = searchMemTable(compileTable[k].regNum);
3945        if(index < 0) {
3946            ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
3947            return false;
3948        }
3949        ptr = memVRTable[index].ranges;
3950        while(ptr != NULL) {
3951            if(offsetPC == ptr->end) return true;
3952            ptr = ptr->next;
3953        }
3954        return false;
3955    }
3956    /* size of the VR is 64 */
3957    /* check live ranges of the low half */
3958    index = searchMemTable(compileTable[k].regNum);
3959    bool tmpB = false;
3960    if(index < 0) {
3961        ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
3962        return false;
3963    }
3964    ptr = memVRTable[index].ranges;
3965    while(ptr != NULL) {
3966        if(offsetPC == ptr->end) {
3967            tmpB = true;
3968            break;
3969        }
3970        ptr = ptr->next;
3971    }
3972    if(!tmpB) return false;
3973    /* check live ranges of the high half */
3974    index = searchMemTable(compileTable[k].regNum+1);
3975    if(index < 0) {
3976        ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum+1);
3977        return false;
3978    }
3979    ptr = memVRTable[index].ranges;
3980    while(ptr != NULL) {
3981        if(offsetPC == ptr->end) {
3982            return true;
3983        }
3984        ptr = ptr->next;
3985    }
3986    return false;
3987}
3988
3989//! check whether the current bytecode is in a live range that extends to end of a basic block
3990
3991//!for 64 bit, return true if true for both low half and high half
3992bool reachEndOfBB(int compileIndex) {
3993    int k = compileIndex;
3994    OpndSize tSize = getRegSize(compileTable[k].physicalType);
3995    int index;
3996    bool retCode = false;
3997    /* check live ranges of the low half */
3998    index = searchMemTable(compileTable[k].regNum);
3999    if(index < 0) {
4000        ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
4001        return false;
4002    }
4003    LiveRange* ptr = memVRTable[index].ranges;
4004    while(ptr != NULL) {
4005        if(offsetPC >= ptr->start &&
4006           offsetPC <= ptr->end) {
4007            if(ptr->end == currentBB->pc_end) {
4008                retCode = true;
4009            }
4010            break;
4011        }
4012        ptr = ptr->next;
4013    }
4014    if(!retCode) return false;
4015    if(tSize == OpndSize_32) return true;
4016    /* check live ranges of the high half */
4017    index = searchMemTable(compileTable[k].regNum+1);
4018    if(index < 0) {
4019        ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum+1);
4020        return false;
4021    }
4022    ptr = memVRTable[index].ranges;
4023    while(ptr != NULL) {
4024        if(offsetPC >= ptr->start &&
4025           offsetPC <= ptr->end) {
4026            if(ptr->end == currentBB->pc_end) return true;
4027            return false;
4028        }
4029        ptr = ptr->next;
4030    }
4031#ifdef PRINT_WARNING
4032    ALOGW("offsetPC %d not in live range of VR %d", offsetPC, compileTable[k].regNum+1);
4033#endif
4034    return false;
4035}
4036
4037//!check whether the current bytecode is the next to last access to a VR within a live range
4038
4039//!for 64 bit, return true if true for both low half and high half
4040bool isNextToLastAccess(int compileIndex) {
4041    int k = compileIndex;
4042    OpndSize tSize = getRegSize(compileTable[k].physicalType);
4043    int index;
4044    /* check live ranges for the low half */
4045    bool retCode = false;
4046    index = searchMemTable(compileTable[k].regNum);
4047    if(index < 0) {
4048        ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
4049        return false;
4050    }
4051    LiveRange* ptr = memVRTable[index].ranges;
4052    while(ptr != NULL) {
4053        int num_access = ptr->num_access;
4054
4055        if(num_access < 2) {
4056           ptr = ptr->next;
4057           continue;
4058        }
4059
4060        if(offsetPC == ptr->accessPC[num_access-2]) {
4061           retCode = true;
4062           break;
4063        }
4064        ptr = ptr->next;
4065    }
4066    if(!retCode) return false;
4067    if(tSize == OpndSize_32) return true;
4068    /* check live ranges for the high half */
4069    index = searchMemTable(compileTable[k].regNum+1);
4070    if(index < 0) {
4071        ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum+1);
4072        return false;
4073    }
4074    ptr = memVRTable[index].ranges;
4075    while(ptr != NULL) {
4076        int num_access = ptr->num_access;
4077
4078        if(num_access < 2) {
4079           ptr = ptr->next;
4080           continue;
4081        }
4082
4083        if(offsetPC == ptr->accessPC[num_access-2]) return true;
4084        ptr = ptr->next;
4085    }
4086    return false;
4087}
4088
4089/** return the start of the next live range
4090    if there does not exist a next live range, return pc_end of the basic block
4091    for 64 bits, return the larger one for low half and high half
4092    Assume live ranges are sorted in order
4093*/
4094int getNextLiveRange(int compileIndex) {
4095    int k = compileIndex;
4096    OpndSize tSize = getRegSize(compileTable[k].physicalType);
4097    /* check live ranges of the low half */
4098    int index;
4099    index = searchMemTable(compileTable[k].regNum);
4100    if(index < 0) {
4101        ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
4102        return offsetPC;
4103    }
4104    bool found = false;
4105    int nextUse = offsetPC;
4106    LiveRange* ptr = memVRTable[index].ranges;
4107    while(ptr != NULL) {
4108        if(ptr->start > offsetPC) {
4109            nextUse = ptr->start;
4110            found = true;
4111            break;
4112        }
4113        ptr = ptr->next;
4114    }
4115    if(!found) return currentBB->pc_end;
4116    if(tSize == OpndSize_32) return nextUse;
4117
4118    /* check live ranges of the high half */
4119    found = false;
4120    index = searchMemTable(compileTable[k].regNum+1);
4121    if(index < 0) {
4122        ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum+1);
4123        return offsetPC;
4124    }
4125    int nextUse2 = offsetPC;
4126    ptr = memVRTable[index].ranges;
4127    while(ptr != NULL) {
4128        if(ptr->start > offsetPC) {
4129            nextUse2 = ptr->start;
4130            found = true;
4131            break;
4132        }
4133        ptr = ptr->next;
4134    }
4135    if(!found) return currentBB->pc_end;
4136    /* return the larger one */
4137    return (nextUse2 > nextUse ? nextUse2 : nextUse);
4138}
4139
4140/** return the next access to a variable
4141    If variable is 64-bit, get the next access to the lower half and the high half
4142        return the eariler one
4143*/
4144int getNextAccess(int compileIndex) {
4145    int k = compileIndex;
4146    OpndSize tSize = getRegSize(compileTable[k].physicalType);
4147    int index, k3;
4148    /* check live ranges of the low half */
4149    index = searchMemTable(compileTable[k].regNum);
4150    if(index < 0) {
4151        ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum);
4152        return offsetPC;
4153    }
4154    bool found = false;
4155    int nextUse = offsetPC;
4156    LiveRange* ptr = memVRTable[index].ranges;
4157    while(ptr != NULL) {
4158        if(offsetPC >= ptr->start &&
4159           offsetPC <= ptr->end) {
4160            /* offsetPC belongs to this live range */
4161            for(k3 = 0; k3 < ptr->num_access; k3++) {
4162                if(ptr->accessPC[k3] > offsetPC) {
4163                    nextUse = ptr->accessPC[k3];
4164                    break;
4165                }
4166            }
4167            found = true;
4168            break;
4169        }
4170        ptr = ptr->next;
4171    }
4172#ifdef PRINT_WARNING
4173    if(!found)
4174        ALOGW("offsetPC %d not in live range of VR %d", offsetPC, compileTable[k].regNum);
4175#endif
4176    if(tSize == OpndSize_32) return nextUse;
4177
4178    /* check live ranges of the high half */
4179    found = false;
4180    index = searchMemTable(compileTable[k].regNum+1);
4181    if(index < 0) {
4182        ALOGE("couldn't find VR %d in memTable", compileTable[k].regNum+1);
4183        return offsetPC;
4184    }
4185    int nextUse2 = offsetPC;
4186    ptr = memVRTable[index].ranges;
4187    while(ptr != NULL) {
4188        if(offsetPC >= ptr->start &&
4189           offsetPC <= ptr->end) {
4190            for(k3 = 0; k3 < ptr->num_access; k3++) {
4191                if(ptr->accessPC[k3] > offsetPC) {
4192                    nextUse2 = ptr->accessPC[k3];
4193                    break;
4194                }
4195            }
4196            found = true;
4197            break;
4198        }
4199        ptr = ptr->next;
4200    }
4201#ifdef PRINT_WARNING
4202    if(!found) ALOGW("offsetPC %d not in live range of VR %d", offsetPC, compileTable[k].regNum+1);
4203#endif
4204    /* return the earlier one */
4205    if(nextUse2 < nextUse) return nextUse2;
4206    return nextUse;
4207}
4208
4209/** free variables that are no longer in use
4210    free a temporary with reference count of zero
4211    will dump content of a GL VR to memory if necessary
4212*/
4213int freeReg(bool spillGL) {
4214    if(currentBB == NULL) return 0;
4215    int k;
4216    for(k = 0; k < num_compile_entries; k++) {
4217        if(compileTable[k].refCount == 0 && compileTable[k].physicalReg != PhysicalReg_Null) {
4218            /* check entries with reference count of zero and is mapped to a physical register */
4219            bool typeA = !isVirtualReg(compileTable[k].physicalType);
4220            bool freeCrit = true, delayFreeing = false;
4221            bool typeC = false, typeB = false, reachEnd = false;
4222            if(isVirtualReg(compileTable[k].physicalType)) {
4223                /* VRs in the compile table */
4224
4225                /* Check if delay for freeing was requested for this VR */
4226                delayFreeing = getVRFreeDelayRequested(compileTable[k].regNum);
4227
4228                freeCrit = isLastByteCodeOfLiveRange(k); /* last bytecode of a live range */
4229                reachEnd = reachEndOfBB(k); /* in a live range that extends to end of a basic block */
4230#ifdef DEBUG_LIVE_RANGE
4231                ALOGI("IN freeReg: VR %d offsetPC %x freecrit %d reachEnd %d nextToLast %d", compileTable[k].regNum, offsetPC, freeCrit, reachEnd, isNextToLastAccess(k));
4232#endif
4233                /* Bug: spilling of VRs after edi(rFP) is updated in RETURN bytecode
4234                        will cause variables for callee to be spilled to the caller stack frame and
4235                                                        to overwrite varaibles for caller
4236                */
4237                /* last bytecode of a live range reaching end of BB if not counting the fake usage at end */
4238                bool boolB = reachEnd && isNextToLastAccess(k);
4239                /* Bug: when a GG VR is checked at end of a basic block,
4240                        freeCrit will be true and physicalReg will be set to Null
4241                   Fix: change free condition from freeCrit to (freeCrit && offsetPC != currentBB->pc_end)
4242                */
4243                /* conditions to free a GG VR:
4244                       last bytecode of a live range reaching end of BB if not counting the fake usage at end && endsWithReturn
4245                       or
4246                       last bytecode of a live range && offsetPC != currentBB->pc_end
4247                           -> last bytecode of a live range not reaching end
4248                */
4249                typeC = ((freeCrit && offsetPC != currentBB->pc_end) ||
4250                         (currentBB->endsWithReturn && boolB)) &&
4251                        compileTable[k].gType == GLOBALTYPE_GG &&
4252                        !delayFreeing;
4253                /* conditions to free a L|GL VR:
4254                       last bytecode of a live range
4255                       or
4256                       last bytecode of a live range reaching end of BB if not counting the fake usage at end
4257                */
4258                typeB = (freeCrit || boolB) &&
4259                        (compileTable[k].gType != GLOBALTYPE_GG) &&
4260                        !delayFreeing;
4261            }
4262            if(typeA || typeB || typeC) {
4263#ifdef DEBUG_REGALLOC
4264                if(typeA)
4265                    ALOGI("FREE TEMP %d with type %d allocated to %d",
4266                           compileTable[k].regNum, compileTable[k].physicalType,
4267                           compileTable[k].physicalReg);
4268                else if(typeB)
4269                    ALOGI("FREE VR L|GL %d with type %d allocated to %d",
4270                           compileTable[k].regNum, compileTable[k].physicalType,
4271                           compileTable[k].physicalReg);
4272                else if(typeC)
4273                    ALOGI("FREE VR GG %d with type %d allocated to %d",
4274                           compileTable[k].regNum, compileTable[k].physicalType,
4275                           compileTable[k].physicalReg);
4276#endif
4277                bool dumpGL = false;
4278                if(compileTable[k].gType == GLOBALTYPE_GL && !reachEnd) {
4279                    /* if the live range does not reach end of basic block
4280                       and there exists a try block from offsetPC to the next live range
4281                           dump VR to interpreted stack */
4282                    int tmpPC = getNextLiveRange(k);
4283                    if(existATryBlock(currentMethod, offsetPC, tmpPC)) dumpGL = true;
4284                }
4285                /* if the live range reach end of basic block, dump VR to interpreted stack */
4286                if(compileTable[k].gType == GLOBALTYPE_GL && reachEnd) dumpGL = true;
4287                if(dumpGL) {
4288                    if(spillGL) {
4289#ifdef DEBUG_REGALLOC
4290                        ALOGI("SPILL VR GL %d %d", compileTable[k].regNum, compileTable[k].physicalType);
4291#endif
4292                        spillLogicalReg(k, true); //will dump VR to memory & update physicalReg
4293                    }
4294                }
4295                else
4296                     compileTable[k].physicalReg = PhysicalReg_Null;
4297            }
4298            if(typeA) {
4299                if(compileTable[k].spill_loc_index >= 0) {
4300                    /* update spill info for temporaries */
4301                    spillIndexUsed[compileTable[k].spill_loc_index >> 2] = 0;
4302                    compileTable[k].spill_loc_index = -1;
4303                    ALOGE("free a temporary register with TRSTATE_SPILLED");
4304                }
4305            }
4306        }
4307    }
4308    syncAllRegs(); //sync up allRegs (isUsed & freeTimeStamp) with compileTable
4309    return 0;
4310}
4311
4312//! reduce the reference count by 1
4313
4314//! input: index to compileTable
4315void decreaseRefCount(int index) {
4316#ifdef DEBUG_REFCOUNT
4317    ALOGI("REFCOUNT: %d in decreaseRefCount %d %d", compileTable[index].refCount,
4318            compileTable[index].regNum, compileTable[index].physicalType);
4319#endif
4320    compileTable[index].refCount--;
4321    if(compileTable[index].refCount < 0) {
4322        ALOGE("refCount is negative for REG %d %d", compileTable[index].regNum, compileTable[index].physicalType);
4323        dvmAbort();
4324    }
4325}
4326//! reduce the reference count of a VR by 1
4327
4328//! input: reg & type
4329int updateRefCount(int reg, LowOpndRegType type) {
4330    if(currentBB == NULL) return 0;
4331    int index = searchCompileTable(LowOpndRegType_virtual | type, reg);
4332    if(index < 0) {
4333        ALOGE("virtual reg %d type %d not found in updateRefCount", reg, type);
4334        return -1;
4335    }
4336    decreaseRefCount(index);
4337    return 0;
4338}
4339//! reduce the reference count of a variable by 1
4340
4341//! The variable is named with lowering module's naming mechanism
4342int updateRefCount2(int reg, int type, bool isPhysical) {
4343    if(currentBB == NULL) return 0;
4344    int newType = convertType(type, reg, isPhysical);
4345    if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
4346    int index = searchCompileTable(newType, reg);
4347    if(index < 0) {
4348        ALOGE("reg %d type %d not found in updateRefCount", reg, newType);
4349        return -1;
4350    }
4351    decreaseRefCount(index);
4352    return 0;
4353}
4354//! check whether a glue variable is in physical register or spilled
4355
4356//!
4357bool isGlueHandled(int glue_reg) {
4358    if(currentBB == NULL) return false;
4359    int index = searchCompileTable(LowOpndRegType_gp, glue_reg);
4360    if(index < 0) {
4361        ALOGE("glue reg %d not found in isGlueHandled", glue_reg);
4362        return -1;
4363    }
4364    if(compileTable[index].spill_loc_index >= 0 ||
4365       compileTable[index].physicalReg != PhysicalReg_Null) {
4366#ifdef DEBUG_GLUE
4367        ALOGI("GLUE isGlueHandled for %d returns true", glue_reg);
4368#endif
4369        return true;
4370    }
4371#ifdef DEBUG_GLUE
4372    ALOGI("GLUE isGlueHandled for %d returns false", glue_reg);
4373#endif
4374    return false;
4375}
4376//! reset the state of a glue variable to not existant (not in physical register nor spilled)
4377
4378//!
4379void resetGlue(int glue_reg) {
4380    if(currentBB == NULL) return;
4381    int index = searchCompileTable(LowOpndRegType_gp, glue_reg);
4382    if(index < 0) {
4383        ALOGE("glue reg %d not found in resetGlue", glue_reg);
4384        return;
4385    }
4386#ifdef DEBUG_GLUE
4387    ALOGI("GLUE reset for %d", glue_reg);
4388#endif
4389    compileTable[index].physicalReg = PhysicalReg_Null;
4390    if(compileTable[index].spill_loc_index >= 0)
4391        spillIndexUsed[compileTable[index].spill_loc_index >> 2] = 0;
4392    compileTable[index].spill_loc_index = -1;
4393}
4394//! set a glue variable in a physical register allocated for a variable
4395
4396//! Variable is using lowering module's naming convention
4397void updateGlue(int reg, bool isPhysical, int glue_reg) {
4398    if(currentBB == NULL) return;
4399    int index = searchCompileTable(LowOpndRegType_gp, glue_reg);
4400    if(index < 0) {
4401        ALOGE("glue reg %d not found in updateGlue", glue_reg);
4402        return;
4403    }
4404    /* find the compileTable entry for variable <reg, isPhysical> */
4405    int newType = convertType(LowOpndRegType_gp, reg, isPhysical);
4406    if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
4407    int index2 = searchCompileTable(newType, reg);
4408    if(index2 < 0 || compileTable[index2].physicalReg == PhysicalReg_Null) {
4409        ALOGE("updateGlue reg %d type %d", reg, newType);
4410        return;
4411    }
4412#ifdef DEBUG_GLUE
4413    ALOGI("physical register for GLUE %d set to %d", glue_reg, compileTable[index2].physicalReg);
4414#endif
4415    compileTable[index].physicalReg = compileTable[index2].physicalReg;
4416    compileTable[index].spill_loc_index = -1;
4417}
4418
4419//! check whether a virtual register is in a physical register
4420
4421//! If updateRefCount is 0, do not update reference count;
4422//!If updateRefCount is 1, update reference count only when VR is in a physical register
4423//!If updateRefCount is 2, update reference count
4424int checkVirtualReg(int reg, LowOpndRegType type, int updateRefCount) {
4425    if(currentBB == NULL) return PhysicalReg_Null;
4426    int index = searchCompileTable(LowOpndRegType_virtual | type, reg);
4427    if(index < 0) {
4428        ALOGE("virtual reg %d type %d not found in checkVirtualReg", reg, type);
4429        return PhysicalReg_Null;
4430    }
4431    //reduce reference count
4432    if(compileTable[index].physicalReg != PhysicalReg_Null) {
4433        if(updateRefCount != 0) decreaseRefCount(index);
4434        return compileTable[index].physicalReg;
4435    }
4436    if(updateRefCount == 2) decreaseRefCount(index);
4437    return PhysicalReg_Null;
4438}
4439//!check whether a temporary can share the same physical register with a VR
4440
4441//!This is called in get_virtual_reg
4442//!If this function returns false, new register will be allocated for this temporary
4443bool checkTempReg2(int reg, int type, bool isPhysical, int physicalRegForVR) {
4444    if(currentBB == NULL) return false;
4445    if(isPhysical) return false;
4446
4447    int newType = convertType(type, reg, isPhysical);
4448    if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
4449    int k;
4450    for(k = 0; k < num_temp_regs_per_bytecode; k++) {
4451        if(infoByteCodeTemp[k].physicalType == newType &&
4452           infoByteCodeTemp[k].regNum == reg) {
4453#ifdef DEBUG_MOVE_OPT
4454            ALOGI("MOVE_OPT checkTempRegs for %d %d returns %d %d",
4455                   reg, newType, infoByteCodeTemp[k].shareWithVR, infoByteCodeTemp[k].is8Bit);
4456#endif
4457            if(!infoByteCodeTemp[k].is8Bit) return infoByteCodeTemp[k].shareWithVR;
4458            //is8Bit true for gp type only
4459            if(!infoByteCodeTemp[k].shareWithVR) return false;
4460            //both true
4461            if(physicalRegForVR >= PhysicalReg_EAX && physicalRegForVR <= PhysicalReg_EDX) return true;
4462#ifdef DEBUG_MOVE_OPT
4463            ALOGI("MOVE_OPT registerAllocMove not used for 8-bit register");
4464#endif
4465            return false;
4466        }
4467    }
4468    ALOGE("checkTempReg2 %d %d", reg, newType);
4469    return false;
4470}
4471//!check whether a temporary can share the same physical register with a VR
4472
4473//!This is called in set_virtual_reg
4474int checkTempReg(int reg, int type, bool isPhysical, int vrNum) {
4475    if(currentBB == NULL) return PhysicalReg_Null;
4476
4477    int newType = convertType(type, reg, isPhysical);
4478    if(newType & LowOpndRegType_scratch) reg = reg - PhysicalReg_SCRATCH_1 + 1;
4479    int index = searchCompileTable(newType, reg);
4480    if(index < 0) {
4481        ALOGE("temp reg %d type %d not found in checkTempReg", reg, newType);
4482        return PhysicalReg_Null;
4483    }
4484
4485    //a temporary register can share the same physical reg with a VR if registerAllocMove is called
4486    //this will cause problem with move bytecode
4487    //get_VR(v1, t1) t1 and v1 point to the same physical reg
4488    //set_VR(t1, v2) t1 and v2 point to the same physical reg
4489    //this will cause v1 and v2 point to the same physical reg
4490    //FIX: if this temp reg shares a physical reg with another reg
4491    if(compileTable[index].physicalReg != PhysicalReg_Null) {
4492        int k;
4493        for(k = 0; k < num_compile_entries; k++) {
4494            if(k == index) continue;
4495            if(compileTable[k].physicalReg == compileTable[index].physicalReg) {
4496                return PhysicalReg_Null; //will allocate a register for VR
4497            }
4498        }
4499        decreaseRefCount(index);
4500        return compileTable[index].physicalReg;
4501    }
4502    if(compileTable[index].spill_loc_index >= 0) {
4503        //registerAlloc will call unspillLogicalReg (load from memory)
4504#ifdef DEBUG_REGALLOC
4505        ALOGW("in checkTempReg, the temporary register %d %d was spilled", reg, type);
4506#endif
4507        int regAll = registerAlloc(type, reg, isPhysical, true/* updateRefCount */);
4508        return regAll;
4509    }
4510    return PhysicalReg_Null;
4511}
4512//!check whether a variable has exposed usage in a basic block
4513
4514//!It calls hasExposedUsage2
4515bool hasExposedUsage(LowOpndRegType type, int regNum, BasicBlock_O1* bb) {
4516    int index = searchVirtualInfoOfBB(type, regNum, bb);
4517    if(index >= 0 && hasExposedUsage2(bb, index)) {
4518        return true;
4519    }
4520    return false;
4521}
4522//!check whether a variable has exposed usage in other basic blocks
4523
4524//!
4525bool hasOtherExposedUsage(OpndSize size, int regNum, BasicBlock_O1* bb) {
4526    return true; //assume the worst case
4527}
4528
4529//! handles constant VRs at end of a basic block
4530
4531//!If a VR is constant at end of a basic block and (it has exposed usage in other basic blocks or reaches a GG VR), dump immediate to memory
4532void constVREndOfBB() {
4533    BasicBlock_O1* bb = currentBB;
4534    int k, k2;
4535    //go through GG VRs, update a bool array
4536    int constUsedByGG[MAX_CONST_REG];
4537    for(k = 0; k < num_const_vr; k++)
4538        constUsedByGG[k] = 0;
4539    for(k = 0; k < num_compile_entries; k++) {
4540        if(isVirtualReg(compileTable[k].physicalType) && compileTable[k].gType == GLOBALTYPE_GG) {
4541            OpndSize size = getRegSize(compileTable[k].physicalType);
4542            int regNum = compileTable[k].regNum;
4543            int indexL = -1;
4544            int indexH = -1;
4545            for(k2 = 0; k2 < num_const_vr; k2++) {
4546                if(constVRTable[k2].regNum == regNum) {
4547                    indexL = k2;
4548                    continue;
4549                }
4550                if(constVRTable[k2].regNum == regNum + 1 && size == OpndSize_64) {
4551                    indexH = k2;
4552                    continue;
4553                }
4554            }
4555            if(indexL >= 0) constUsedByGG[indexL] = 1;
4556            if(indexH >= 0) constUsedByGG[indexH] = 1;
4557        } //GG VR
4558    }
4559    for(k = 0; k < num_const_vr; k++) {
4560        if(!constVRTable[k].isConst) continue;
4561        bool hasExp = false;
4562        if(constUsedByGG[k] == 0)
4563            hasExp = hasOtherExposedUsage(OpndSize_32, constVRTable[k].regNum, bb);
4564        if(constUsedByGG[k] != 0 || hasExp) {
4565            dumpImmToMem(constVRTable[k].regNum, OpndSize_32, constVRTable[k].value);
4566            setVRToMemory(constVRTable[k].regNum, OpndSize_32);
4567#ifdef DEBUG_ENDOFBB
4568            ALOGI("ENDOFBB: exposed VR %d is const %d (%x)",
4569                  constVRTable[k].regNum, constVRTable[k].value, constVRTable[k].value);
4570#endif
4571        } else {
4572#ifdef DEBUG_ENDOFBB
4573            ALOGI("ENDOFBB: unexposed VR %d is const %d (%x)",
4574                  constVRTable[k].regNum, constVRTable[k].value, constVRTable[k].value);
4575#endif
4576        }
4577    }
4578}
4579
4580//!handles GG VRs at end of a basic block
4581
4582//!make sure all GG VRs are in pre-defined physical registers
4583void globalVREndOfBB(const Method* method) {
4584    //fix: freeReg first to write LL VR back to memory to avoid it gets overwritten by GG VRs
4585    freeReg(true);
4586    int k;
4587    //spill GG VR first if it is not mapped to the specific reg
4588    //release GLUE regs
4589    for(k = 0; k < num_compile_entries; k++) {
4590        if(compileTable[k].regNum >= PhysicalReg_GLUE_DVMDEX &&
4591           compileTable[k].regNum != PhysicalReg_GLUE) {
4592            compileTable[k].physicalReg = PhysicalReg_Null;
4593            compileTable[k].spill_loc_index = -1;
4594        }
4595        //if part of a GG VR is const, the physical reg is set to null
4596        if(isVirtualReg(compileTable[k].physicalType) &&
4597           compileTable[k].gType == GLOBALTYPE_GG && compileTable[k].physicalReg != PhysicalReg_Null &&
4598           compileTable[k].physicalReg != compileTable[k].physicalReg_prev) {
4599#ifdef DEBUG_ENDOFBB
4600            ALOGW("end of BB GG VR is not mapped to the specific reg: %d %d %d",
4601                  compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].physicalReg);
4602            ALOGW("ENDOFBB SPILL VR %d %d", compileTable[k].regNum, compileTable[k].physicalType);
4603#endif
4604            spillLogicalReg(k, true); //the next section will load VR from memory to the specific reg
4605        }
4606    }
4607    syncAllRegs();
4608    for(k = 0; k < num_compile_entries; k++) {
4609        if(isVirtualReg(compileTable[k].physicalType)) {
4610            if(compileTable[k].gType == GLOBALTYPE_GG &&
4611               compileTable[k].physicalReg == PhysicalReg_Null && (!currentBB->endsWithReturn)) {
4612#ifdef DEBUG_ENDOFBB
4613                ALOGI("ENDOFBB GET GG VR %d %d to physical register %d", compileTable[k].regNum,
4614                      compileTable[k].physicalType, compileTable[k].physicalReg_prev);
4615#endif
4616                compileTable[k].physicalReg = compileTable[k].physicalReg_prev;
4617                if(allRegs[compileTable[k].physicalReg_prev].isUsed) {
4618                    ALOGE("physical register for GG VR is still used");
4619                }
4620                get_virtual_reg_noalloc(compileTable[k].regNum,
4621                                        getRegSize(compileTable[k].physicalType),
4622                                        compileTable[k].physicalReg_prev,
4623                                        true);
4624            }
4625        }//not const
4626    }
4627    if(indexForGlue >= 0 &&
4628        compileTable[indexForGlue].physicalReg == PhysicalReg_Null) {
4629        unspillLogicalReg(indexForGlue, PhysicalReg_EBP); //load %ebp
4630    }
4631}
4632
4633//! get ready for the next version of a hard-coded register
4634
4635//!set its physicalReg to Null and update its reference count
4636int nextVersionOfHardReg(PhysicalReg pReg, int refCount) {
4637    int indexT = searchCompileTable(LowOpndRegType_gp | LowOpndRegType_hard, pReg);
4638    if(indexT < 0)
4639        return -1;
4640    compileTable[indexT].physicalReg = PhysicalReg_Null;
4641#ifdef DEBUG_REFCOUNT
4642    ALOGI("REFCOUNT: to %d in nextVersionOfHardReg %d", refCount, pReg);
4643#endif
4644    compileTable[indexT].refCount = refCount;
4645    return 0;
4646}
4647
4648/** update compileTable with bb->infoBasicBlock[k]
4649*/
4650void insertFromVirtualInfo(BasicBlock_O1* bb, int k) {
4651    int index = searchCompileTable(LowOpndRegType_virtual | bb->infoBasicBlock[k].physicalType, bb->infoBasicBlock[k].regNum);
4652    if(index < 0) {
4653        /* the virtual register is not in compileTable, insert it */
4654        index = num_compile_entries;
4655        compileTable[num_compile_entries].physicalType = (LowOpndRegType_virtual | bb->infoBasicBlock[k].physicalType);
4656        compileTable[num_compile_entries].regNum = bb->infoBasicBlock[k].regNum;
4657        compileTable[num_compile_entries].physicalReg = PhysicalReg_Null;
4658        compileTable[num_compile_entries].bb = bb;
4659        compileTable[num_compile_entries].indexToInfoBB = k;
4660        compileTable[num_compile_entries].spill_loc_index = -1;
4661        compileTable[num_compile_entries].gType = bb->infoBasicBlock[k].gType;
4662        num_compile_entries++;
4663        if(num_compile_entries >= COMPILE_TABLE_SIZE) {
4664            ALOGE("compileTable overflow");
4665            dvmAbort();
4666        }
4667    }
4668    /* re-set reference count of all VRs */
4669    compileTable[index].refCount = bb->infoBasicBlock[k].refCount;
4670    compileTable[index].accessType = bb->infoBasicBlock[k].accessType;
4671    if(compileTable[index].gType == GLOBALTYPE_GG)
4672        compileTable[index].physicalReg_prev = bb->infoBasicBlock[k].physicalReg_GG;
4673}
4674
4675/** update compileTable with infoByteCodeTemp[k]
4676*/
4677void insertFromTempInfo(int k) {
4678    int index = searchCompileTable(infoByteCodeTemp[k].physicalType, infoByteCodeTemp[k].regNum);
4679    if(index < 0) {
4680        /* the temporary is not in compileTable, insert it */
4681        index = num_compile_entries;
4682        compileTable[num_compile_entries].physicalType = infoByteCodeTemp[k].physicalType;
4683        compileTable[num_compile_entries].regNum = infoByteCodeTemp[k].regNum;
4684        num_compile_entries++;
4685        if(num_compile_entries >= COMPILE_TABLE_SIZE) {
4686            ALOGE("compileTable overflow");
4687            dvmAbort();
4688        }
4689    }
4690    compileTable[index].physicalReg = PhysicalReg_Null;
4691    compileTable[index].refCount = infoByteCodeTemp[k].refCount;
4692    compileTable[index].linkageToVR = infoByteCodeTemp[k].linkageToVR;
4693    compileTable[index].gType = GLOBALTYPE_L;
4694    compileTable[index].spill_loc_index = -1;
4695}
4696
4697/* insert a glue-related register GLUE_DVMDEX to compileTable */
4698void insertGlueReg() {
4699    compileTable[num_compile_entries].physicalType = LowOpndRegType_gp;
4700    compileTable[num_compile_entries].regNum = PhysicalReg_GLUE_DVMDEX;
4701    compileTable[num_compile_entries].refCount = 2;
4702    compileTable[num_compile_entries].physicalReg = PhysicalReg_Null;
4703    compileTable[num_compile_entries].bb = NULL;
4704    compileTable[num_compile_entries].spill_loc_index = -1;
4705    compileTable[num_compile_entries].accessType = REGACCESS_N;
4706    compileTable[num_compile_entries].linkageToVR = -1;
4707    compileTable[num_compile_entries].gType = GLOBALTYPE_L;
4708
4709    num_compile_entries++;
4710    if(num_compile_entries >= COMPILE_TABLE_SIZE) {
4711        ALOGE("compileTable overflow");
4712        dvmAbort();
4713    }
4714}
4715
4716/** print infoBasicBlock of the given basic block
4717*/
4718void dumpVirtualInfoOfBasicBlock(BasicBlock_O1* bb) {
4719    int jj;
4720    ALOGI("Virtual Info for BB%d --------", bb->bb_index);
4721    for(jj = 0; jj < bb->num_regs; jj++) {
4722        ALOGI("regNum %d physicalType %d accessType %d refCount %d def ",
4723               bb->infoBasicBlock[jj].regNum, bb->infoBasicBlock[jj].physicalType,
4724               bb->infoBasicBlock[jj].accessType, bb->infoBasicBlock[jj].refCount);
4725        int k;
4726        for(k = 0; k < bb->infoBasicBlock[jj].num_reaching_defs; k++)
4727            ALOGI("[%x %d %d %d] ", bb->infoBasicBlock[jj].reachingDefs[k].offsetPC,
4728                   bb->infoBasicBlock[jj].reachingDefs[k].regNum,
4729                   bb->infoBasicBlock[jj].reachingDefs[k].physicalType,
4730                   bb->infoBasicBlock[jj].reachingDefs[k].accessType);
4731        ALOGI("");
4732    }
4733}
4734
4735/** print compileTable
4736*/
4737void dumpCompileTable() {
4738    int jj;
4739    ALOGI("Compile Table for method ----------");
4740    for(jj = 0; jj < num_compile_entries; jj++) {
4741        ALOGI("regNum %d physicalType %d refCount %d isConst %d physicalReg %d type %d",
4742               compileTable[jj].regNum, compileTable[jj].physicalType,
4743               compileTable[jj].refCount, compileTable[jj].isConst, compileTable[jj].physicalReg, compileTable[jj].gType);
4744    }
4745}
4746
4747//!check whether a basic block is the start of an exception handler
4748
4749//!
4750bool isFirstOfHandler(BasicBlock_O1* bb) {
4751    int i;
4752    for(i = 0; i < num_exception_handlers; i++) {
4753        if(bb->pc_start == exceptionHandlers[i]) return true;
4754    }
4755    return false;
4756}
4757
4758//! create a basic block that starts at src_pc and ends at end_pc
4759
4760//!
4761BasicBlock_O1* createBasicBlock(int src_pc, int end_pc) {
4762    BasicBlock_O1* bb = (BasicBlock_O1*)malloc(sizeof(BasicBlock_O1));
4763    if(bb == NULL) {
4764        ALOGE("out of memory");
4765        return NULL;
4766    }
4767    bb->pc_start = src_pc;
4768    bb->bb_index = num_bbs_for_method;
4769    if(bb_entry == NULL) bb_entry = bb;
4770
4771    /* insert the basic block to method_bbs_sorted in ascending order of pc_start */
4772    int k;
4773    int index = -1;
4774    for(k = 0; k < num_bbs_for_method; k++)
4775        if(method_bbs_sorted[k]->pc_start > src_pc) {
4776            index = k;
4777            break;
4778        }
4779    if(index == -1)
4780        method_bbs_sorted[num_bbs_for_method] = bb;
4781    else {
4782        /* push the elements from index by 1 */
4783        for(k = num_bbs_for_method-1; k >= index; k--)
4784            method_bbs_sorted[k+1] = method_bbs_sorted[k];
4785        method_bbs_sorted[index] = bb;
4786    }
4787    num_bbs_for_method++;
4788    if(num_bbs_for_method >= MAX_NUM_BBS_PER_METHOD) {
4789        ALOGE("too many basic blocks");
4790        dvmAbort();
4791    }
4792    return bb;
4793}
4794
4795/* BEGIN code to handle state transfers */
4796//! save the current state of register allocator to a state table
4797
4798//!
4799void rememberState(int stateNum) {
4800#ifdef DEBUG_STATE
4801    ALOGI("STATE: remember state %d", stateNum);
4802#endif
4803    int k;
4804    for(k = 0; k < num_compile_entries; k++) {
4805        if(stateNum == 1) {
4806            stateTable1_1[k].physicalReg = compileTable[k].physicalReg;
4807            stateTable1_1[k].spill_loc_index = compileTable[k].spill_loc_index;
4808        }
4809        else if(stateNum == 2) {
4810            stateTable1_2[k].physicalReg = compileTable[k].physicalReg;
4811            stateTable1_2[k].spill_loc_index = compileTable[k].spill_loc_index;
4812        }
4813        else if(stateNum == 3) {
4814            stateTable1_3[k].physicalReg = compileTable[k].physicalReg;
4815            stateTable1_3[k].spill_loc_index = compileTable[k].spill_loc_index;
4816        }
4817        else if(stateNum == 4) {
4818            stateTable1_4[k].physicalReg = compileTable[k].physicalReg;
4819            stateTable1_4[k].spill_loc_index = compileTable[k].spill_loc_index;
4820        }
4821        else ALOGE("state table overflow");
4822#ifdef DEBUG_STATE
4823        ALOGI("logical reg %d %d mapped to physical reg %d with spill index %d refCount %d",
4824               compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].physicalReg,
4825               compileTable[k].spill_loc_index, compileTable[k].refCount);
4826#endif
4827    }
4828    for(k = 0; k < num_memory_vr; k++) {
4829        if(stateNum == 1) {
4830            stateTable2_1[k].regNum = memVRTable[k].regNum;
4831            stateTable2_1[k].inMemory = memVRTable[k].inMemory;
4832        }
4833        else if(stateNum == 2) {
4834            stateTable2_2[k].regNum = memVRTable[k].regNum;
4835            stateTable2_2[k].inMemory = memVRTable[k].inMemory;
4836        }
4837        else if(stateNum == 3) {
4838            stateTable2_3[k].regNum = memVRTable[k].regNum;
4839            stateTable2_3[k].inMemory = memVRTable[k].inMemory;
4840        }
4841        else if(stateNum == 4) {
4842            stateTable2_4[k].regNum = memVRTable[k].regNum;
4843            stateTable2_4[k].inMemory = memVRTable[k].inMemory;
4844        }
4845        else ALOGE("state table overflow");
4846#ifdef DEBUG_STATE
4847        ALOGI("virtual reg %d in memory %d", memVRTable[k].regNum, memVRTable[k].inMemory);
4848#endif
4849    }
4850}
4851
4852//!update current state of register allocator with a state table
4853
4854//!
4855void goToState(int stateNum) {
4856    int k;
4857#ifdef DEBUG_STATE
4858    ALOGI("STATE: go to state %d", stateNum);
4859#endif
4860    for(k = 0; k < num_compile_entries; k++) {
4861        if(stateNum == 1) {
4862            compileTable[k].physicalReg = stateTable1_1[k].physicalReg;
4863            compileTable[k].spill_loc_index = stateTable1_1[k].spill_loc_index;
4864        }
4865        else if(stateNum == 2) {
4866            compileTable[k].physicalReg = stateTable1_2[k].physicalReg;
4867            compileTable[k].spill_loc_index = stateTable1_2[k].spill_loc_index;
4868        }
4869        else if(stateNum == 3) {
4870            compileTable[k].physicalReg = stateTable1_3[k].physicalReg;
4871            compileTable[k].spill_loc_index = stateTable1_3[k].spill_loc_index;
4872        }
4873        else if(stateNum == 4) {
4874            compileTable[k].physicalReg = stateTable1_4[k].physicalReg;
4875            compileTable[k].spill_loc_index = stateTable1_4[k].spill_loc_index;
4876        }
4877        else ALOGE("state table overflow");
4878    }
4879    updateSpillIndexUsed();
4880    syncAllRegs(); //to sync up allRegs CAN'T call freeReg here
4881    //since it will change the state!!!
4882    for(k = 0; k < num_memory_vr; k++) {
4883        if(stateNum == 1) {
4884            memVRTable[k].regNum = stateTable2_1[k].regNum;
4885            memVRTable[k].inMemory = stateTable2_1[k].inMemory;
4886        }
4887        else if(stateNum == 2) {
4888            memVRTable[k].regNum = stateTable2_2[k].regNum;
4889            memVRTable[k].inMemory = stateTable2_2[k].inMemory;
4890        }
4891        else if(stateNum == 3) {
4892            memVRTable[k].regNum = stateTable2_3[k].regNum;
4893            memVRTable[k].inMemory = stateTable2_3[k].inMemory;
4894        }
4895        else if(stateNum == 4) {
4896            memVRTable[k].regNum = stateTable2_4[k].regNum;
4897            memVRTable[k].inMemory = stateTable2_4[k].inMemory;
4898        }
4899        else ALOGE("state table overflow");
4900    }
4901}
4902typedef struct TransferOrder {
4903    int targetReg;
4904    int targetSpill;
4905    int compileIndex;
4906} TransferOrder;
4907#define MAX_NUM_DEST 20
4908//! a source register is used as a source in transfer
4909//! it can have a maximum of MAX_NUM_DEST destinations
4910typedef struct SourceReg {
4911    int physicalReg;
4912    int num_dests; //check bound
4913    TransferOrder dsts[MAX_NUM_DEST];
4914} SourceReg;
4915int num_src_regs = 0; //check bound
4916//! physical registers that are used as a source in transfer
4917//! we allow a maximum of MAX_NUM_DEST sources in a transfer
4918SourceReg srcRegs[MAX_NUM_DEST];
4919//! tell us whether a source register is handled already
4920bool handledSrc[MAX_NUM_DEST];
4921//! in what order should the source registers be handled
4922int handledOrder[MAX_NUM_DEST];
4923//! insert a source register with a single destination
4924
4925//!
4926void insertSrcReg(int srcPhysical, int targetReg, int targetSpill, int index) {
4927    int k = 0;
4928    for(k = 0; k < num_src_regs; k++) {
4929        if(srcRegs[k].physicalReg == srcPhysical) { //increase num_dests
4930            if(srcRegs[k].num_dests >= MAX_NUM_DEST) {
4931                ALOGE("exceed number dst regs for a source reg");
4932                dvmAbort();
4933            }
4934            srcRegs[k].dsts[srcRegs[k].num_dests].targetReg = targetReg;
4935            srcRegs[k].dsts[srcRegs[k].num_dests].targetSpill = targetSpill;
4936            srcRegs[k].dsts[srcRegs[k].num_dests].compileIndex = index;
4937            srcRegs[k].num_dests++;
4938            return;
4939        }
4940    }
4941    if(num_src_regs >= MAX_NUM_DEST) {
4942        ALOGE("exceed number of source regs");
4943        dvmAbort();
4944    }
4945    srcRegs[num_src_regs].physicalReg = srcPhysical;
4946    srcRegs[num_src_regs].num_dests = 1;
4947    srcRegs[num_src_regs].dsts[0].targetReg = targetReg;
4948    srcRegs[num_src_regs].dsts[0].targetSpill = targetSpill;
4949    srcRegs[num_src_regs].dsts[0].compileIndex = index;
4950    num_src_regs++;
4951}
4952//! check whether a register is a source and the source is not yet handled
4953
4954//!
4955bool dstStillInUse(int dstReg) {
4956    if(dstReg == PhysicalReg_Null) return false;
4957    int k;
4958    int index = -1;
4959    for(k = 0; k < num_src_regs; k++) {
4960        if(dstReg == srcRegs[k].physicalReg) {
4961            index = k;
4962            break;
4963        }
4964    }
4965    if(index < 0) return false; //not in use
4966    if(handledSrc[index]) return false; //not in use
4967    return true;
4968}
4969//! reset the state of glue variables in a state table
4970
4971//!
4972void resetStateOfGlue(int stateNum, int k) {
4973#ifdef DEBUG_STATE
4974    ALOGI("resetStateOfGlue state %d regNum %d", stateNum, compileTable[k].regNum);
4975#endif
4976    if(stateNum == 1) {
4977        stateTable1_1[k].physicalReg = PhysicalReg_Null;
4978        stateTable1_1[k].spill_loc_index = -1;
4979    }
4980    else if(stateNum == 2) {
4981        stateTable1_2[k].physicalReg = PhysicalReg_Null;
4982        stateTable1_2[k].spill_loc_index = -1;
4983    }
4984    else if(stateNum == 3) {
4985        stateTable1_3[k].physicalReg = PhysicalReg_Null;
4986        stateTable1_3[k].spill_loc_index = -1;
4987    }
4988    else if(stateNum == 4) {
4989        stateTable1_4[k].physicalReg = PhysicalReg_Null;
4990        stateTable1_4[k].spill_loc_index = -1;
4991    }
4992}
4993//! construct a legal order of the source registers in this transfer
4994
4995//!
4996void constructSrcRegs(int stateNum) {
4997    int k;
4998    num_src_regs = 0;
4999#ifdef DEBUG_STATE
5000    ALOGI("IN constructSrcRegs");
5001#endif
5002
5003    for(k = 0; k < num_compile_entries; k++) {
5004#ifdef DEBUG_STATE
5005        ALOGI("logical reg %d %d mapped to physical reg %d with spill index %d refCount %d",
5006               compileTable[k].regNum, compileTable[k].physicalType, compileTable[k].physicalReg,
5007               compileTable[k].spill_loc_index, compileTable[k].refCount);
5008#endif
5009
5010        int pType = compileTable[k].physicalType;
5011        //ignore hardcoded logical registers
5012        if((pType & LowOpndRegType_hard) != 0) continue;
5013        //ignore type _fs
5014        if((pType & MASK_FOR_TYPE) == LowOpndRegType_fs) continue;
5015        if((pType & MASK_FOR_TYPE) == LowOpndRegType_fs_s) continue;
5016
5017        //GL VR refCount is zero, can't ignore
5018        //L VR refCount is zero, ignore
5019        //GG VR refCount is zero, can't ignore
5020        //temporary refCount is zero, ignore
5021
5022        //for GLUE variables, if they do not exist, reset the entries in state table
5023        if(compileTable[k].physicalReg == PhysicalReg_Null &&
5024           compileTable[k].regNum >= PhysicalReg_GLUE_DVMDEX &&
5025           compileTable[k].regNum != PhysicalReg_GLUE &&
5026           compileTable[k].spill_loc_index < 0) {
5027            resetStateOfGlue(stateNum, k);
5028        }
5029
5030        /* get the target state */
5031        int targetReg = PhysicalReg_Null;
5032        int targetSpill = -1;
5033        if(stateNum == 1) {
5034            targetReg = stateTable1_1[k].physicalReg;
5035            targetSpill = stateTable1_1[k].spill_loc_index;
5036        }
5037        else if(stateNum == 2) {
5038            targetReg = stateTable1_2[k].physicalReg;
5039            targetSpill = stateTable1_2[k].spill_loc_index;
5040        }
5041        else if(stateNum == 3) {
5042            targetReg = stateTable1_3[k].physicalReg;
5043            targetSpill = stateTable1_3[k].spill_loc_index;
5044        }
5045        else if(stateNum == 4) {
5046            targetReg = stateTable1_4[k].physicalReg;
5047            targetSpill = stateTable1_4[k].spill_loc_index;
5048        }
5049
5050        /* there exists an ordering problem
5051           for example:
5052             for a VR, move from memory to a physical reg esi
5053             for a temporary regsiter, from esi to ecx
5054             if we handle VR first, content of the temporary reg. will be overwritten
5055           there are 4 cases:
5056             I: a variable is currently in memory and its target is in physical reg
5057             II: a variable is currently in a register and its target is in memory
5058             III: a variable is currently in a different register
5059             IV: a variable is currently in a different memory location (for non-VRs)
5060           for GLUE, since it can only be allocated to %ebp, we don't have case III
5061           For now, case IV is not handled since it didn't show
5062        */
5063        if(compileTable[k].physicalReg != targetReg &&
5064           isVirtualReg(compileTable[k].physicalType)) {
5065            /* handles VR for case I to III */
5066
5067            if(compileTable[k].physicalReg == PhysicalReg_Null && targetReg != PhysicalReg_Null) {
5068                /* handles VR for case I:
5069                   insert a xfer order from PhysicalReg_Null to targetReg */
5070                insertSrcReg(PhysicalReg_Null, targetReg, targetSpill, k);
5071#ifdef DEBUG_STATE
5072                ALOGI("insert for VR Null %d %d %d", targetReg, targetSpill, k);
5073#endif
5074            }
5075
5076            if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg != PhysicalReg_Null) {
5077                /* handles VR for case III
5078                   insert a xfer order from srcReg to targetReg */
5079                insertSrcReg(compileTable[k].physicalReg, targetReg, targetSpill, k);
5080            }
5081
5082            if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg == PhysicalReg_Null) {
5083                /* handles VR for case II
5084                   insert a xfer order from srcReg to memory */
5085                insertSrcReg(compileTable[k].physicalReg, targetReg, targetSpill, k);
5086            }
5087        }
5088
5089        if(compileTable[k].physicalReg != targetReg &&
5090           !isVirtualReg(compileTable[k].physicalType)) {
5091            /* handles non-VR for case I to III */
5092
5093            if(compileTable[k].physicalReg == PhysicalReg_Null && targetReg != PhysicalReg_Null) {
5094                /* handles non-VR for case I */
5095                if(compileTable[k].spill_loc_index < 0) {
5096                    /* this variable is freed, no need to transfer */
5097#ifdef DEBUG_STATE
5098                    ALOGW("in transferToState spill_loc_index is negative for temporary %d", compileTable[k].regNum);
5099#endif
5100                } else {
5101                    /* insert a xfer order from memory to targetReg */
5102#ifdef DEBUG_STATE
5103                    ALOGI("insert Null %d %d %d", targetReg, targetSpill, k);
5104#endif
5105                    insertSrcReg(PhysicalReg_Null, targetReg, targetSpill, k);
5106                }
5107            }
5108
5109            if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg != PhysicalReg_Null) {
5110                /* handles non-VR for case III
5111                   insert a xfer order from srcReg to targetReg */
5112                insertSrcReg(compileTable[k].physicalReg, targetReg, targetSpill, k);
5113            }
5114
5115            if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg == PhysicalReg_Null) {
5116                /* handles non-VR for case II */
5117                if(targetSpill < 0) {
5118                    /* this variable is freed, no need to transfer */
5119#ifdef DEBUG_STATE
5120                    ALOGW("in transferToState spill_loc_index is negative for temporary %d", compileTable[k].regNum);
5121#endif
5122                } else {
5123                    /* insert a xfer order from srcReg to memory */
5124                    insertSrcReg(compileTable[k].physicalReg, targetReg, targetSpill, k);
5125                }
5126            }
5127
5128        }
5129    }//for compile entries
5130
5131    int k2;
5132#ifdef DEBUG_STATE
5133    for(k = 0; k < num_src_regs; k++) {
5134        ALOGI("SRCREG %d: ", srcRegs[k].physicalReg);
5135        for(k2 = 0; k2 < srcRegs[k].num_dests; k2++) {
5136            int index = srcRegs[k].dsts[k2].compileIndex;
5137            ALOGI("[%d %d %d: %d %d %d] ", srcRegs[k].dsts[k2].targetReg,
5138                   srcRegs[k].dsts[k2].targetSpill, srcRegs[k].dsts[k2].compileIndex,
5139                   compileTable[index].regNum, compileTable[index].physicalType,
5140                   compileTable[index].spill_loc_index);
5141        }
5142        ALOGI("");
5143    }
5144#endif
5145
5146    /* construct an order: xfers from srcReg first, then xfers from memory */
5147    int num_handled = 0;
5148    int num_in_order = 0;
5149    for(k = 0; k < num_src_regs; k++) {
5150        if(srcRegs[k].physicalReg == PhysicalReg_Null) {
5151            handledSrc[k] = true;
5152            num_handled++;
5153        } else {
5154            handledSrc[k] = false;
5155        }
5156    }
5157    while(num_handled < num_src_regs) {
5158        int prev_handled = num_handled;
5159        for(k = 0; k < num_src_regs; k++) {
5160            if(handledSrc[k]) continue;
5161            bool canHandleNow = true;
5162            for(k2 = 0; k2 < srcRegs[k].num_dests; k2++) {
5163                if(dstStillInUse(srcRegs[k].dsts[k2].targetReg)) {
5164                    canHandleNow = false;
5165                    break;
5166                }
5167            }
5168            if(canHandleNow) {
5169                handledSrc[k] = true;
5170                num_handled++;
5171                handledOrder[num_in_order] = k;
5172                num_in_order++;
5173            }
5174        } //for k
5175        if(num_handled == prev_handled) {
5176            ALOGE("no progress in selecting order");
5177            dvmAbort();
5178        }
5179    } //while
5180    for(k = 0; k < num_src_regs; k++) {
5181        if(srcRegs[k].physicalReg == PhysicalReg_Null) {
5182            handledOrder[num_in_order] = k;
5183            num_in_order++;
5184        }
5185    }
5186    if(num_in_order != num_src_regs) {
5187        ALOGE("num_in_order != num_src_regs");
5188        dvmAbort();
5189    }
5190#ifdef DEBUG_STATE
5191    ALOGI("ORDER: ");
5192    for(k = 0; k < num_src_regs; k++) {
5193        ALOGI("%d ", handledOrder[k]);
5194    }
5195    ALOGI("");
5196#endif
5197}
5198//! transfer the state of register allocator to a state specified in a state table
5199
5200//!
5201void transferToState(int stateNum) {
5202    freeReg(false); //do not spill GL
5203    int k;
5204#ifdef DEBUG_STATE
5205    ALOGI("STATE: transfer to state %d", stateNum);
5206#endif
5207    if(stateNum > 4 || stateNum < 1) ALOGE("state table overflow");
5208    constructSrcRegs(stateNum);
5209    int k4, k3;
5210    for(k4 = 0; k4 < num_src_regs; k4++) {
5211        int k2 = handledOrder[k4]; //index to srcRegs
5212        for(k3 = 0; k3 < srcRegs[k2].num_dests; k3++) {
5213            k = srcRegs[k2].dsts[k3].compileIndex;
5214            int targetReg = srcRegs[k2].dsts[k3].targetReg;
5215            int targetSpill = srcRegs[k2].dsts[k3].targetSpill;
5216            if(compileTable[k].physicalReg != targetReg && isVirtualReg(compileTable[k].physicalType)) {
5217                OpndSize oSize = getRegSize(compileTable[k].physicalType);
5218                bool isSS = ((compileTable[k].physicalType & MASK_FOR_TYPE) == LowOpndRegType_ss);
5219                if(compileTable[k].physicalReg == PhysicalReg_Null && targetReg != PhysicalReg_Null) {
5220                    if(isSS)
5221                        move_ss_mem_to_reg_noalloc(4*compileTable[k].regNum,
5222                                                   PhysicalReg_FP, true,
5223                                                   MemoryAccess_VR, compileTable[k].regNum,
5224                                                   targetReg, true);
5225                    else
5226                        move_mem_to_reg_noalloc(oSize, 4*compileTable[k].regNum,
5227                                                PhysicalReg_FP, true,
5228                                                MemoryAccess_VR, compileTable[k].regNum,
5229                                                targetReg, true);
5230                }
5231                if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg != PhysicalReg_Null) {
5232                    move_reg_to_reg_noalloc((isSS ? OpndSize_64 : oSize),
5233                                            compileTable[k].physicalReg, true,
5234                                            targetReg, true);
5235                }
5236                if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg == PhysicalReg_Null) {
5237                    dumpToMem(compileTable[k].regNum, (LowOpndRegType)(compileTable[k].physicalType & MASK_FOR_TYPE),
5238                              compileTable[k].physicalReg);
5239                }
5240            } //VR
5241            if(compileTable[k].physicalReg != targetReg && !isVirtualReg(compileTable[k].physicalType)) {
5242                OpndSize oSize = getRegSize(compileTable[k].physicalType);
5243                if(compileTable[k].physicalReg == PhysicalReg_Null && targetReg != PhysicalReg_Null) {
5244                    loadFromSpillRegion(oSize, targetReg,
5245                                        compileTable[k].spill_loc_index);
5246                }
5247                //both are not null, move from one to the other
5248                if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg != PhysicalReg_Null) {
5249                    move_reg_to_reg_noalloc(oSize, compileTable[k].physicalReg, true,
5250                                            targetReg, true);
5251                }
5252                //current is not null, target is null (move from reg to memory)
5253                if(compileTable[k].physicalReg != PhysicalReg_Null && targetReg == PhysicalReg_Null) {
5254                    saveToSpillRegion(oSize, compileTable[k].physicalReg, targetSpill);
5255                }
5256            } //temporary
5257        }//for
5258    }//for
5259    for(k = 0; k < num_memory_vr; k++) {
5260        bool targetBool = false;
5261        int targetReg = -1;
5262        if(stateNum == 1) {
5263            targetReg = stateTable2_1[k].regNum;
5264            targetBool = stateTable2_1[k].inMemory;
5265        }
5266        else if(stateNum == 2) {
5267            targetReg = stateTable2_2[k].regNum;
5268            targetBool = stateTable2_2[k].inMemory;
5269        }
5270        else if(stateNum == 3) {
5271            targetReg = stateTable2_3[k].regNum;
5272            targetBool = stateTable2_3[k].inMemory;
5273        }
5274        else if(stateNum == 4) {
5275            targetReg = stateTable2_4[k].regNum;
5276            targetBool = stateTable2_4[k].inMemory;
5277        }
5278        if(targetReg != memVRTable[k].regNum)
5279            ALOGE("regNum mismatch in transferToState");
5280        if(targetBool && (!memVRTable[k].inMemory)) {
5281            //dump to memory, check entries in compileTable: vA gp vA xmm vA ss
5282#ifdef DEBUG_STATE
5283            ALOGW("inMemory mismatch for VR %d in transferToState", targetReg);
5284#endif
5285            bool doneXfer = false;
5286            int index = searchCompileTable(LowOpndRegType_xmm | LowOpndRegType_virtual, targetReg);
5287            if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
5288                dumpToMem(targetReg, LowOpndRegType_xmm, compileTable[index].physicalReg);
5289                doneXfer = true;
5290            }
5291            if(!doneXfer) { //vA-1, xmm
5292                index = searchCompileTable(LowOpndRegType_xmm | LowOpndRegType_virtual, targetReg-1);
5293                if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
5294                    dumpToMem(targetReg-1, LowOpndRegType_xmm, compileTable[index].physicalReg);
5295                    doneXfer = true;
5296                }
5297            }
5298            if(!doneXfer) { //vA gp
5299                index = searchCompileTable(LowOpndRegType_gp | LowOpndRegType_virtual, targetReg);
5300                if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
5301                    dumpToMem(targetReg, LowOpndRegType_gp, compileTable[index].physicalReg);
5302                    doneXfer = true;
5303                }
5304            }
5305            if(!doneXfer) { //vA, ss
5306                index = searchCompileTable(LowOpndRegType_ss | LowOpndRegType_virtual, targetReg);
5307                if(index >= 0 && compileTable[index].physicalReg != PhysicalReg_Null) {
5308                    dumpToMem(targetReg, LowOpndRegType_ss, compileTable[index].physicalReg);
5309                    doneXfer = true;
5310                }
5311            }
5312            if(!doneXfer) ALOGW("can't match inMemory of VR %d in transferToState", targetReg);
5313        }
5314        if((!targetBool) && memVRTable[k].inMemory) {
5315            //do nothing
5316        }
5317    }
5318#ifdef DEBUG_STATE
5319    ALOGI("END transferToState %d", stateNum);
5320#endif
5321    goToState(stateNum);
5322}
5323/* END code to handle state transfers */
5324