blob: 02d450329055afadfb076ac8cba482d0e66158ab [file] [log] [blame]
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001//===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===//
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
Andrew Scull57e12682015-09-16 11:30:19 -070011/// This file implements the Cfg class, including constant pool management.
Andrew Scull9612d322015-07-06 14:53:25 -070012///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070013//===----------------------------------------------------------------------===//
14
15#include "IceCfg.h"
John Porto67f8de92015-06-25 10:14:17 -070016
17#include "IceAssembler.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070018#include "IceCfgNode.h"
Jim Stichnoth989a7032014-08-08 10:13:44 -070019#include "IceClFlags.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070020#include "IceDefs.h"
Jan Voungec270732015-01-12 17:00:22 -080021#include "IceELFObjectWriter.h"
John Portof8b4cc82015-06-09 18:06:19 -070022#include "IceGlobalInits.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070023#include "IceInst.h"
John Portoec3f5652015-08-31 15:07:09 -070024#include "IceInstVarIter.h"
Jim Stichnothd97c7df2014-06-04 11:57:08 -070025#include "IceLiveness.h"
Andrew Scullaa6c1092015-09-03 17:50:30 -070026#include "IceLoopAnalyzer.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070027#include "IceOperand.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070028#include "IceTargetLowering.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070029
30namespace Ice {
31
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080032ICE_TLS_DEFINE_FIELD(const Cfg *, Cfg, CurrentCfg);
Jim Stichnoth31c95592014-12-19 12:51:35 -080033
Jan Voung1d62cf02015-01-09 14:57:32 -080034ArenaAllocator<> *getCurrentCfgAllocator() {
Jim Stichnoth31c95592014-12-19 12:51:35 -080035 return Cfg::getCurrentCfgAllocator();
36}
37
Jim Stichnothbbca7542015-02-11 16:08:31 -080038Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber)
Jan Voung1f47ad02015-03-20 15:01:26 -070039 : Ctx(Ctx), SequenceNumber(SequenceNumber),
Jim Stichnotheafb56c2015-06-22 10:35:22 -070040 VMask(Ctx->getFlags().getVerbose()), NextInstNumber(Inst::NumberInitial),
41 Allocator(new ArenaAllocator<>()), Live(nullptr),
42 Target(TargetLowering::createLowering(Ctx->getFlags().getTargetArch(),
43 this)),
Jan Voung8acded02014-09-22 18:02:25 -070044 VMetadata(new VariablesMetadata(this)),
Jan Voung1f47ad02015-03-20 15:01:26 -070045 TargetAssembler(TargetLowering::createAssembler(
Jim Stichnotheafb56c2015-06-22 10:35:22 -070046 Ctx->getFlags().getTargetArch(), this)) {
Qining Luaee5fa82015-08-20 14:59:03 -070047 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Randomize) {
Andrew Scull57e12682015-09-16 11:30:19 -070048 // If -randomize-pool-immediates=randomize, create a random number
49 // generator to generate a cookie for constant blinding.
Qining Luaee5fa82015-08-20 14:59:03 -070050 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
Qining Lu360e3192015-08-20 17:13:07 -070051 RPE_ConstantBlinding, this->SequenceNumber);
Qining Luaee5fa82015-08-20 14:59:03 -070052 ConstantBlindingCookie =
Qining Lu360e3192015-08-20 17:13:07 -070053 (uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max() + 1);
Qining Luaee5fa82015-08-20 14:59:03 -070054 }
Karl Schimpf6fcbddd2014-11-06 09:49:24 -080055}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070056
Jim Stichnoth8e928382015-02-02 17:03:08 -080057Cfg::~Cfg() { assert(ICE_TLS_GET_FIELD(CurrentCfg) == nullptr); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070058
59void Cfg::setError(const IceString &Message) {
60 HasError = true;
61 ErrorMessage = Message;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070062}
63
Jim Stichnoth668a7a32014-12-10 15:32:25 -080064CfgNode *Cfg::makeNode() {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070065 SizeT LabelIndex = Nodes.size();
Jim Stichnoth668a7a32014-12-10 15:32:25 -080066 CfgNode *Node = CfgNode::create(this, LabelIndex);
Jim Stichnothf7c9a142014-04-29 10:52:43 -070067 Nodes.push_back(Node);
68 return Node;
69}
70
Karl Schimpfac7d7342015-08-06 12:55:23 -070071void Cfg::swapNodes(NodeList &NewNodes) {
Jim Stichnothe7dbc0b2015-09-15 10:09:24 -070072 assert(Nodes.size() == NewNodes.size());
Karl Schimpfac7d7342015-08-06 12:55:23 -070073 Nodes.swap(NewNodes);
74 for (SizeT I = 0, NumNodes = getNumNodes(); I < NumNodes; ++I)
75 Nodes[I]->resetIndex(I);
76}
77
Jim Stichnothf7c9a142014-04-29 10:52:43 -070078void Cfg::addArg(Variable *Arg) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -070079 Arg->setIsArg();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070080 Args.push_back(Arg);
81}
82
Jim Stichnoth144cdce2014-09-22 16:02:59 -070083void Cfg::addImplicitArg(Variable *Arg) {
84 Arg->setIsImplicitArg();
85 ImplicitArgs.push_back(Arg);
86}
87
Andrew Scull57e12682015-09-16 11:30:19 -070088// Returns whether the stack frame layout has been computed yet. This is used
89// for dumping the stack frame location of Variables.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070090bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); }
91
John Portof8b4cc82015-06-09 18:06:19 -070092namespace {
93constexpr char BlockNameGlobalPrefix[] = ".L$profiler$block_name$";
94constexpr char BlockStatsGlobalPrefix[] = ".L$profiler$block_info$";
95
John Porto1bec8bc2015-06-22 10:51:13 -070096VariableDeclaration *nodeNameDeclaration(GlobalContext *Ctx,
97 const IceString &NodeAsmName) {
98 VariableDeclaration *Var = VariableDeclaration::create(Ctx);
John Portof8b4cc82015-06-09 18:06:19 -070099 Var->setName(BlockNameGlobalPrefix + NodeAsmName);
100 Var->setIsConstant(true);
John Porto1bec8bc2015-06-22 10:51:13 -0700101 Var->addInitializer(VariableDeclaration::DataInitializer::create(
John Portof8b4cc82015-06-09 18:06:19 -0700102 NodeAsmName.data(), NodeAsmName.size() + 1));
103 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64);
104 Var->setAlignment(Int64ByteSize); // Wasteful, 32-bit could use 4 bytes.
105 return Var;
106}
107
108VariableDeclaration *
John Porto1bec8bc2015-06-22 10:51:13 -0700109blockProfilingInfoDeclaration(GlobalContext *Ctx, const IceString &NodeAsmName,
John Portof8b4cc82015-06-09 18:06:19 -0700110 VariableDeclaration *NodeNameDeclaration) {
John Porto1bec8bc2015-06-22 10:51:13 -0700111 VariableDeclaration *Var = VariableDeclaration::create(Ctx);
John Portof8b4cc82015-06-09 18:06:19 -0700112 Var->setName(BlockStatsGlobalPrefix + NodeAsmName);
113 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64);
John Porto1bec8bc2015-06-22 10:51:13 -0700114 Var->addInitializer(
115 VariableDeclaration::ZeroInitializer::create(Int64ByteSize));
John Portof8b4cc82015-06-09 18:06:19 -0700116
117 const RelocOffsetT NodeNameDeclarationOffset = 0;
John Porto1bec8bc2015-06-22 10:51:13 -0700118 Var->addInitializer(VariableDeclaration::RelocInitializer::create(
John Portof8b4cc82015-06-09 18:06:19 -0700119 NodeNameDeclaration, NodeNameDeclarationOffset));
120 Var->setAlignment(Int64ByteSize);
121 return Var;
122}
John Portof8b4cc82015-06-09 18:06:19 -0700123} // end of anonymous namespace
124
125void Cfg::profileBlocks() {
126 if (GlobalInits == nullptr)
127 GlobalInits.reset(new VariableDeclarationList());
128
129 for (CfgNode *Node : Nodes) {
130 IceString NodeAsmName = Node->getAsmName();
John Porto1bec8bc2015-06-22 10:51:13 -0700131 GlobalInits->push_back(nodeNameDeclaration(Ctx, NodeAsmName));
John Portof8b4cc82015-06-09 18:06:19 -0700132 GlobalInits->push_back(
John Porto1bec8bc2015-06-22 10:51:13 -0700133 blockProfilingInfoDeclaration(Ctx, NodeAsmName, GlobalInits->back()));
John Portof8b4cc82015-06-09 18:06:19 -0700134 Node->profileExecutionCount(GlobalInits->back());
135 }
136}
137
138bool Cfg::isProfileGlobal(const VariableDeclaration &Var) {
139 return Var.getName().find(BlockStatsGlobalPrefix) == 0;
140}
141
142void Cfg::addCallToProfileSummary() {
143 // The call(s) to __Sz_profile_summary are added by the profiler in functions
144 // that cause the program to exit. This function is defined in
145 // runtime/szrt_profiler.c.
146 Constant *ProfileSummarySym =
147 Ctx->getConstantExternSym("__Sz_profile_summary");
148 constexpr SizeT NumArgs = 0;
149 constexpr Variable *Void = nullptr;
150 constexpr bool HasTailCall = false;
151 auto *Call =
152 InstCall::create(this, NumArgs, Void, ProfileSummarySym, HasTailCall);
153 getEntryNode()->getInsts().push_front(Call);
154}
155
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700156void Cfg::translate() {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700157 if (hasError())
158 return;
Andrew Scull57e12682015-09-16 11:30:19 -0700159 // FunctionTimer conditionally pushes/pops a TimerMarker if TimeEachFunction
160 // is enabled.
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800161 std::unique_ptr<TimerMarker> FunctionTimer;
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700162 if (BuildDefs::dump()) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800163 const IceString &TimingFocusOn =
164 getContext()->getFlags().getTimingFocusOn();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800165 const IceString &Name = getFunctionName();
166 if (TimingFocusOn == "*" || TimingFocusOn == Name) {
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800167 setFocusedTiming();
168 getContext()->resetTimer(GlobalContext::TSK_Default);
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800169 getContext()->setTimerName(GlobalContext::TSK_Default, Name);
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800170 }
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800171 if (getContext()->getFlags().getTimeEachFunction())
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800172 FunctionTimer.reset(new TimerMarker(
173 getContext()->getTimerID(GlobalContext::TSK_Funcs, Name),
174 getContext(), GlobalContext::TSK_Funcs));
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700175 }
Jim Stichnoth8363a062014-10-07 10:02:38 -0700176 TimerMarker T(TimerStack::TT_translate, this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700177
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700178 dump("Initial CFG");
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700179
John Portof8b4cc82015-06-09 18:06:19 -0700180 if (getContext()->getFlags().getEnableBlockProfile()) {
181 profileBlocks();
Andrew Scull57e12682015-09-16 11:30:19 -0700182 // TODO(jpp): this is fragile, at best. Figure out a better way of
183 // detecting exit functions.
John Portof8b4cc82015-06-09 18:06:19 -0700184 if (GlobalContext::matchSymbolName(getFunctionName(), "exit")) {
185 addCallToProfileSummary();
186 }
187 dump("Profiled CFG");
188 }
189
Andrew Scull57e12682015-09-16 11:30:19 -0700190 // The set of translation passes and their order are determined by the
191 // target.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700192 getTarget()->translate();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700193
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700194 dump("Final output");
Jim Stichnoth8363a062014-10-07 10:02:38 -0700195 if (getFocusedTiming())
196 getContext()->dumpTimers();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700197}
198
Jim Stichnoth69d3f9c2015-03-23 10:33:38 -0700199void Cfg::computeInOutEdges() {
200 // Compute the out-edges.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700201 for (CfgNode *Node : Nodes)
Jim Stichnoth69d3f9c2015-03-23 10:33:38 -0700202 Node->computeSuccessors();
203
204 // Prune any unreachable nodes before computing in-edges.
205 SizeT NumNodes = getNumNodes();
206 llvm::BitVector Reachable(NumNodes);
207 llvm::BitVector Pending(NumNodes);
208 Pending.set(getEntryNode()->getIndex());
209 while (true) {
210 int Index = Pending.find_first();
211 if (Index == -1)
212 break;
213 Pending.reset(Index);
214 Reachable.set(Index);
215 CfgNode *Node = Nodes[Index];
216 assert(Node->getIndex() == (SizeT)Index);
217 for (CfgNode *Succ : Node->getOutEdges()) {
218 SizeT SuccIndex = Succ->getIndex();
219 if (!Reachable.test(SuccIndex))
220 Pending.set(SuccIndex);
221 }
222 }
223 SizeT Dest = 0;
224 for (SizeT Source = 0; Source < NumNodes; ++Source) {
225 if (Reachable.test(Source)) {
226 Nodes[Dest] = Nodes[Source];
227 Nodes[Dest]->resetIndex(Dest);
228 // Compute the in-edges.
229 Nodes[Dest]->computePredecessors();
230 ++Dest;
231 }
232 }
233 Nodes.resize(Dest);
Jim Stichnoth1aca2302015-09-16 11:25:22 -0700234
235 TimerMarker T(TimerStack::TT_phiValidation, this);
236 for (CfgNode *Node : Nodes)
237 Node->validatePhis();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700238}
239
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700240void Cfg::renumberInstructions() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700241 TimerMarker T(TimerStack::TT_renumberInstructions, this);
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800242 NextInstNumber = Inst::NumberInitial;
Jim Stichnothf44f3712014-10-01 14:05:51 -0700243 for (CfgNode *Node : Nodes)
244 Node->renumberInstructions();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700245}
246
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700247// placePhiLoads() must be called before placePhiStores().
248void Cfg::placePhiLoads() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700249 TimerMarker T(TimerStack::TT_placePhiLoads, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700250 for (CfgNode *Node : Nodes)
251 Node->placePhiLoads();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700252}
253
254// placePhiStores() must be called after placePhiLoads().
255void Cfg::placePhiStores() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700256 TimerMarker T(TimerStack::TT_placePhiStores, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700257 for (CfgNode *Node : Nodes)
258 Node->placePhiStores();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700259}
260
261void Cfg::deletePhis() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700262 TimerMarker T(TimerStack::TT_deletePhis, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700263 for (CfgNode *Node : Nodes)
264 Node->deletePhis();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700265}
266
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700267void Cfg::advancedPhiLowering() {
268 TimerMarker T(TimerStack::TT_advancedPhiLowering, this);
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700269 // Clear all previously computed live ranges (but not live-in/live-out bit
270 // vectors or last-use markers), because the follow-on register allocation is
271 // only concerned with live ranges across the newly created blocks.
272 for (Variable *Var : Variables) {
273 Var->getLiveRange().reset();
274 }
Andrew Scull57e12682015-09-16 11:30:19 -0700275 // This splits edges and appends new nodes to the end of the node list. This
276 // can invalidate iterators, so don't use an iterator.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700277 SizeT NumNodes = getNumNodes();
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700278 SizeT NumVars = getNumVariables();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700279 for (SizeT I = 0; I < NumNodes; ++I)
280 Nodes[I]->advancedPhiLowering();
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700281
282 TimerMarker TT(TimerStack::TT_lowerPhiAssignments, this);
283 if (true) {
Andrew Scull57e12682015-09-16 11:30:19 -0700284 // The following code does an in-place update of liveness and live ranges
285 // as a result of adding the new phi edge split nodes.
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700286 getLiveness()->initPhiEdgeSplits(Nodes.begin() + NumNodes,
287 Variables.begin() + NumVars);
288 TimerMarker TTT(TimerStack::TT_liveness, this);
289 // Iterate over the newly added nodes to add their liveness info.
290 for (auto I = Nodes.begin() + NumNodes, E = Nodes.end(); I != E; ++I) {
291 InstNumberT FirstInstNum = getNextInstNumber();
292 (*I)->renumberInstructions();
293 InstNumberT LastInstNum = getNextInstNumber() - 1;
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700294 (*I)->liveness(getLiveness());
295 (*I)->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
296 }
297 } else {
298 // The following code does a brute-force recalculation of live ranges as a
Andrew Scull57e12682015-09-16 11:30:19 -0700299 // result of adding the new phi edge split nodes. The liveness calculation
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700300 // is particularly expensive because the new nodes are not yet in a proper
301 // topological order and so convergence is slower.
302 //
303 // This code is kept here for reference and can be temporarily enabled in
304 // case the incremental code is under suspicion.
305 renumberInstructions();
306 liveness(Liveness_Intervals);
307 getVMetadata()->init(VMK_All);
308 }
309 Target->regAlloc(RAK_Phi);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700310}
311
Andrew Scull57e12682015-09-16 11:30:19 -0700312// Find a reasonable placement for nodes that have not yet been placed, while
313// maintaining the same relative ordering among already placed nodes.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700314void Cfg::reorderNodes() {
Andrew Scull57e12682015-09-16 11:30:19 -0700315 // TODO(ascull): it would be nice if the switch tests were always followed by
316 // the default case to allow for fall through.
Andrew Scull00741a02015-09-16 19:04:09 -0700317 using PlacedList = CfgList<CfgNode *>;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700318 PlacedList Placed; // Nodes with relative placement locked down
319 PlacedList Unreachable; // Unreachable nodes
320 PlacedList::iterator NoPlace = Placed.end();
Andrew Scull57e12682015-09-16 11:30:19 -0700321 // Keep track of where each node has been tentatively placed so that we can
322 // manage insertions into the middle.
Andrew Scull00741a02015-09-16 19:04:09 -0700323 CfgVector<PlacedList::iterator> PlaceIndex(Nodes.size(), NoPlace);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700324 for (CfgNode *Node : Nodes) {
Andrew Scull57e12682015-09-16 11:30:19 -0700325 // The "do ... while(0);" construct is to factor out the --PlaceIndex and
326 // assert() statements before moving to the next node.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700327 do {
Andrew Scull713278a2015-07-22 17:17:02 -0700328 if (Node != getEntryNode() && Node->getInEdges().empty()) {
Andrew Scull57e12682015-09-16 11:30:19 -0700329 // The node has essentially been deleted since it is not a successor of
330 // any other node.
Andrew Scull713278a2015-07-22 17:17:02 -0700331 Unreachable.push_back(Node);
332 PlaceIndex[Node->getIndex()] = Unreachable.end();
333 Node->setNeedsPlacement(false);
334 continue;
335 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700336 if (!Node->needsPlacement()) {
337 // Add to the end of the Placed list.
338 Placed.push_back(Node);
339 PlaceIndex[Node->getIndex()] = Placed.end();
340 continue;
341 }
342 Node->setNeedsPlacement(false);
Andrew Scull57e12682015-09-16 11:30:19 -0700343 // Assume for now that the unplaced node is from edge-splitting and
344 // therefore has 1 in-edge and 1 out-edge (actually, possibly more than 1
345 // in-edge if the predecessor node was contracted). If this changes in
346 // the future, rethink the strategy.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700347 assert(Node->getInEdges().size() >= 1);
348 assert(Node->getOutEdges().size() == 1);
349
350 // If it's a (non-critical) edge where the successor has a single
351 // in-edge, then place it before the successor.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800352 CfgNode *Succ = Node->getOutEdges().front();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700353 if (Succ->getInEdges().size() == 1 &&
354 PlaceIndex[Succ->getIndex()] != NoPlace) {
355 Placed.insert(PlaceIndex[Succ->getIndex()], Node);
356 PlaceIndex[Node->getIndex()] = PlaceIndex[Succ->getIndex()];
357 continue;
358 }
359
360 // Otherwise, place it after the (first) predecessor.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800361 CfgNode *Pred = Node->getInEdges().front();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700362 auto PredPosition = PlaceIndex[Pred->getIndex()];
Andrew Scull57e12682015-09-16 11:30:19 -0700363 // It shouldn't be the case that PredPosition==NoPlace, but if that
364 // somehow turns out to be true, we just insert Node before
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700365 // PredPosition=NoPlace=Placed.end() .
366 if (PredPosition != NoPlace)
367 ++PredPosition;
368 Placed.insert(PredPosition, Node);
369 PlaceIndex[Node->getIndex()] = PredPosition;
370 } while (0);
371
372 --PlaceIndex[Node->getIndex()];
373 assert(*PlaceIndex[Node->getIndex()] == Node);
374 }
375
376 // Reorder Nodes according to the built-up lists.
Karl Schimpfac7d7342015-08-06 12:55:23 -0700377 NodeList Reordered;
378 Reordered.reserve(Placed.size() + Unreachable.size());
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700379 for (CfgNode *Node : Placed)
Karl Schimpfac7d7342015-08-06 12:55:23 -0700380 Reordered.push_back(Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700381 for (CfgNode *Node : Unreachable)
Karl Schimpfac7d7342015-08-06 12:55:23 -0700382 Reordered.push_back(Node);
383 assert(getNumNodes() == Reordered.size());
384 swapNodes(Reordered);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700385}
386
Qining Lu969f6a32015-07-31 09:58:34 -0700387namespace {
388void getRandomPostOrder(CfgNode *Node, llvm::BitVector &ToVisit,
389 Ice::NodeList &PostOrder,
390 Ice::RandomNumberGenerator *RNG) {
391 assert(ToVisit[Node->getIndex()]);
392 ToVisit[Node->getIndex()] = false;
393 NodeList Outs = Node->getOutEdges();
394 Ice::RandomShuffle(Outs.begin(), Outs.end(),
395 [RNG](int N) { return RNG->next(N); });
396 for (CfgNode *Next : Outs) {
397 if (ToVisit[Next->getIndex()])
398 getRandomPostOrder(Next, ToVisit, PostOrder, RNG);
399 }
400 PostOrder.push_back(Node);
401}
402} // end of anonymous namespace
403
404void Cfg::shuffleNodes() {
405 if (!Ctx->getFlags().shouldReorderBasicBlocks())
406 return;
407
408 NodeList ReversedReachable;
409 NodeList Unreachable;
410 llvm::BitVector ToVisit(Nodes.size(), true);
Qining Luaee5fa82015-08-20 14:59:03 -0700411 // Create Random number generator for function reordering
412 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
413 RPE_BasicBlockReordering, SequenceNumber);
Qining Lu969f6a32015-07-31 09:58:34 -0700414 // Traverse from entry node.
Qining Luaee5fa82015-08-20 14:59:03 -0700415 getRandomPostOrder(getEntryNode(), ToVisit, ReversedReachable, &RNG);
Qining Lu969f6a32015-07-31 09:58:34 -0700416 // Collect the unreachable nodes.
417 for (CfgNode *Node : Nodes)
418 if (ToVisit[Node->getIndex()])
419 Unreachable.push_back(Node);
420 // Copy the layout list to the Nodes.
Karl Schimpfac7d7342015-08-06 12:55:23 -0700421 NodeList Shuffled;
422 Shuffled.reserve(ReversedReachable.size() + Unreachable.size());
Qining Lu969f6a32015-07-31 09:58:34 -0700423 for (CfgNode *Node : reverse_range(ReversedReachable))
Karl Schimpfac7d7342015-08-06 12:55:23 -0700424 Shuffled.push_back(Node);
425 for (CfgNode *Node : Unreachable)
426 Shuffled.push_back(Node);
427 assert(Nodes.size() == Shuffled.size());
428 swapNodes(Shuffled);
Qining Lu969f6a32015-07-31 09:58:34 -0700429
430 dump("After basic block shuffling");
431}
432
Matt Wala45a06232014-07-09 16:33:22 -0700433void Cfg::doArgLowering() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700434 TimerMarker T(TimerStack::TT_doArgLowering, this);
Matt Wala45a06232014-07-09 16:33:22 -0700435 getTarget()->lowerArguments();
436}
437
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700438void Cfg::doAddressOpt() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700439 TimerMarker T(TimerStack::TT_doAddressOpt, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700440 for (CfgNode *Node : Nodes)
441 Node->doAddressOpt();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700442}
443
Matt Walac3302742014-08-15 16:21:56 -0700444void Cfg::doNopInsertion() {
Qining Lu969f6a32015-07-31 09:58:34 -0700445 if (!Ctx->getFlags().shouldDoNopInsertion())
446 return;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700447 TimerMarker T(TimerStack::TT_doNopInsertion, this);
Qining Luaee5fa82015-08-20 14:59:03 -0700448 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), RPE_NopInsertion,
449 SequenceNumber);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700450 for (CfgNode *Node : Nodes)
Qining Luaee5fa82015-08-20 14:59:03 -0700451 Node->doNopInsertion(RNG);
Matt Walac3302742014-08-15 16:21:56 -0700452}
453
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700454void Cfg::genCode() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700455 TimerMarker T(TimerStack::TT_genCode, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700456 for (CfgNode *Node : Nodes)
457 Node->genCode();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700458}
459
460// Compute the stack frame layout.
461void Cfg::genFrame() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700462 TimerMarker T(TimerStack::TT_genFrame, this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700463 getTarget()->addProlog(Entry);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700464 for (CfgNode *Node : Nodes)
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700465 if (Node->getHasReturn())
466 getTarget()->addEpilog(Node);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700467}
468
Andrew Scullaa6c1092015-09-03 17:50:30 -0700469void Cfg::computeLoopNestDepth() {
470 TimerMarker T(TimerStack::TT_computeLoopNestDepth, this);
471 LoopAnalyzer LA(this);
472 LA.computeLoopNestDepth();
473}
474
Andrew Scull57e12682015-09-16 11:30:19 -0700475// This is a lightweight version of live-range-end calculation. Marks the last
Andrew Scullaa6c1092015-09-03 17:50:30 -0700476// use of only those variables whose definition and uses are completely with a
Andrew Scull57e12682015-09-16 11:30:19 -0700477// single block. It is a quick single pass and doesn't need to iterate until
Andrew Scullaa6c1092015-09-03 17:50:30 -0700478// convergence.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700479void Cfg::livenessLightweight() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700480 TimerMarker T(TimerStack::TT_livenessLightweight, this);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700481 getVMetadata()->init(VMK_Uses);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700482 for (CfgNode *Node : Nodes)
483 Node->livenessLightweight();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700484}
485
486void Cfg::liveness(LivenessMode Mode) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700487 TimerMarker T(TimerStack::TT_liveness, this);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700488 Live.reset(new Liveness(this, Mode));
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700489 getVMetadata()->init(VMK_Uses);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700490 Live->init();
491 // Initialize with all nodes needing to be processed.
492 llvm::BitVector NeedToProcess(Nodes.size(), true);
493 while (NeedToProcess.any()) {
494 // Iterate in reverse topological order to speed up convergence.
Jim Stichnoth7e571362015-01-09 11:43:26 -0800495 for (CfgNode *Node : reverse_range(Nodes)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700496 if (NeedToProcess[Node->getIndex()]) {
497 NeedToProcess[Node->getIndex()] = false;
498 bool Changed = Node->liveness(getLiveness());
499 if (Changed) {
500 // If the beginning-of-block liveness changed since the last
501 // iteration, mark all in-edges as needing to be processed.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700502 for (CfgNode *Pred : Node->getInEdges())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700503 NeedToProcess[Pred->getIndex()] = true;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700504 }
505 }
506 }
507 }
508 if (Mode == Liveness_Intervals) {
509 // Reset each variable's live range.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700510 for (Variable *Var : Variables)
511 Var->resetLiveRange();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700512 }
Andrew Scull57e12682015-09-16 11:30:19 -0700513 // Make a final pass over each node to delete dead instructions, collect the
514 // first and last instruction numbers, and add live range segments for that
515 // node.
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800516 for (CfgNode *Node : Nodes) {
517 InstNumberT FirstInstNum = Inst::NumberSentinel;
518 InstNumberT LastInstNum = Inst::NumberSentinel;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800519 for (Inst &I : Node->getPhis()) {
520 I.deleteIfDead();
521 if (Mode == Liveness_Intervals && !I.isDeleted()) {
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800522 if (FirstInstNum == Inst::NumberSentinel)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800523 FirstInstNum = I.getNumber();
524 assert(I.getNumber() > LastInstNum);
525 LastInstNum = I.getNumber();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700526 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800527 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800528 for (Inst &I : Node->getInsts()) {
529 I.deleteIfDead();
530 if (Mode == Liveness_Intervals && !I.isDeleted()) {
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800531 if (FirstInstNum == Inst::NumberSentinel)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800532 FirstInstNum = I.getNumber();
533 assert(I.getNumber() > LastInstNum);
534 LastInstNum = I.getNumber();
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800535 }
536 }
537 if (Mode == Liveness_Intervals) {
Andrew Scull57e12682015-09-16 11:30:19 -0700538 // Special treatment for live in-args. Their liveness needs to extend
539 // beyond the beginning of the function, otherwise an arg whose only use
540 // is in the first instruction will end up having the trivial live range
541 // [2,2) and will *not* interfere with other arguments. So if the first
542 // instruction of the method is "r=arg1+arg2", both args may be assigned
543 // the same register. This is accomplished by extending the entry block's
544 // instruction range from [2,n) to [1,n) which will transform the
545 // problematic [2,2) live ranges into [1,2).
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700546 if (Node == getEntryNode()) {
Andrew Scull57e12682015-09-16 11:30:19 -0700547 // TODO(stichnot): Make it a strict requirement that the entry node
548 // gets the lowest instruction numbers, so that extending the live
549 // range for in-args is guaranteed to work.
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800550 FirstInstNum = Inst::NumberExtended;
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700551 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800552 Node->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700553 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700554 }
555}
556
Andrew Scull57e12682015-09-16 11:30:19 -0700557// Traverse every Variable of every Inst and verify that it appears within the
558// Variable's computed live range.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700559bool Cfg::validateLiveness() const {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700560 TimerMarker T(TimerStack::TT_validateLiveness, this);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700561 bool Valid = true;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800562 OstreamLocker L(Ctx);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700563 Ostream &Str = Ctx->getStrDump();
Jim Stichnothf44f3712014-10-01 14:05:51 -0700564 for (CfgNode *Node : Nodes) {
Jim Stichnothae953202014-12-20 06:17:49 -0800565 Inst *FirstInst = nullptr;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800566 for (Inst &Inst : Node->getInsts()) {
567 if (Inst.isDeleted())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700568 continue;
Jim Stichnothae953202014-12-20 06:17:49 -0800569 if (FirstInst == nullptr)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800570 FirstInst = &Inst;
571 InstNumberT InstNumber = Inst.getNumber();
572 if (Variable *Dest = Inst.getDest()) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700573 if (!Dest->getIgnoreLiveness()) {
574 bool Invalid = false;
575 const bool IsDest = true;
576 if (!Dest->getLiveRange().containsValue(InstNumber, IsDest))
577 Invalid = true;
Andrew Scull57e12682015-09-16 11:30:19 -0700578 // Check that this instruction actually *begins* Dest's live range,
579 // by checking that Dest is not live in the previous instruction. As
580 // a special exception, we don't check this for the first instruction
581 // of the block, because a Phi temporary may be live at the end of
582 // the previous block, and if it is also assigned in the first
583 // instruction of this block, the adjacent live ranges get merged.
Jim Stichnoth29841e82014-12-23 12:26:24 -0800584 if (static_cast<class Inst *>(&Inst) != FirstInst &&
585 !Inst.isDestNonKillable() &&
Jim Stichnoth47752552014-10-13 17:15:08 -0700586 Dest->getLiveRange().containsValue(InstNumber - 1, IsDest))
587 Invalid = true;
588 if (Invalid) {
589 Valid = false;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800590 Str << "Liveness error: inst " << Inst.getNumber() << " dest ";
Jim Stichnoth47752552014-10-13 17:15:08 -0700591 Dest->dump(this);
592 Str << " live range " << Dest->getLiveRange() << "\n";
593 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700594 }
595 }
John Portoec3f5652015-08-31 15:07:09 -0700596 FOREACH_VAR_IN_INST(Var, Inst) {
597 static constexpr bool IsDest = false;
598 if (!Var->getIgnoreLiveness() &&
599 !Var->getLiveRange().containsValue(InstNumber, IsDest)) {
600 Valid = false;
601 Str << "Liveness error: inst " << Inst.getNumber() << " var ";
602 Var->dump(this);
603 Str << " live range " << Var->getLiveRange() << "\n";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700604 }
605 }
606 }
607 }
608 return Valid;
609}
610
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700611void Cfg::contractEmptyNodes() {
Andrew Scullaa6c1092015-09-03 17:50:30 -0700612 // If we're decorating the asm output with register liveness info, this
613 // information may become corrupted or incorrect after contracting nodes that
614 // contain only redundant assignments. As such, we disable this pass when
615 // DecorateAsm is specified. This may make the resulting code look more
616 // branchy, but it should have no effect on the register assignments.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800617 if (Ctx->getFlags().getDecorateAsm())
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700618 return;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700619 for (CfgNode *Node : Nodes) {
620 Node->contractIfEmpty();
621 }
622}
623
Jim Stichnothff9c7062014-09-18 04:50:49 -0700624void Cfg::doBranchOpt() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700625 TimerMarker T(TimerStack::TT_doBranchOpt, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700626 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
Andrew Scull713278a2015-07-22 17:17:02 -0700627 auto NextNode = I + 1;
Jim Stichnothae953202014-12-20 06:17:49 -0800628 (*I)->doBranchOpt(NextNode == E ? nullptr : *NextNode);
Jim Stichnothff9c7062014-09-18 04:50:49 -0700629 }
630}
631
Andrew Scull86df4e92015-07-30 13:54:44 -0700632void Cfg::markNodesForSandboxing() {
633 for (const InstJumpTable *JT : JumpTables)
634 for (SizeT I = 0; I < JT->getNumTargets(); ++I)
635 JT->getTarget(I)->setNeedsAlignment();
636}
637
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700638// ======================== Dump routines ======================== //
639
Andrew Scull57e12682015-09-16 11:30:19 -0700640// emitTextHeader() is not target-specific (apart from what is abstracted by
641// the Assembler), so it is defined here rather than in the target lowering
642// class.
Jim Stichnothbbca7542015-02-11 16:08:31 -0800643void Cfg::emitTextHeader(const IceString &MangledName, GlobalContext *Ctx,
644 const Assembler *Asm) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700645 if (!BuildDefs::dump())
Jim Stichnoth729dbd02015-02-25 14:48:43 -0800646 return;
Jan Voung0faec4c2014-11-05 17:29:56 -0800647 Ostream &Str = Ctx->getStrEmit();
648 Str << "\t.text\n";
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800649 if (Ctx->getFlags().getFunctionSections())
Jan Voung0faec4c2014-11-05 17:29:56 -0800650 Str << "\t.section\t.text." << MangledName << ",\"ax\",@progbits\n";
Jim Stichnothbbca7542015-02-11 16:08:31 -0800651 if (!Asm->getInternal() || Ctx->getFlags().getDisableInternal()) {
Jan Voung0faec4c2014-11-05 17:29:56 -0800652 Str << "\t.globl\t" << MangledName << "\n";
Jan Voungb2d50842015-05-12 09:53:50 -0700653 Str << "\t.type\t" << MangledName << ",%function\n";
Jan Voung0faec4c2014-11-05 17:29:56 -0800654 }
Andrew Scull86df4e92015-07-30 13:54:44 -0700655 Str << "\t" << Asm->getAlignDirective() << " "
Jan Voungb2d50842015-05-12 09:53:50 -0700656 << Asm->getBundleAlignLog2Bytes() << ",0x";
Jan Voung08c3bcd2014-12-01 17:55:16 -0800657 for (uint8_t I : Asm->getNonExecBundlePadding())
Jan Voung0faec4c2014-11-05 17:29:56 -0800658 Str.write_hex(I);
659 Str << "\n";
660 Str << MangledName << ":\n";
661}
662
Andrew Scull86df4e92015-07-30 13:54:44 -0700663void Cfg::deleteJumpTableInsts() {
664 for (InstJumpTable *JumpTable : JumpTables)
665 JumpTable->setDeleted();
666}
667
668void Cfg::emitJumpTables() {
669 switch (Ctx->getFlags().getOutFileType()) {
670 case FT_Elf:
671 case FT_Iasm: {
Andrew Scull57e12682015-09-16 11:30:19 -0700672 // The emission needs to be delayed until the after the text section so
673 // save the offsets in the global context.
Andrew Scull86df4e92015-07-30 13:54:44 -0700674 IceString MangledName = Ctx->mangleName(getFunctionName());
675 for (const InstJumpTable *JumpTable : JumpTables) {
676 SizeT NumTargets = JumpTable->getNumTargets();
677 JumpTableData &JT =
678 Ctx->addJumpTable(MangledName, JumpTable->getId(), NumTargets);
679 for (SizeT I = 0; I < NumTargets; ++I) {
680 SizeT Index = JumpTable->getTarget(I)->getIndex();
Jan Voungc2ec5812015-08-05 09:35:18 -0700681 JT.pushTarget(getAssembler()->getCfgNodeLabel(Index)->getPosition());
Andrew Scull86df4e92015-07-30 13:54:44 -0700682 }
683 }
684 } break;
685 case FT_Asm: {
686 // Emit the assembly directly so we don't need to hang on to all the names
687 for (const InstJumpTable *JumpTable : JumpTables)
688 getTarget()->emitJumpTable(this, JumpTable);
689 } break;
Andrew Scull86df4e92015-07-30 13:54:44 -0700690 }
691}
692
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700693void Cfg::emit() {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700694 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800695 return;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700696 TimerMarker T(TimerStack::TT_emit, this);
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800697 if (Ctx->getFlags().getDecorateAsm()) {
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700698 renumberInstructions();
699 getVMetadata()->init(VMK_Uses);
700 liveness(Liveness_Basic);
701 dump("After recomputing liveness for -decorate-asm");
702 }
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800703 OstreamLocker L(Ctx);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700704 Ostream &Str = Ctx->getStrEmit();
Andrew Scull86df4e92015-07-30 13:54:44 -0700705 IceString MangledName = Ctx->mangleName(getFunctionName());
706 const Assembler *Asm = getAssembler<>();
707 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing();
708
709 emitTextHeader(MangledName, Ctx, Asm);
710 deleteJumpTableInsts();
711 for (CfgNode *Node : Nodes) {
712 if (NeedSandboxing && Node->needsAlignment()) {
713 Str << "\t" << Asm->getAlignDirective() << " "
714 << Asm->getBundleAlignLog2Bytes() << "\n";
715 }
Jim Stichnothf44f3712014-10-01 14:05:51 -0700716 Node->emit(this);
Andrew Scull86df4e92015-07-30 13:54:44 -0700717 }
718 emitJumpTables();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700719 Str << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700720}
721
Jan Voung0faec4c2014-11-05 17:29:56 -0800722void Cfg::emitIAS() {
723 TimerMarker T(TimerStack::TT_emit, this);
Andrew Scull57e12682015-09-16 11:30:19 -0700724 // The emitIAS() routines emit into the internal assembler buffer, so there's
725 // no need to lock the streams.
Andrew Scull86df4e92015-07-30 13:54:44 -0700726 deleteJumpTableInsts();
727 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing();
728 for (CfgNode *Node : Nodes) {
729 if (NeedSandboxing && Node->needsAlignment())
730 getAssembler()->alignCfgNode();
Jan Voung0faec4c2014-11-05 17:29:56 -0800731 Node->emitIAS(this);
Andrew Scull86df4e92015-07-30 13:54:44 -0700732 }
733 emitJumpTables();
Jan Voung0faec4c2014-11-05 17:29:56 -0800734}
735
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700736// Dumps the IR with an optional introductory message.
737void Cfg::dump(const IceString &Message) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700738 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800739 return;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800740 if (!isVerbose())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700741 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800742 OstreamLocker L(Ctx);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700743 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700744 if (!Message.empty())
745 Str << "================ " << Message << " ================\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700746 setCurrentNode(getEntryNode());
747 // Print function name+args
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800748 if (isVerbose(IceV_Instructions)) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700749 Str << "define ";
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800750 if (getInternal() && !Ctx->getFlags().getDisableInternal())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700751 Str << "internal ";
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700752 Str << ReturnType << " @" << Ctx->mangleName(getFunctionName()) << "(";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700753 for (SizeT i = 0; i < Args.size(); ++i) {
754 if (i > 0)
755 Str << ", ";
756 Str << Args[i]->getType() << " ";
757 Args[i]->dump(this);
758 }
759 Str << ") {\n";
760 }
Jim Stichnoth800dab22014-09-20 12:25:02 -0700761 resetCurrentNode();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800762 if (isVerbose(IceV_Liveness)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700763 // Print summary info about variables
Jim Stichnothf44f3712014-10-01 14:05:51 -0700764 for (Variable *Var : Variables) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700765 Str << "// multiblock=";
766 if (getVMetadata()->isTracked(Var))
767 Str << getVMetadata()->isMultiBlock(Var);
768 else
769 Str << "?";
Andrew Scull11c9a322015-08-28 14:24:14 -0700770 Str << " weight=" << Var->getWeight(this) << " ";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700771 Var->dump(this);
772 Str << " LIVE=" << Var->getLiveRange() << "\n";
773 }
774 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700775 // Print each basic block
Jim Stichnothf44f3712014-10-01 14:05:51 -0700776 for (CfgNode *Node : Nodes)
777 Node->dump(this);
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800778 if (isVerbose(IceV_Instructions))
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700779 Str << "}\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700780}
781
782} // end of namespace Ice