blob: 176876144662868d9c3b7769cdda9eaf7dc8680e [file] [log] [blame]
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001//===- subzero/src/IceCfg.h - Control flow graph ----------------*- C++ -*-===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares the Cfg class, which represents the control flow
11// graph and the overall per-function compilation context.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef SUBZERO_SRC_ICECFG_H
16#define SUBZERO_SRC_ICECFG_H
17
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070018#include <memory>
19
20#include "llvm/Support/Allocator.h"
Jan Voung8acded02014-09-22 18:02:25 -070021
22#include "assembler.h"
23#include "IceClFlags.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070024#include "IceDefs.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070025#include "IceGlobalContext.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070026#include "IceTypes.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070027
28namespace Ice {
29
30class Cfg {
Jim Stichnoth7b451a92014-10-15 14:39:23 -070031 Cfg(const Cfg &) = delete;
32 Cfg &operator=(const Cfg &) = delete;
33
Jim Stichnothf7c9a142014-04-29 10:52:43 -070034public:
35 Cfg(GlobalContext *Ctx);
36 ~Cfg();
37
38 GlobalContext *getContext() const { return Ctx; }
39
40 // Manage the name and return type of the function being translated.
41 void setFunctionName(const IceString &Name) { FunctionName = Name; }
42 IceString getFunctionName() const { return FunctionName; }
43 void setReturnType(Type Ty) { ReturnType = Ty; }
44
45 // Manage the "internal" attribute of the function.
46 void setInternal(bool Internal) { IsInternalLinkage = Internal; }
47 bool getInternal() const { return IsInternalLinkage; }
48
49 // Translation error flagging. If support for some construct is
50 // known to be missing, instead of an assertion failure, setError()
51 // should be called and the error should be propagated back up.
52 // This way, we can gracefully fail to translate and let a fallback
53 // translator handle the function.
54 void setError(const IceString &Message);
55 bool hasError() const { return HasError; }
56 IceString getError() const { return ErrorMessage; }
57
58 // Manage nodes (a.k.a. basic blocks, CfgNodes).
59 void setEntryNode(CfgNode *EntryNode) { Entry = EntryNode; }
60 CfgNode *getEntryNode() const { return Entry; }
61 // Create a node and append it to the end of the linearized list.
Jim Stichnoth668a7a32014-12-10 15:32:25 -080062 CfgNode *makeNode();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070063 SizeT getNumNodes() const { return Nodes.size(); }
64 const NodeList &getNodes() const { return Nodes; }
Jim Stichnoth9a04c072014-12-11 15:51:42 -080065
66 typedef int32_t IdentifierIndexType;
Jim Stichnoth668a7a32014-12-10 15:32:25 -080067 // Adds a name to the list and returns its index, suitable for the
Jim Stichnoth9a04c072014-12-11 15:51:42 -080068 // argument to getIdentifierName(). No checking for duplicates is
69 // done. This is generally used for node names and variable names
70 // to avoid embedding a std::string inside an arena-allocated
71 // object.
72 IdentifierIndexType addIdentifierName(const IceString &Name) {
73 IdentifierIndexType Index = IdentifierNames.size();
74 IdentifierNames.push_back(Name);
Jim Stichnoth668a7a32014-12-10 15:32:25 -080075 return Index;
76 }
Jim Stichnoth9a04c072014-12-11 15:51:42 -080077 const IceString &getIdentifierName(IdentifierIndexType Index) const {
78 return IdentifierNames[Index];
79 }
80 enum {
81 IdentifierIndexInvalid = -1
82 };
Jim Stichnothf7c9a142014-04-29 10:52:43 -070083
84 // Manage instruction numbering.
Jim Stichnothd97c7df2014-06-04 11:57:08 -070085 InstNumberT newInstNumber() { return NextInstNumber++; }
Jim Stichnoth47752552014-10-13 17:15:08 -070086 InstNumberT getNextInstNumber() const { return NextInstNumber; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070087
88 // Manage Variables.
Jim Stichnoth800dab22014-09-20 12:25:02 -070089 // Create a new Variable with a particular type and an optional
90 // name. The Node argument is the node where the variable is defined.
Jim Stichnoth9a04c072014-12-11 15:51:42 -080091 template <typename T = Variable> T *makeVariable(Type Ty) {
Jim Stichnoth800dab22014-09-20 12:25:02 -070092 SizeT Index = Variables.size();
Jim Stichnoth9a04c072014-12-11 15:51:42 -080093 T *Var = T::create(this, Ty, Index);
Jim Stichnoth800dab22014-09-20 12:25:02 -070094 Variables.push_back(Var);
95 return Var;
96 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070097 SizeT getNumVariables() const { return Variables.size(); }
98 const VarList &getVariables() const { return Variables; }
99
100 // Manage arguments to the function.
101 void addArg(Variable *Arg);
102 const VarList &getArgs() const { return Args; }
Matt Wala45a06232014-07-09 16:33:22 -0700103 VarList &getArgs() { return Args; }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700104 void addImplicitArg(Variable *Arg);
105 const VarList &getImplicitArgs() const { return ImplicitArgs; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700106
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700107 // Miscellaneous accessors.
108 TargetLowering *getTarget() const { return Target.get(); }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700109 VariablesMetadata *getVMetadata() const { return VMetadata.get(); }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700110 Liveness *getLiveness() const { return Live.get(); }
Jan Voung8acded02014-09-22 18:02:25 -0700111 template <typename T> T *getAssembler() const {
112 return static_cast<T *>(TargetAssembler.get());
113 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700114 bool hasComputedFrame() const;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700115 bool getFocusedTiming() const { return FocusedTiming; }
116 void setFocusedTiming() { FocusedTiming = true; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700117
118 // Passes over the CFG.
119 void translate();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700120 // After the CFG is fully constructed, iterate over the nodes and
121 // compute the predecessor edges, in the form of
122 // CfgNode::InEdges[].
123 void computePredecessors();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700124 void renumberInstructions();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700125 void placePhiLoads();
126 void placePhiStores();
127 void deletePhis();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700128 void advancedPhiLowering();
129 void reorderNodes();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700130 void doAddressOpt();
Matt Wala45a06232014-07-09 16:33:22 -0700131 void doArgLowering();
Matt Walac3302742014-08-15 16:21:56 -0700132 void doNopInsertion();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700133 void genCode();
134 void genFrame();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700135 void livenessLightweight();
136 void liveness(LivenessMode Mode);
137 bool validateLiveness() const;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700138 void contractEmptyNodes();
Jim Stichnothff9c7062014-09-18 04:50:49 -0700139 void doBranchOpt();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700140
141 // Manage the CurrentNode field, which is used for validating the
142 // Variable::DefNode field during dumping/emitting.
143 void setCurrentNode(const CfgNode *Node) { CurrentNode = Node; }
Jim Stichnoth800dab22014-09-20 12:25:02 -0700144 void resetCurrentNode() { setCurrentNode(NULL); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700145 const CfgNode *getCurrentNode() const { return CurrentNode; }
146
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700147 void emit();
Jan Voung0faec4c2014-11-05 17:29:56 -0800148 void emitIAS();
149 void emitTextHeader(const IceString &MangledName);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700150 void dump(const IceString &Message = "");
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700151
152 // Allocate data of type T using the per-Cfg allocator.
153 template <typename T> T *allocate() { return Allocator.Allocate<T>(); }
154
155 // Allocate an instruction of type T using the per-Cfg instruction allocator.
156 template <typename T> T *allocateInst() { return Allocator.Allocate<T>(); }
157
158 // Allocate an array of data of type T using the per-Cfg allocator.
159 template <typename T> T *allocateArrayOf(size_t NumElems) {
160 return Allocator.Allocate<T>(NumElems);
161 }
162
163 // Deallocate data that was allocated via allocate<T>().
164 template <typename T> void deallocate(T *Object) {
165 Allocator.Deallocate(Object);
166 }
167
168 // Deallocate data that was allocated via allocateInst<T>().
169 template <typename T> void deallocateInst(T *Instr) {
170 Allocator.Deallocate(Instr);
171 }
172
173 // Deallocate data that was allocated via allocateArrayOf<T>().
174 template <typename T> void deallocateArrayOf(T *Array) {
175 Allocator.Deallocate(Array);
176 }
177
178private:
179 // TODO: for now, everything is allocated from the same allocator. In the
180 // future we may want to split this to several allocators, for example in
181 // order to use a "Recycler" to preserve memory. If we keep all allocation
182 // requests from the Cfg exposed via methods, we can always switch the
183 // implementation over at a later point.
Jim Stichnoth9d801a02014-11-26 14:11:53 -0800184 llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 1024 * 1024> Allocator;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700185
186 GlobalContext *Ctx;
187 IceString FunctionName;
188 Type ReturnType;
189 bool IsInternalLinkage;
190 bool HasError;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700191 bool FocusedTiming;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700192 IceString ErrorMessage;
193 CfgNode *Entry; // entry basic block
194 NodeList Nodes; // linearized node list; Entry should be first
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800195 std::vector<IceString> IdentifierNames;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700196 InstNumberT NextInstNumber;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700197 VarList Variables;
198 VarList Args; // subset of Variables, in argument order
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700199 VarList ImplicitArgs; // subset of Variables
Jim Stichnotha18cc9c2014-09-30 19:10:22 -0700200 std::unique_ptr<Liveness> Live;
201 std::unique_ptr<TargetLowering> Target;
202 std::unique_ptr<VariablesMetadata> VMetadata;
203 std::unique_ptr<Assembler> TargetAssembler;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700204
205 // CurrentNode is maintained during dumping/emitting just for
206 // validating Variable::DefNode. Normally, a traversal over
207 // CfgNodes maintains this, but before global operations like
Jim Stichnoth800dab22014-09-20 12:25:02 -0700208 // register allocation, resetCurrentNode() should be called to avoid
209 // spurious validation failures.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700210 const CfgNode *CurrentNode;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700211};
212
213} // end of namespace Ice
214
215#endif // SUBZERO_SRC_ICECFG_H