blob: 218ecd9017197485c2e0a2401daf0700b655e268 [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
11/// This file implements the Cfg class, including constant pool
12/// management.
13///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070014//===----------------------------------------------------------------------===//
15
16#include "IceCfg.h"
John Porto67f8de92015-06-25 10:14:17 -070017
18#include "IceAssembler.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070019#include "IceCfgNode.h"
Jim Stichnoth989a7032014-08-08 10:13:44 -070020#include "IceClFlags.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070021#include "IceDefs.h"
Jan Voungec270732015-01-12 17:00:22 -080022#include "IceELFObjectWriter.h"
John Portof8b4cc82015-06-09 18:06:19 -070023#include "IceGlobalInits.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070024#include "IceInst.h"
Jim Stichnothd97c7df2014-06-04 11:57:08 -070025#include "IceLiveness.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070026#include "IceOperand.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070027#include "IceTargetLowering.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070028
29namespace Ice {
30
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080031ICE_TLS_DEFINE_FIELD(const Cfg *, Cfg, CurrentCfg);
Jim Stichnoth31c95592014-12-19 12:51:35 -080032
Jan Voung1d62cf02015-01-09 14:57:32 -080033ArenaAllocator<> *getCurrentCfgAllocator() {
Jim Stichnoth31c95592014-12-19 12:51:35 -080034 return Cfg::getCurrentCfgAllocator();
35}
36
Jim Stichnothbbca7542015-02-11 16:08:31 -080037Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber)
Jan Voung1f47ad02015-03-20 15:01:26 -070038 : Ctx(Ctx), SequenceNumber(SequenceNumber),
Jim Stichnotheafb56c2015-06-22 10:35:22 -070039 VMask(Ctx->getFlags().getVerbose()), NextInstNumber(Inst::NumberInitial),
40 Allocator(new ArenaAllocator<>()), Live(nullptr),
41 Target(TargetLowering::createLowering(Ctx->getFlags().getTargetArch(),
42 this)),
Jan Voung8acded02014-09-22 18:02:25 -070043 VMetadata(new VariablesMetadata(this)),
Jan Voung1f47ad02015-03-20 15:01:26 -070044 TargetAssembler(TargetLowering::createAssembler(
Jim Stichnotheafb56c2015-06-22 10:35:22 -070045 Ctx->getFlags().getTargetArch(), this)) {
Karl Schimpf6fcbddd2014-11-06 09:49:24 -080046}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070047
Jim Stichnoth8e928382015-02-02 17:03:08 -080048Cfg::~Cfg() { assert(ICE_TLS_GET_FIELD(CurrentCfg) == nullptr); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070049
50void Cfg::setError(const IceString &Message) {
51 HasError = true;
52 ErrorMessage = Message;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070053}
54
Jim Stichnoth668a7a32014-12-10 15:32:25 -080055CfgNode *Cfg::makeNode() {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070056 SizeT LabelIndex = Nodes.size();
Jim Stichnoth668a7a32014-12-10 15:32:25 -080057 CfgNode *Node = CfgNode::create(this, LabelIndex);
Jim Stichnothf7c9a142014-04-29 10:52:43 -070058 Nodes.push_back(Node);
59 return Node;
60}
61
Karl Schimpfac7d7342015-08-06 12:55:23 -070062void Cfg::swapNodes(NodeList &NewNodes) {
63 Nodes.swap(NewNodes);
64 for (SizeT I = 0, NumNodes = getNumNodes(); I < NumNodes; ++I)
65 Nodes[I]->resetIndex(I);
66}
67
Jim Stichnothf7c9a142014-04-29 10:52:43 -070068void Cfg::addArg(Variable *Arg) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -070069 Arg->setIsArg();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070070 Args.push_back(Arg);
71}
72
Jim Stichnoth144cdce2014-09-22 16:02:59 -070073void Cfg::addImplicitArg(Variable *Arg) {
74 Arg->setIsImplicitArg();
75 ImplicitArgs.push_back(Arg);
76}
77
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070078// Returns whether the stack frame layout has been computed yet. This
79// is used for dumping the stack frame location of Variables.
80bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); }
81
John Portof8b4cc82015-06-09 18:06:19 -070082namespace {
83constexpr char BlockNameGlobalPrefix[] = ".L$profiler$block_name$";
84constexpr char BlockStatsGlobalPrefix[] = ".L$profiler$block_info$";
85
John Porto1bec8bc2015-06-22 10:51:13 -070086VariableDeclaration *nodeNameDeclaration(GlobalContext *Ctx,
87 const IceString &NodeAsmName) {
88 VariableDeclaration *Var = VariableDeclaration::create(Ctx);
John Portof8b4cc82015-06-09 18:06:19 -070089 Var->setName(BlockNameGlobalPrefix + NodeAsmName);
90 Var->setIsConstant(true);
John Porto1bec8bc2015-06-22 10:51:13 -070091 Var->addInitializer(VariableDeclaration::DataInitializer::create(
John Portof8b4cc82015-06-09 18:06:19 -070092 NodeAsmName.data(), NodeAsmName.size() + 1));
93 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64);
94 Var->setAlignment(Int64ByteSize); // Wasteful, 32-bit could use 4 bytes.
95 return Var;
96}
97
98VariableDeclaration *
John Porto1bec8bc2015-06-22 10:51:13 -070099blockProfilingInfoDeclaration(GlobalContext *Ctx, const IceString &NodeAsmName,
John Portof8b4cc82015-06-09 18:06:19 -0700100 VariableDeclaration *NodeNameDeclaration) {
John Porto1bec8bc2015-06-22 10:51:13 -0700101 VariableDeclaration *Var = VariableDeclaration::create(Ctx);
John Portof8b4cc82015-06-09 18:06:19 -0700102 Var->setName(BlockStatsGlobalPrefix + NodeAsmName);
103 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64);
John Porto1bec8bc2015-06-22 10:51:13 -0700104 Var->addInitializer(
105 VariableDeclaration::ZeroInitializer::create(Int64ByteSize));
John Portof8b4cc82015-06-09 18:06:19 -0700106
107 const RelocOffsetT NodeNameDeclarationOffset = 0;
John Porto1bec8bc2015-06-22 10:51:13 -0700108 Var->addInitializer(VariableDeclaration::RelocInitializer::create(
John Portof8b4cc82015-06-09 18:06:19 -0700109 NodeNameDeclaration, NodeNameDeclarationOffset));
110 Var->setAlignment(Int64ByteSize);
111 return Var;
112}
John Portof8b4cc82015-06-09 18:06:19 -0700113} // end of anonymous namespace
114
115void Cfg::profileBlocks() {
116 if (GlobalInits == nullptr)
117 GlobalInits.reset(new VariableDeclarationList());
118
119 for (CfgNode *Node : Nodes) {
120 IceString NodeAsmName = Node->getAsmName();
John Porto1bec8bc2015-06-22 10:51:13 -0700121 GlobalInits->push_back(nodeNameDeclaration(Ctx, NodeAsmName));
John Portof8b4cc82015-06-09 18:06:19 -0700122 GlobalInits->push_back(
John Porto1bec8bc2015-06-22 10:51:13 -0700123 blockProfilingInfoDeclaration(Ctx, NodeAsmName, GlobalInits->back()));
John Portof8b4cc82015-06-09 18:06:19 -0700124 Node->profileExecutionCount(GlobalInits->back());
125 }
126}
127
128bool Cfg::isProfileGlobal(const VariableDeclaration &Var) {
129 return Var.getName().find(BlockStatsGlobalPrefix) == 0;
130}
131
132void Cfg::addCallToProfileSummary() {
133 // The call(s) to __Sz_profile_summary are added by the profiler in functions
134 // that cause the program to exit. This function is defined in
135 // runtime/szrt_profiler.c.
136 Constant *ProfileSummarySym =
137 Ctx->getConstantExternSym("__Sz_profile_summary");
138 constexpr SizeT NumArgs = 0;
139 constexpr Variable *Void = nullptr;
140 constexpr bool HasTailCall = false;
141 auto *Call =
142 InstCall::create(this, NumArgs, Void, ProfileSummarySym, HasTailCall);
143 getEntryNode()->getInsts().push_front(Call);
144}
145
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700146void Cfg::translate() {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700147 if (hasError())
148 return;
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800149 // FunctionTimer conditionally pushes/pops a TimerMarker if
150 // TimeEachFunction is enabled.
151 std::unique_ptr<TimerMarker> FunctionTimer;
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700152 if (BuildDefs::dump()) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800153 const IceString &TimingFocusOn =
154 getContext()->getFlags().getTimingFocusOn();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800155 const IceString &Name = getFunctionName();
156 if (TimingFocusOn == "*" || TimingFocusOn == Name) {
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800157 setFocusedTiming();
158 getContext()->resetTimer(GlobalContext::TSK_Default);
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800159 getContext()->setTimerName(GlobalContext::TSK_Default, Name);
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800160 }
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800161 if (getContext()->getFlags().getTimeEachFunction())
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800162 FunctionTimer.reset(new TimerMarker(
163 getContext()->getTimerID(GlobalContext::TSK_Funcs, Name),
164 getContext(), GlobalContext::TSK_Funcs));
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700165 }
Jim Stichnoth8363a062014-10-07 10:02:38 -0700166 TimerMarker T(TimerStack::TT_translate, this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700167
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700168 dump("Initial CFG");
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700169
John Portof8b4cc82015-06-09 18:06:19 -0700170 if (getContext()->getFlags().getEnableBlockProfile()) {
171 profileBlocks();
172 // TODO(jpp): this is fragile, at best. Figure out a better way of detecting
173 // exit functions.
174 if (GlobalContext::matchSymbolName(getFunctionName(), "exit")) {
175 addCallToProfileSummary();
176 }
177 dump("Profiled CFG");
178 }
179
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700180 // The set of translation passes and their order are determined by
181 // the target.
182 getTarget()->translate();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700183
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700184 dump("Final output");
Jim Stichnoth8363a062014-10-07 10:02:38 -0700185 if (getFocusedTiming())
186 getContext()->dumpTimers();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700187}
188
Jim Stichnoth69d3f9c2015-03-23 10:33:38 -0700189void Cfg::computeInOutEdges() {
190 // Compute the out-edges.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700191 for (CfgNode *Node : Nodes)
Jim Stichnoth69d3f9c2015-03-23 10:33:38 -0700192 Node->computeSuccessors();
193
194 // Prune any unreachable nodes before computing in-edges.
195 SizeT NumNodes = getNumNodes();
196 llvm::BitVector Reachable(NumNodes);
197 llvm::BitVector Pending(NumNodes);
198 Pending.set(getEntryNode()->getIndex());
199 while (true) {
200 int Index = Pending.find_first();
201 if (Index == -1)
202 break;
203 Pending.reset(Index);
204 Reachable.set(Index);
205 CfgNode *Node = Nodes[Index];
206 assert(Node->getIndex() == (SizeT)Index);
207 for (CfgNode *Succ : Node->getOutEdges()) {
208 SizeT SuccIndex = Succ->getIndex();
209 if (!Reachable.test(SuccIndex))
210 Pending.set(SuccIndex);
211 }
212 }
213 SizeT Dest = 0;
214 for (SizeT Source = 0; Source < NumNodes; ++Source) {
215 if (Reachable.test(Source)) {
216 Nodes[Dest] = Nodes[Source];
217 Nodes[Dest]->resetIndex(Dest);
218 // Compute the in-edges.
219 Nodes[Dest]->computePredecessors();
220 ++Dest;
221 }
222 }
223 Nodes.resize(Dest);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700224}
225
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700226void Cfg::renumberInstructions() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700227 TimerMarker T(TimerStack::TT_renumberInstructions, this);
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800228 NextInstNumber = Inst::NumberInitial;
Jim Stichnothf44f3712014-10-01 14:05:51 -0700229 for (CfgNode *Node : Nodes)
230 Node->renumberInstructions();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700231}
232
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700233// placePhiLoads() must be called before placePhiStores().
234void Cfg::placePhiLoads() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700235 TimerMarker T(TimerStack::TT_placePhiLoads, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700236 for (CfgNode *Node : Nodes)
237 Node->placePhiLoads();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700238}
239
240// placePhiStores() must be called after placePhiLoads().
241void Cfg::placePhiStores() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700242 TimerMarker T(TimerStack::TT_placePhiStores, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700243 for (CfgNode *Node : Nodes)
244 Node->placePhiStores();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700245}
246
247void Cfg::deletePhis() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700248 TimerMarker T(TimerStack::TT_deletePhis, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700249 for (CfgNode *Node : Nodes)
250 Node->deletePhis();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700251}
252
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700253void Cfg::advancedPhiLowering() {
254 TimerMarker T(TimerStack::TT_advancedPhiLowering, this);
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700255 // Clear all previously computed live ranges (but not live-in/live-out bit
256 // vectors or last-use markers), because the follow-on register allocation is
257 // only concerned with live ranges across the newly created blocks.
258 for (Variable *Var : Variables) {
259 Var->getLiveRange().reset();
260 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700261 // This splits edges and appends new nodes to the end of the node
262 // list. This can invalidate iterators, so don't use an iterator.
263 SizeT NumNodes = getNumNodes();
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700264 SizeT NumVars = getNumVariables();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700265 for (SizeT I = 0; I < NumNodes; ++I)
266 Nodes[I]->advancedPhiLowering();
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700267
268 TimerMarker TT(TimerStack::TT_lowerPhiAssignments, this);
269 if (true) {
270 // The following code does an in-place update of liveness and live ranges as
271 // a result of adding the new phi edge split nodes.
272 getLiveness()->initPhiEdgeSplits(Nodes.begin() + NumNodes,
273 Variables.begin() + NumVars);
274 TimerMarker TTT(TimerStack::TT_liveness, this);
275 // Iterate over the newly added nodes to add their liveness info.
276 for (auto I = Nodes.begin() + NumNodes, E = Nodes.end(); I != E; ++I) {
277 InstNumberT FirstInstNum = getNextInstNumber();
278 (*I)->renumberInstructions();
279 InstNumberT LastInstNum = getNextInstNumber() - 1;
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700280 (*I)->liveness(getLiveness());
281 (*I)->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
282 }
283 } else {
284 // The following code does a brute-force recalculation of live ranges as a
285 // result of adding the new phi edge split nodes. The liveness calculation
286 // is particularly expensive because the new nodes are not yet in a proper
287 // topological order and so convergence is slower.
288 //
289 // This code is kept here for reference and can be temporarily enabled in
290 // case the incremental code is under suspicion.
291 renumberInstructions();
292 liveness(Liveness_Intervals);
293 getVMetadata()->init(VMK_All);
294 }
295 Target->regAlloc(RAK_Phi);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700296}
297
298// Find a reasonable placement for nodes that have not yet been
299// placed, while maintaining the same relative ordering among already
300// placed nodes.
301void Cfg::reorderNodes() {
Andrew Scull713278a2015-07-22 17:17:02 -0700302 // TODO(ascull): it would be nice if the switch tests were always followed
303 // by the default case to allow for fall through.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700304 typedef std::list<CfgNode *> PlacedList;
305 PlacedList Placed; // Nodes with relative placement locked down
306 PlacedList Unreachable; // Unreachable nodes
307 PlacedList::iterator NoPlace = Placed.end();
308 // Keep track of where each node has been tentatively placed so that
309 // we can manage insertions into the middle.
310 std::vector<PlacedList::iterator> PlaceIndex(Nodes.size(), NoPlace);
311 for (CfgNode *Node : Nodes) {
312 // The "do ... while(0);" construct is to factor out the
313 // --PlaceIndex and assert() statements before moving to the next
314 // node.
315 do {
Andrew Scull713278a2015-07-22 17:17:02 -0700316 if (Node != getEntryNode() && Node->getInEdges().empty()) {
317 // The node has essentially been deleted since it is not a
318 // successor of any other node.
319 Unreachable.push_back(Node);
320 PlaceIndex[Node->getIndex()] = Unreachable.end();
321 Node->setNeedsPlacement(false);
322 continue;
323 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700324 if (!Node->needsPlacement()) {
325 // Add to the end of the Placed list.
326 Placed.push_back(Node);
327 PlaceIndex[Node->getIndex()] = Placed.end();
328 continue;
329 }
330 Node->setNeedsPlacement(false);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700331 // Assume for now that the unplaced node is from edge-splitting
332 // and therefore has 1 in-edge and 1 out-edge (actually, possibly
333 // more than 1 in-edge if the predecessor node was contracted).
334 // If this changes in the future, rethink the strategy.
335 assert(Node->getInEdges().size() >= 1);
336 assert(Node->getOutEdges().size() == 1);
337
338 // If it's a (non-critical) edge where the successor has a single
339 // in-edge, then place it before the successor.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800340 CfgNode *Succ = Node->getOutEdges().front();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700341 if (Succ->getInEdges().size() == 1 &&
342 PlaceIndex[Succ->getIndex()] != NoPlace) {
343 Placed.insert(PlaceIndex[Succ->getIndex()], Node);
344 PlaceIndex[Node->getIndex()] = PlaceIndex[Succ->getIndex()];
345 continue;
346 }
347
348 // Otherwise, place it after the (first) predecessor.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800349 CfgNode *Pred = Node->getInEdges().front();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700350 auto PredPosition = PlaceIndex[Pred->getIndex()];
351 // It shouldn't be the case that PredPosition==NoPlace, but if
352 // that somehow turns out to be true, we just insert Node before
353 // PredPosition=NoPlace=Placed.end() .
354 if (PredPosition != NoPlace)
355 ++PredPosition;
356 Placed.insert(PredPosition, Node);
357 PlaceIndex[Node->getIndex()] = PredPosition;
358 } while (0);
359
360 --PlaceIndex[Node->getIndex()];
361 assert(*PlaceIndex[Node->getIndex()] == Node);
362 }
363
364 // Reorder Nodes according to the built-up lists.
Karl Schimpfac7d7342015-08-06 12:55:23 -0700365 NodeList Reordered;
366 Reordered.reserve(Placed.size() + Unreachable.size());
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700367 for (CfgNode *Node : Placed)
Karl Schimpfac7d7342015-08-06 12:55:23 -0700368 Reordered.push_back(Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700369 for (CfgNode *Node : Unreachable)
Karl Schimpfac7d7342015-08-06 12:55:23 -0700370 Reordered.push_back(Node);
371 assert(getNumNodes() == Reordered.size());
372 swapNodes(Reordered);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700373}
374
Qining Lu969f6a32015-07-31 09:58:34 -0700375namespace {
376void getRandomPostOrder(CfgNode *Node, llvm::BitVector &ToVisit,
377 Ice::NodeList &PostOrder,
378 Ice::RandomNumberGenerator *RNG) {
379 assert(ToVisit[Node->getIndex()]);
380 ToVisit[Node->getIndex()] = false;
381 NodeList Outs = Node->getOutEdges();
382 Ice::RandomShuffle(Outs.begin(), Outs.end(),
383 [RNG](int N) { return RNG->next(N); });
384 for (CfgNode *Next : Outs) {
385 if (ToVisit[Next->getIndex()])
386 getRandomPostOrder(Next, ToVisit, PostOrder, RNG);
387 }
388 PostOrder.push_back(Node);
389}
390} // end of anonymous namespace
391
392void Cfg::shuffleNodes() {
393 if (!Ctx->getFlags().shouldReorderBasicBlocks())
394 return;
395
396 NodeList ReversedReachable;
397 NodeList Unreachable;
398 llvm::BitVector ToVisit(Nodes.size(), true);
399 // Traverse from entry node.
400 getRandomPostOrder(getEntryNode(), ToVisit, ReversedReachable,
401 &Ctx->getRNG());
402 // Collect the unreachable nodes.
403 for (CfgNode *Node : Nodes)
404 if (ToVisit[Node->getIndex()])
405 Unreachable.push_back(Node);
406 // Copy the layout list to the Nodes.
Karl Schimpfac7d7342015-08-06 12:55:23 -0700407 NodeList Shuffled;
408 Shuffled.reserve(ReversedReachable.size() + Unreachable.size());
Qining Lu969f6a32015-07-31 09:58:34 -0700409 for (CfgNode *Node : reverse_range(ReversedReachable))
Karl Schimpfac7d7342015-08-06 12:55:23 -0700410 Shuffled.push_back(Node);
411 for (CfgNode *Node : Unreachable)
412 Shuffled.push_back(Node);
413 assert(Nodes.size() == Shuffled.size());
414 swapNodes(Shuffled);
Qining Lu969f6a32015-07-31 09:58:34 -0700415
416 dump("After basic block shuffling");
417}
418
Matt Wala45a06232014-07-09 16:33:22 -0700419void Cfg::doArgLowering() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700420 TimerMarker T(TimerStack::TT_doArgLowering, this);
Matt Wala45a06232014-07-09 16:33:22 -0700421 getTarget()->lowerArguments();
422}
423
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700424void Cfg::doAddressOpt() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700425 TimerMarker T(TimerStack::TT_doAddressOpt, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700426 for (CfgNode *Node : Nodes)
427 Node->doAddressOpt();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700428}
429
Matt Walac3302742014-08-15 16:21:56 -0700430void Cfg::doNopInsertion() {
Qining Lu969f6a32015-07-31 09:58:34 -0700431 if (!Ctx->getFlags().shouldDoNopInsertion())
432 return;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700433 TimerMarker T(TimerStack::TT_doNopInsertion, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700434 for (CfgNode *Node : Nodes)
435 Node->doNopInsertion();
Matt Walac3302742014-08-15 16:21:56 -0700436}
437
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700438void Cfg::genCode() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700439 TimerMarker T(TimerStack::TT_genCode, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700440 for (CfgNode *Node : Nodes)
441 Node->genCode();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700442}
443
444// Compute the stack frame layout.
445void Cfg::genFrame() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700446 TimerMarker T(TimerStack::TT_genFrame, this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700447 getTarget()->addProlog(Entry);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700448 for (CfgNode *Node : Nodes)
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700449 if (Node->getHasReturn())
450 getTarget()->addEpilog(Node);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700451}
452
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700453// This is a lightweight version of live-range-end calculation. Marks
454// the last use of only those variables whose definition and uses are
455// completely with a single block. It is a quick single pass and
456// doesn't need to iterate until convergence.
457void Cfg::livenessLightweight() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700458 TimerMarker T(TimerStack::TT_livenessLightweight, this);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700459 getVMetadata()->init(VMK_Uses);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700460 for (CfgNode *Node : Nodes)
461 Node->livenessLightweight();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700462}
463
464void Cfg::liveness(LivenessMode Mode) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700465 TimerMarker T(TimerStack::TT_liveness, this);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700466 Live.reset(new Liveness(this, Mode));
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700467 getVMetadata()->init(VMK_Uses);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700468 Live->init();
469 // Initialize with all nodes needing to be processed.
470 llvm::BitVector NeedToProcess(Nodes.size(), true);
471 while (NeedToProcess.any()) {
472 // Iterate in reverse topological order to speed up convergence.
Jim Stichnoth7e571362015-01-09 11:43:26 -0800473 for (CfgNode *Node : reverse_range(Nodes)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700474 if (NeedToProcess[Node->getIndex()]) {
475 NeedToProcess[Node->getIndex()] = false;
476 bool Changed = Node->liveness(getLiveness());
477 if (Changed) {
478 // If the beginning-of-block liveness changed since the last
479 // iteration, mark all in-edges as needing to be processed.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700480 for (CfgNode *Pred : Node->getInEdges())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700481 NeedToProcess[Pred->getIndex()] = true;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700482 }
483 }
484 }
485 }
486 if (Mode == Liveness_Intervals) {
487 // Reset each variable's live range.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700488 for (Variable *Var : Variables)
489 Var->resetLiveRange();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700490 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800491 // Make a final pass over each node to delete dead instructions,
492 // collect the first and last instruction numbers, and add live
493 // range segments for that node.
494 for (CfgNode *Node : Nodes) {
495 InstNumberT FirstInstNum = Inst::NumberSentinel;
496 InstNumberT LastInstNum = Inst::NumberSentinel;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800497 for (Inst &I : Node->getPhis()) {
498 I.deleteIfDead();
499 if (Mode == Liveness_Intervals && !I.isDeleted()) {
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800500 if (FirstInstNum == Inst::NumberSentinel)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800501 FirstInstNum = I.getNumber();
502 assert(I.getNumber() > LastInstNum);
503 LastInstNum = I.getNumber();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700504 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800505 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800506 for (Inst &I : Node->getInsts()) {
507 I.deleteIfDead();
508 if (Mode == Liveness_Intervals && !I.isDeleted()) {
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800509 if (FirstInstNum == Inst::NumberSentinel)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800510 FirstInstNum = I.getNumber();
511 assert(I.getNumber() > LastInstNum);
512 LastInstNum = I.getNumber();
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800513 }
514 }
515 if (Mode == Liveness_Intervals) {
516 // Special treatment for live in-args. Their liveness needs to
517 // extend beyond the beginning of the function, otherwise an arg
518 // whose only use is in the first instruction will end up having
519 // the trivial live range [2,2) and will *not* interfere with
520 // other arguments. So if the first instruction of the method
521 // is "r=arg1+arg2", both args may be assigned the same
522 // register. This is accomplished by extending the entry
523 // block's instruction range from [2,n) to [1,n) which will
524 // transform the problematic [2,2) live ranges into [1,2).
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700525 if (Node == getEntryNode()) {
526 // TODO(stichnot): Make it a strict requirement that the entry
527 // node gets the lowest instruction numbers, so that extending
528 // the live range for in-args is guaranteed to work.
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800529 FirstInstNum = Inst::NumberExtended;
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700530 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800531 Node->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700532 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700533 }
534}
535
536// Traverse every Variable of every Inst and verify that it
537// appears within the Variable's computed live range.
538bool Cfg::validateLiveness() const {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700539 TimerMarker T(TimerStack::TT_validateLiveness, this);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700540 bool Valid = true;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800541 OstreamLocker L(Ctx);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700542 Ostream &Str = Ctx->getStrDump();
Jim Stichnothf44f3712014-10-01 14:05:51 -0700543 for (CfgNode *Node : Nodes) {
Jim Stichnothae953202014-12-20 06:17:49 -0800544 Inst *FirstInst = nullptr;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800545 for (Inst &Inst : Node->getInsts()) {
546 if (Inst.isDeleted())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700547 continue;
Jim Stichnothae953202014-12-20 06:17:49 -0800548 if (FirstInst == nullptr)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800549 FirstInst = &Inst;
550 InstNumberT InstNumber = Inst.getNumber();
551 if (Variable *Dest = Inst.getDest()) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700552 if (!Dest->getIgnoreLiveness()) {
553 bool Invalid = false;
554 const bool IsDest = true;
555 if (!Dest->getLiveRange().containsValue(InstNumber, IsDest))
556 Invalid = true;
557 // Check that this instruction actually *begins* Dest's live
558 // range, by checking that Dest is not live in the previous
559 // instruction. As a special exception, we don't check this
560 // for the first instruction of the block, because a Phi
561 // temporary may be live at the end of the previous block,
562 // and if it is also assigned in the first instruction of
563 // this block, the adjacent live ranges get merged.
Jim Stichnoth29841e82014-12-23 12:26:24 -0800564 if (static_cast<class Inst *>(&Inst) != FirstInst &&
565 !Inst.isDestNonKillable() &&
Jim Stichnoth47752552014-10-13 17:15:08 -0700566 Dest->getLiveRange().containsValue(InstNumber - 1, IsDest))
567 Invalid = true;
568 if (Invalid) {
569 Valid = false;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800570 Str << "Liveness error: inst " << Inst.getNumber() << " dest ";
Jim Stichnoth47752552014-10-13 17:15:08 -0700571 Dest->dump(this);
572 Str << " live range " << Dest->getLiveRange() << "\n";
573 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700574 }
575 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800576 for (SizeT I = 0; I < Inst.getSrcSize(); ++I) {
577 Operand *Src = Inst.getSrc(I);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700578 SizeT NumVars = Src->getNumVars();
579 for (SizeT J = 0; J < NumVars; ++J) {
580 const Variable *Var = Src->getVar(J);
Jim Stichnoth47752552014-10-13 17:15:08 -0700581 const bool IsDest = false;
582 if (!Var->getIgnoreLiveness() &&
583 !Var->getLiveRange().containsValue(InstNumber, IsDest)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700584 Valid = false;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800585 Str << "Liveness error: inst " << Inst.getNumber() << " var ";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700586 Var->dump(this);
587 Str << " live range " << Var->getLiveRange() << "\n";
588 }
589 }
590 }
591 }
592 }
593 return Valid;
594}
595
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700596void Cfg::contractEmptyNodes() {
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700597 // If we're decorating the asm output with register liveness info,
598 // this information may become corrupted or incorrect after
599 // contracting nodes that contain only redundant assignments. As
600 // such, we disable this pass when DecorateAsm is specified. This
601 // may make the resulting code look more branchy, but it should have
602 // no effect on the register assignments.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800603 if (Ctx->getFlags().getDecorateAsm())
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700604 return;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700605 for (CfgNode *Node : Nodes) {
606 Node->contractIfEmpty();
607 }
608}
609
Jim Stichnothff9c7062014-09-18 04:50:49 -0700610void Cfg::doBranchOpt() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700611 TimerMarker T(TimerStack::TT_doBranchOpt, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700612 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
Andrew Scull713278a2015-07-22 17:17:02 -0700613 auto NextNode = I + 1;
Jim Stichnothae953202014-12-20 06:17:49 -0800614 (*I)->doBranchOpt(NextNode == E ? nullptr : *NextNode);
Jim Stichnothff9c7062014-09-18 04:50:49 -0700615 }
616}
617
Andrew Scull86df4e92015-07-30 13:54:44 -0700618void Cfg::markNodesForSandboxing() {
619 for (const InstJumpTable *JT : JumpTables)
620 for (SizeT I = 0; I < JT->getNumTargets(); ++I)
621 JT->getTarget(I)->setNeedsAlignment();
622}
623
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700624// ======================== Dump routines ======================== //
625
Jim Stichnothbbca7542015-02-11 16:08:31 -0800626// emitTextHeader() is not target-specific (apart from what is
627// abstracted by the Assembler), so it is defined here rather than in
628// the target lowering class.
629void Cfg::emitTextHeader(const IceString &MangledName, GlobalContext *Ctx,
630 const Assembler *Asm) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700631 if (!BuildDefs::dump())
Jim Stichnoth729dbd02015-02-25 14:48:43 -0800632 return;
Jan Voung0faec4c2014-11-05 17:29:56 -0800633 Ostream &Str = Ctx->getStrEmit();
634 Str << "\t.text\n";
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800635 if (Ctx->getFlags().getFunctionSections())
Jan Voung0faec4c2014-11-05 17:29:56 -0800636 Str << "\t.section\t.text." << MangledName << ",\"ax\",@progbits\n";
Jim Stichnothbbca7542015-02-11 16:08:31 -0800637 if (!Asm->getInternal() || Ctx->getFlags().getDisableInternal()) {
Jan Voung0faec4c2014-11-05 17:29:56 -0800638 Str << "\t.globl\t" << MangledName << "\n";
Jan Voungb2d50842015-05-12 09:53:50 -0700639 Str << "\t.type\t" << MangledName << ",%function\n";
Jan Voung0faec4c2014-11-05 17:29:56 -0800640 }
Andrew Scull86df4e92015-07-30 13:54:44 -0700641 Str << "\t" << Asm->getAlignDirective() << " "
Jan Voungb2d50842015-05-12 09:53:50 -0700642 << Asm->getBundleAlignLog2Bytes() << ",0x";
Jan Voung08c3bcd2014-12-01 17:55:16 -0800643 for (uint8_t I : Asm->getNonExecBundlePadding())
Jan Voung0faec4c2014-11-05 17:29:56 -0800644 Str.write_hex(I);
645 Str << "\n";
646 Str << MangledName << ":\n";
647}
648
Andrew Scull86df4e92015-07-30 13:54:44 -0700649void Cfg::deleteJumpTableInsts() {
650 for (InstJumpTable *JumpTable : JumpTables)
651 JumpTable->setDeleted();
652}
653
654void Cfg::emitJumpTables() {
655 switch (Ctx->getFlags().getOutFileType()) {
656 case FT_Elf:
657 case FT_Iasm: {
658 // The emission needs to be delayed until the after the text section so save
659 // the offsets in the global context.
660 IceString MangledName = Ctx->mangleName(getFunctionName());
661 for (const InstJumpTable *JumpTable : JumpTables) {
662 SizeT NumTargets = JumpTable->getNumTargets();
663 JumpTableData &JT =
664 Ctx->addJumpTable(MangledName, JumpTable->getId(), NumTargets);
665 for (SizeT I = 0; I < NumTargets; ++I) {
666 SizeT Index = JumpTable->getTarget(I)->getIndex();
Jan Voungc2ec5812015-08-05 09:35:18 -0700667 JT.pushTarget(getAssembler()->getCfgNodeLabel(Index)->getPosition());
Andrew Scull86df4e92015-07-30 13:54:44 -0700668 }
669 }
670 } break;
671 case FT_Asm: {
672 // Emit the assembly directly so we don't need to hang on to all the names
673 for (const InstJumpTable *JumpTable : JumpTables)
674 getTarget()->emitJumpTable(this, JumpTable);
675 } break;
Andrew Scull86df4e92015-07-30 13:54:44 -0700676 }
677}
678
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700679void Cfg::emit() {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700680 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800681 return;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700682 TimerMarker T(TimerStack::TT_emit, this);
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800683 if (Ctx->getFlags().getDecorateAsm()) {
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700684 renumberInstructions();
685 getVMetadata()->init(VMK_Uses);
686 liveness(Liveness_Basic);
687 dump("After recomputing liveness for -decorate-asm");
688 }
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800689 OstreamLocker L(Ctx);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700690 Ostream &Str = Ctx->getStrEmit();
Andrew Scull86df4e92015-07-30 13:54:44 -0700691 IceString MangledName = Ctx->mangleName(getFunctionName());
692 const Assembler *Asm = getAssembler<>();
693 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing();
694
695 emitTextHeader(MangledName, Ctx, Asm);
696 deleteJumpTableInsts();
697 for (CfgNode *Node : Nodes) {
698 if (NeedSandboxing && Node->needsAlignment()) {
699 Str << "\t" << Asm->getAlignDirective() << " "
700 << Asm->getBundleAlignLog2Bytes() << "\n";
701 }
Jim Stichnothf44f3712014-10-01 14:05:51 -0700702 Node->emit(this);
Andrew Scull86df4e92015-07-30 13:54:44 -0700703 }
704 emitJumpTables();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700705 Str << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700706}
707
Jan Voung0faec4c2014-11-05 17:29:56 -0800708void Cfg::emitIAS() {
709 TimerMarker T(TimerStack::TT_emit, this);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800710 // The emitIAS() routines emit into the internal assembler buffer,
Jim Stichnothbbca7542015-02-11 16:08:31 -0800711 // so there's no need to lock the streams.
Andrew Scull86df4e92015-07-30 13:54:44 -0700712 deleteJumpTableInsts();
713 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing();
714 for (CfgNode *Node : Nodes) {
715 if (NeedSandboxing && Node->needsAlignment())
716 getAssembler()->alignCfgNode();
Jan Voung0faec4c2014-11-05 17:29:56 -0800717 Node->emitIAS(this);
Andrew Scull86df4e92015-07-30 13:54:44 -0700718 }
719 emitJumpTables();
Jan Voung0faec4c2014-11-05 17:29:56 -0800720}
721
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700722// Dumps the IR with an optional introductory message.
723void Cfg::dump(const IceString &Message) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700724 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800725 return;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800726 if (!isVerbose())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700727 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800728 OstreamLocker L(Ctx);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700729 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700730 if (!Message.empty())
731 Str << "================ " << Message << " ================\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700732 setCurrentNode(getEntryNode());
733 // Print function name+args
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800734 if (isVerbose(IceV_Instructions)) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700735 Str << "define ";
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800736 if (getInternal() && !Ctx->getFlags().getDisableInternal())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700737 Str << "internal ";
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700738 Str << ReturnType << " @" << Ctx->mangleName(getFunctionName()) << "(";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700739 for (SizeT i = 0; i < Args.size(); ++i) {
740 if (i > 0)
741 Str << ", ";
742 Str << Args[i]->getType() << " ";
743 Args[i]->dump(this);
744 }
745 Str << ") {\n";
746 }
Jim Stichnoth800dab22014-09-20 12:25:02 -0700747 resetCurrentNode();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800748 if (isVerbose(IceV_Liveness)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700749 // Print summary info about variables
Jim Stichnothf44f3712014-10-01 14:05:51 -0700750 for (Variable *Var : Variables) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700751 Str << "// multiblock=";
752 if (getVMetadata()->isTracked(Var))
753 Str << getVMetadata()->isMultiBlock(Var);
754 else
755 Str << "?";
756 Str << " weight=" << Var->getWeight() << " ";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700757 Var->dump(this);
758 Str << " LIVE=" << Var->getLiveRange() << "\n";
759 }
760 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700761 // Print each basic block
Jim Stichnothf44f3712014-10-01 14:05:51 -0700762 for (CfgNode *Node : Nodes)
763 Node->dump(this);
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800764 if (isVerbose(IceV_Instructions))
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700765 Str << "}\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700766}
767
768} // end of namespace Ice