xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceLiveness.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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