//===- subzero/src/IceLiveness.h - Liveness analysis ------------*- C++ -*-===// // // The Subzero Code Generator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file /// \brief Declares the Liveness and LivenessNode classes, which are used for /// liveness analysis. /// /// The node-specific information tracked for each Variable includes whether it /// is live on entry, whether it is live on exit, the instruction number that /// starts its live range, and the instruction number that ends its live range. /// At the Cfg level, the actual live intervals are recorded. /// //===----------------------------------------------------------------------===// #ifndef SUBZERO_SRC_ICELIVENESS_H #define SUBZERO_SRC_ICELIVENESS_H #include "IceBitVector.h" #include "IceCfgNode.h" #include "IceDefs.h" #include "IceTLS.h" #include "IceTypes.h" #include #include namespace Ice { class Liveness { Liveness() = delete; Liveness(const Liveness &) = delete; Liveness &operator=(const Liveness &) = delete; class LivenessNode { LivenessNode &operator=(const LivenessNode &) = delete; public: LivenessNode() = default; LivenessNode(const LivenessNode &) = default; /// NumLocals is the number of Variables local to this block. SizeT NumLocals = 0; /// NumNonDeadPhis tracks the number of Phi instructions that /// Inst::liveness() identified as tentatively live. If NumNonDeadPhis /// changes from the last liveness pass, then liveness has not yet /// converged. SizeT NumNonDeadPhis = 0; // LiveToVarMap maps a liveness bitvector index to a Variable. This is // generally just for printing/dumping. The index should be less than // NumLocals + Liveness::NumGlobals. LivenessVector LiveToVarMap; // LiveIn and LiveOut track the in- and out-liveness of the global // variables. The size of each vector is LivenessNode::NumGlobals. LivenessBV LiveIn, LiveOut; // LiveBegin and LiveEnd track the instruction numbers of the start and end // of each variable's live range within this block. The index/key of each // element is less than NumLocals + Liveness::NumGlobals. LiveBeginEndMap LiveBegin, LiveEnd; }; public: void init(); void initPhiEdgeSplits(NodeList::const_iterator FirstNode, VarList::const_iterator FirstVar); Cfg *getFunc() const { return Func; } LivenessMode getMode() const { return Mode; } Variable *getVariable(SizeT LiveIndex, const CfgNode *Node) const; SizeT getLiveIndex(SizeT VarIndex) const { const SizeT LiveIndex = VarToLiveMap[VarIndex]; assert(LiveIndex != InvalidLiveIndex); return LiveIndex; } SizeT getNumGlobalVars() const { return NumGlobals; } SizeT getNumVarsInNode(const CfgNode *Node) const { return NumGlobals + Nodes[Node->getIndex()].NumLocals; } SizeT &getNumNonDeadPhis(const CfgNode *Node) { return Nodes[Node->getIndex()].NumNonDeadPhis; } LivenessBV &getLiveIn(const CfgNode *Node) { SizeT Index = Node->getIndex(); resize(Index); return Nodes[Index].LiveIn; } LivenessBV &getLiveOut(const CfgNode *Node) { SizeT Index = Node->getIndex(); resize(Index); return Nodes[Index].LiveOut; } LivenessBV &getScratchBV() { return ScratchBV; } LiveBeginEndMap *getLiveBegin(const CfgNode *Node) { SizeT Index = Node->getIndex(); resize(Index); return &Nodes[Index].LiveBegin; } LiveBeginEndMap *getLiveEnd(const CfgNode *Node) { SizeT Index = Node->getIndex(); resize(Index); return &Nodes[Index].LiveEnd; } bool getRangeMask(SizeT Index) const { return RangeMask[Index]; } ArenaAllocator *getAllocator() const { return Alloc.get(); } static std::unique_ptr create(Cfg *Func, LivenessMode Mode) { return std::unique_ptr(new Liveness(Func, Mode)); } static void TlsInit() { LivenessAllocatorTraits::init(); } std::string dumpStr() const { return "MaxLocals(" + std::to_string(MaxLocals) + "), " "NumGlobals(" + std::to_string(NumGlobals) + ")"; } private: Liveness(Cfg *Func, LivenessMode Mode) : Alloc(new ArenaAllocator()), AllocScope(this), Func(Func), Mode(Mode) {} void initInternal(NodeList::const_iterator FirstNode, VarList::const_iterator FirstVar, bool IsFullInit); /// Resize Nodes so that Nodes[Index] is valid. void resize(SizeT Index) { if (Index >= Nodes.size()) { assert(false && "The Nodes array is not expected to be resized."); Nodes.resize(Index + 1); } } std::unique_ptr Alloc; LivenessAllocatorScope AllocScope; // Must be declared after Alloc. static constexpr SizeT InvalidLiveIndex = -1; Cfg *Func; LivenessMode Mode; /// Size of Nodes is Cfg::Nodes.size(). LivenessVector Nodes; /// VarToLiveMap maps a Variable's Variable::Number to its live index within /// its basic block. LivenessVector VarToLiveMap; /// LiveToVarMap is analogous to LivenessNode::LiveToVarMap, but for non-local /// variables. LivenessVector LiveToVarMap; /// RangeMask[Variable::Number] indicates whether we want to track that /// Variable's live range. LivenessBV RangeMask; /// ScratchBV is a bitvector that can be reused across CfgNode passes, to /// avoid having to allocate/deallocate memory so frequently. LivenessBV ScratchBV; /// MaxLocals indicates what is the maximum number of local variables in a /// single basic block, across all blocks in a function. SizeT MaxLocals = 0; /// NumGlobals indicates how many global variables (i.e., Multi Block) exist /// for a function. SizeT NumGlobals = 0; }; } // end of namespace Ice #endif // SUBZERO_SRC_ICELIVENESS_H