| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| /*! \file ncg_o1_data.h |
| \brief A header file to define data structures used by register allocator & const folding |
| */ |
| #ifndef _DALVIK_NCG_ANALYSISO1_H |
| #define _DALVIK_NCG_ANALYSISO1_H |
| |
| #include "Dalvik.h" |
| #include "enc_wrapper.h" |
| #include "Lower.h" |
| #ifdef WITH_JIT |
| #include "compiler/CompilerIR.h" |
| #endif |
| |
| //! maximal number of edges per basic block |
| #define MAX_NUM_EDGE_PER_BB 300 |
| //! maximal number of basic blocks per method |
| #define MAX_NUM_BBS_PER_METHOD 1000 |
| //! maximal number of virtual registers per basic block |
| #define MAX_REG_PER_BASICBLOCK 140 |
| //! maximal number of virtual registers per bytecode |
| #define MAX_REG_PER_BYTECODE 40 |
| //! maximal number of virtual registers per method |
| #define MAX_REG_PER_METHOD 200 |
| //! maximal number of temporaries per bytecode |
| #define MAX_TEMP_REG_PER_BYTECODE 30 |
| //! maximal number of GG GPR VRs in a method |
| #define MAX_GLOBAL_VR 2 |
| //! maximal number of GG XMM VRs in a method |
| #define MAX_GLOBAL_VR_XMM 4 |
| #define MAX_CONST_REG 150 |
| |
| #define MASK_FOR_TYPE 7 //last 3 bits 111 |
| |
| #define LOOP_COUNT 10 |
| //! maximal number of entries in compileTable |
| #define COMPILE_TABLE_SIZE 200 |
| //! maximal number of transfer points per basic block |
| #define MAX_XFER_PER_BB 1000 //on Jan 4 |
| #define PC_FOR_END_OF_BB -999 |
| #define PC_FOR_START_OF_BB -998 |
| |
| //! various cases of overlapping between 2 variables |
| typedef enum OverlapCase { |
| OVERLAP_ALIGN = 0, |
| OVERLAP_B_IS_LOW_OF_A, |
| OVERLAP_B_IS_HIGH_OF_A, |
| OVERLAP_LOW_OF_A_IS_HIGH_OF_B, |
| OVERLAP_HIGH_OF_A_IS_LOW_OF_B, |
| OVERLAP_A_IS_LOW_OF_B, |
| OVERLAP_A_IS_HIGH_OF_B, |
| OVERLAP_B_COVER_A, |
| OVERLAP_B_COVER_LOW_OF_A, |
| OVERLAP_B_COVER_HIGH_OF_A, |
| OVERLAP_NO |
| } OverlapCase; |
| |
| //!access type of a variable |
| typedef enum RegAccessType { |
| REGACCESS_D = 0, |
| REGACCESS_U, |
| REGACCESS_DU, |
| REGACCESS_UD, |
| REGACCESS_L, |
| REGACCESS_H, |
| REGACCESS_UL, |
| REGACCESS_UH, |
| REGACCESS_LU, |
| REGACCESS_HU, |
| REGACCESS_N, //no access |
| REGACCESS_UNKNOWN |
| } RegAccessType; |
| //! a variable can be local (L), globally local (GL) or global (GG) |
| typedef enum GlobalType { |
| GLOBALTYPE_GG, |
| GLOBALTYPE_GL, |
| GLOBALTYPE_L |
| } GlobalType; |
| typedef enum VRState { |
| VRSTATE_SPILLED, |
| VRSTATE_UPDATED, |
| VRSTATE_CLEAN |
| } VRState; |
| //! helper state to determine if freeing VRs needs to be delayed |
| enum VRDelayFreeFlags { |
| VRDELAY_NONE = 0, // used when VR can be freed from using physical register if needed |
| VRDELAY_NULLCHECK = 1 << 0, // used when VR is used for null check and freeing must be delayed |
| VRDELAY_BOUNDCHECK = 1 << 1 // used when VR is used for bound check and freeing must be delayed |
| }; |
| typedef enum TRState { //state of temporary registers |
| TRSTATE_SPILLED, |
| TRSTATE_UNSPILLED, |
| TRSTATE_CLEAN |
| } TRState; |
| //!information about a physical register |
| typedef struct RegisterInfo { |
| PhysicalReg physicalReg; |
| bool isUsed; |
| bool isCalleeSaved; |
| int freeTimeStamp; |
| } RegisterInfo; |
| typedef struct UniqueRegister { |
| LowOpndRegType physicalType; |
| int regNum; |
| int numExposedUsage; |
| PhysicalReg physicalReg; |
| } UniqueRegister; |
| //!specifies the weight of a VR allocated to a specific physical register |
| //!it is used for GPR VR only |
| typedef struct RegAllocConstraint { |
| PhysicalReg physicalReg; |
| int count; |
| } RegAllocConstraint; |
| |
| typedef enum XferType { |
| XFER_MEM_TO_XMM, //for usage |
| XFER_DEF_TO_MEM, //def is gp |
| XFER_DEF_TO_GP_MEM, |
| XFER_DEF_TO_GP, |
| XFER_DEF_IS_XMM //def is xmm |
| } XferType; |
| typedef struct XferPoint { |
| int tableIndex; //generated from a def-use pair |
| XferType xtype; |
| int offsetPC; |
| int regNum; //get or set VR at offsetPC |
| LowOpndRegType physicalType; |
| |
| //if XFER_DEF_IS_XMM |
| int vr_gpl; //a gp VR that uses the lower half of the def |
| int vr_gph; |
| bool dumpToXmm; |
| bool dumpToMem; |
| } XferPoint; |
| |
| //!for def: accessType means which part of the VR defined at offestPC is live now |
| //!for use: accessType means which part of the usage comes from the reachingDef |
| typedef struct DefOrUse { |
| int offsetPC; //!the program point |
| int regNum; //!access the virtual reg |
| LowOpndRegType physicalType; //!xmm or gp or ss |
| RegAccessType accessType; //!D, L, H, N |
| } DefOrUse; |
| //!a link list of DefOrUse |
| typedef struct DefOrUseLink { |
| int offsetPC; |
| int regNum; //access the virtual reg |
| LowOpndRegType physicalType; //xmm or gp |
| RegAccessType accessType; //D, L, H, N |
| struct DefOrUseLink* next; |
| } DefOrUseLink; |
| //!pair of def and uses |
| typedef struct DefUsePair { |
| DefOrUseLink* uses; |
| DefOrUseLink* useTail; |
| int num_uses; |
| DefOrUse def; |
| struct DefUsePair* next; |
| } DefUsePair; |
| |
| //!information associated with a virtual register |
| //!the pair <regNum, physicalType> uniquely determines a variable |
| typedef struct VirtualRegInfo { |
| int regNum; |
| LowOpndRegType physicalType; |
| int refCount; |
| RegAccessType accessType; |
| GlobalType gType; |
| int physicalReg_GG; |
| RegAllocConstraint allocConstraints[8]; |
| RegAllocConstraint allocConstraintsSorted[8]; |
| |
| DefOrUse reachingDefs[3]; //!reaching defs to the virtual register |
| int num_reaching_defs; |
| } VirtualRegInfo; |
| //!information of whether a VR is constant and its value |
| typedef struct ConstVRInfo { |
| int regNum; |
| int value; |
| bool isConst; |
| } ConstVRInfo; |
| #define NUM_ACCESS_IN_LIVERANGE 10 |
| //!specifies one live range |
| typedef struct LiveRange { |
| int start; |
| int end; //inclusive |
| //all accesses in the live range |
| int num_access; |
| int num_alloc; |
| int* accessPC; |
| struct LiveRange* next; |
| } LiveRange; |
| typedef struct BoundCheckIndex { |
| int indexVR; |
| bool checkDone; |
| } BoundCheckIndex; |
| //!information for a virtual register such as live ranges, in memory |
| typedef struct MemoryVRInfo { |
| int regNum; |
| bool inMemory; |
| bool nullCheckDone; |
| BoundCheckIndex boundCheck; |
| int num_ranges; |
| LiveRange* ranges; |
| u4 delayFreeFlags; //! for use with flags defined by VRDelayFreeFlags enum |
| } MemoryVRInfo; |
| //!information of a temporary |
| //!the pair <regNum, physicalType> uniquely determines a variable |
| typedef struct TempRegInfo { |
| int regNum; |
| int physicalType; |
| int refCount; |
| int linkageToVR; |
| int versionNum; |
| bool shareWithVR; //for temp. regs updated by get_virtual_reg |
| bool is8Bit; |
| } TempRegInfo; |
| struct BasicBlock_O1; |
| //!all variables accessed |
| //!the pair <regNum, physicalType> uniquely determines a variable |
| typedef struct compileTableEntry { |
| int regNum; |
| int physicalType; //gp, xmm or scratch, virtual |
| int physicalReg; |
| int physicalReg_prev; //for spilled GG VR |
| RegAccessType accessType; |
| |
| bool isConst; |
| int value[2]; //[0]: lower [1]: higher |
| int refCount; |
| |
| int linkageToVR; //for temporary registers only |
| GlobalType gType; |
| struct BasicBlock_O1* bb; //bb VR belongs to |
| int indexToInfoBB; |
| |
| VRState regState; |
| TRState trState; //for temporary registers only |
| int spill_loc_index; //for temporary registers only |
| } compileTableEntry; |
| //!to save the state of register allocator |
| typedef struct regAllocStateEntry1 { |
| int spill_loc_index; |
| int physicalReg; |
| } regAllocStateEntry1; |
| typedef struct regAllocStateEntry2 { |
| int regNum; // |
| bool inMemory; //whether 4-byte virtual reg is in memory |
| } regAllocStateEntry2; |
| //!edge in control flow graph |
| typedef struct Edge_O1 { |
| struct BasicBlock_O1* src; |
| struct BasicBlock_O1* dst; |
| } Edge_O1; |
| //!information associated with a basic block |
| typedef struct BasicBlock_O1 { |
| int bb_index; |
| int bb_index2; |
| int pc_start; //!inclusive |
| #ifndef WITH_JIT |
| int pc_end; //!exclusive |
| Edge_O1* in_edges[MAX_NUM_EDGE_PER_BB]; //array of Edge* |
| int num_in_edges; |
| Edge_O1* out_edges[MAX_NUM_EDGE_PER_BB]; |
| int num_out_edges; |
| #else |
| int pc_end; |
| BasicBlock* jitBasicBlock; |
| #endif |
| VirtualRegInfo infoBasicBlock[MAX_REG_PER_BASICBLOCK]; |
| int num_regs; |
| |
| RegAllocConstraint allocConstraints[8]; //# of times a hardcoded register is used in this basic block |
| //a physical register that is used many times has a lower priority to get picked in getFreeReg |
| RegAllocConstraint allocConstraintsSorted[8]; //count from low to high |
| |
| DefUsePair* defUseTable; |
| DefUsePair* defUseTail; |
| int num_defs; |
| XferPoint xferPoints[MAX_XFER_PER_BB]; //program points where the transfer is required |
| int num_xfer_points; |
| |
| bool endsWithReturn; |
| bool hasAccessToGlue; |
| } BasicBlock_O1; |
| typedef struct CFG_O1 { |
| BasicBlock_O1* head; |
| } CFG_O1; |
| //!worklist to create a control flow graph |
| typedef struct CFGWork { |
| BasicBlock_O1* bb_prev; |
| int targetOff; |
| struct CFGWork* nextItem; |
| } CFGWork; |
| |
| ///////////////////////////////////////// |
| extern compileTableEntry compileTable[COMPILE_TABLE_SIZE]; |
| extern int num_compile_entries; |
| extern VirtualRegInfo infoByteCode[MAX_REG_PER_BYTECODE]; |
| extern int num_regs_per_bytecode; |
| extern TempRegInfo infoByteCodeTemp[MAX_TEMP_REG_PER_BYTECODE]; |
| extern int num_temp_regs_per_bytecode; |
| extern VirtualRegInfo infoMethod[MAX_REG_PER_METHOD]; |
| extern int num_regs_per_method; |
| extern BasicBlock_O1* currentBB; |
| |
| extern BasicBlock_O1* method_bbs[MAX_NUM_BBS_PER_METHOD]; |
| extern int num_bbs_for_method; |
| extern BasicBlock_O1* method_bbs_sorted[MAX_NUM_BBS_PER_METHOD]; |
| extern BasicBlock_O1* bb_entry; |
| extern int pc_start; |
| extern int pc_end; |
| extern int current_bc_size; |
| extern int num_exception_handlers; |
| extern int exceptionHandlers[10]; |
| |
| extern int num_const_vr; |
| extern ConstVRInfo constVRTable[MAX_CONST_REG]; |
| |
| extern int genSet[MAX_REG_PER_BYTECODE]; |
| extern int killSet[MAX_REG_PER_BYTECODE]; |
| extern int num_regs_gen; //per bytecode |
| extern int num_regs_kill; //per bytecode |
| |
| extern int genSetBB[MAX_NUM_BBS_PER_METHOD][40]; |
| extern int killSetBB[MAX_NUM_BBS_PER_METHOD][40]; //same as size of memVRTable |
| extern int num_gen_bb[MAX_NUM_BBS_PER_METHOD]; |
| extern int num_kill_bb[MAX_NUM_BBS_PER_METHOD]; |
| |
| extern int nullCheck_inB[MAX_NUM_BBS_PER_METHOD][40]; |
| extern int nullCheck_inSize[MAX_NUM_BBS_PER_METHOD]; |
| extern int nullCheck_outB[MAX_NUM_BBS_PER_METHOD][40]; |
| extern int nullCheck_outSize[MAX_NUM_BBS_PER_METHOD]; |
| |
| typedef enum GlueVarType { |
| RES_CLASS = 0, |
| RES_METHOD, |
| RES_FIELD, |
| RES_STRING, |
| GLUE_DVMDEX, |
| GLUE_METHOD_CLASS, |
| GLUE_METHOD |
| } GlueVarType; |
| |
| void forwardAnalysis(int type); |
| |
| //functions in bc_visitor.c |
| int getByteCodeSize(); |
| bool getConstInfo(BasicBlock_O1* bb); |
| int getVirtualRegInfo(VirtualRegInfo* infoArray); |
| int getTempRegInfo(TempRegInfo* infoArray); |
| int createCFGHandler(Method* method); |
| |
| int findVirtualRegInTable(u2 vA, LowOpndRegType type, bool printError); |
| int searchCompileTable(int type, int regNum); |
| BasicBlock_O1* createBasicBlock(int src_pc, int end_pc); |
| void handleJump(BasicBlock_O1* bb_prev, int relOff); |
| void connectBasicBlock(BasicBlock_O1* src, BasicBlock_O1* dst); |
| int insertWorklist(BasicBlock_O1* bb_prev, int targetOff); |
| |
| int collectInfoOfBasicBlock(Method* method, BasicBlock_O1* bb); //update bb->infoBasicBlock |
| |
| void updateCurrentBBWithConstraints(PhysicalReg reg); |
| void updateConstInfo(BasicBlock_O1*); |
| OpndSize getRegSize(int type); |
| void invalidateVRDueToConst(int reg, OpndSize size); |
| #endif |
| |