xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceCfg.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceCfg.h - Control flow graph ----------------*- 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 Cfg class, which represents the control flow graph and
12*03ce13f7SAndroid Build Coastguard Worker /// the overall per-function compilation context.
13*03ce13f7SAndroid Build Coastguard Worker ///
14*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*03ce13f7SAndroid Build Coastguard Worker 
16*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICECFG_H
17*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICECFG_H
18*03ce13f7SAndroid Build Coastguard Worker 
19*03ce13f7SAndroid Build Coastguard Worker #include "IceAssembler.h"
20*03ce13f7SAndroid Build Coastguard Worker #include "IceClFlags.h"
21*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "IceGlobalContext.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "IceLoopAnalyzer.h"
24*03ce13f7SAndroid Build Coastguard Worker #include "IceStringPool.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h"
26*03ce13f7SAndroid Build Coastguard Worker 
27*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
28*03ce13f7SAndroid Build Coastguard Worker 
29*03ce13f7SAndroid Build Coastguard Worker class Cfg {
30*03ce13f7SAndroid Build Coastguard Worker   Cfg() = delete;
31*03ce13f7SAndroid Build Coastguard Worker   Cfg(const Cfg &) = delete;
32*03ce13f7SAndroid Build Coastguard Worker   Cfg &operator=(const Cfg &) = delete;
33*03ce13f7SAndroid Build Coastguard Worker 
34*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<ArenaAllocator> Allocator;
35*03ce13f7SAndroid Build Coastguard Worker 
36*03ce13f7SAndroid Build Coastguard Worker public:
37*03ce13f7SAndroid Build Coastguard Worker   ~Cfg();
38*03ce13f7SAndroid Build Coastguard Worker 
create(GlobalContext * Ctx,uint32_t SequenceNumber)39*03ce13f7SAndroid Build Coastguard Worker   static std::unique_ptr<Cfg> create(GlobalContext *Ctx,
40*03ce13f7SAndroid Build Coastguard Worker                                      uint32_t SequenceNumber) {
41*03ce13f7SAndroid Build Coastguard Worker     return std::unique_ptr<Cfg>(new Cfg(Ctx, SequenceNumber));
42*03ce13f7SAndroid Build Coastguard Worker   }
43*03ce13f7SAndroid Build Coastguard Worker 
getContext()44*03ce13f7SAndroid Build Coastguard Worker   GlobalContext *getContext() const { return Ctx; }
getSequenceNumber()45*03ce13f7SAndroid Build Coastguard Worker   uint32_t getSequenceNumber() const { return SequenceNumber; }
getOptLevel()46*03ce13f7SAndroid Build Coastguard Worker   OptLevel getOptLevel() const { return OptimizationLevel; }
47*03ce13f7SAndroid Build Coastguard Worker 
defaultVerboseMask()48*03ce13f7SAndroid Build Coastguard Worker   static constexpr VerboseMask defaultVerboseMask() {
49*03ce13f7SAndroid Build Coastguard Worker     return (IceV_NO_PER_PASS_DUMP_BEYOND << 1) - 1;
50*03ce13f7SAndroid Build Coastguard Worker   }
51*03ce13f7SAndroid Build Coastguard Worker   /// Returns true if any of the specified options in the verbose mask are set.
52*03ce13f7SAndroid Build Coastguard Worker   /// If the argument is omitted, it checks if any verbose options at all are
53*03ce13f7SAndroid Build Coastguard Worker   /// set.
54*03ce13f7SAndroid Build Coastguard Worker   bool isVerbose(VerboseMask Mask = defaultVerboseMask()) const {
55*03ce13f7SAndroid Build Coastguard Worker     return VMask & Mask;
56*03ce13f7SAndroid Build Coastguard Worker   }
setVerbose(VerboseMask Mask)57*03ce13f7SAndroid Build Coastguard Worker   void setVerbose(VerboseMask Mask) { VMask = Mask; }
58*03ce13f7SAndroid Build Coastguard Worker 
59*03ce13f7SAndroid Build Coastguard Worker   /// \name Manage the name and return type of the function being translated.
60*03ce13f7SAndroid Build Coastguard Worker   /// @{
setFunctionName(GlobalString Name)61*03ce13f7SAndroid Build Coastguard Worker   void setFunctionName(GlobalString Name) { FunctionName = Name; }
getFunctionName()62*03ce13f7SAndroid Build Coastguard Worker   GlobalString getFunctionName() const { return FunctionName; }
63*03ce13f7SAndroid Build Coastguard Worker   std::string getFunctionNameAndSize() const;
setReturnType(Type Ty)64*03ce13f7SAndroid Build Coastguard Worker   void setReturnType(Type Ty) { ReturnType = Ty; }
getReturnType()65*03ce13f7SAndroid Build Coastguard Worker   Type getReturnType() const { return ReturnType; }
66*03ce13f7SAndroid Build Coastguard Worker   /// @}
67*03ce13f7SAndroid Build Coastguard Worker 
68*03ce13f7SAndroid Build Coastguard Worker   /// \name Manage the "internal" attribute of the function.
69*03ce13f7SAndroid Build Coastguard Worker   /// @{
setInternal(bool Internal)70*03ce13f7SAndroid Build Coastguard Worker   void setInternal(bool Internal) { IsInternalLinkage = Internal; }
getInternal()71*03ce13f7SAndroid Build Coastguard Worker   bool getInternal() const { return IsInternalLinkage; }
72*03ce13f7SAndroid Build Coastguard Worker   /// @}
73*03ce13f7SAndroid Build Coastguard Worker 
74*03ce13f7SAndroid Build Coastguard Worker   /// \name Manage errors.
75*03ce13f7SAndroid Build Coastguard Worker   /// @{
76*03ce13f7SAndroid Build Coastguard Worker 
77*03ce13f7SAndroid Build Coastguard Worker   /// Translation error flagging. If support for some construct is known to be
78*03ce13f7SAndroid Build Coastguard Worker   /// missing, instead of an assertion failure, setError() should be called and
79*03ce13f7SAndroid Build Coastguard Worker   /// the error should be propagated back up. This way, we can gracefully fail
80*03ce13f7SAndroid Build Coastguard Worker   /// to translate and let a fallback translator handle the function.
81*03ce13f7SAndroid Build Coastguard Worker   void setError(const std::string &Message);
hasError()82*03ce13f7SAndroid Build Coastguard Worker   bool hasError() const { return HasError; }
getError()83*03ce13f7SAndroid Build Coastguard Worker   std::string getError() const { return ErrorMessage; }
84*03ce13f7SAndroid Build Coastguard Worker   /// @}
85*03ce13f7SAndroid Build Coastguard Worker 
86*03ce13f7SAndroid Build Coastguard Worker   /// \name Manage nodes (a.k.a. basic blocks, CfgNodes).
87*03ce13f7SAndroid Build Coastguard Worker   /// @{
setEntryNode(CfgNode * EntryNode)88*03ce13f7SAndroid Build Coastguard Worker   void setEntryNode(CfgNode *EntryNode) { Entry = EntryNode; }
getEntryNode()89*03ce13f7SAndroid Build Coastguard Worker   CfgNode *getEntryNode() const { return Entry; }
90*03ce13f7SAndroid Build Coastguard Worker   /// Create a node and append it to the end of the linearized list. The loop
91*03ce13f7SAndroid Build Coastguard Worker   /// nest depth of the new node may not be valid if it is created after
92*03ce13f7SAndroid Build Coastguard Worker   /// computeLoopNestDepth.
93*03ce13f7SAndroid Build Coastguard Worker   CfgNode *makeNode();
getNumNodes()94*03ce13f7SAndroid Build Coastguard Worker   SizeT getNumNodes() const { return Nodes.size(); }
getNodes()95*03ce13f7SAndroid Build Coastguard Worker   const NodeList &getNodes() const { return Nodes; }
96*03ce13f7SAndroid Build Coastguard Worker   /// Swap nodes of Cfg with given list of nodes.  The number of nodes must
97*03ce13f7SAndroid Build Coastguard Worker   /// remain unchanged.
98*03ce13f7SAndroid Build Coastguard Worker   void swapNodes(NodeList &NewNodes);
99*03ce13f7SAndroid Build Coastguard Worker   /// @}
100*03ce13f7SAndroid Build Coastguard Worker 
101*03ce13f7SAndroid Build Coastguard Worker   /// String pool for CfgNode::Name values.
getNodeStrings()102*03ce13f7SAndroid Build Coastguard Worker   StringPool *getNodeStrings() const { return NodeStrings.get(); }
103*03ce13f7SAndroid Build Coastguard Worker   /// String pool for Variable::Name values.
getVarStrings()104*03ce13f7SAndroid Build Coastguard Worker   StringPool *getVarStrings() const { return VarStrings.get(); }
105*03ce13f7SAndroid Build Coastguard Worker 
106*03ce13f7SAndroid Build Coastguard Worker   /// \name Manage instruction numbering.
107*03ce13f7SAndroid Build Coastguard Worker   /// @{
newInstNumber()108*03ce13f7SAndroid Build Coastguard Worker   InstNumberT newInstNumber() { return NextInstNumber++; }
getNextInstNumber()109*03ce13f7SAndroid Build Coastguard Worker   InstNumberT getNextInstNumber() const { return NextInstNumber; }
110*03ce13f7SAndroid Build Coastguard Worker   /// @}
111*03ce13f7SAndroid Build Coastguard Worker 
112*03ce13f7SAndroid Build Coastguard Worker   /// \name Manage Variables.
113*03ce13f7SAndroid Build Coastguard Worker   /// @{
114*03ce13f7SAndroid Build Coastguard Worker 
115*03ce13f7SAndroid Build Coastguard Worker   /// Create a new Variable with a particular type and an optional name. The
116*03ce13f7SAndroid Build Coastguard Worker   /// Node argument is the node where the variable is defined.
117*03ce13f7SAndroid Build Coastguard Worker   // TODO(jpp): untemplate this with separate methods: makeVariable and
118*03ce13f7SAndroid Build Coastguard Worker   // makeStackVariable.
makeVariable(Type Ty)119*03ce13f7SAndroid Build Coastguard Worker   template <typename T = Variable> T *makeVariable(Type Ty) {
120*03ce13f7SAndroid Build Coastguard Worker     SizeT Index = Variables.size();
121*03ce13f7SAndroid Build Coastguard Worker     auto *Var = T::create(this, Ty, Index);
122*03ce13f7SAndroid Build Coastguard Worker     Variables.push_back(Var);
123*03ce13f7SAndroid Build Coastguard Worker     return Var;
124*03ce13f7SAndroid Build Coastguard Worker   }
getNumVariables()125*03ce13f7SAndroid Build Coastguard Worker   SizeT getNumVariables() const { return Variables.size(); }
getVariables()126*03ce13f7SAndroid Build Coastguard Worker   const VarList &getVariables() const { return Variables; }
127*03ce13f7SAndroid Build Coastguard Worker   /// @}
128*03ce13f7SAndroid Build Coastguard Worker 
129*03ce13f7SAndroid Build Coastguard Worker   /// \name Manage arguments to the function.
130*03ce13f7SAndroid Build Coastguard Worker   /// @{
131*03ce13f7SAndroid Build Coastguard Worker   void addArg(Variable *Arg);
getArgs()132*03ce13f7SAndroid Build Coastguard Worker   const VarList &getArgs() const { return Args; }
getArgs()133*03ce13f7SAndroid Build Coastguard Worker   VarList &getArgs() { return Args; }
134*03ce13f7SAndroid Build Coastguard Worker   void addImplicitArg(Variable *Arg);
getImplicitArgs()135*03ce13f7SAndroid Build Coastguard Worker   const VarList &getImplicitArgs() const { return ImplicitArgs; }
136*03ce13f7SAndroid Build Coastguard Worker   /// @}
137*03ce13f7SAndroid Build Coastguard Worker 
138*03ce13f7SAndroid Build Coastguard Worker   /// \name Manage the jump tables.
139*03ce13f7SAndroid Build Coastguard Worker   /// @{
addJumpTable(InstJumpTable * JumpTable)140*03ce13f7SAndroid Build Coastguard Worker   void addJumpTable(InstJumpTable *JumpTable) {
141*03ce13f7SAndroid Build Coastguard Worker     JumpTables.emplace_back(JumpTable);
142*03ce13f7SAndroid Build Coastguard Worker   }
143*03ce13f7SAndroid Build Coastguard Worker   /// @}
144*03ce13f7SAndroid Build Coastguard Worker 
145*03ce13f7SAndroid Build Coastguard Worker   /// \name Manage the Globals used by this function.
146*03ce13f7SAndroid Build Coastguard Worker   /// @{
getGlobalInits()147*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<VariableDeclarationList> getGlobalInits() {
148*03ce13f7SAndroid Build Coastguard Worker     return std::move(GlobalInits);
149*03ce13f7SAndroid Build Coastguard Worker   }
addGlobal(VariableDeclaration * Global)150*03ce13f7SAndroid Build Coastguard Worker   void addGlobal(VariableDeclaration *Global) {
151*03ce13f7SAndroid Build Coastguard Worker     if (GlobalInits == nullptr) {
152*03ce13f7SAndroid Build Coastguard Worker       GlobalInits.reset(new VariableDeclarationList);
153*03ce13f7SAndroid Build Coastguard Worker     }
154*03ce13f7SAndroid Build Coastguard Worker     GlobalInits->push_back(Global);
155*03ce13f7SAndroid Build Coastguard Worker   }
getGlobalPool()156*03ce13f7SAndroid Build Coastguard Worker   VariableDeclarationList *getGlobalPool() {
157*03ce13f7SAndroid Build Coastguard Worker     if (GlobalInits == nullptr) {
158*03ce13f7SAndroid Build Coastguard Worker       GlobalInits.reset(new VariableDeclarationList);
159*03ce13f7SAndroid Build Coastguard Worker     }
160*03ce13f7SAndroid Build Coastguard Worker     return GlobalInits.get();
161*03ce13f7SAndroid Build Coastguard Worker   }
162*03ce13f7SAndroid Build Coastguard Worker   /// @}
163*03ce13f7SAndroid Build Coastguard Worker 
164*03ce13f7SAndroid Build Coastguard Worker   /// \name Miscellaneous accessors.
165*03ce13f7SAndroid Build Coastguard Worker   /// @{
getTarget()166*03ce13f7SAndroid Build Coastguard Worker   TargetLowering *getTarget() const { return Target.get(); }
getVMetadata()167*03ce13f7SAndroid Build Coastguard Worker   VariablesMetadata *getVMetadata() const { return VMetadata.get(); }
getLiveness()168*03ce13f7SAndroid Build Coastguard Worker   Liveness *getLiveness() const { return Live.get(); }
getAssembler()169*03ce13f7SAndroid Build Coastguard Worker   template <typename T = Assembler> T *getAssembler() const {
170*03ce13f7SAndroid Build Coastguard Worker     return llvm::dyn_cast<T>(TargetAssembler.get());
171*03ce13f7SAndroid Build Coastguard Worker   }
releaseAssembler()172*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<Assembler> releaseAssembler() {
173*03ce13f7SAndroid Build Coastguard Worker     return std::move(TargetAssembler);
174*03ce13f7SAndroid Build Coastguard Worker   }
175*03ce13f7SAndroid Build Coastguard Worker   bool hasComputedFrame() const;
getFocusedTiming()176*03ce13f7SAndroid Build Coastguard Worker   bool getFocusedTiming() const { return FocusedTiming; }
setFocusedTiming()177*03ce13f7SAndroid Build Coastguard Worker   void setFocusedTiming() { FocusedTiming = true; }
178*03ce13f7SAndroid Build Coastguard Worker   /// @}
179*03ce13f7SAndroid Build Coastguard Worker 
180*03ce13f7SAndroid Build Coastguard Worker   /// Passes over the CFG.
181*03ce13f7SAndroid Build Coastguard Worker   void translate();
182*03ce13f7SAndroid Build Coastguard Worker   /// After the CFG is fully constructed, iterate over the nodes and compute the
183*03ce13f7SAndroid Build Coastguard Worker   /// predecessor and successor edges, in the form of CfgNode::InEdges[] and
184*03ce13f7SAndroid Build Coastguard Worker   /// CfgNode::OutEdges[].
185*03ce13f7SAndroid Build Coastguard Worker   void computeInOutEdges();
186*03ce13f7SAndroid Build Coastguard Worker   /// Renumber the non-deleted instructions in the Cfg.  This needs to be done
187*03ce13f7SAndroid Build Coastguard Worker   /// in preparation for live range analysis.  The instruction numbers in a
188*03ce13f7SAndroid Build Coastguard Worker   /// block must be monotonically increasing.  The range of instruction numbers
189*03ce13f7SAndroid Build Coastguard Worker   /// in a block, from lowest to highest, must not overlap with the range of any
190*03ce13f7SAndroid Build Coastguard Worker   /// other block.
191*03ce13f7SAndroid Build Coastguard Worker   ///
192*03ce13f7SAndroid Build Coastguard Worker   /// Also, if the configuration specifies to do so, remove/unlink all deleted
193*03ce13f7SAndroid Build Coastguard Worker   /// instructions from the Cfg, to speed up later passes over the instructions.
194*03ce13f7SAndroid Build Coastguard Worker   void renumberInstructions();
195*03ce13f7SAndroid Build Coastguard Worker   void placePhiLoads();
196*03ce13f7SAndroid Build Coastguard Worker   void placePhiStores();
197*03ce13f7SAndroid Build Coastguard Worker   void deletePhis();
198*03ce13f7SAndroid Build Coastguard Worker   void advancedPhiLowering();
199*03ce13f7SAndroid Build Coastguard Worker   void reorderNodes();
200*03ce13f7SAndroid Build Coastguard Worker   void localCSE(bool AssumeSSA);
201*03ce13f7SAndroid Build Coastguard Worker   void floatConstantCSE();
202*03ce13f7SAndroid Build Coastguard Worker   void shortCircuitJumps();
203*03ce13f7SAndroid Build Coastguard Worker   void loopInvariantCodeMotion();
204*03ce13f7SAndroid Build Coastguard Worker 
205*03ce13f7SAndroid Build Coastguard Worker   /// Scan allocas to determine whether we need to use a frame pointer.
206*03ce13f7SAndroid Build Coastguard Worker   /// If SortAndCombine == true, merge all the fixed-size allocas in the
207*03ce13f7SAndroid Build Coastguard Worker   /// entry block and emit stack or frame pointer-relative addressing.
208*03ce13f7SAndroid Build Coastguard Worker   void processAllocas(bool SortAndCombine);
209*03ce13f7SAndroid Build Coastguard Worker   void doAddressOpt();
210*03ce13f7SAndroid Build Coastguard Worker   /// Find clusters of insertelement/extractelement instructions that can be
211*03ce13f7SAndroid Build Coastguard Worker   /// replaced by a shufflevector instruction.
212*03ce13f7SAndroid Build Coastguard Worker   void materializeVectorShuffles();
213*03ce13f7SAndroid Build Coastguard Worker   void doArgLowering();
214*03ce13f7SAndroid Build Coastguard Worker   void genCode();
215*03ce13f7SAndroid Build Coastguard Worker   void genFrame();
216*03ce13f7SAndroid Build Coastguard Worker   void generateLoopInfo();
217*03ce13f7SAndroid Build Coastguard Worker   void livenessLightweight();
218*03ce13f7SAndroid Build Coastguard Worker   void liveness(LivenessMode Mode);
219*03ce13f7SAndroid Build Coastguard Worker   bool validateLiveness() const;
220*03ce13f7SAndroid Build Coastguard Worker   void contractEmptyNodes();
221*03ce13f7SAndroid Build Coastguard Worker   void doBranchOpt();
222*03ce13f7SAndroid Build Coastguard Worker 
223*03ce13f7SAndroid Build Coastguard Worker   /// \name  Manage the CurrentNode field.
224*03ce13f7SAndroid Build Coastguard Worker   /// CurrentNode is used for validating the Variable::DefNode field during
225*03ce13f7SAndroid Build Coastguard Worker   /// dumping/emitting.
226*03ce13f7SAndroid Build Coastguard Worker   /// @{
setCurrentNode(const CfgNode * Node)227*03ce13f7SAndroid Build Coastguard Worker   void setCurrentNode(const CfgNode *Node) { CurrentNode = Node; }
resetCurrentNode()228*03ce13f7SAndroid Build Coastguard Worker   void resetCurrentNode() { setCurrentNode(nullptr); }
getCurrentNode()229*03ce13f7SAndroid Build Coastguard Worker   const CfgNode *getCurrentNode() const { return CurrentNode; }
230*03ce13f7SAndroid Build Coastguard Worker   /// @}
231*03ce13f7SAndroid Build Coastguard Worker 
232*03ce13f7SAndroid Build Coastguard Worker   /// Get the total amount of memory held by the per-Cfg allocator.
233*03ce13f7SAndroid Build Coastguard Worker   size_t getTotalMemoryMB() const;
234*03ce13f7SAndroid Build Coastguard Worker 
235*03ce13f7SAndroid Build Coastguard Worker   /// Get the current memory usage due to liveness data structures.
236*03ce13f7SAndroid Build Coastguard Worker   size_t getLivenessMemoryMB() const;
237*03ce13f7SAndroid Build Coastguard Worker 
238*03ce13f7SAndroid Build Coastguard Worker   void emit();
239*03ce13f7SAndroid Build Coastguard Worker   void emitIAS();
240*03ce13f7SAndroid Build Coastguard Worker   static void emitTextHeader(GlobalString Name, GlobalContext *Ctx,
241*03ce13f7SAndroid Build Coastguard Worker                              const Assembler *Asm);
242*03ce13f7SAndroid Build Coastguard Worker   void dump(const char *Message = "");
243*03ce13f7SAndroid Build Coastguard Worker 
244*03ce13f7SAndroid Build Coastguard Worker   /// Allocate data of type T using the per-Cfg allocator.
allocate()245*03ce13f7SAndroid Build Coastguard Worker   template <typename T> T *allocate() { return Allocator->Allocate<T>(); }
246*03ce13f7SAndroid Build Coastguard Worker 
247*03ce13f7SAndroid Build Coastguard Worker   /// Allocate an array of data of type T using the per-Cfg allocator.
allocateArrayOf(size_t NumElems)248*03ce13f7SAndroid Build Coastguard Worker   template <typename T> T *allocateArrayOf(size_t NumElems) {
249*03ce13f7SAndroid Build Coastguard Worker     return Allocator->Allocate<T>(NumElems);
250*03ce13f7SAndroid Build Coastguard Worker   }
251*03ce13f7SAndroid Build Coastguard Worker 
252*03ce13f7SAndroid Build Coastguard Worker   /// Deallocate data that was allocated via allocate<T>().
deallocate(T * Object)253*03ce13f7SAndroid Build Coastguard Worker   template <typename T> void deallocate(T *Object) {
254*03ce13f7SAndroid Build Coastguard Worker     Allocator->Deallocate(Object);
255*03ce13f7SAndroid Build Coastguard Worker   }
256*03ce13f7SAndroid Build Coastguard Worker 
257*03ce13f7SAndroid Build Coastguard Worker   /// Deallocate data that was allocated via allocateArrayOf<T>().
deallocateArrayOf(T * Array)258*03ce13f7SAndroid Build Coastguard Worker   template <typename T> void deallocateArrayOf(T *Array) {
259*03ce13f7SAndroid Build Coastguard Worker     Allocator->Deallocate(Array);
260*03ce13f7SAndroid Build Coastguard Worker   }
261*03ce13f7SAndroid Build Coastguard Worker 
262*03ce13f7SAndroid Build Coastguard Worker   /// Update Phi labels with InEdges.
263*03ce13f7SAndroid Build Coastguard Worker   ///
264*03ce13f7SAndroid Build Coastguard Worker   /// The WASM translator cannot always determine the right incoming edge for a
265*03ce13f7SAndroid Build Coastguard Worker   /// value due to the CFG being built incrementally. The fixPhiNodes pass fills
266*03ce13f7SAndroid Build Coastguard Worker   /// in the correct information once everything is known.
267*03ce13f7SAndroid Build Coastguard Worker   void fixPhiNodes();
268*03ce13f7SAndroid Build Coastguard Worker 
setStackSizeLimit(uint32_t Limit)269*03ce13f7SAndroid Build Coastguard Worker   void setStackSizeLimit(uint32_t Limit) { StackSizeLimit = Limit; }
getStackSizeLimit()270*03ce13f7SAndroid Build Coastguard Worker   uint32_t getStackSizeLimit() const { return StackSizeLimit; }
271*03ce13f7SAndroid Build Coastguard Worker 
272*03ce13f7SAndroid Build Coastguard Worker private:
273*03ce13f7SAndroid Build Coastguard Worker   friend class CfgAllocatorTraits; // for Allocator access.
274*03ce13f7SAndroid Build Coastguard Worker 
275*03ce13f7SAndroid Build Coastguard Worker   Cfg(GlobalContext *Ctx, uint32_t SequenceNumber);
276*03ce13f7SAndroid Build Coastguard Worker 
277*03ce13f7SAndroid Build Coastguard Worker   void createNodeNameDeclaration(const std::string &NodeAsmName);
278*03ce13f7SAndroid Build Coastguard Worker   void
279*03ce13f7SAndroid Build Coastguard Worker   createBlockProfilingInfoDeclaration(const std::string &NodeAsmName,
280*03ce13f7SAndroid Build Coastguard Worker                                       VariableDeclaration *NodeNameDeclaration);
281*03ce13f7SAndroid Build Coastguard Worker 
282*03ce13f7SAndroid Build Coastguard Worker   /// Iterate through the registered jump tables and emit them.
283*03ce13f7SAndroid Build Coastguard Worker   void emitJumpTables();
284*03ce13f7SAndroid Build Coastguard Worker 
285*03ce13f7SAndroid Build Coastguard Worker   enum AllocaBaseVariableType {
286*03ce13f7SAndroid Build Coastguard Worker     BVT_StackPointer,
287*03ce13f7SAndroid Build Coastguard Worker     BVT_FramePointer,
288*03ce13f7SAndroid Build Coastguard Worker     BVT_UserPointer
289*03ce13f7SAndroid Build Coastguard Worker   };
290*03ce13f7SAndroid Build Coastguard Worker   void sortAndCombineAllocas(CfgVector<InstAlloca *> &Allocas,
291*03ce13f7SAndroid Build Coastguard Worker                              uint32_t CombinedAlignment, InstList &Insts,
292*03ce13f7SAndroid Build Coastguard Worker                              AllocaBaseVariableType BaseVariableType);
293*03ce13f7SAndroid Build Coastguard Worker   void findRematerializable();
294*03ce13f7SAndroid Build Coastguard Worker   CfgVector<Inst *>
295*03ce13f7SAndroid Build Coastguard Worker   findLoopInvariantInstructions(const CfgUnorderedSet<SizeT> &Body);
296*03ce13f7SAndroid Build Coastguard Worker 
297*03ce13f7SAndroid Build Coastguard Worker   static ArenaAllocator *createAllocator();
298*03ce13f7SAndroid Build Coastguard Worker 
299*03ce13f7SAndroid Build Coastguard Worker   GlobalContext *Ctx;
300*03ce13f7SAndroid Build Coastguard Worker   uint32_t SequenceNumber; /// output order for emission
301*03ce13f7SAndroid Build Coastguard Worker   OptLevel OptimizationLevel = Opt_m1;
302*03ce13f7SAndroid Build Coastguard Worker   VerboseMask VMask;
303*03ce13f7SAndroid Build Coastguard Worker   GlobalString FunctionName;
304*03ce13f7SAndroid Build Coastguard Worker   Type ReturnType = IceType_void;
305*03ce13f7SAndroid Build Coastguard Worker   bool IsInternalLinkage = false;
306*03ce13f7SAndroid Build Coastguard Worker   bool HasError = false;
307*03ce13f7SAndroid Build Coastguard Worker   bool FocusedTiming = false;
308*03ce13f7SAndroid Build Coastguard Worker   std::string ErrorMessage = "";
309*03ce13f7SAndroid Build Coastguard Worker   CfgNode *Entry = nullptr; /// entry basic block
310*03ce13f7SAndroid Build Coastguard Worker   NodeList Nodes;           /// linearized node list; Entry should be first
311*03ce13f7SAndroid Build Coastguard Worker   InstNumberT NextInstNumber;
312*03ce13f7SAndroid Build Coastguard Worker   VarList Variables;
313*03ce13f7SAndroid Build Coastguard Worker   VarList Args;         /// subset of Variables, in argument order
314*03ce13f7SAndroid Build Coastguard Worker   VarList ImplicitArgs; /// subset of Variables
315*03ce13f7SAndroid Build Coastguard Worker   // Separate string pools for CfgNode and Variable names, due to a combination
316*03ce13f7SAndroid Build Coastguard Worker   // of the uniqueness requirement, and assumptions in lit tests.
317*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<StringPool> NodeStrings;
318*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<StringPool> VarStrings;
319*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<Liveness> Live;
320*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<TargetLowering> Target;
321*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<VariablesMetadata> VMetadata;
322*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<Assembler> TargetAssembler;
323*03ce13f7SAndroid Build Coastguard Worker   /// Globals required by this CFG.
324*03ce13f7SAndroid Build Coastguard Worker   std::unique_ptr<VariableDeclarationList> GlobalInits;
325*03ce13f7SAndroid Build Coastguard Worker   CfgVector<InstJumpTable *> JumpTables;
326*03ce13f7SAndroid Build Coastguard Worker   /// CurrentNode is maintained during dumping/emitting just for validating
327*03ce13f7SAndroid Build Coastguard Worker   /// Variable::DefNode. Normally, a traversal over CfgNodes maintains this, but
328*03ce13f7SAndroid Build Coastguard Worker   /// before global operations like register allocation, resetCurrentNode()
329*03ce13f7SAndroid Build Coastguard Worker   /// should be called to avoid spurious validation failures.
330*03ce13f7SAndroid Build Coastguard Worker   const CfgNode *CurrentNode = nullptr;
331*03ce13f7SAndroid Build Coastguard Worker   CfgVector<Loop> LoopInfo;
332*03ce13f7SAndroid Build Coastguard Worker   uint32_t StackSizeLimit = 1 * 1024 * 1024; // 1 MiB
333*03ce13f7SAndroid Build Coastguard Worker 
334*03ce13f7SAndroid Build Coastguard Worker public:
TlsInit()335*03ce13f7SAndroid Build Coastguard Worker   static void TlsInit() { CfgAllocatorTraits::init(); }
336*03ce13f7SAndroid Build Coastguard Worker };
337*03ce13f7SAndroid Build Coastguard Worker 
338*03ce13f7SAndroid Build Coastguard Worker template <> Variable *Cfg::makeVariable<Variable>(Type Ty);
339*03ce13f7SAndroid Build Coastguard Worker 
340*03ce13f7SAndroid Build Coastguard Worker struct NodeStringPoolTraits {
341*03ce13f7SAndroid Build Coastguard Worker   using OwnerType = Cfg;
getStringsNodeStringPoolTraits342*03ce13f7SAndroid Build Coastguard Worker   static StringPool *getStrings(const OwnerType *PoolOwner) {
343*03ce13f7SAndroid Build Coastguard Worker     return PoolOwner->getNodeStrings();
344*03ce13f7SAndroid Build Coastguard Worker   }
345*03ce13f7SAndroid Build Coastguard Worker };
346*03ce13f7SAndroid Build Coastguard Worker using NodeString = StringID<NodeStringPoolTraits>;
347*03ce13f7SAndroid Build Coastguard Worker 
348*03ce13f7SAndroid Build Coastguard Worker struct VariableStringPoolTraits {
349*03ce13f7SAndroid Build Coastguard Worker   using OwnerType = Cfg;
getStringsVariableStringPoolTraits350*03ce13f7SAndroid Build Coastguard Worker   static StringPool *getStrings(const OwnerType *PoolOwner) {
351*03ce13f7SAndroid Build Coastguard Worker     return PoolOwner->getVarStrings();
352*03ce13f7SAndroid Build Coastguard Worker   }
353*03ce13f7SAndroid Build Coastguard Worker };
354*03ce13f7SAndroid Build Coastguard Worker using VariableString = StringID<VariableStringPoolTraits>;
355*03ce13f7SAndroid Build Coastguard Worker 
356*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
357*03ce13f7SAndroid Build Coastguard Worker 
358*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICECFG_H
359