blob: c231860388176b094fe83665c1c744db506af1bb [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
John Portoaff4ccf2015-06-10 16:35:06 -070018#include "IceAssembler.h"
Jan Voung8acded02014-09-22 18:02:25 -070019#include "IceClFlags.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070020#include "IceDefs.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070021#include "IceGlobalContext.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070022#include "IceTypes.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070023
24namespace Ice {
25
26class Cfg {
Jim Stichnothc6ead202015-02-24 09:30:30 -080027 Cfg() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -070028 Cfg(const Cfg &) = delete;
29 Cfg &operator=(const Cfg &) = delete;
30
Jim Stichnothf7c9a142014-04-29 10:52:43 -070031public:
Jim Stichnothf7c9a142014-04-29 10:52:43 -070032 ~Cfg();
33
Jim Stichnothbbca7542015-02-11 16:08:31 -080034 static std::unique_ptr<Cfg> create(GlobalContext *Ctx,
35 uint32_t SequenceNumber) {
36 return std::unique_ptr<Cfg>(new Cfg(Ctx, SequenceNumber));
Jim Stichnoth31c95592014-12-19 12:51:35 -080037 }
38 // Gets a pointer to the current thread's Cfg.
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080039 static const Cfg *getCurrentCfg() { return ICE_TLS_GET_FIELD(CurrentCfg); }
Jim Stichnoth8e928382015-02-02 17:03:08 -080040 static void setCurrentCfg(const Cfg *Func) {
41 ICE_TLS_SET_FIELD(CurrentCfg, Func);
42 }
Jim Stichnoth31c95592014-12-19 12:51:35 -080043 // Gets a pointer to the current thread's Cfg's allocator.
Jan Voung1d62cf02015-01-09 14:57:32 -080044 static ArenaAllocator<> *getCurrentCfgAllocator() {
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080045 assert(ICE_TLS_GET_FIELD(CurrentCfg));
46 return ICE_TLS_GET_FIELD(CurrentCfg)->Allocator.get();
Jim Stichnoth31c95592014-12-19 12:51:35 -080047 }
48
Jim Stichnothf7c9a142014-04-29 10:52:43 -070049 GlobalContext *getContext() const { return Ctx; }
Jim Stichnothbbca7542015-02-11 16:08:31 -080050 uint32_t getSequenceNumber() const { return SequenceNumber; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070051
Jim Stichnothfa4efea2015-01-27 05:06:03 -080052 // Returns true if any of the specified options in the verbose mask
53 // are set. If the argument is omitted, it checks if any verbose
54 // options at all are set.
55 bool isVerbose(VerboseMask Mask = IceV_All) const { return VMask & Mask; }
56 void setVerbose(VerboseMask Mask) { VMask = Mask; }
57
Jim Stichnothf7c9a142014-04-29 10:52:43 -070058 // Manage the name and return type of the function being translated.
59 void setFunctionName(const IceString &Name) { FunctionName = Name; }
60 IceString getFunctionName() const { return FunctionName; }
61 void setReturnType(Type Ty) { ReturnType = Ty; }
62
63 // Manage the "internal" attribute of the function.
64 void setInternal(bool Internal) { IsInternalLinkage = Internal; }
65 bool getInternal() const { return IsInternalLinkage; }
66
67 // Translation error flagging. If support for some construct is
68 // known to be missing, instead of an assertion failure, setError()
69 // should be called and the error should be propagated back up.
70 // This way, we can gracefully fail to translate and let a fallback
71 // translator handle the function.
72 void setError(const IceString &Message);
73 bool hasError() const { return HasError; }
74 IceString getError() const { return ErrorMessage; }
75
76 // Manage nodes (a.k.a. basic blocks, CfgNodes).
77 void setEntryNode(CfgNode *EntryNode) { Entry = EntryNode; }
78 CfgNode *getEntryNode() const { return Entry; }
79 // Create a node and append it to the end of the linearized list.
Jim Stichnoth668a7a32014-12-10 15:32:25 -080080 CfgNode *makeNode();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070081 SizeT getNumNodes() const { return Nodes.size(); }
82 const NodeList &getNodes() const { return Nodes; }
Jim Stichnoth9a04c072014-12-11 15:51:42 -080083
84 typedef int32_t IdentifierIndexType;
Jim Stichnoth668a7a32014-12-10 15:32:25 -080085 // Adds a name to the list and returns its index, suitable for the
Jim Stichnoth9a04c072014-12-11 15:51:42 -080086 // argument to getIdentifierName(). No checking for duplicates is
87 // done. This is generally used for node names and variable names
88 // to avoid embedding a std::string inside an arena-allocated
89 // object.
90 IdentifierIndexType addIdentifierName(const IceString &Name) {
91 IdentifierIndexType Index = IdentifierNames.size();
92 IdentifierNames.push_back(Name);
Jim Stichnoth668a7a32014-12-10 15:32:25 -080093 return Index;
94 }
Jim Stichnoth9a04c072014-12-11 15:51:42 -080095 const IceString &getIdentifierName(IdentifierIndexType Index) const {
96 return IdentifierNames[Index];
97 }
Jim Stichnothdd842db2015-01-27 12:53:53 -080098 enum { IdentifierIndexInvalid = -1 };
Jim Stichnothf7c9a142014-04-29 10:52:43 -070099
100 // Manage instruction numbering.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700101 InstNumberT newInstNumber() { return NextInstNumber++; }
Jim Stichnoth47752552014-10-13 17:15:08 -0700102 InstNumberT getNextInstNumber() const { return NextInstNumber; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700103
104 // Manage Variables.
Jim Stichnoth800dab22014-09-20 12:25:02 -0700105 // Create a new Variable with a particular type and an optional
106 // name. The Node argument is the node where the variable is defined.
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800107 template <typename T = Variable> T *makeVariable(Type Ty) {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700108 SizeT Index = Variables.size();
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800109 T *Var = T::create(this, Ty, Index);
Jim Stichnoth800dab22014-09-20 12:25:02 -0700110 Variables.push_back(Var);
111 return Var;
112 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700113 SizeT getNumVariables() const { return Variables.size(); }
114 const VarList &getVariables() const { return Variables; }
115
116 // Manage arguments to the function.
117 void addArg(Variable *Arg);
118 const VarList &getArgs() const { return Args; }
Matt Wala45a06232014-07-09 16:33:22 -0700119 VarList &getArgs() { return Args; }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700120 void addImplicitArg(Variable *Arg);
121 const VarList &getImplicitArgs() const { return ImplicitArgs; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700122
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700123 // Miscellaneous accessors.
124 TargetLowering *getTarget() const { return Target.get(); }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700125 VariablesMetadata *getVMetadata() const { return VMetadata.get(); }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700126 Liveness *getLiveness() const { return Live.get(); }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800127 template <typename T = Assembler> T *getAssembler() const {
Jan Voung8acded02014-09-22 18:02:25 -0700128 return static_cast<T *>(TargetAssembler.get());
129 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800130 Assembler *releaseAssembler() { return TargetAssembler.release(); }
John Portof8b4cc82015-06-09 18:06:19 -0700131 std::unique_ptr<VariableDeclarationList> getGlobalInits() {
132 return std::move(GlobalInits);
133 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700134 bool hasComputedFrame() const;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700135 bool getFocusedTiming() const { return FocusedTiming; }
136 void setFocusedTiming() { FocusedTiming = true; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700137
John Portof8b4cc82015-06-09 18:06:19 -0700138 // Returns true if Var is a global variable that is used by the profiling
139 // code.
140 static bool isProfileGlobal(const VariableDeclaration &Var);
141
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700142 // Passes over the CFG.
143 void translate();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700144 // After the CFG is fully constructed, iterate over the nodes and
Jim Stichnoth69d3f9c2015-03-23 10:33:38 -0700145 // compute the predecessor and successor edges, in the form of
146 // CfgNode::InEdges[] and CfgNode::OutEdges[].
147 void computeInOutEdges();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700148 void renumberInstructions();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700149 void placePhiLoads();
150 void placePhiStores();
151 void deletePhis();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700152 void advancedPhiLowering();
153 void reorderNodes();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700154 void doAddressOpt();
Matt Wala45a06232014-07-09 16:33:22 -0700155 void doArgLowering();
Matt Walac3302742014-08-15 16:21:56 -0700156 void doNopInsertion();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700157 void genCode();
158 void genFrame();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700159 void livenessLightweight();
160 void liveness(LivenessMode Mode);
161 bool validateLiveness() const;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700162 void contractEmptyNodes();
Jim Stichnothff9c7062014-09-18 04:50:49 -0700163 void doBranchOpt();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700164
165 // Manage the CurrentNode field, which is used for validating the
166 // Variable::DefNode field during dumping/emitting.
167 void setCurrentNode(const CfgNode *Node) { CurrentNode = Node; }
Jim Stichnothae953202014-12-20 06:17:49 -0800168 void resetCurrentNode() { setCurrentNode(nullptr); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700169 const CfgNode *getCurrentNode() const { return CurrentNode; }
170
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700171 void emit();
Jan Voung0faec4c2014-11-05 17:29:56 -0800172 void emitIAS();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800173 static void emitTextHeader(const IceString &MangledName, GlobalContext *Ctx,
174 const Assembler *Asm);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700175 void dump(const IceString &Message = "");
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700176
177 // Allocate data of type T using the per-Cfg allocator.
Jim Stichnoth31c95592014-12-19 12:51:35 -0800178 template <typename T> T *allocate() { return Allocator->Allocate<T>(); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700179
180 // Allocate an array of data of type T using the per-Cfg allocator.
181 template <typename T> T *allocateArrayOf(size_t NumElems) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800182 return Allocator->Allocate<T>(NumElems);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700183 }
184
185 // Deallocate data that was allocated via allocate<T>().
186 template <typename T> void deallocate(T *Object) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800187 Allocator->Deallocate(Object);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700188 }
189
190 // Deallocate data that was allocated via allocateArrayOf<T>().
191 template <typename T> void deallocateArrayOf(T *Array) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800192 Allocator->Deallocate(Array);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700193 }
194
195private:
Jim Stichnothbbca7542015-02-11 16:08:31 -0800196 Cfg(GlobalContext *Ctx, uint32_t SequenceNumber);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700197
John Portof8b4cc82015-06-09 18:06:19 -0700198 // Adds a call to the ProfileSummary runtime function as the first instruction
199 // in this CFG's entry block.
200 void addCallToProfileSummary();
201
202 // Iterates over the basic blocks in this CFG, adding profiling code to each
203 // one of them. It returns a list with all the globals that the profiling code
204 // needs to be defined.
205 void profileBlocks();
206
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700207 GlobalContext *Ctx;
Jim Stichnothbbca7542015-02-11 16:08:31 -0800208 uint32_t SequenceNumber; // output order for emission
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800209 VerboseMask VMask;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700210 IceString FunctionName;
211 Type ReturnType;
212 bool IsInternalLinkage;
213 bool HasError;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700214 bool FocusedTiming;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700215 IceString ErrorMessage;
216 CfgNode *Entry; // entry basic block
217 NodeList Nodes; // linearized node list; Entry should be first
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800218 std::vector<IceString> IdentifierNames;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700219 InstNumberT NextInstNumber;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700220 VarList Variables;
Jim Stichnothdd842db2015-01-27 12:53:53 -0800221 VarList Args; // subset of Variables, in argument order
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700222 VarList ImplicitArgs; // subset of Variables
Jan Voung1d62cf02015-01-09 14:57:32 -0800223 std::unique_ptr<ArenaAllocator<>> Allocator;
Jim Stichnotha18cc9c2014-09-30 19:10:22 -0700224 std::unique_ptr<Liveness> Live;
225 std::unique_ptr<TargetLowering> Target;
226 std::unique_ptr<VariablesMetadata> VMetadata;
227 std::unique_ptr<Assembler> TargetAssembler;
John Portof8b4cc82015-06-09 18:06:19 -0700228 // Globals required by this CFG. Mostly used for the profiler's globals.
229 std::unique_ptr<VariableDeclarationList> GlobalInits;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700230
231 // CurrentNode is maintained during dumping/emitting just for
232 // validating Variable::DefNode. Normally, a traversal over
233 // CfgNodes maintains this, but before global operations like
Jim Stichnoth800dab22014-09-20 12:25:02 -0700234 // register allocation, resetCurrentNode() should be called to avoid
235 // spurious validation failures.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700236 const CfgNode *CurrentNode;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800237
238 // Maintain a pointer in TLS to the current Cfg being translated.
239 // This is primarily for accessing its allocator statelessly, but
240 // other uses are possible.
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800241 ICE_TLS_DECLARE_FIELD(const Cfg *, CurrentCfg);
242
243public:
244 static void TlsInit() { ICE_TLS_INIT_FIELD(CurrentCfg); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700245};
246
247} // end of namespace Ice
248
249#endif // SUBZERO_SRC_ICECFG_H