/* * 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