blob: b5ded6a44bbe8eef96834300d30dc6ae1eac3228 [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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
11/// This file declares the Cfg class, which represents the control flow
12/// graph and the overall per-function compilation context.
13///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070014//===----------------------------------------------------------------------===//
15
16#ifndef SUBZERO_SRC_ICECFG_H
17#define SUBZERO_SRC_ICECFG_H
18
John Portoaff4ccf2015-06-10 16:35:06 -070019#include "IceAssembler.h"
Jan Voung8acded02014-09-22 18:02:25 -070020#include "IceClFlags.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070021#include "IceDefs.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070022#include "IceGlobalContext.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070023#include "IceTypes.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070024
25namespace Ice {
26
27class Cfg {
Jim Stichnothc6ead202015-02-24 09:30:30 -080028 Cfg() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -070029 Cfg(const Cfg &) = delete;
30 Cfg &operator=(const Cfg &) = delete;
31
Jim Stichnothf7c9a142014-04-29 10:52:43 -070032public:
Jim Stichnothf7c9a142014-04-29 10:52:43 -070033 ~Cfg();
34
Jim Stichnothbbca7542015-02-11 16:08:31 -080035 static std::unique_ptr<Cfg> create(GlobalContext *Ctx,
36 uint32_t SequenceNumber) {
37 return std::unique_ptr<Cfg>(new Cfg(Ctx, SequenceNumber));
Jim Stichnoth31c95592014-12-19 12:51:35 -080038 }
Andrew Scull9612d322015-07-06 14:53:25 -070039 /// Gets a pointer to the current thread's Cfg.
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080040 static const Cfg *getCurrentCfg() { return ICE_TLS_GET_FIELD(CurrentCfg); }
Jim Stichnoth8e928382015-02-02 17:03:08 -080041 static void setCurrentCfg(const Cfg *Func) {
42 ICE_TLS_SET_FIELD(CurrentCfg, Func);
43 }
Andrew Scull9612d322015-07-06 14:53:25 -070044 /// Gets a pointer to the current thread's Cfg's allocator.
Jan Voung1d62cf02015-01-09 14:57:32 -080045 static ArenaAllocator<> *getCurrentCfgAllocator() {
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080046 assert(ICE_TLS_GET_FIELD(CurrentCfg));
47 return ICE_TLS_GET_FIELD(CurrentCfg)->Allocator.get();
Jim Stichnoth31c95592014-12-19 12:51:35 -080048 }
49
Jim Stichnothf7c9a142014-04-29 10:52:43 -070050 GlobalContext *getContext() const { return Ctx; }
Jim Stichnothbbca7542015-02-11 16:08:31 -080051 uint32_t getSequenceNumber() const { return SequenceNumber; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070052
Andrew Scull9612d322015-07-06 14:53:25 -070053 /// Returns true if any of the specified options in the verbose mask
54 /// are set. If the argument is omitted, it checks if any verbose
55 /// options at all are set.
Jim Stichnothfa4efea2015-01-27 05:06:03 -080056 bool isVerbose(VerboseMask Mask = IceV_All) const { return VMask & Mask; }
57 void setVerbose(VerboseMask Mask) { VMask = Mask; }
58
Andrew Scull9612d322015-07-06 14:53:25 -070059 /// \name Manage the name and return type of the function being translated.
60 /// @{
Jim Stichnothf7c9a142014-04-29 10:52:43 -070061 void setFunctionName(const IceString &Name) { FunctionName = Name; }
62 IceString getFunctionName() const { return FunctionName; }
63 void setReturnType(Type Ty) { ReturnType = Ty; }
Andrew Scull9612d322015-07-06 14:53:25 -070064 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070065
Andrew Scull9612d322015-07-06 14:53:25 -070066 /// \name Manage the "internal" attribute of the function.
67 /// @{
Jim Stichnothf7c9a142014-04-29 10:52:43 -070068 void setInternal(bool Internal) { IsInternalLinkage = Internal; }
69 bool getInternal() const { return IsInternalLinkage; }
Andrew Scull9612d322015-07-06 14:53:25 -070070 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070071
Andrew Scull9612d322015-07-06 14:53:25 -070072 /// \name Manage errors.
73 /// @{
74
75 /// Translation error flagging. If support for some construct is
76 /// known to be missing, instead of an assertion failure, setError()
77 /// should be called and the error should be propagated back up.
78 /// This way, we can gracefully fail to translate and let a fallback
79 /// translator handle the function.
Jim Stichnothf7c9a142014-04-29 10:52:43 -070080 void setError(const IceString &Message);
81 bool hasError() const { return HasError; }
82 IceString getError() const { return ErrorMessage; }
Andrew Scull9612d322015-07-06 14:53:25 -070083 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070084
Andrew Scull9612d322015-07-06 14:53:25 -070085 /// \name Manage nodes (a.k.a. basic blocks, CfgNodes).
86 /// @{
Jim Stichnothf7c9a142014-04-29 10:52:43 -070087 void setEntryNode(CfgNode *EntryNode) { Entry = EntryNode; }
88 CfgNode *getEntryNode() const { return Entry; }
Andrew Scull9612d322015-07-06 14:53:25 -070089 /// Create a node and append it to the end of the linearized list.
Jim Stichnoth668a7a32014-12-10 15:32:25 -080090 CfgNode *makeNode();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070091 SizeT getNumNodes() const { return Nodes.size(); }
92 const NodeList &getNodes() const { return Nodes; }
Karl Schimpfac7d7342015-08-06 12:55:23 -070093 /// Swap nodes of Cfg with given list of nodes.
94 void swapNodes(NodeList &NewNodes);
Andrew Scull9612d322015-07-06 14:53:25 -070095 /// @}
Jim Stichnoth9a04c072014-12-11 15:51:42 -080096
97 typedef int32_t IdentifierIndexType;
Andrew Scull9612d322015-07-06 14:53:25 -070098 /// Adds a name to the list and returns its index, suitable for the
99 /// argument to getIdentifierName(). No checking for duplicates is
100 /// done. This is generally used for node names and variable names
101 /// to avoid embedding a std::string inside an arena-allocated
102 /// object.
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800103 IdentifierIndexType addIdentifierName(const IceString &Name) {
104 IdentifierIndexType Index = IdentifierNames.size();
105 IdentifierNames.push_back(Name);
Jim Stichnoth668a7a32014-12-10 15:32:25 -0800106 return Index;
107 }
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800108 const IceString &getIdentifierName(IdentifierIndexType Index) const {
109 return IdentifierNames[Index];
110 }
Jim Stichnothdd842db2015-01-27 12:53:53 -0800111 enum { IdentifierIndexInvalid = -1 };
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700112
Andrew Scull9612d322015-07-06 14:53:25 -0700113 /// \name Manage instruction numbering.
114 /// @{
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700115 InstNumberT newInstNumber() { return NextInstNumber++; }
Jim Stichnoth47752552014-10-13 17:15:08 -0700116 InstNumberT getNextInstNumber() const { return NextInstNumber; }
Andrew Scull9612d322015-07-06 14:53:25 -0700117 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700118
Andrew Scull9612d322015-07-06 14:53:25 -0700119 /// \name Manage Variables.
120 /// @{
121
122 /// Create a new Variable with a particular type and an optional
123 /// name. The Node argument is the node where the variable is defined.
Jan Voung28068ad2015-07-31 12:58:46 -0700124 // TODO(jpp): untemplate this with separate methods: makeVariable,
125 // makeSpillVariable, and makeStackVariable.
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800126 template <typename T = Variable> T *makeVariable(Type Ty) {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700127 SizeT Index = Variables.size();
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800128 T *Var = T::create(this, Ty, Index);
Jim Stichnoth800dab22014-09-20 12:25:02 -0700129 Variables.push_back(Var);
130 return Var;
131 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700132 SizeT getNumVariables() const { return Variables.size(); }
133 const VarList &getVariables() const { return Variables; }
Andrew Scull9612d322015-07-06 14:53:25 -0700134 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700135
Andrew Scull9612d322015-07-06 14:53:25 -0700136 /// \name Manage arguments to the function.
137 /// @{
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700138 void addArg(Variable *Arg);
139 const VarList &getArgs() const { return Args; }
Matt Wala45a06232014-07-09 16:33:22 -0700140 VarList &getArgs() { return Args; }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700141 void addImplicitArg(Variable *Arg);
142 const VarList &getImplicitArgs() const { return ImplicitArgs; }
Andrew Scull9612d322015-07-06 14:53:25 -0700143 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700144
Andrew Scull86df4e92015-07-30 13:54:44 -0700145 /// \name Manage the jump tables.
146 /// @{
147 void addJumpTable(InstJumpTable *JumpTable) {
148 JumpTables.emplace_back(JumpTable);
149 }
150 /// @}
151
Andrew Scull9612d322015-07-06 14:53:25 -0700152 /// \name Miscellaneous accessors.
153 /// @{
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700154 TargetLowering *getTarget() const { return Target.get(); }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700155 VariablesMetadata *getVMetadata() const { return VMetadata.get(); }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700156 Liveness *getLiveness() const { return Live.get(); }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800157 template <typename T = Assembler> T *getAssembler() const {
John Porto2da710c2015-06-29 07:57:02 -0700158 return llvm::dyn_cast<T>(TargetAssembler.get());
Jan Voung8acded02014-09-22 18:02:25 -0700159 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800160 Assembler *releaseAssembler() { return TargetAssembler.release(); }
John Portof8b4cc82015-06-09 18:06:19 -0700161 std::unique_ptr<VariableDeclarationList> getGlobalInits() {
162 return std::move(GlobalInits);
163 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700164 bool hasComputedFrame() const;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700165 bool getFocusedTiming() const { return FocusedTiming; }
166 void setFocusedTiming() { FocusedTiming = true; }
Andrew Scull9612d322015-07-06 14:53:25 -0700167 /// @}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700168
Andrew Scull9612d322015-07-06 14:53:25 -0700169 /// Returns true if Var is a global variable that is used by the profiling
170 /// code.
John Portof8b4cc82015-06-09 18:06:19 -0700171 static bool isProfileGlobal(const VariableDeclaration &Var);
172
Andrew Scull9612d322015-07-06 14:53:25 -0700173 /// Passes over the CFG.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700174 void translate();
Andrew Scull9612d322015-07-06 14:53:25 -0700175 /// After the CFG is fully constructed, iterate over the nodes and
176 /// compute the predecessor and successor edges, in the form of
177 /// CfgNode::InEdges[] and CfgNode::OutEdges[].
Jim Stichnoth69d3f9c2015-03-23 10:33:38 -0700178 void computeInOutEdges();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700179 void renumberInstructions();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700180 void placePhiLoads();
181 void placePhiStores();
182 void deletePhis();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700183 void advancedPhiLowering();
184 void reorderNodes();
Qining Lu969f6a32015-07-31 09:58:34 -0700185 void shuffleNodes();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700186 void doAddressOpt();
Matt Wala45a06232014-07-09 16:33:22 -0700187 void doArgLowering();
Matt Walac3302742014-08-15 16:21:56 -0700188 void doNopInsertion();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700189 void genCode();
190 void genFrame();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700191 void livenessLightweight();
192 void liveness(LivenessMode Mode);
193 bool validateLiveness() const;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700194 void contractEmptyNodes();
Jim Stichnothff9c7062014-09-18 04:50:49 -0700195 void doBranchOpt();
Andrew Scull86df4e92015-07-30 13:54:44 -0700196 void markNodesForSandboxing();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700197
Andrew Scull9612d322015-07-06 14:53:25 -0700198 /// \name Manage the CurrentNode field.
199 /// CurrentNode is used for validating the Variable::DefNode field during
200 /// dumping/emitting.
201 /// @{
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700202 void setCurrentNode(const CfgNode *Node) { CurrentNode = Node; }
Jim Stichnothae953202014-12-20 06:17:49 -0800203 void resetCurrentNode() { setCurrentNode(nullptr); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700204 const CfgNode *getCurrentNode() const { return CurrentNode; }
Andrew Scull9612d322015-07-06 14:53:25 -0700205 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700206
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700207 void emit();
Jan Voung0faec4c2014-11-05 17:29:56 -0800208 void emitIAS();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800209 static void emitTextHeader(const IceString &MangledName, GlobalContext *Ctx,
210 const Assembler *Asm);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700211 void dump(const IceString &Message = "");
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700212
Andrew Scull9612d322015-07-06 14:53:25 -0700213 /// Allocate data of type T using the per-Cfg allocator.
Jim Stichnoth31c95592014-12-19 12:51:35 -0800214 template <typename T> T *allocate() { return Allocator->Allocate<T>(); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700215
Andrew Scull9612d322015-07-06 14:53:25 -0700216 /// Allocate an array of data of type T using the per-Cfg allocator.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700217 template <typename T> T *allocateArrayOf(size_t NumElems) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800218 return Allocator->Allocate<T>(NumElems);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700219 }
220
Andrew Scull9612d322015-07-06 14:53:25 -0700221 /// Deallocate data that was allocated via allocate<T>().
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700222 template <typename T> void deallocate(T *Object) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800223 Allocator->Deallocate(Object);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700224 }
225
Andrew Scull9612d322015-07-06 14:53:25 -0700226 /// Deallocate data that was allocated via allocateArrayOf<T>().
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700227 template <typename T> void deallocateArrayOf(T *Array) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800228 Allocator->Deallocate(Array);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700229 }
230
231private:
Jim Stichnothbbca7542015-02-11 16:08:31 -0800232 Cfg(GlobalContext *Ctx, uint32_t SequenceNumber);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700233
Andrew Scull9612d322015-07-06 14:53:25 -0700234 /// Adds a call to the ProfileSummary runtime function as the first
235 /// instruction in this CFG's entry block.
John Portof8b4cc82015-06-09 18:06:19 -0700236 void addCallToProfileSummary();
237
Andrew Scull9612d322015-07-06 14:53:25 -0700238 /// Iterates over the basic blocks in this CFG, adding profiling code to each
239 /// one of them. It returns a list with all the globals that the profiling
240 /// code needs to be defined.
John Portof8b4cc82015-06-09 18:06:19 -0700241 void profileBlocks();
242
Andrew Scull86df4e92015-07-30 13:54:44 -0700243 /// Delete registered jump table placeholder instructions. This should only be
244 /// called once all repointing has taken place.
245 void deleteJumpTableInsts();
246 /// Iterate through the registered jump tables and emit them.
247 void emitJumpTables();
248
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700249 GlobalContext *Ctx;
Andrew Scull9612d322015-07-06 14:53:25 -0700250 uint32_t SequenceNumber; /// output order for emission
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800251 VerboseMask VMask;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700252 IceString FunctionName = "";
253 Type ReturnType = IceType_void;
254 bool IsInternalLinkage = false;
255 bool HasError = false;
256 bool FocusedTiming = false;
257 IceString ErrorMessage = "";
Andrew Scull9612d322015-07-06 14:53:25 -0700258 CfgNode *Entry = nullptr; /// entry basic block
259 NodeList Nodes; /// linearized node list; Entry should be first
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800260 std::vector<IceString> IdentifierNames;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700261 InstNumberT NextInstNumber;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700262 VarList Variables;
Andrew Scull9612d322015-07-06 14:53:25 -0700263 VarList Args; /// subset of Variables, in argument order
264 VarList ImplicitArgs; /// subset of Variables
Jan Voung1d62cf02015-01-09 14:57:32 -0800265 std::unique_ptr<ArenaAllocator<>> Allocator;
Jim Stichnotha18cc9c2014-09-30 19:10:22 -0700266 std::unique_ptr<Liveness> Live;
267 std::unique_ptr<TargetLowering> Target;
268 std::unique_ptr<VariablesMetadata> VMetadata;
269 std::unique_ptr<Assembler> TargetAssembler;
Andrew Scull9612d322015-07-06 14:53:25 -0700270 /// Globals required by this CFG. Mostly used for the profiler's globals.
John Portof8b4cc82015-06-09 18:06:19 -0700271 std::unique_ptr<VariableDeclarationList> GlobalInits;
Andrew Scull86df4e92015-07-30 13:54:44 -0700272 std::vector<InstJumpTable *> JumpTables;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700273
Andrew Scull9612d322015-07-06 14:53:25 -0700274 /// CurrentNode is maintained during dumping/emitting just for
275 /// validating Variable::DefNode. Normally, a traversal over
276 /// CfgNodes maintains this, but before global operations like
277 /// register allocation, resetCurrentNode() should be called to avoid
278 /// spurious validation failures.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700279 const CfgNode *CurrentNode = nullptr;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800280
Andrew Scull9612d322015-07-06 14:53:25 -0700281 /// Maintain a pointer in TLS to the current Cfg being translated.
282 /// This is primarily for accessing its allocator statelessly, but
283 /// other uses are possible.
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800284 ICE_TLS_DECLARE_FIELD(const Cfg *, CurrentCfg);
285
286public:
287 static void TlsInit() { ICE_TLS_INIT_FIELD(CurrentCfg); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700288};
289
290} // end of namespace Ice
291
292#endif // SUBZERO_SRC_ICECFG_H