blob: 8cfe4748558a7e3c67cc1c5047d57f40cf574dfd [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
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares the Cfg class, which represents the control flow graph and
12/// the overall per-function compilation context.
Andrew Scull9612d322015-07-06 14:53:25 -070013///
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 }
Jim Stichnoth31c95592014-12-19 12:51:35 -080039
Jim Stichnothf7c9a142014-04-29 10:52:43 -070040 GlobalContext *getContext() const { return Ctx; }
Jim Stichnothbbca7542015-02-11 16:08:31 -080041 uint32_t getSequenceNumber() const { return SequenceNumber; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070042
Jim Stichnotha5229652015-11-12 10:25:21 -080043 static constexpr VerboseMask defaultVerboseMask() {
Karl Schimpf5403f5d2016-01-15 11:07:46 -080044 return IceV_All & ~IceV_Status & ~IceV_AvailableRegs;
Jim Stichnotha5229652015-11-12 10:25:21 -080045 }
Andrew Scull57e12682015-09-16 11:30:19 -070046 /// Returns true if any of the specified options in the verbose mask are set.
47 /// If the argument is omitted, it checks if any verbose options at all are
48 /// set.
Jim Stichnotha5229652015-11-12 10:25:21 -080049 bool isVerbose(VerboseMask Mask = defaultVerboseMask()) const {
50 return VMask & Mask;
51 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -080052 void setVerbose(VerboseMask Mask) { VMask = Mask; }
53
Andrew Scull9612d322015-07-06 14:53:25 -070054 /// \name Manage the name and return type of the function being translated.
55 /// @{
Jim Stichnothf7c9a142014-04-29 10:52:43 -070056 void setFunctionName(const IceString &Name) { FunctionName = Name; }
Jim Stichnothb40595a2016-01-29 06:14:31 -080057 const IceString &getFunctionName() const { return FunctionName; }
58 IceString getFunctionNameAndSize() const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070059 void setReturnType(Type Ty) { ReturnType = Ty; }
David Sehr0d9cf482015-11-16 17:00:38 -080060 Type getReturnType() const { return ReturnType; }
Andrew Scull9612d322015-07-06 14:53:25 -070061 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070062
Andrew Scull9612d322015-07-06 14:53:25 -070063 /// \name Manage the "internal" attribute of the function.
64 /// @{
Jim Stichnothf7c9a142014-04-29 10:52:43 -070065 void setInternal(bool Internal) { IsInternalLinkage = Internal; }
66 bool getInternal() const { return IsInternalLinkage; }
Andrew Scull9612d322015-07-06 14:53:25 -070067 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070068
Andrew Scull9612d322015-07-06 14:53:25 -070069 /// \name Manage errors.
70 /// @{
71
Andrew Scull57e12682015-09-16 11:30:19 -070072 /// Translation error flagging. If support for some construct is known to be
73 /// missing, instead of an assertion failure, setError() should be called and
74 /// the error should be propagated back up. This way, we can gracefully fail
75 /// to translate and let a fallback translator handle the function.
Jim Stichnothf7c9a142014-04-29 10:52:43 -070076 void setError(const IceString &Message);
77 bool hasError() const { return HasError; }
78 IceString getError() const { return ErrorMessage; }
Andrew Scull9612d322015-07-06 14:53:25 -070079 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070080
Andrew Scull9612d322015-07-06 14:53:25 -070081 /// \name Manage nodes (a.k.a. basic blocks, CfgNodes).
82 /// @{
Jim Stichnothf7c9a142014-04-29 10:52:43 -070083 void setEntryNode(CfgNode *EntryNode) { Entry = EntryNode; }
84 CfgNode *getEntryNode() const { return Entry; }
Andrew Scullaa6c1092015-09-03 17:50:30 -070085 /// Create a node and append it to the end of the linearized list. The loop
86 /// nest depth of the new node may not be valid if it is created after
87 /// computeLoopNestDepth.
Jim Stichnoth668a7a32014-12-10 15:32:25 -080088 CfgNode *makeNode();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070089 SizeT getNumNodes() const { return Nodes.size(); }
90 const NodeList &getNodes() const { return Nodes; }
Jim Stichnothe7dbc0b2015-09-15 10:09:24 -070091 /// Swap nodes of Cfg with given list of nodes. The number of nodes must
92 /// remain unchanged.
Karl Schimpfac7d7342015-08-06 12:55:23 -070093 void swapNodes(NodeList &NewNodes);
Andrew Scull9612d322015-07-06 14:53:25 -070094 /// @}
Jim Stichnoth9a04c072014-12-11 15:51:42 -080095
Andrew Scull8072bae2015-09-14 16:01:26 -070096 using IdentifierIndexType = int32_t;
Andrew Scull57e12682015-09-16 11:30:19 -070097 /// Adds a name to the list and returns its index, suitable for the argument
98 /// to getIdentifierName(). No checking for duplicates is done. This is
99 /// generally used for node names and variable names to avoid embedding a
100 /// std::string inside an arena-allocated object.
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800101 IdentifierIndexType addIdentifierName(const IceString &Name) {
102 IdentifierIndexType Index = IdentifierNames.size();
103 IdentifierNames.push_back(Name);
Jim Stichnoth668a7a32014-12-10 15:32:25 -0800104 return Index;
105 }
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800106 const IceString &getIdentifierName(IdentifierIndexType Index) const {
107 return IdentifierNames[Index];
108 }
Jim Stichnothdd842db2015-01-27 12:53:53 -0800109 enum { IdentifierIndexInvalid = -1 };
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700110
Andrew Scull9612d322015-07-06 14:53:25 -0700111 /// \name Manage instruction numbering.
112 /// @{
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700113 InstNumberT newInstNumber() { return NextInstNumber++; }
Jim Stichnoth47752552014-10-13 17:15:08 -0700114 InstNumberT getNextInstNumber() const { return NextInstNumber; }
Andrew Scull9612d322015-07-06 14:53:25 -0700115 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700116
Andrew Scull9612d322015-07-06 14:53:25 -0700117 /// \name Manage Variables.
118 /// @{
119
Andrew Scull57e12682015-09-16 11:30:19 -0700120 /// Create a new Variable with a particular type and an optional name. The
121 /// Node argument is the node where the variable is defined.
Jan Voung28068ad2015-07-31 12:58:46 -0700122 // TODO(jpp): untemplate this with separate methods: makeVariable,
123 // makeSpillVariable, and makeStackVariable.
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800124 template <typename T = Variable> T *makeVariable(Type Ty) {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700125 SizeT Index = Variables.size();
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800126 auto *Var = T::create(this, Ty, Index);
Jim Stichnoth800dab22014-09-20 12:25:02 -0700127 Variables.push_back(Var);
128 return Var;
129 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700130 SizeT getNumVariables() const { return Variables.size(); }
131 const VarList &getVariables() const { return Variables; }
Andrew Scull9612d322015-07-06 14:53:25 -0700132 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700133
Andrew Scull9612d322015-07-06 14:53:25 -0700134 /// \name Manage arguments to the function.
135 /// @{
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700136 void addArg(Variable *Arg);
137 const VarList &getArgs() const { return Args; }
Matt Wala45a06232014-07-09 16:33:22 -0700138 VarList &getArgs() { return Args; }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700139 void addImplicitArg(Variable *Arg);
140 const VarList &getImplicitArgs() const { return ImplicitArgs; }
Andrew Scull9612d322015-07-06 14:53:25 -0700141 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700142
Andrew Scull86df4e92015-07-30 13:54:44 -0700143 /// \name Manage the jump tables.
144 /// @{
145 void addJumpTable(InstJumpTable *JumpTable) {
146 JumpTables.emplace_back(JumpTable);
147 }
148 /// @}
149
John Portodc619252016-02-10 15:57:16 -0800150 /// \name Manage the Globals used by this function.
151 /// @{
152 std::unique_ptr<VariableDeclarationList> getGlobalInits() {
153 return std::move(GlobalInits);
154 }
155 void addGlobal(VariableDeclaration *Global) {
156 if (GlobalInits == nullptr) {
157 GlobalInits.reset(new VariableDeclarationList);
158 }
159 GlobalInits->push_back(Global);
160 }
161 /// @}
162
Andrew Scull9612d322015-07-06 14:53:25 -0700163 /// \name Miscellaneous accessors.
164 /// @{
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700165 TargetLowering *getTarget() const { return Target.get(); }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700166 VariablesMetadata *getVMetadata() const { return VMetadata.get(); }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700167 Liveness *getLiveness() const { return Live.get(); }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800168 template <typename T = Assembler> T *getAssembler() const {
John Porto2da710c2015-06-29 07:57:02 -0700169 return llvm::dyn_cast<T>(TargetAssembler.get());
Jan Voung8acded02014-09-22 18:02:25 -0700170 }
Jim Stichnothbbca7542015-02-11 16:08:31 -0800171 Assembler *releaseAssembler() { return TargetAssembler.release(); }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700172 bool hasComputedFrame() const;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700173 bool getFocusedTiming() const { return FocusedTiming; }
174 void setFocusedTiming() { FocusedTiming = true; }
Qining Luaee5fa82015-08-20 14:59:03 -0700175 uint32_t getConstantBlindingCookie() const { return ConstantBlindingCookie; }
Andrew Scull9612d322015-07-06 14:53:25 -0700176 /// @}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700177
Andrew Scull9612d322015-07-06 14:53:25 -0700178 /// Returns true if Var is a global variable that is used by the profiling
179 /// code.
John Portof8b4cc82015-06-09 18:06:19 -0700180 static bool isProfileGlobal(const VariableDeclaration &Var);
181
Andrew Scull9612d322015-07-06 14:53:25 -0700182 /// Passes over the CFG.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700183 void translate();
Andrew Scull57e12682015-09-16 11:30:19 -0700184 /// After the CFG is fully constructed, iterate over the nodes and compute the
185 /// predecessor and successor edges, in the form of CfgNode::InEdges[] and
186 /// CfgNode::OutEdges[].
Jim Stichnoth69d3f9c2015-03-23 10:33:38 -0700187 void computeInOutEdges();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700188 void renumberInstructions();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700189 void placePhiLoads();
190 void placePhiStores();
191 void deletePhis();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700192 void advancedPhiLowering();
193 void reorderNodes();
Qining Lu969f6a32015-07-31 09:58:34 -0700194 void shuffleNodes();
David Sehr4318a412015-11-11 15:01:55 -0800195
David Sehr4318a412015-11-11 15:01:55 -0800196 /// Scan allocas to determine whether we need to use a frame pointer.
197 /// If SortAndCombine == true, merge all the fixed-size allocas in the
198 /// entry block and emit stack or frame pointer-relative addressing.
199 void processAllocas(bool SortAndCombine);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700200 void doAddressOpt();
Matt Wala45a06232014-07-09 16:33:22 -0700201 void doArgLowering();
Matt Walac3302742014-08-15 16:21:56 -0700202 void doNopInsertion();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700203 void genCode();
204 void genFrame();
Andrew Scullaa6c1092015-09-03 17:50:30 -0700205 void computeLoopNestDepth();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700206 void livenessLightweight();
207 void liveness(LivenessMode Mode);
208 bool validateLiveness() const;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700209 void contractEmptyNodes();
Jim Stichnothff9c7062014-09-18 04:50:49 -0700210 void doBranchOpt();
Andrew Scull86df4e92015-07-30 13:54:44 -0700211 void markNodesForSandboxing();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700212
Andrew Scull9612d322015-07-06 14:53:25 -0700213 /// \name Manage the CurrentNode field.
214 /// CurrentNode is used for validating the Variable::DefNode field during
215 /// dumping/emitting.
216 /// @{
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700217 void setCurrentNode(const CfgNode *Node) { CurrentNode = Node; }
Jim Stichnothae953202014-12-20 06:17:49 -0800218 void resetCurrentNode() { setCurrentNode(nullptr); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700219 const CfgNode *getCurrentNode() const { return CurrentNode; }
Andrew Scull9612d322015-07-06 14:53:25 -0700220 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700221
Jim Stichnoth1bdb7352016-02-29 16:58:15 -0800222 /// Get the total amount of memory held by the per-Cfg allocator. This is
223 /// mostly meant for use inside a debugger.
224 static size_t getTotalMemoryMB();
225
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700226 void emit();
Jan Voung0faec4c2014-11-05 17:29:56 -0800227 void emitIAS();
Jim Stichnothbbca7542015-02-11 16:08:31 -0800228 static void emitTextHeader(const IceString &MangledName, GlobalContext *Ctx,
229 const Assembler *Asm);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700230 void dump(const IceString &Message = "");
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700231
Andrew Scull9612d322015-07-06 14:53:25 -0700232 /// Allocate data of type T using the per-Cfg allocator.
Jim Stichnoth31c95592014-12-19 12:51:35 -0800233 template <typename T> T *allocate() { return Allocator->Allocate<T>(); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700234
Andrew Scull9612d322015-07-06 14:53:25 -0700235 /// Allocate an array of data of type T using the per-Cfg allocator.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700236 template <typename T> T *allocateArrayOf(size_t NumElems) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800237 return Allocator->Allocate<T>(NumElems);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700238 }
239
Andrew Scull9612d322015-07-06 14:53:25 -0700240 /// Deallocate data that was allocated via allocate<T>().
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700241 template <typename T> void deallocate(T *Object) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800242 Allocator->Deallocate(Object);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700243 }
244
Andrew Scull9612d322015-07-06 14:53:25 -0700245 /// Deallocate data that was allocated via allocateArrayOf<T>().
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700246 template <typename T> void deallocateArrayOf(T *Array) {
Jim Stichnoth31c95592014-12-19 12:51:35 -0800247 Allocator->Deallocate(Array);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700248 }
249
250private:
John Portoe82b5602016-02-24 15:58:55 -0800251 friend class CfgAllocatorTraits; // for Allocator access.
252
Jim Stichnothbbca7542015-02-11 16:08:31 -0800253 Cfg(GlobalContext *Ctx, uint32_t SequenceNumber);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700254
Andrew Scull9612d322015-07-06 14:53:25 -0700255 /// Adds a call to the ProfileSummary runtime function as the first
256 /// instruction in this CFG's entry block.
John Portof8b4cc82015-06-09 18:06:19 -0700257 void addCallToProfileSummary();
258
Andrew Scull9612d322015-07-06 14:53:25 -0700259 /// Iterates over the basic blocks in this CFG, adding profiling code to each
260 /// one of them. It returns a list with all the globals that the profiling
261 /// code needs to be defined.
John Portof8b4cc82015-06-09 18:06:19 -0700262 void profileBlocks();
263
Andrew Scull86df4e92015-07-30 13:54:44 -0700264 /// Delete registered jump table placeholder instructions. This should only be
265 /// called once all repointing has taken place.
266 void deleteJumpTableInsts();
267 /// Iterate through the registered jump tables and emit them.
268 void emitJumpTables();
269
Jim Stichnoth3607b6c2015-11-13 14:28:23 -0800270 enum AllocaBaseVariableType {
271 BVT_StackPointer,
272 BVT_FramePointer,
273 BVT_UserPointer
274 };
275 void sortAndCombineAllocas(CfgVector<Inst *> &Allocas,
276 uint32_t CombinedAlignment, InstList &Insts,
277 AllocaBaseVariableType BaseVariableType);
278 void findRematerializable();
279
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700280 GlobalContext *Ctx;
Qining Luaee5fa82015-08-20 14:59:03 -0700281 uint32_t SequenceNumber; /// output order for emission
282 uint32_t ConstantBlindingCookie = 0; /// cookie for constant blinding
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800283 VerboseMask VMask;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700284 IceString FunctionName = "";
285 Type ReturnType = IceType_void;
286 bool IsInternalLinkage = false;
287 bool HasError = false;
288 bool FocusedTiming = false;
289 IceString ErrorMessage = "";
Andrew Scull9612d322015-07-06 14:53:25 -0700290 CfgNode *Entry = nullptr; /// entry basic block
291 NodeList Nodes; /// linearized node list; Entry should be first
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800292 std::vector<IceString> IdentifierNames;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700293 InstNumberT NextInstNumber;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700294 VarList Variables;
Andrew Scull9612d322015-07-06 14:53:25 -0700295 VarList Args; /// subset of Variables, in argument order
296 VarList ImplicitArgs; /// subset of Variables
John Portoe82b5602016-02-24 15:58:55 -0800297 std::unique_ptr<ArenaAllocator> Allocator;
Jim Stichnotha18cc9c2014-09-30 19:10:22 -0700298 std::unique_ptr<Liveness> Live;
299 std::unique_ptr<TargetLowering> Target;
300 std::unique_ptr<VariablesMetadata> VMetadata;
301 std::unique_ptr<Assembler> TargetAssembler;
Andrew Scull9612d322015-07-06 14:53:25 -0700302 /// Globals required by this CFG. Mostly used for the profiler's globals.
John Portof8b4cc82015-06-09 18:06:19 -0700303 std::unique_ptr<VariableDeclarationList> GlobalInits;
Andrew Scull00741a02015-09-16 19:04:09 -0700304 CfgVector<InstJumpTable *> JumpTables;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700305
Andrew Scull57e12682015-09-16 11:30:19 -0700306 /// CurrentNode is maintained during dumping/emitting just for validating
307 /// Variable::DefNode. Normally, a traversal over CfgNodes maintains this, but
308 /// before global operations like register allocation, resetCurrentNode()
309 /// should be called to avoid spurious validation failures.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700310 const CfgNode *CurrentNode = nullptr;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800311
Jim Stichnotha5fe17a2015-01-26 11:10:03 -0800312public:
John Portoe82b5602016-02-24 15:58:55 -0800313 static void TlsInit() { CfgAllocatorTraits::init(); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700314};
315
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700316template <> Variable *Cfg::makeVariable<Variable>(Type Ty);
317
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700318} // end of namespace Ice
319
320#endif // SUBZERO_SRC_ICECFG_H