1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceLiveness.h - Liveness analysis ------------*- C++ -*-===// 2*03ce13f7SAndroid Build Coastguard Worker // 3*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator 4*03ce13f7SAndroid Build Coastguard Worker // 5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*03ce13f7SAndroid Build Coastguard Worker // 8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*03ce13f7SAndroid Build Coastguard Worker /// 10*03ce13f7SAndroid Build Coastguard Worker /// \file 11*03ce13f7SAndroid Build Coastguard Worker /// \brief Declares the Liveness and LivenessNode classes, which are used for 12*03ce13f7SAndroid Build Coastguard Worker /// liveness analysis. 13*03ce13f7SAndroid Build Coastguard Worker /// 14*03ce13f7SAndroid Build Coastguard Worker /// The node-specific information tracked for each Variable includes whether it 15*03ce13f7SAndroid Build Coastguard Worker /// is live on entry, whether it is live on exit, the instruction number that 16*03ce13f7SAndroid Build Coastguard Worker /// starts its live range, and the instruction number that ends its live range. 17*03ce13f7SAndroid Build Coastguard Worker /// At the Cfg level, the actual live intervals are recorded. 18*03ce13f7SAndroid Build Coastguard Worker /// 19*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 20*03ce13f7SAndroid Build Coastguard Worker 21*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICELIVENESS_H 22*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICELIVENESS_H 23*03ce13f7SAndroid Build Coastguard Worker 24*03ce13f7SAndroid Build Coastguard Worker #include "IceBitVector.h" 25*03ce13f7SAndroid Build Coastguard Worker #include "IceCfgNode.h" 26*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h" 27*03ce13f7SAndroid Build Coastguard Worker #include "IceTLS.h" 28*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h" 29*03ce13f7SAndroid Build Coastguard Worker 30*03ce13f7SAndroid Build Coastguard Worker #include <memory> 31*03ce13f7SAndroid Build Coastguard Worker #include <utility> 32*03ce13f7SAndroid Build Coastguard Worker 33*03ce13f7SAndroid Build Coastguard Worker namespace Ice { 34*03ce13f7SAndroid Build Coastguard Worker 35*03ce13f7SAndroid Build Coastguard Worker class Liveness { 36*03ce13f7SAndroid Build Coastguard Worker Liveness() = delete; 37*03ce13f7SAndroid Build Coastguard Worker Liveness(const Liveness &) = delete; 38*03ce13f7SAndroid Build Coastguard Worker Liveness &operator=(const Liveness &) = delete; 39*03ce13f7SAndroid Build Coastguard Worker 40*03ce13f7SAndroid Build Coastguard Worker class LivenessNode { 41*03ce13f7SAndroid Build Coastguard Worker LivenessNode &operator=(const LivenessNode &) = delete; 42*03ce13f7SAndroid Build Coastguard Worker 43*03ce13f7SAndroid Build Coastguard Worker public: 44*03ce13f7SAndroid Build Coastguard Worker LivenessNode() = default; 45*03ce13f7SAndroid Build Coastguard Worker LivenessNode(const LivenessNode &) = default; 46*03ce13f7SAndroid Build Coastguard Worker /// NumLocals is the number of Variables local to this block. 47*03ce13f7SAndroid Build Coastguard Worker SizeT NumLocals = 0; 48*03ce13f7SAndroid Build Coastguard Worker /// NumNonDeadPhis tracks the number of Phi instructions that 49*03ce13f7SAndroid Build Coastguard Worker /// Inst::liveness() identified as tentatively live. If NumNonDeadPhis 50*03ce13f7SAndroid Build Coastguard Worker /// changes from the last liveness pass, then liveness has not yet 51*03ce13f7SAndroid Build Coastguard Worker /// converged. 52*03ce13f7SAndroid Build Coastguard Worker SizeT NumNonDeadPhis = 0; 53*03ce13f7SAndroid Build Coastguard Worker // LiveToVarMap maps a liveness bitvector index to a Variable. This is 54*03ce13f7SAndroid Build Coastguard Worker // generally just for printing/dumping. The index should be less than 55*03ce13f7SAndroid Build Coastguard Worker // NumLocals + Liveness::NumGlobals. 56*03ce13f7SAndroid Build Coastguard Worker LivenessVector<Variable *> LiveToVarMap; 57*03ce13f7SAndroid Build Coastguard Worker // LiveIn and LiveOut track the in- and out-liveness of the global 58*03ce13f7SAndroid Build Coastguard Worker // variables. The size of each vector is LivenessNode::NumGlobals. 59*03ce13f7SAndroid Build Coastguard Worker LivenessBV LiveIn, LiveOut; 60*03ce13f7SAndroid Build Coastguard Worker // LiveBegin and LiveEnd track the instruction numbers of the start and end 61*03ce13f7SAndroid Build Coastguard Worker // of each variable's live range within this block. The index/key of each 62*03ce13f7SAndroid Build Coastguard Worker // element is less than NumLocals + Liveness::NumGlobals. 63*03ce13f7SAndroid Build Coastguard Worker LiveBeginEndMap LiveBegin, LiveEnd; 64*03ce13f7SAndroid Build Coastguard Worker }; 65*03ce13f7SAndroid Build Coastguard Worker 66*03ce13f7SAndroid Build Coastguard Worker public: 67*03ce13f7SAndroid Build Coastguard Worker void init(); 68*03ce13f7SAndroid Build Coastguard Worker void initPhiEdgeSplits(NodeList::const_iterator FirstNode, 69*03ce13f7SAndroid Build Coastguard Worker VarList::const_iterator FirstVar); getFunc()70*03ce13f7SAndroid Build Coastguard Worker Cfg *getFunc() const { return Func; } getMode()71*03ce13f7SAndroid Build Coastguard Worker LivenessMode getMode() const { return Mode; } 72*03ce13f7SAndroid Build Coastguard Worker Variable *getVariable(SizeT LiveIndex, const CfgNode *Node) const; getLiveIndex(SizeT VarIndex)73*03ce13f7SAndroid Build Coastguard Worker SizeT getLiveIndex(SizeT VarIndex) const { 74*03ce13f7SAndroid Build Coastguard Worker const SizeT LiveIndex = VarToLiveMap[VarIndex]; 75*03ce13f7SAndroid Build Coastguard Worker assert(LiveIndex != InvalidLiveIndex); 76*03ce13f7SAndroid Build Coastguard Worker return LiveIndex; 77*03ce13f7SAndroid Build Coastguard Worker } getNumGlobalVars()78*03ce13f7SAndroid Build Coastguard Worker SizeT getNumGlobalVars() const { return NumGlobals; } getNumVarsInNode(const CfgNode * Node)79*03ce13f7SAndroid Build Coastguard Worker SizeT getNumVarsInNode(const CfgNode *Node) const { 80*03ce13f7SAndroid Build Coastguard Worker return NumGlobals + Nodes[Node->getIndex()].NumLocals; 81*03ce13f7SAndroid Build Coastguard Worker } getNumNonDeadPhis(const CfgNode * Node)82*03ce13f7SAndroid Build Coastguard Worker SizeT &getNumNonDeadPhis(const CfgNode *Node) { 83*03ce13f7SAndroid Build Coastguard Worker return Nodes[Node->getIndex()].NumNonDeadPhis; 84*03ce13f7SAndroid Build Coastguard Worker } getLiveIn(const CfgNode * Node)85*03ce13f7SAndroid Build Coastguard Worker LivenessBV &getLiveIn(const CfgNode *Node) { 86*03ce13f7SAndroid Build Coastguard Worker SizeT Index = Node->getIndex(); 87*03ce13f7SAndroid Build Coastguard Worker resize(Index); 88*03ce13f7SAndroid Build Coastguard Worker return Nodes[Index].LiveIn; 89*03ce13f7SAndroid Build Coastguard Worker } getLiveOut(const CfgNode * Node)90*03ce13f7SAndroid Build Coastguard Worker LivenessBV &getLiveOut(const CfgNode *Node) { 91*03ce13f7SAndroid Build Coastguard Worker SizeT Index = Node->getIndex(); 92*03ce13f7SAndroid Build Coastguard Worker resize(Index); 93*03ce13f7SAndroid Build Coastguard Worker return Nodes[Index].LiveOut; 94*03ce13f7SAndroid Build Coastguard Worker } getScratchBV()95*03ce13f7SAndroid Build Coastguard Worker LivenessBV &getScratchBV() { return ScratchBV; } getLiveBegin(const CfgNode * Node)96*03ce13f7SAndroid Build Coastguard Worker LiveBeginEndMap *getLiveBegin(const CfgNode *Node) { 97*03ce13f7SAndroid Build Coastguard Worker SizeT Index = Node->getIndex(); 98*03ce13f7SAndroid Build Coastguard Worker resize(Index); 99*03ce13f7SAndroid Build Coastguard Worker return &Nodes[Index].LiveBegin; 100*03ce13f7SAndroid Build Coastguard Worker } getLiveEnd(const CfgNode * Node)101*03ce13f7SAndroid Build Coastguard Worker LiveBeginEndMap *getLiveEnd(const CfgNode *Node) { 102*03ce13f7SAndroid Build Coastguard Worker SizeT Index = Node->getIndex(); 103*03ce13f7SAndroid Build Coastguard Worker resize(Index); 104*03ce13f7SAndroid Build Coastguard Worker return &Nodes[Index].LiveEnd; 105*03ce13f7SAndroid Build Coastguard Worker } getRangeMask(SizeT Index)106*03ce13f7SAndroid Build Coastguard Worker bool getRangeMask(SizeT Index) const { return RangeMask[Index]; } 107*03ce13f7SAndroid Build Coastguard Worker getAllocator()108*03ce13f7SAndroid Build Coastguard Worker ArenaAllocator *getAllocator() const { return Alloc.get(); } 109*03ce13f7SAndroid Build Coastguard Worker create(Cfg * Func,LivenessMode Mode)110*03ce13f7SAndroid Build Coastguard Worker static std::unique_ptr<Liveness> create(Cfg *Func, LivenessMode Mode) { 111*03ce13f7SAndroid Build Coastguard Worker return std::unique_ptr<Liveness>(new Liveness(Func, Mode)); 112*03ce13f7SAndroid Build Coastguard Worker } 113*03ce13f7SAndroid Build Coastguard Worker TlsInit()114*03ce13f7SAndroid Build Coastguard Worker static void TlsInit() { LivenessAllocatorTraits::init(); } 115*03ce13f7SAndroid Build Coastguard Worker dumpStr()116*03ce13f7SAndroid Build Coastguard Worker std::string dumpStr() const { 117*03ce13f7SAndroid Build Coastguard Worker return "MaxLocals(" + std::to_string(MaxLocals) + 118*03ce13f7SAndroid Build Coastguard Worker "), " 119*03ce13f7SAndroid Build Coastguard Worker "NumGlobals(" + 120*03ce13f7SAndroid Build Coastguard Worker std::to_string(NumGlobals) + ")"; 121*03ce13f7SAndroid Build Coastguard Worker } 122*03ce13f7SAndroid Build Coastguard Worker 123*03ce13f7SAndroid Build Coastguard Worker private: Liveness(Cfg * Func,LivenessMode Mode)124*03ce13f7SAndroid Build Coastguard Worker Liveness(Cfg *Func, LivenessMode Mode) 125*03ce13f7SAndroid Build Coastguard Worker : Alloc(new ArenaAllocator()), AllocScope(this), Func(Func), Mode(Mode) {} 126*03ce13f7SAndroid Build Coastguard Worker 127*03ce13f7SAndroid Build Coastguard Worker void initInternal(NodeList::const_iterator FirstNode, 128*03ce13f7SAndroid Build Coastguard Worker VarList::const_iterator FirstVar, bool IsFullInit); 129*03ce13f7SAndroid Build Coastguard Worker /// Resize Nodes so that Nodes[Index] is valid. resize(SizeT Index)130*03ce13f7SAndroid Build Coastguard Worker void resize(SizeT Index) { 131*03ce13f7SAndroid Build Coastguard Worker if (Index >= Nodes.size()) { 132*03ce13f7SAndroid Build Coastguard Worker assert(false && "The Nodes array is not expected to be resized."); 133*03ce13f7SAndroid Build Coastguard Worker Nodes.resize(Index + 1); 134*03ce13f7SAndroid Build Coastguard Worker } 135*03ce13f7SAndroid Build Coastguard Worker } 136*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<ArenaAllocator> Alloc; 137*03ce13f7SAndroid Build Coastguard Worker LivenessAllocatorScope AllocScope; // Must be declared after Alloc. 138*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT InvalidLiveIndex = -1; 139*03ce13f7SAndroid Build Coastguard Worker Cfg *Func; 140*03ce13f7SAndroid Build Coastguard Worker LivenessMode Mode; 141*03ce13f7SAndroid Build Coastguard Worker /// Size of Nodes is Cfg::Nodes.size(). 142*03ce13f7SAndroid Build Coastguard Worker LivenessVector<LivenessNode> Nodes; 143*03ce13f7SAndroid Build Coastguard Worker /// VarToLiveMap maps a Variable's Variable::Number to its live index within 144*03ce13f7SAndroid Build Coastguard Worker /// its basic block. 145*03ce13f7SAndroid Build Coastguard Worker LivenessVector<SizeT> VarToLiveMap; 146*03ce13f7SAndroid Build Coastguard Worker /// LiveToVarMap is analogous to LivenessNode::LiveToVarMap, but for non-local 147*03ce13f7SAndroid Build Coastguard Worker /// variables. 148*03ce13f7SAndroid Build Coastguard Worker LivenessVector<Variable *> LiveToVarMap; 149*03ce13f7SAndroid Build Coastguard Worker /// RangeMask[Variable::Number] indicates whether we want to track that 150*03ce13f7SAndroid Build Coastguard Worker /// Variable's live range. 151*03ce13f7SAndroid Build Coastguard Worker LivenessBV RangeMask; 152*03ce13f7SAndroid Build Coastguard Worker /// ScratchBV is a bitvector that can be reused across CfgNode passes, to 153*03ce13f7SAndroid Build Coastguard Worker /// avoid having to allocate/deallocate memory so frequently. 154*03ce13f7SAndroid Build Coastguard Worker LivenessBV ScratchBV; 155*03ce13f7SAndroid Build Coastguard Worker /// MaxLocals indicates what is the maximum number of local variables in a 156*03ce13f7SAndroid Build Coastguard Worker /// single basic block, across all blocks in a function. 157*03ce13f7SAndroid Build Coastguard Worker SizeT MaxLocals = 0; 158*03ce13f7SAndroid Build Coastguard Worker /// NumGlobals indicates how many global variables (i.e., Multi Block) exist 159*03ce13f7SAndroid Build Coastguard Worker /// for a function. 160*03ce13f7SAndroid Build Coastguard Worker SizeT NumGlobals = 0; 161*03ce13f7SAndroid Build Coastguard Worker }; 162*03ce13f7SAndroid Build Coastguard Worker 163*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice 164*03ce13f7SAndroid Build Coastguard Worker 165*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICELIVENESS_H 166